Agendamento para ligar e desligar instâncias EC2 na AWS
Como realizar o agendamento de ligar e desligar instancias na AWS por TAGs
Você esta precisando otimizar custos no ambiente AWS? Esta é uma estratégia bastante falada, quando o assunto de FinOps esta em pauta. Neste artigo vou demonstrar como configurar o famoso “Start/Stop” em instâncias EC2 na AWS, filtrando-as por Tags.
Pré-Requisitos
Defina as TAGs, que serão utilizadas antes de iniciar o passo a passo.
Implementação dos recursos
- Criar duas função e política do IAM
- Função e política para lamba
- Função e política para Scheduled EventBridge [O agendamento cria automaticamente]
- Criar uma função lambda com script em Pyton
- Criar um agendamento no AWS EventBridge Scheduled
Procedimentos técnicos
1. Criar política e função do IAM para utilização do serviço AWS Lambda
Criar uma política, com o seguinte código JSON
{
"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": "*"
}
]
}
Criar a função XPTO (NOME_DA_ROLE), vinculando a política criada no item anterior e na relação de confiança, incluir a ARN da própria função. Exemplo:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com",
"AWS":"arn:aws:iam::637xxxxxx:role/EC2-STOP-START-ROLE"
},
"Action": "sts:AssumeRole"
}
]
}
Opcionalmente, você pode criar uma política para o EventBridge Schedule manualmente. Caso você queria deixar que o serviço AWS EventBridge crie a Role automaticamente, também funcionará.
Se você optar por criar uma política para o EventBrigde, segue o código JSON:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
"arn:aws:lambda:us-east-1:29529XXXXXX:function:NOME_DA_LAMBDA:*",
"arn:aws:lambda:us-east-1:29529XXXXXX:function:NOME_DA_LAMBDA"
]
}
]
}
Criar a função XPTO (NOME_DA_ROLE), vinculando a política criada no item anterior e na relação de confiança, incluir a ARN da própria função. Exemplo:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "scheduler.amazonaws.com",
"AWS": "arn:aws:iam::29529XXXXXX:role/service-role/NOME_DA_ROLE"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "29529XXXXXXX"
}
}
}
]
}
2. Função lambda com script em Pyton
Criar uma função lambda, procure pelo serviço Lambda na barra de pesquisa da console da AWS.
Clique para criar a função lambda, preencha as informações do nome e na opção “runtime”, selecione Pyton
Na opção “Permissions”, marque a opção “Use an existing role”, e selecione a ROLE criada na etapa nº 1.
Clique para criar a função lambda
Inserindo o script. Na aba “code”, inserir o script em pyton, a seguir:
IMPORTANTE:
- Inserir a TAG já cadastrada na EC2 ou criar a TAG, conforme já está inserido no script em vermelho.
- Alterar a região, conforme necessário
Descrição do script: Script faz uma varredura no serviço EC2, realizando a leitura das informações das instâncias. Com base no status da instância, o script toma uma ação diferente. Caso a instância estiver desligada, o script vai ligar a instância. Caso a instância estiver ligada, o script vai ligar a instância.
SCRIP PARA DESLIGAR AS INSTÂNCIAS EC2
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'
}
SCRIPT PARA LIGAR AS INSTÂNCIAS EC2
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'
}
Clique em Deploy, para gravar o script na função lambda.
Alterar o tempo de execução da função lambda para 30 segundos
Pode clicar para executar o teste, e validar o funcionamento do script.
Agendamento no AWS EventBridge Scheduled
Procure o serviço AWS EventBridge na barra de pesquisa da console da AWS
Clique em Create Schedule, para iniciar a criação do agendamento
Preencha as informações a seguir:
Selecione a opção “Recurring schedule” e preencha as expressões CRON, conforme programação desejada
Selecione a opção Invoke AWS Lambda
Selecione a função lambda, criada na etapa anterior
Na opção “Action after schedule completion” selecione a opção NONE
Na opção de permissões, marque a opção “Use existing role” e selecione a ROLE criada na etapa nº 1
Faça uma revisão, das configurações e clique no botão “Create schudule”
Repita todas as etapas conforme sua necessidade.
Considerações
Durante o uso, me deparei com uma falha na execução dos scripts inseridos na Função Lambda, devido à chave de criptografia KMS personalizada dos volumes EBS. Foi identificado que o script não tinha permissão para ler o volume EBS
Solução: Na chave personalizada do serviço KMS, incluir a role (que permite o Lambda conectar no serviço EC2).
Conclusão
Seguindo as etapas descritas neste documento, você será capaz de realizar a programar o horário de funcionando das suas instâncias EC2, conforme a sua necessidade.
Despedida e agradecimentos.
Espero ter ajudado. Deixe seu feedback nos comentários logo abaixo, não esqueça de se inscrever, compartilhe nas redes sociais e fique ligado nas novidades. Abraços!