1. Introdução
Em muitos ambientes corporativos, é comum manter instâncias ligadas mesmo durante períodos em que não estão sendo utilizadas. Em ambientes de desenvolvimento, homologação e testes, por exemplo, muitas instâncias EC2 permanecem em execução fora do horário comercial, gerando custos mesmo sem demanda. Uma alternativa simples para reduzir esse desperdício é automatizar o start/stop das máquinas, definindo horários para ligar e desligar de acordo com a necessidade do ambiente.
Neste artigo, será apresentada uma arquitetura na AWS, utilizando os serviços EC2, EventBridge, Lambda (o código será em Python), IAM e CloudWatch Logs para automatizar esse processo. A solução também utiliza tags para identificar quais recursos devem participar da automação. Além de reduzir custos, a automação ajuda a evitar processos manuais e cria um padrão para o gerenciamento de ambientes que não precisam permanecer ativos 24h por dia.
Abaixo, arquitetura da solução:
2. Serviços utilizados na arquitetura
2.1 Amazon EC2
O Amazon EC2 oferece as máquinas virtuais (instâncias) que a automação vai ligar e desligar. Para dizer à automação quais instâncias devem participar, será utilizada uma tag, que é uma etiqueta formada por uma chave e um valor.
Por exemplo:
tag_key = "lambda-start-stop"
tag_value = "true"
Assim, a função Lambda pode buscar somente as instâncias que possuem essa tag.
Documentação: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html
Documentação: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Instances.html
--
2.2 Amazon EventBridge
Responsável por definir quando a automação será executada. O EventBridge Scheduler chama a função Lambda no horário configurado.
Exemplo comum nas empresas:
- 08h00 - ligar as instâncias
- 18h00 - desligar as instâncias
Documentação: https://docs.aws.amazon.com/scheduler/latest/UserGuide/what-is-scheduler.html
--
2.3 AWS Lambda
É responsável por executar o código da automação, sem a necessidade de gerenciar servidores. Neste caso, a função roda um código em Python que usa o boto3 (o SDK da AWS para Python) para:
- Procurar as instâncias com a tag lambda-start-stop = true
- Executar a ação de start ou stop, conforme o horário que disparou a função.
Documentação: https://docs.aws.amazon.com/lambda/latest/dg/welcome.html
--
2.4 IAM Role
Define quais permissões a Lambda possui. Por exemplo, a função pode receber permissão para:
- Iniciar instâncias EC2
- Parar instâncias EC2
- Consultar informações das instâncias
- Enviar logs para o CloudWatch
Documentação: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html
--
2.5 Amazon CloudWatch
O CloudWatch guarda os logs de cada execução da Lambda. A Lambda envia esses logs automaticamente, desde que a role tenha as permissões adequadas. Os logs podem mostrar:
- Quando a função foi executada
- Status das instâncias encontradas
- Quais ações foram realizadas
- Possíveis erros durante a execução
Documentação: https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html
3. Implementação
3.1 Criação da IAM policy
Para que a Lambda consiga ligar e desligar as instâncias, é necessário criar no IAM uma policy com as permissões necessárias e uma role (função de execução) que será associada à Lambda. A policy deve permitir que a Lambda chame as ações da API do EC2 para consultar, iniciar e parar instâncias, além de enviar os logs para o CloudWatch.
1.Na barra de pesquisa, procurar por “IAM” e acessar o serviço:
2.Após acessar o IAM, clicar em “Policies” e “Create policy” para criar uma nova política:
3.Ao abrir a tela de criação, clicar em “JSON”, inserir o código abaixo e clicar em “Next” para dar continuidade:
Essa política define o que a função Lambda está autorizada a fazer. Neste caso, ela permite que a Lambda registre logs no CloudWatch e consulte, inicie e pare instâncias EC2.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"ec2:Start*",
"ec2:Stop*",
"ec2:Describe*"
],
"Resource": "*"
}
]
}
4.Em seguida, revisar e clicar em “Create policy”:
5.A política foi criada com sucesso:
--
3.2 Criação da IAM role
1.Acessar a aba “Roles” e clicar em “Create role”:
2.Em seguida, selecionar o serviço “Lambda”, caso de uso e clicar em “Next”:
3.Na próxima tela, pesquisar e selecionar a política “ec2-start-stop-policy” criada anteriormente e clicar em “Next”:
4.Em seguida, definir um nome para a role, revisar e clicar em “Create role”, para criar a “ec2-start-stop-role”:
5.A role foi criada com sucesso:

