Revista Tecnología

Cómo ejecutar un script en una EC2 con Lambda y System Manager en AWS

Publicado el 02 octubre 2017 por Dbigcloud @dbigcloud

Hace unos meses os hablé sobre EC2 Systems Manager en AWS y el conjunto de servicios que nos ofrecía para administrar tareas sobre instancias EC2. Uno de ellos, Run command, nos permite ejecutar comandos/scripts en la instancia EC2. Hoy os voy a explicar cómo podemos combinar Run Command junto con Lambda y CloudWatch rules para ejecutar scripts en Linux periódicamente sin necesidad de configurar un cron.

amazon ec2

Para poder usar EC2 System Manager, nuestra instancia EC2 necesita tener un agente instalado. Dependiente de si es Linux o Windows, la instalación de SSM Agent se realizará de una forma u otra. Para ello os enlazo a la documentación oficial de AWS en la que os indica paso a paso, de forma detallada, cómo instalarlo en cada sistema operativo y distintas distribuciones.

NOTA: En el blog de AWS han publicado que desde el 3 de Octubre de 2017, la disponibilidad de la AMI 2017.09 de Amazon Linux que ya trae el agente preinstalado.

Una vez hemos instalado el agente, podemos comprobar su estado desde el terminal o bien desde la consola de AWS. Con el siguiente comando, desde un terminal linux, podemos comprobar el estado del agente y nos indicará el uso de memoria, CPU, incluso si ya tenemos algún comando ejecutándose desde System Manager.

sudo systemctl status amazon-ssm-agent

La otra forma de comprobar el estado del agente es dirigirnos a la consola de AWS -> EC2 -> System Manager Services -> Run Command en la ventana que se nos abre, en el apartado de Command document* seleccionamos cualquier nombre de comando en el que en Platform type aparezca Linux.

AWS run command

En Select Targets by elegimos Manually Selecting Instaces y hacemos click sobre Select Instances, justo se nos desplegará un listado de instancias en las que el agente SSM esta ejecutándose.

Desde Run Command solo podemos ejecutar el comando de forma manual, la idea es poder realizarlo de forma periódica, por lo que para ello he creado una Lambda en Python que usa la API de Boto3 y me va a permitir ejecutar el comando que le indiqué.

Pasos para ejecutar un script en EC2 a través de Lambda usando SSM.

1 - Creación del Rol en AWS.

Necesitamos un Rol con los suficientes permisos para invocar la Lambda, desde IAM, creamos uno que tenga permisos para invocar la Lambda, acceso a SSM y a CloudWatch events, podéis probar son los siguientes:

  • AmazonSSMFullAccess
  • CloudWatchEventsFullAccess
  • AWSLambdaRole

NOTA: Este Rol, es solo para el ejemplo, no es buena práctica usar ningún Rol con acceso a todos los recursos, por lo que mi recomendación es que creeis una policy con los permisos mínimos para ejecutar la Lambda, SSM y CloudWatch Events.


2 - Creación de la Lambda.

El código fuente de la Lambda podéis encontrarlo también en el repositorio de GitHub de DBigClouddebéis crear una Lambda con Runtime Python 2.7 y asignarle el Rol creado anteriormente.

import boto3

client_ssm = boto3.client('ssm')

def lambda_handler(event, context):
   values = con.return_constant_command(event)
   # INIT vars from lambda tags
   instanceid = event['INSTANCEID']
   environment = event['ENVIR']
   timeout = event['TIMEOUT']
   command_run = event['COMMAND']
   command_run = command_run + ' ' + environment + ' >> /opt/scripts/backups.log'
   ServiceRole = event['SERVICEROLE']
   description = "Example of command run from DBigCloud"

   try:
      command = client_ssm.send_command(InstanceIds=[instanceid], DocumentName='AWS-RunShellScript',
      Parameters={"commands" : [command_run], "executionTimeout" : [timeout]},
      TimeoutSeconds=30, Comment=description, ServiceRoleArn = ServiceRole )
      commandid = command['Command']['CommandId']
      response = client_ssm.list_commands(CommandId=commandid)
      for item in response['Commands']:
         status = item['Status']
      print "Command",commandid, "for provider", values['provider'],"was executed", status

      return "Success"
   except Exception as e:
      print "Error running command " + command_run,e

Si accedéis al código y os fijáis en las siguientes variables:

instanceid = event['INSTANCEID']
environment = event['ENVIR']
timeout = event['TIMEOUT']
command_run = event['COMMAND']
ServiceRole = event['SERVICEROLE']

Son variables de entorno configuradas en la Lambda y que podemos cambiar a vuestro antojo sin tener que tocar el código fuente, como por ejemplo ejecutar un comando distinto o bien ejecutarlo en otra instancia EC2. Tenéis que rellenarlas en el apartado Environment variables, en la siguiente imagen podéis ver un ejemplo.

 

Lambda Environment variable


3 - Programar la ejecución de la Lambda con CloudWatch.

 Por último, para ejecutar de forma periódica la Lambda creada anteriormente nos vamos a dirigir a CloudWatch -> Events -> Rule pulsamos en create rule y en Event Source elegimos Schedule, ahora tenemos dos posibilidades:

  • Ejecutar la Lambda cada X tiempo, para ello se selecciona Fixed rate of.
  • Ejecutar la tarea cuando queramos, para ello seleccionamos Cron expressión, que funciona con la misma sintaxis que un Cron en linux.

Lo siguiente es elegir que hacer, para ello en Targets, elegimos Lambda function y seleccionamos la Lambda que hemos creado anteriormente. Con esto ya podríamos ejecutar la Lambda de forma periódica.

NOTA: Debéis tener en cuenta que el máximo tiempo permitido que el comando puede estar corriendo son  8 horas, en caso de que el script tarde más tiempo se cortaría el proceso.

Cómo veis es una utilidad bastante interesante, que nos puede ayudar a administrar nuestras instancias EC2 o bien ejecutar tareas de backend, si habéis seguido el ejemplo os habréis dado cuenta que desde CloudWatch Rules podéis ejecutar directamente un comando / scripts sin necesidad de la Lambda, yo en mi caso, antes y después de ejecutar el comando, interactuo con la base de datos, por eso lo realizo desde la Lambda, ya que lo utilizo para tareas de backend.

Podéis ampliar más información sobre instancias EC2 en el blog de AWS.


Compártelo:


Volver a la Portada de Logo Paperblog

Revista