Implantar rotinas periódicas de Start/Stop em Instâncias EC2 via Lambda
Tags: ptbr, aws, python, lambda
Published: 2023-01-14 15:36:18

_Este é meu primeiro post para o DEV e venho trazer uma solução simples, embora muito útil. Mostrarei uma abordagem para gerenciar rotinas de start e stop com a possibilidade de configurar diferentes períodos de dias e horários para uma determinada Instância EC2 através do AWS Lambda._

## **Introdução**

Suponha que você tenha um Lambda que faz o start/stop de várias instâncias em seu ambiente filtrando-as através de Tags. Se todas as instâncias funcionarem no mesmo período (dias da semana, hora que liga e hora que desliga) tudo bem. Bastaria apenas uma configuração no EventBridge para cuidar do acionamento.
Agora, e se você precisar que apenas algumas instâncias específicas funcionem em um período diferente? Faria outra função com outro EventBridge? E se você tivesse 100 instâncias, cada uma com um período de funcionamento diferente da outra? Já pensou como seria?

## **Objetivo**

O objetivo desse Lambda é oferecer uma maneira de gerenciar o Start/Stop de suas instâncias EC2 em diferentes períodos de dias e horários, além de reduzir seus custos na AWS para ambientes onde você possa interromper esses recursos, como ambiente de DEV, homologação e outros usados para testes. Usaremos uma única função Lambda que irá filtrar as EC2 através de tags, sendo acionada de tempos em tempos conforme agendamento no EventBridge.

## **Vamos aos passos:**


## 1 - Criar função IAM com permissões para a Função do Lambda.

A primeira parte será dar as devidas permissões para a execução da Função Lambda. Para isso, abra o console do IAM e clique em Roles no menu lateral esquerdo e depois em Create role.


![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/onwwb64fh94820x2dbvi.png)

Selecione AWS service, em seguida selecione Lambda e depois clique em Next.
Clique em Create policy. Uma nova guia será aberta, não feche a anterior. Clique na aba JSON da nova guia aberta e cole o seguinte código:

```
{ 
  "Version": "2012-10-17", 
  "Statement": [  
    { 
      "Effect": "Allow", 
      "Action": [ 
            "ec2:DescribeInstances",
            "ec2:DescribeTags",
            "ec2:DescribeInstanceTypes",
            "ec2:DescribeInstanceStatus",
            "ec2:StartInstances",
            "ec2:StopInstances"
      ], 
      "Resource": "*" 
    } 
  ] 
}
```
Clique em Next e avance para dar um nome para a Policy e depois clique em Create policy.


![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6vnc5bg1e6ean9jt3g3t.png)

Volte na guia anterior, clique no botão de refresh e pesquise pela policy criada. Marque a caixa ao lado do nome da policy e selecione também a seguinte policy:

- CloudWatchFullAccessV2 

Dê um nome para sua Role e clique em Create role.
Mais detalhes sobre como criar uma Role, acesse [esse link](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html#access_policies_create-json-editor).

## 2 - Criar Função Lambda

Acesse o console do Lambda e clique em Create function. Escolha a opção Author from scratch para iniciar com um exemplo de código. Dê um nome para sua Função Lambda e escolha o Runtime Python 3.12.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ts454hszlu5teg414jfs.png)

Em Change default execution role escolha Use an existing role e selecione a Role que você criou no passo anterior. Feito isso clique em Create function.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1b97zg5dsbzpqndi2dv9.png)

Agora que você criou a Função, substitua o código de exemplo pelo código que está [neste repositório](https://github.com/isaque21/lambda/blob/main/start-stop-routines/start-stop-ec2/lambda_function.py).

Após inserir o código, clique em Deploy para Salvar as alterações.
Feito isso, vá para a aba Configuration e mude o Timeout para 30 segundos (pode ser necessário um tempo maior de acordo com a quantidade de instâncias do ambiente).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0vsrtdyhq3e9ch7xutpi.png)

