En nuestra migración de Docker Cloud a Elastic Beanstalk, nos encontramos con la necesidad de correr tareas de rake periódicamente en los ambientes. Amazon recomienda algunas formas de hacerlo, por ejemplo usando Lambda, .ebextensions o el worker tier.
La opción con Lambda la descartamos por complejidad y seguridad. Requiere subir el .pem a S3 y que la función lo baje, se conecte por SSH a la instancia y ejecute el comando.
La opción con el worker tier también fue descartada porque requería mantener un ambiente extra.
La opción con ebextensions tenía un pequeño problema: todas las instancias tienen el crontab, pero tenemos comandos que solo queremos correr en una instancia a la vez. Esto lo pudimos resolver con una pequeña modificación:
Pero nos trajo otros problemas:
- Si una instancia es reemplazada, la nueva no tiene el crontab
- En deploys inmutables tenemos dos líderes, con la posibilidad de ejecutar dos veces los comandos.
Si mejoramos cómo identificar al ‘líder’ de la versión estable, podemos poner el crontab en todas las instancias, solucionando ambos problemas. Para eso definimos al líder como la instancia más antigua y los comandos validan si son el líder antes de correr.
Nuestra validación entonces:
- Busca el tag
aws:cloudformation:stack-name
de la instancia actual (durante los deploys las instancias nuevas tienen otro valor) - Trae los
LaunchTime
eInstanceId
de las instancias del stack - Si la instancia actual es la más antigua, es el líder.
Nuestra ebextension finalmente quedó: