Cloud & Infraestrutura

Dominando EC2 em Profundidade: Instance Types, AMIs e Placement Groups em Projetos Reais

8 min de leitura

Dominando EC2 em Profundidade: Instance Types, AMIs e Placement Groups em Projetos Reais

Instance Types: Escolhendo a Máquina Correta Os tipos de instância EC2 são organizados em famílias otimizadas para diferentes cargas de trabalho. Entender essa classificação é fundamental para dimensionar sua infraestrutura corretamente e controlar custos. As principais famílias são: General Purpose (t3, m5, m6i) para aplicações balanceadas, Compute Optimized (c5, c6i) para processamento intensivo, Memory Optimized (r5, r6i) para bancos de dados em memória, e Storage Optimized (i3, d2) para workloads I/O intensivas. Cada tipo possui variações de tamanho (nano, micro, small, medium, large, xlarge, 2xlarge, etc.) que determinam vCPUs, memória RAM e largura de banda de rede. Em um projeto real, cometi o erro de usar t3.large para um worker de processamento de imagens — a burst capacity da família t3 não era suficiente para picos constantes. Migrar para c5.large (compute optimized) reduziu o tempo de processamento em 40%. Use o AWS Compute Optimizer para análises de uso real. AMIs: Construindo Imagens Otimizadas Uma AMI (Amazon Machine Image) é o

<h2>Instance Types: Escolhendo a Máquina Correta</h2>

<p>Os tipos de instância EC2 são organizados em famílias otimizadas para diferentes cargas de trabalho. Entender essa classificação é fundamental para dimensionar sua infraestrutura corretamente e controlar custos. As principais famílias são: <strong>General Purpose</strong> (t3, m5, m6i) para aplicações balanceadas, <strong>Compute Optimized</strong> (c5, c6i) para processamento intensivo, <strong>Memory Optimized</strong> (r5, r6i) para bancos de dados em memória, e <strong>Storage Optimized</strong> (i3, d2) para workloads I/O intensivas.</p>

<p>Cada tipo possui variações de tamanho (nano, micro, small, medium, large, xlarge, 2xlarge, etc.) que determinam vCPUs, memória RAM e largura de banda de rede. Em um projeto real, cometi o erro de usar t3.large para um worker de processamento de imagens — a burst capacity da família t3 não era suficiente para picos constantes. Migrar para c5.large (compute optimized) reduziu o tempo de processamento em 40%. Use o <strong>AWS Compute Optimizer</strong> para análises de uso real.</p>

<pre><code class="language-python">import boto3

from datetime import datetime, timedelta

