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.
import boto3
from datetime import datetime, timedelta
ec2 = boto3.client('ec2')
compute_optimizer = boto3.client('compute-optimizer')
# Analisar recomendações de instância
response = compute_optimizer.get_ec2_instance_recommendations(
filters=[
{
'name': 'finding',
'values': ['Underprovisioned', 'Overprovisioned']
}
]
)
for recommendation in response['instanceRecommendations']:
current = recommendation['currentInstanceType']
option = recommendation['recommendationOptions'][0]['instanceType']
savings = recommendation['recommendationOptions'][0]['savingsOpportunity']
print(f"Instância: {current} → {option}")
print(f"Economia potencial: {savings['estimatedMonthlySavings']['value']}%")
AMIs: Construindo Imagens Otimizadas
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.
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.
# packer-config.hcl
source "amazon-ebs" "web_server" {
ami_name = "web-app-${formatdate("YYYY-MM-DD-hhmm", timestamp())}"
instance_type = "t3.micro"
source_ami_filter {
filters = {
name = "amzn2-ami-hvm-*-x86_64-gp2"
root-device-type = "ebs"
virtualization-type = "hvm"
}
owners = ["137112412989"] # Amazon
most_recent = true
}
tags = {
Name = "web-app"
Version = "1.0"
Team = "platform"
}
}
build {
sources = ["source.amazon-ebs.web_server"]
provisioner "shell" {
inline = [
"sudo yum update -y",
"sudo yum install -y python3 python3-pip",
"pip3 install flask gunicorn",
"sudo systemctl enable application"
]
}
provisioner "shell" {
script = "tests/validate-ami.sh"
}
}
Prática essencial: Versionize suas AMIs. Use tags descritivas e mantenha histórico. Uma AMI descartada sem documentação é débito técnico.
Placement Groups: Otimizando Performance e Disponibilidade
Placement Groups controlam como suas instâncias são distribuídas na infraestrutura AWS. Existem três estratégias: Cluster (máxima performance, latência ultra-baixa), Partition (distribui entre partições para workloads distribuídos), e Spread (máxima disponibilidade, instâncias em racks diferentes).
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.
import boto3
ec2 = boto3.resource('ec2')
ec2_client = boto3.client('ec2')
# Criar Placement Group do tipo Cluster para Spark
pg_response = ec2_client.create_placement_group(
GroupName='spark-cluster-pg',
Strategy='cluster',
TagSpecifications=[
{
'ResourceType': 'placement-group',
'Tags': [
{'Key': 'Project', 'Value': 'data-processing'},
{'Key': 'Type', 'Value': 'spark-worker'}
]
}
]
)
# Executar instâncias no Placement Group
instances = ec2.create_instances(
ImageId='ami-0c55b159cbfafe1f0', # Amazon Linux 2
MinCount=4,
MaxCount=4,
InstanceType='c5.2xlarge',
Placement={
'GroupName': 'spark-cluster-pg'
},
TagSpecifications=[
{
'ResourceType': 'instance',
'Tags': [
{'Key': 'Name', 'Value': 'spark-worker'},
{'Key': 'Role', 'Value': 'compute'}
]
}
]
)
print(f"Instâncias criadas: {[i.id for i in instances]}")
# Validar distribuição
describe_response = ec2_client.describe_instances(
Filters=[
{'Name': 'placement.group-name', 'Values': ['spark-cluster-pg']}
]
)
for reservation in describe_response['Reservations']:
for instance in reservation['Instances']:
print(f"Instância {instance['InstanceId']} em {instance['Placement']['AvailabilityZone']}")
Monitoramento de Placement Group
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.
Padrões em Projetos Reais
Combinação Estratégica
Em meu último projeto, usamos t3.medium para APIs stateless (General Purpose, custos reduzidos com burst), c5.large para workers de processamento (Compute Optimized), e r5.xlarge 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.
# Auto Scaling com tipos múltiplos
autoscaling = boto3.client('autoscaling')
autoscaling.create_launch_template(
LaunchTemplateName='api-servers',
LaunchTemplateData={
'ImageId': 'ami-optimized-api-v2.1',
'InstanceType': 't3.medium',
'Monitoring': {'Enabled': True},
'TagSpecifications': [
{
'ResourceType': 'instance',
'Tags': [{'Key': 'Tier', 'Value': 'api'}]
}
]
}
)
autoscaling.create_auto_scaling_group(
AutoScalingGroupName='api-asg',
LaunchTemplate={'LaunchTemplateName': 'api-servers'},
MinSize=2,
MaxSize=10,
DesiredCapacity=3,
AvailabilityZones=['us-east-1a', 'us-east-1b', 'us-east-1c'],
VPCZoneIdentifier='subnet-xxx,subnet-yyy,subnet-zzz'
)
Conclusão
Dominar EC2 significa fazer três escolhas corretas: (1) Selecionar o Instance Type adequado — use Compute Optimizer para dados reais, não adivinhe. (2) Construir AMIs versionadas e automatizadas — seu tempo de deployment e consistência dependem disso. (3) Aplicar Placement Groups estrategicamente — apenas onde latência ou disponibilidade justifiquem o overhead. Qualquer infraestrutura AWS escala primeiro quando essas três dimensões estão otimizadas.