Ainda em Configuration, configure as variáveis de ambientes conforme a imagem a seguir:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9pvgsgtsa4oc2ood7exg.png)

- ALARMS_MANAGER

Define se os alarmes do CloudWatch referente as instâncias serão habilitados/desabilitados junto com a ação de start/stop.

O valor chave True define que a fução irá alterar o status dos alarmes. Caso não queira alterar o status dos alarmes, altere o valor para False.

- REGIONS

Define as regiões que a função irá percorrer e listar as instâncias.

O valor deve estar como uma lista de regiões da AWS, separadas por vírgulas (por exemplo: us-east-1,sa-east-1).

## 3 - Configurar EventBridge

Na parte superior da página da função, em Function Overview, clique em Add trigger.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ux4ewi0kysix2y515xt.png)

Em Trigger configuration selecione EventBridge (CloudWatch Events). Crie uma nova regra, dê um nome para a regra e em seguida selecione Schedule expression para inserir uma Cron.
Aqui você pode configurar uma expressão que melhor atende a sua necessidade. Neste exemplo usei uma expressão que chamará a função Lambda de 5 em 5 minutos.

`cron(0/5 * * * ? *)`

Após inserir o valor clique em Add.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m97gwloyw0w0g71xwqtq.png)

Para mais detalhes sobre Cron Expressions consulte [este link](https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html).

## 4 - Adicionando Tags

Para incluir suas instâncias na rotina de Start/Stop é necessário adicionar Tags que definem o acionamento e os períodos em que serão executadas.

No console de gerenciamento do EC2, no menu lateral esquerdo selecione Instances. Selecione a instância que deseja incluir na rotina de Start/Stop, vá até a aba Tags e clique em Manage tags. Adicione as seguintes tags (alterando o período e os horários de acordo com sua necessidade) e clique em Save.

```
Scheduled      : Active
Period-1       : Monday-Friday
ScheduleStart-1: 08:00
ScheduleStop-1 : 18:00
```

A função tentará filtrar as instâncias que contêm uma Tag chamada '_Scheduled_' definida como '_Active_'.

A função utiliza um período de dias da semana para comparar a tag '_Period-x_' e verifica se o dia atual está dentro do período. Se esta condição for atendida, a função irá comparar a hora atual (H:M) com um valor das tags adicionais que definem o gatilho '_ScheduleStop-x_' ou '_ScheduleStart-x_'.


![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p8thnfmign1bi1mavqq7.png)

## **IMPORTANTE!!!**

- As tags devem seguir a nomenclatura em inglês e são case-sensitive;
- O período começa no domingo e termina no sábado;
- O valor 'Period-x' deve estar no seguinte formato 'Sunday-Saturday';
- O valor de 'ScheduleStop-x' ou 'ScheduleStart-x' deve estar no seguinte formato 'H:M';
- O valor de ‘x' das tags 'ScheduleStop-x' e 'ScheduleStart-x' devem corresponder ao mesmo valor do 'period-x’;
- Não há limite de períodos a serem adicionados;
- Para acionar esta função, certifique-se de configurar o EventBridge para que seja executado em um intervalo de sua escolha (a cada 5 minutos é recomendado);
- Esta função está configurada para funcionar com horário local (UTC-3).

`current_time = datetime.now()-timedelta(hours=3)`

- Caso queira retirar uma instância da rotina, basta alterar a tag ‘Scheduled’ para ‘Inactive’.

## **Exemplos de tags de instância do EC2**

```
Scheduled       : Active

Period-1        : Monday-Friday
ScheduleStart-1 : 06:00
ScheduleStop-1  : 18:00

Period-2        : Saturday
ScheduleStart-2 : 09:00

Period-3        : Sunday
ScheduleStop-3  : 02:00

```

## **Conclusão**

Espero que este artigo possa ajudar a implantar uma rotina de Start/Stop de recursos de forma centralizada e simplificada. 
Feedbacks são bem-vindos ;)