ec2 = boto3.client(&#039;ec2&#039;)

compute_optimizer = boto3.client(&#039;compute-optimizer&#039;)

Analisar recomendações de instância

response = compute_optimizer.get_ec2_instance_recommendations(

filters=[

{

&#039;name&#039;: &#039;finding&#039;,

&#039;values&#039;: [&#039;Underprovisioned&#039;, &#039;Overprovisioned&#039;]

}

]

)

for recommendation in response[&#039;instanceRecommendations&#039;]:

current = recommendation[&#039;currentInstanceType&#039;]

option = recommendation[&#039;recommendationOptions&#039;][0][&#039;instanceType&#039;]

savings = recommendation[&#039;recommendationOptions&#039;][0][&#039;savingsOpportunity&#039;]

print(f&quot;Instância: {current} → {option}&quot;)

print(f&quot;Economia potencial: {savings[&#039;estimatedMonthlySavings&#039;][&#039;value&#039;]}%&quot;)</code></pre>

<h2>AMIs: Construindo Imagens Otimizadas</h2>

<p>Uma AMI (Amazon Machine Image) é o template que define o sistema operacional, software e configurações de uma instância. Você pode usar AMIs pré-construídas (Amazon Linux 2, Ubuntu) ou criar imagens personalizadas otimizadas para sua aplicação. A estratégia correta de AMI reduz drasticamente o tempo de boot e garante consistência entre ambientes.</p>

<p>Criei uma pipeline automatizada que constrói AMIs com Packer, executando testes antes do versionamento. Cada AMI recebe um timestamp e tag de versão, permitindo rollback rápido em caso de problemas. Assim, em vez de provisionar uma instância t3.micro demorando 5 minutos para instalar dependências, a instância já inicia em 30 segundos com tudo pré-configurado.</p>

<pre><code class="language-hcl"># packer-config.hcl

source &quot;amazon-ebs&quot; &quot;web_server&quot; {

ami_name = &quot;web-app-${formatdate(&quot;YYYY-MM-DD-hhmm&quot;, timestamp())}&quot;

instance_type = &quot;t3.micro&quot;

source_ami_filter {

filters = {

name = &quot;amzn2-ami-hvm-*-x86_64-gp2&quot;

root-device-type = &quot;ebs&quot;

virtualization-type = &quot;hvm&quot;

}

owners = [&quot;137112412989&quot;] # Amazon

most_recent = true

}

tags = {

Name = &quot;web-app&quot;

Version = &quot;1.0&quot;

Team = &quot;platform&quot;

}

}

build {

sources = [&quot;source.amazon-ebs.web_server&quot;]

provisioner &quot;shell&quot; {

inline = [

&quot;sudo yum update -y&quot;,

&quot;sudo yum install -y python3 python3-pip&quot;,

&quot;pip3 install flask gunicorn&quot;,

&quot;sudo systemctl enable application&quot;

]

}

provisioner &quot;shell&quot; {

script = &quot;tests/validate-ami.sh&quot;

}

}</code></pre>

<blockquote><p><strong>Prática essencial</strong>: Versionize suas AMIs. Use tags descritivas e mantenha histórico. Uma AMI descartada sem documentação é débito técnico.</p></blockquote>

<h2>Placement Groups: Otimizando Performance e Disponibilidade</h2>

<p>Placement Groups controlam como suas instâncias são distribuídas na infraestrutura AWS. Existem três estratégias: <strong>Cluster</strong> (máxima performance, latência ultra-baixa), <strong>Partition</strong> (distribui entre partições para workloads distribuídos), e <strong>Spread</strong> (máxima disponibilidade, instâncias em racks diferentes).</p>

<p>Num projeto de processamento distribuído com Apache Spark, usar Placement Group Cluster reduziu latência inter-nó de 15ms para 0.3ms. Para aplicações de alta disponibilidade (como websites), o Spread Group evita que falhas de rack isolem múltiplas instâncias simultaneamente. Conheça suas limitações: Cluster Groups requerem instâncias do mesmo tipo e não suportam interrupção; Partition Groups funcionam bem apenas com workloads que entendem distribuição.</p>

<pre><code class="language-python">import boto3

ec2 = boto3.resource(&#039;ec2&#039;)

ec2_client = boto3.client(&#039;ec2&#039;)

Criar Placement Group do tipo Cluster para Spark

pg_response = ec2_client.create_placement_group(

GroupName=&#039;spark-cluster-pg&#039;,

Strategy=&#039;cluster&#039;,

TagSpecifications=[

{

&#039;ResourceType&#039;: &#039;placement-group&#039;,

&#039;Tags&#039;: [

{&#039;Key&#039;: &#039;Project&#039;, &#039;Value&#039;: &#039;data-processing&#039;},

{&#039;Key&#039;: &#039;Type&#039;, &#039;Value&#039;: &#039;spark-worker&#039;}

]

}

]

)

Executar instâncias no Placement Group

instances = ec2.create_instances(

ImageId=&#039;ami-0c55b159cbfafe1f0&#039;, # Amazon Linux 2

MinCount=4,

MaxCount=4,

InstanceType=&#039;c5.2xlarge&#039;,

Placement={

&#039;GroupName&#039;: &#039;spark-cluster-pg&#039;

},

TagSpecifications=[

{

&#039;ResourceType&#039;: &#039;instance&#039;,

&#039;Tags&#039;: [

{&#039;Key&#039;: &#039;Name&#039;, &#039;Value&#039;: &#039;spark-worker&#039;},

{&#039;Key&#039;: &#039;Role&#039;, &#039;Value&#039;: &#039;compute&#039;}

]

}

]

)

print(f&quot;Instâncias criadas: {[i.id for i in instances]}&quot;)

Validar distribuição

describe_response = ec2_client.describe_instances(

Filters=[

{&#039;Name&#039;: &#039;placement.group-name&#039;, &#039;Values&#039;: [&#039;spark-cluster-pg&#039;]}

]

)

for reservation in describe_response[&#039;Reservations&#039;]:

for instance in reservation[&#039;Instances&#039;]:

print(f&quot;Instância {instance[&#039;InstanceId&#039;]} em {instance[&#039;Placement&#039;][&#039;AvailabilityZone&#039;]}&quot;)</code></pre>

<h3>Monitoramento de Placement Group</h3>

<p>Crie um CloudWatch alarm para detectar quando instâncias são expulsas do grupo (situação degradada). Em produção, monitore a latência de rede entre instâncias — um pico inesperado indica que o Placement Group não está mais otimizado.</p>

<h2>Padrões em Projetos Reais</h2>

<h3>Combinação Estratégica</h3>

<p>Em meu último projeto, usamos <strong>t3.medium</strong> para APIs stateless (General Purpose, custos reduzidos com burst), <strong>c5.large</strong> para workers de processamento (Compute Optimized), e <strong>r5.xlarge</strong> para cache Redis (Memory Optimized). Cada instância foi incluída em uma AMI otimizada e grupo de Auto Scaling próprio. Um Placement Group Cluster foi criado apenas para o cluster Redis — o overhead de comunicação justificava.</p>

<pre><code class="language-python"># Auto Scaling com tipos múltiplos

autoscaling = boto3.client(&#039;autoscaling&#039;)

autoscaling.create_launch_template(

LaunchTemplateName=&#039;api-servers&#039;,

LaunchTemplateData={

&#039;ImageId&#039;: &#039;ami-optimized-api-v2.1&#039;,

&#039;InstanceType&#039;: &#039;t3.medium&#039;,

&#039;Monitoring&#039;: {&#039;Enabled&#039;: True},

&#039;TagSpecifications&#039;: [

{

&#039;ResourceType&#039;: &#039;instance&#039;,

&#039;Tags&#039;: [{&#039;Key&#039;: &#039;Tier&#039;, &#039;Value&#039;: &#039;api&#039;}]

}

]

}

)

autoscaling.create_auto_scaling_group(

AutoScalingGroupName=&#039;api-asg&#039;,

LaunchTemplate={&#039;LaunchTemplateName&#039;: &#039;api-servers&#039;},

MinSize=2,

MaxSize=10,

DesiredCapacity=3,

AvailabilityZones=[&#039;us-east-1a&#039;, &#039;us-east-1b&#039;, &#039;us-east-1c&#039;],

VPCZoneIdentifier=&#039;subnet-xxx,subnet-yyy,subnet-zzz&#039;

)</code></pre>

<h2>Conclusão</h2>

<p>Dominar EC2 significa fazer três escolhas corretas: <strong>(1) Selecionar o Instance Type adequado</strong> — use Compute Optimizer para dados reais, não adivinhe. <strong>(2) Construir AMIs versionadas e automatizadas</strong> — seu tempo de deployment e consistência dependem disso. <strong>(3) Aplicar Placement Groups estrategicamente</strong> — apenas onde latência ou disponibilidade justifiquem o overhead. Qualquer infraestrutura AWS escala primeiro quando essas três dimensões estão otimizadas.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://docs.aws.amazon.com/ec2/index.html" target="_blank" rel="noopener noreferrer">AWS EC2 Instance Types - Documentação Oficial</a></li>

<li><a href="https://docs.aws.amazon.com/compute-optimizer/latest/ug/what-is-compute-optimizer.html" target="_blank" rel="noopener noreferrer">AWS Compute Optimizer - Best Practices</a></li>

<li><a href="https://www.packer.io/docs/builders/amazon" target="_blank" rel="noopener noreferrer">Packer by HashiCorp - AMI Building Guide</a></li>

<li><a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html" target="_blank" rel="noopener noreferrer">EC2 Placement Groups - AWS Documentation</a></li>

<li><a href="https://docs.aws.amazon.com/wellarchitected/latest/userguide/compute.html" target="_blank" rel="noopener noreferrer">AWS Well-Architected Framework - Compute Pillar</a></li>

</ul>

Comentários

Mais em Cloud & Infraestrutura

Boas Práticas de AWS WAF e Shield: Proteção contra DDoS e Ataques Web para Times Ágeis
Boas Práticas de AWS WAF e Shield: Proteção contra DDoS e Ataques Web para Times Ágeis

Fundamentos de AWS WAF e Shield para Proteção Web AWS WAF (Web Application Fi...

IAM Avançado: SCP, Permission Boundaries e Attribute-Based Access: Do Básico ao Avançado
IAM Avançado: SCP, Permission Boundaries e Attribute-Based Access: Do Básico ao Avançado

IAM Avançado: SCP, Permission Boundaries e Attribute-Based Access O que é IAM...

Dominando FinOps Avançado na AWS: Reserved Instances, Savings Plans e Spot em Projetos Reais
Dominando FinOps Avançado na AWS: Reserved Instances, Savings Plans e Spot em Projetos Reais

Entendendo os Modelos de Preços na AWS A otimização de custos na AWS vai muit...