Automatización de encendido/apagado (start/stop) de instancias de AWS EC2 con AWS Lambda, Python y AWS EventBridge - Chuda
15792
post-template-default,single,single-post,postid-15792,single-format-standard,bridge-core-3.3,qode-page-transition-enabled,ajax_fade,page_not_loaded,,qode-child-theme-ver-1.0.0,qode-theme-ver-30.8,qode-theme-bridge,disabled_footer_top,qode_header_in_grid,wpb-js-composer js-comp-ver-8.1,vc_responsive

Automatización de encendido/apagado (start/stop) de instancias de AWS EC2 con AWS Lambda, Python y AWS EventBridge

Automatización de encendido/apagado (start/stop) de instancias de AWS EC2 con AWS Lambda, Python y AWS EventBridge

Si queremos automatizar el encendido y apagado de recursos de cómputo EC2 en AWS lo podemos hacer utilizando para ello funciones lambdas, AWS EventBridge como trigger y Roles IAM, para su ejecución.

Listado de servicios a utilizar.

  •  IAM
  • EC2
  • Lambda
  • EventBridge

Imaginando el escenario tenemos tres instancias EC2 en que necesitamos que se detengan (stop) y enciendan (start) en un horario específico, bien sea porque es un ambiente de desarrollo, QA, o instancias que no necesitamos que estén encendidas 24/7 y queremos detenerla en el horario que no se están usando sus recursos para ahorro de costos en la nube.

A estas instancias les debemos colocar dos etiquetas (tags) con su clave (key) y valor (value).

Key Value
Start Yes
Stop Yes

Con estas etiquetas podemos crear una función lambda que las use para detener (stop) y encender (start) múltiples instancias EC2.

Comencemos:

Primer paso  crear un rol IAM para lambda que nos permita según la política de mínimos privilegios  listar (describe), ver status, encender (start) y detener (stop) instancias EC2.

Para esto vamos a el servicio IAM y nos creamos un rol y una política.

Datos para el Rol:

Nombre role: role-for-lambda-stop-start-ec2
Description: Allows Lambda functions to call AWS services on your behalf.

Politicas Agregadas:
AWS: CloudWatchLogsFullAccess
Custom: lambda-ec2-start-stop-policy

Al crear la política seleccionamos JSON y colocamos lo siguiente:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstanceStatus",
                "ec2:DescribeInstances",
                "ec2:StartInstances",
                "ec2:StopInstances"
            ],
            "Resource": "*"
        }
    ]
}

Adjuntamos la política creada el rol y continuamos.

En el servicio Lambda, nos creamos una nueva funciona lambda para apagar/detener (stop) la instancia EC2, se debe crear para el lenguaje de programación python.

Nombre de la función lambda: ec2-stop-dev.

Código para la función lambda en python:

import json
import boto3

region = 'us-east-1'

def lambda_handler(event, lambda_context):
    ec2_client = boto3.client("ec2", region_name=region)
    reservations = ec2_client.describe_instances(Filters=[
        {
            "Name": 'tag:Stop',
            "Values": ['Yes'],
        }
    ]).get("Reservations")

    for reservation in reservations:
        for instance in reservation["Instances"]:
            instance_id = instance["InstanceId"]
            ec2_client.stop_instances(InstanceIds=[instance_id])
            print(f"Instances Stopped " + str(instance_id))

Hacemos deploy de la función y podemos hacer unas pruebas corriendo la lambda  de manera manual, en test.

Configuramos un Trigger de EventBridge y configuramos con un cron el disparador de la función lambda como ejemplo podemos elegir un cron para apagar las instancias EC2  de lunes a viernes a las 21:00 Horas.

Nota los tiempos de los cron en AWS son tomados en UTC. 

cron(0 21 ? * 2-6 *) GMT - UTC -4

cron(0 1 ? * 2-6 *) GMT - UTC

Para encender,levantar (start) las instancias nos creamos una nueva función lambda.

Nombre de la función lambda: ec2-start-dev.

Código para la función lambda en python:

import json
import boto3

region = 'us-east-1'

def lambda_handler(event, lambda_context):
    ec2_client = boto3.client("ec2", region_name=region)
    reservations = ec2_client.describe_instances(Filters=[
        {
            "Name": 'tag:Start',
            "Values": ['Yes'],
        }
    ]).get("Reservations")

    for reservation in reservations:
        for instance in reservation["Instances"]:
            instance_id = instance["InstanceId"]
            ec2_client.start_instances(InstanceIds=[instance_id])
            print(f"Instances Started " + str(instance_id))

Hacemos deploy de la función y podemos hacer unas pruebas corriendo la lambda  de manera manual, en test.

Configuramos un Trigger de EventBridge y configuramos con un cron el disparador de la función lambda como ejemplo podemos elegir un cron para encender las instancias EC2  de lunes a viernes a las 08:00 Horas.

Nota los tiempos de los cron en AWS son tomados en UTC. 

cron(0 8 ? * 2-6 *) GMT - UTC-4

cron(0 12 ? * 2-6 *) GMT - UTC

Con esta guía podemos programar el encendido y apagado de nuestras instancias EC2  usando etiquetas para ello.


Happy Hacking!


Repositorio en github del codigo utilizado en este tutorial:

https://github.com/chudacontreras/stop-start-multiple-ec2


Documentación y fuentes:

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/automating_with_eventbridge.html

https://repost.aws/knowledge-center/start-stop-lambda-eventbridge

https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html?icmpid=docs_console_unmapped#cron-based

https://medium.com/@srijaanaparthy/automating-ec2-instance-start-and-stop-schedule-using-aws-lambda-and-amazon-eventbridge-988b0843d010

https://medium.com/@arbnair97/automating-aws-ec2-instance-start-stop-state-using-aws-lambda-python-and-aws-eventbridge-ad235d4a139b