Amazon AWSCloud

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
  1. 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]
  2. Criar uma função lambda com script em Pyton
  3. 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!

Inscreva-se na lista VIP e receba todos os conteúdos

Arthur Nycael

Entusiasta por tecnologia, graduado em Redes de Computadores, Pós-Graduado em Segurança da Informação, AWS Solutions Architect, VMware vExpert ⭐⭐ e AWS Community Builder.

Deixe uma respostaCancelar resposta

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.