This content originally appeared on DEV Community and was authored by Marcos Vilela
A Necessidade de Otimizar Custos
Em qualquer ambiente de nuvem, especialmente em contas de desenvolvimento e homologação, os custos podem rapidamente sair do controle. Máquinas virtuais, bancos de dados e serviços ficam ligados 24/7, mesmo que só sejam usados durante o horário de trabalho. Foi observando esse cenário que uma ideia simples surgiu: por que não automatizar o processo de ligar e desligar esses recursos?
Este artigo conta a jornada de como essa ideia, nascida de um projeto pessoal simples, evoluiu para uma solução robusta e foi adotada no meu ambiente de trabalho, utilizando Python, Terraform e GitHub Actions para orquestrar tudo.
A Solução em Python: Mão na Massa com boto3
A escolha do Python foi natural. Sua sintaxe limpa e o poder da biblioteca boto3
(o SDK da AWS para Python) tornaram o desenvolvimento rápido e intuitivo. O objetivo era criar duas funções Lambda: uma para "acordar" os recursos no início do dia (resources_start.py
) e outra para "colocá-los para dormir" no final (resources_stop.py
).
A lógica é direta: para cada serviço da AWS, o script busca os recursos em um determinado estado e aplica a ação desejada.
Desligando Recursos (resources_stop.py
)
A função de parada itera sobre diferentes serviços, encontra o que está em execução e o desliga.
EC2: Busca por instâncias com o estado running
.
# infra/terraform/app/resources_stop.py
# ... (imports e configuração do logger)
def lambda_handler(event, context):
results = []
# EC2 - Para todas as instâncias encontradas
ec2 = boto3.client("ec2")
instances = ec2.describe_instances(Filters=[{"Name": "instance-state-name", "Values": ["running"]}])
for reservation in instances["Reservations"]:
for instance in reservation["Instances"]:
instance_id = instance["InstanceId"]
try:
ec2.stop_instances(InstanceIds=[instance_id])
# ... (logging e append nos resultados)
except Exception as e:
# ... (tratamento de erro)
ECS: Para os serviços ECS, a estratégia é zerar o desiredCount
(número de tarefas desejadas), o que efetivamente para as tarefas em execução.
# infra/terraform/app/resources_stop.py
# ...
# ECS - Para todos os serviços encontrados
ecs = boto3.client("ecs")
clusters = ecs.list_clusters()["clusterArns"]
for cluster_arn in clusters:
services = ecs.list_services(cluster=cluster_arn)["serviceArns"]
for service_arn in services:
# ...
try:
ecs.update_service(cluster=cluster_arn, service=service_arn, desiredCount=0)
# ... (logging e append nos resultados)
except Exception as e:
# ... (tratamento de erro)
RDS e DocumentDB: O processo é semelhante: listar instâncias e clusters e aplicar a ação de stop
.
# infra/terraform/app/resources_stop.py
# ...
# RDS - Para todas as instâncias encontradas
rds = boto3.client("rds")
instances = rds.describe_db_instances()["DBInstances"]
for instance in instances:
try:
rds.stop_db_instance(DBInstanceIdentifier=instance["DBInstanceIdentifier"])
# ...
except Exception as e:
# ...
# DocumentDB - Para todos os clusters encontrados
docdb = boto3.client("docdb")
clusters = docdb.describe_db_clusters()["DBClusters"]
for cluster in clusters:
try:
docdb.stop_db_cluster(DBClusterIdentifier=cluster["DBClusterIdentifier"])
# ...
except Exception as e:
# ...
Ligando Recursos (resources_start.py
)
A função de início (resources_start.py
) segue a mesma lógica, mas com a ação inversa. Para instâncias EC2, busca as que estão stopped
e as inicia. Para serviços ECS, define o desiredCount
de volta para 1
(ou o valor que for ideal para seu ambiente). Para RDS e DocumentDB, inicia as instâncias e clusters parados.
O uso do boto3
se mostrou extremamente poderoso, permitindo interagir com toda a gama de serviços da AWS de forma programática e consistente.
Infraestrutura como Código: Orquestrando com Terraform
Com os scripts prontos, o próximo passo era provisionar a infraestrutura de forma automatizada. O Terraform foi a escolha óbvia para gerenciar a criação das Lambdas, permissões e agendamentos.
O arquivo main.tf
concentra toda a nossa lógica de provisionamento.
-
Empacotando as Lambdas: Primeiro, usamos o
archive_file
para compactar nossos scripts Python em arquivos.zip
, prontos para o deploy.
# infra/terraform/main.tf data "archive_file" "resources_start_lambda" { type = "zip" source_file = "${path.module}/app/resources_start.py" output_path = "${path.module}/app/resources_start.zip" } data "archive_file" "resources_stop_lambda" { # ... (similar para o stop) }
-
Criando as Funções Lambda: Em seguida, definimos as
aws_lambda_function
, apontando para os arquivos zipados, definindo o runtime (python3.12
) e o handler.
# infra/terraform/main.tf resource "aws_lambda_function" "resources_start" { filename = data.archive_file.resources_start_lambda.output_path function_name = "${var.namespace}-${var.stage}-${var.name}-resources-start" role = aws_iam_role.scheduler_role.arn handler = "resources_start.lambda_handler" source_code_hash = data.archive_file.resources_start_lambda.output_base64sha256 runtime = "python3.12" # ... } resource "aws_lambda_function" "resources_stop" { # ... (similar para o stop) }
-
Gerenciando Permissões com IAM: Um dos pontos cruciais é garantir que as Lambdas tenham permissão para agir sobre outros recursos. Criamos uma
aws_iam_role_policy
que concede explicitamente as ações necessárias (ec2:StartInstances
,rds:StopDBInstance
, etc.).
# infra/terraform/main.tf resource "aws_iam_role_policy" "resource_manager_policy" { name = "${var.namespace}-${var.stage}-${var.name}-resource-manager-policy" role = aws_iam_role.scheduler_role.id policy = jsonencode({ Version = "2012-10-17", Statement = [ { Effect = "Allow", Action = [ "rds:StartDBCluster", "rds:StopDBCluster", # ... outras permissões "ec2:StopInstances" ], Resource = "*" } ] }) }
-
Agendando as Execuções com EventBridge Scheduler: Finalmente, para automatizar a execução, usamos o
aws_scheduler_schedule
. Ele nos permite definir uma expressãocron
(schedule_expression
) para invocar cada Lambda em um horário específico.
# infra/terraform/main.tf resource "aws_scheduler_schedule" "resources_start_schedule" { name = "${var.namespace}-${var.stage}-${var.name}-resources-start-schedule" schedule_expression = var.start_schedule_expression # ex: "cron(0 8 * * ? *)" # ... target { arn = aws_lambda_function.resources_start.arn role_arn = aws_iam_role.eventbridge_scheduler_role[0].arn # ... } } resource "aws_scheduler_schedule" "resources_stop_schedule" { # ... (similar para o stop, com outro schedule_expression) }
Implantação Contínua com GitHub Actions
Com o código e a infraestrutura definidos, o ciclo se fecha com a automação do deploy. Um workflow simples no GitHub Actions foi criado para aplicar as mudanças do Terraform a cada push
na branch principal, garantindo que qualquer alteração nos scripts ou na infra fosse implantada de forma rápida e segura.
O pipeline basicamente consiste em:
- Fazer o checkout do código.
- Configurar as credenciais da AWS.
- Inicializar o Terraform (
terraform init
). - Planejar e aplicar as mudanças (
terraform apply
).
Conclusão: De um "Script Simples" a uma Solução de Valor
O que começou como um exercício para resolver um problema simples se transformou em uma ferramenta valiosa. A automação do gerenciamento de recursos não apenas gerou uma economia de custos mensurável, mas também serviu como uma incrível experiência de aprendizado.
Essa jornada reforçou a importância de:
- Começar simples: Uma solução não precisa ser complexa para ser eficaz.
- O poder da automação: Tarefas manuais e repetitivas são candidatas perfeitas para automação.
- Infraestrutura como Código: Ferramentas como o Terraform são essenciais para criar sistemas gerenciáveis, replicáveis e transparentes.
Espero que esta experiência inspire outros a olharem para seus próprios desafios diários e a enxergarem neles oportunidades para inovar, aprender e agregar valor, mesmo que a solução comece com um simples script.
This content originally appeared on DEV Community and was authored by Marcos Vilela

Marcos Vilela | Sciencx (2025-10-14T20:04:40+00:00) Automatizando o Gerenciamento de Recursos na AWS para Reduzir Custos: Uma Jornada com Python e Terraform. Retrieved from https://www.scien.cx/2025/10/14/automatizando-o-gerenciamento-de-recursos-na-aws-para-reduzir-custos-uma-jornada-com-python-e-terraform/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.