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