11 Dec 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