--
3.3 Criação da função Lambda
1.Na barra de pesquisa, procurar por “Lambda” e acessar o serviço:
2.Em seguida, clicar em “Create a function”:
3.Na próxima tela, definir um nome para as duas funções (ec2-start e ec2-stop), selecionar “Python”, que será a linguagem de programação utilizada na automação e clicar em “Create funcion”:
4.O Timeout define o tempo máximo que a função Lambda pode permanecer em execução. O valor padrão é de 3 segundos, mas pode ser alterado conforme a necessidade da aplicação. Para essa automação, será utilizado um timeout de 30 segundos, proporcionando tempo suficiente para consultar e executar as operações nas instâncias EC2.
- Além do timeout, também será necessário selecionar a role que foi criada “ec2-start-stop-role”. Esses procedimentos deverão ser realizados tanto na Lambda “ec2-start” quanto na “ec2-stop”:
5.Agora, podemos inserir o código na função criada “ec2-start” e clicar em “Deploy”:
Código Python “ec2-start”:
import json
import boto3
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
region = 'us-east-1'
client = boto3.client('ec2', region_name=region)
tag_key = "lambda-start-stop"
tag_value = "true"
try:
response = client.describe_instances(
Filters=[
{ 'Name': f'tag:{tag_key}', 'Values': [tag_value] },
]
)
for reservation in response['Reservations']:
for instance in reservation['Instances']:
instanceId = instance['InstanceId']
state = instance['State']['Name']
logger.info(f"Instance ID: {instanceId} - State: {state}")
if state == 'stopped':
logger.info(f"Starting instance {instanceId}")
client.start_instances(InstanceIds=[instanceId])
else:
logger.info(f"Instance {instanceId} is not in 'stopped' state, current state: {state}")
except Exception as e:
logger.error(f"Error managing EC2 instances: {str(e)}")
raise
return {
'statusCode': 200,
'body': 'Start script executed successfully'
}
6.Em seguida, podemos fazer o mesmo com a função Lambda “ec2-stop”:
Código Python “ec2-stop”:
import json
import boto3
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
region = 'us-east-1'
client = boto3.client('ec2', region_name=region)
tag_key = "lambda-start-stop"
tag_value = "true"
try:
response = client.describe_instances(
Filters=[
{ 'Name': f'tag:{tag_key}', 'Values': [tag_value] },
]
)
for reservation in response['Reservations']:
for instance in reservation['Instances']:
instanceId = instance['InstanceId']
state = instance['State']['Name']
logger.info(f"Instance ID: {instanceId} - State: {state}")
if state == 'running':
logger.info(f"Stopping instance {instanceId}")
client.stop_instances(InstanceIds=[instanceId])
else:
logger.info(f"Instance {instanceId} is not in 'running' state, current state: {state}")
except Exception as e:
logger.error(f"Error managing EC2 instances: {str(e)}")
raise
return {
'statusCode': 200,
'body': 'Stop script executed successfully'
}
--
3.4 Configuração do CloudWatch para visualizar os logs
1.Na barra de pesquisa, procurar por “CloudWatch” e acessar o serviço:
2.Na aba “Logs”, clicar em “Log Management” e em “Create log group”:
3.Na próxima tela, definir o nome dos grupos de logs (ec2-start-logs e ec2-stop-logs), retenção (5 dias, por exemplo), classe, habilitar a proteção contra deleção e clicar em “Create”:
4.Os grupos de logs foram criados com sucesso:
5.Agora será necessário acessar a função Lambda “ec2-start” e editar o destino dos logs que vem por padrão, apontando para o grupo de logs criado acima “ec2-start-logs”:
Destino alterado com sucesso:
6.Em seguida, repetir o mesmo com a função Lambda “ec2-stop” removendo o destino padrão e apontando para o grupo de logs “ec2-stop-logs”:
Destino alterado com sucesso:
--
3.5 Criação das instâncias EC2 para testar a Lambda
1.Para testar se as funções Lambda estão funcionando corretamente, será necessário criar uma instância para teste.
- Na aba de pesquisa, procurar por “EC2”, acessar e clicar em “Launch instance”:
2.Definir um nome para a instância (por exemplo: srv-test-01) e clicar em “Add additional tags” para inserir a chave “lambda-start-stop” e valor “true”, conforme está no código:
3.A máquina foi criada com sucesso e está ligada:
4.Para testar se a função “ec2-stop” vai desligar a instância, podemos clicar em “Test” e na barra que irá abrir, escrever algo como “Test” também, seguido e um Enter:
5.Na próxima tela, será necessário definir um nome (por exemplo: test-01) e clicar em “Save”:
6.Em seguida, podemos clicar em “Test” para iniciar a execução:
7.A execução do código está em andamento:
O desligamento da máquina “srv-test-01” foi executado com sucesso:
No CloudWatch, é possível visualizar os logs no grupo “ec2-stop-logs”, onde aparece o estado da instância antes da execução da função Lambda (running) e depois da execução (stopped).
8.Em seguida, podemos repetir o mesmo procedimento com a função “ec2-start”, para ligar a máquina “srv-test-01”. Para isso, outro caminho é clicar em “Create new test event”, na aba “TEST EVENTS”, definir um nome (por exemplo: test-02) e clicar em “Save”:
Em seguida, clicar em “Test” para executar. A função foi executada com sucesso:
A instância foi ligada com sucesso:
No CloudWatch, é possível visualizar os logs no grupo “ec2-start-logs”:
--
3.6 Configuração do EventBridge
1.Na barra de pesquisa, procurar por “EventBridge” e acessar o serviço:
2.Em seguida, selecionar a opção “Schedules”e clicar em “Create schedule” para agendar o start e stop da intância:
3.Definir o nome, recorrência, horário e data do agendamento:
A expressão 30 21 ? * MON-FRI * configura o EventBridge para executar o agendamento às 21h30, de segunda a sexta-feira, considerando o fuso horário America/Sao_Paulo.
- 30: significa 30 minutos
- 21: significa 21h00
- ?: qualquer dia do mês
- *: todos os meses
- MON-FRI: segunda a sexta-feira
- *: todos os anos
4.Na próxima tela, selecionar o serviço Lambda, função “ec2-stop” e clicar em “Next”:
Revisar e concluir a criação:
O agendamento foi criado com sucesso:
Às 21h30, conforme o agendamento configurado, a instância foi desligada:
5.Para criar o agendamento que liga a instância, podemos seguir o mesmo caminho acima, selecionando a função Lambda “ec2-start”. O horário de agendamento será às 21h50, com a expressão cron(50 21 ? * MON-FRI *).
O agendamento foi criado com sucesso:
Às 21h50, conforme o agendamento configurado, a instância foi ligada:
4. Considerações sobre custos
A solução usa apenas serviços serverless e gerenciados, cobrados por uso. Mesmo sendo uma automação simples, vale entender quanto cada componente custa e, principalmente, quais custos continuam existindo mesmo com as instâncias desligadas.
- EventBridge Scheduler: é cobrado pelo número de invocações. O free tier inclui 14 milhões de invocações por mês, e acima disso o preço é de US$1,00 por milhão. https://aws.amazon.com/eventbridge/pricing/
- Lambda: é cobrada por requisições e por tempo de execução (GB por segundo). O free tier inclui um milhão de solicitações gratuitas por mês e 400.000 GB/s de tempo de computação por mês. https://aws.amazon.com/lambda/pricing/
- CloudWatch Logs: armazena os logs de execução da Lambda. Como cada execução gera poucas linhas de log, o volume é mínimo. Mesmo assim, é importante definir um período de retenção no log group (por exemplo, 5 dias), já que o padrão é manter os logs indefinidamente.
- IAM: não possui custo adicional.
- EC2: desligar a instância não zera o custo dela. Alguns recursos continuam sendo cobrados normalmente, como por exemplo, EBS e IP.
5. Conclusão
Ambientes que não precisam ficar disponíveis 24h por dia, como desenvolvimento, homologação e testes, estão entre as maiores fontes de desperdício em cloud. Automatizar o ligar e desligar das instâncias é uma das ações de FinOps mais simples de implementar e com retorno mais rápido. A solução apresentada combina 3 benefícios:
- Redução de custos: ao manter as instâncias ligadas apenas no horário de uso, o custo de computação pode cair cerca de 64% em um cenário de 12h por dia em dias úteis. A automação em si custa praticamente nada, já que o EventBridge Scheduler, a Lambda e o CloudWatch Logs operam dentro dos limites gratuitos na maioria dos casos.
- Automação confiável: com o EventBridge Scheduler configurado no fuso horário correto e a Lambda selecionando as instâncias por tags, a rotina funciona sozinha. Incluir uma nova instância é só questão de aplicar a tag, sem alterar código.
- Menos intervenção manual: o time deixa de depender de alguém lembrar de desligar os servidores no fim do dia e ligá-los novamente pela manhã. Isso elimina esquecimentos que geram custo e libera as pessoas para tarefas de maior valor.
Por fim, vale lembrar que FinOps é um processo contínuo. Automatizar o desligamento das instâncias é um excelente passo para reduzir custos, mas também deve caminhar com outras práticas, como revisar volumes EBS e IPs públicos não utilizados, ajustar o tamanho das instâncias (rightsizing), avaliar savings plans para os recursos que precisam rodar o tempo todo, entre outros processos.



































































Top comments (1)
tr.ee/dev-to