Fargate es un servicio de AWS y es parte de los servicios de contenedor ofrecidos por esta industria creciente. Se destaca como una forma sencilla de implementar contenedores en cualquier parte deseable de la nube AWS y con toda la seguridad integrada de AWS, como las funciones IAM. Con Fargate, es posible evitar la molestia de tener instancias de EC2 únicamente para este propósito o tener que gestionar el servicio docker y las imágenes que ofrecen. ¿Suena sencillo, verdad?
¿Por qué usarlo? Alguien puede considerar alguna ejecución de código en la nube con el fin de dar mantenimiento; como por ejemplo, ejecutar scripts en bases de datos e infraestructura. Sin embargo, en ocasiones estas tareas implican una inversión significativa de tiempo. Una tarea simple como "Crear archivos de base de datos automáticos" podría tener muchas dependencias que de alguna forma se deben abordar y que podrían tomar mucho tiempo.
El desafío es evitar la necesidad de agregar instancias / servicios que demandarán atención y lo más importante, contribuirán a la factura mensual. Se tendrán que considerar los tiempos de inicio y la eficiencia operativa, así como cuándo se piensa en agregar instancias de EC2 a la solución. Enfocarse en tareas de mantenimiento que no sean críticas no es una buena idea.
El mismo razonamiento se aplica cuando se considera la adición de un docker ECS clúster con EC2 o EKS; podría implicar una inversión de tiempo futuro para fines de mantenimiento o monitoreo.
AWS Lambda podría ser una buena opción a considerar. Sin embargo, la falta de control sobre los prolongados flujos de ejecución implica que se debe dedicar más tiempo a la organización de tareas, ya que Lambda tiene un límite de tiempo de ejecución de 15 minutos. Cualquier cosa más allá de eso requeriría un trabajo extra solo para dividir el proceso y organizarlo para ejecutarlo en el orden deseado, con los parámetros correctos.
Por lo tanto, aplicar una metodología de contenedores para scripts y ejecutarlos con Fargate no es una mala idea. Fargate no requeriría tiempo de administración en el futuro. Además, no habría EC2 ejecutándose innecesariamente, a la espera de parches de seguridad y opciones de monitoreo en la nube, desperdiciando los recursos disponibles en la máquina. La solución con Fargate es bastante simple: un contenedor con los scripts deseados, una tarea en ECS con los parámetros correctos y darle clic en Iniciar y ejecutar.
El Enfoque Fargate
Arquitectura Base y Seguridad
Fargate ha demostrado ser una forma rápida de desplegar contenedores sin requerir de un servidor. No solo ayuda a eliminar la sobrecarga de mantener una tarea crítica ejecutada por medio del servicio de contenedores, sino que además delega la gestión de seguridad de AWS y su conjunto de herramientas, las cuales se utilizan para asegurar la infraestructura y los servicios.
Fargate puede operar en cualquier lugar de la nube, siempre que esta tenga acceso a Internet (por lo general se necesita una IP pública para sacar las imágenes del servicio ECR). Dado que estos scripts no requieren de ningún puerto expuesto, como lo requiere un servicio en ejecución, una política de seguridad sin puerto de entrada es ideal.
En caso de que la tarea deba conectarse con un servicio que se ejecuta en la nube, como una Base de Datos MYSQL y una API, se debe adjuntar el enlace de VPC correcto y si se utiliza una configuración VPC múltiple, agregar las rutas correctas a sus tablas.
Actualmente, la seguridad es una preocupación en todo lugar y esto se demuestra al trabajar con Fargate. AWS brinda parámetros de seguridad para evitar la exposición de datos confidenciales, como las contraseñas de las bases de datos:
- El uso de variables de entorno al describir su tarea
- Servicio SSM (Administrador del sistema, por sus siglas en inglés)
Si se decide utilizar el servicio de SSM, los scripts se encargan de retirar esos credenciales del servicio de AWS de esta manera:
SECURE_STRING=$(aws ssm get-parameter --name secure-string-variable --with-decryption --output text --query Parameter.Value --region us-east-1)
[2]
Para que la tarea en ejecución pueda extraer credenciales del servicio SSM, AWS ECS, se selecciona roles de ejecución de tareas y roles de tareas:
- Los roles de ejecución de tareas ayudan al servicio de contenedor administrado por AWS a extraer imágenes de su ECR y colocar registros en Cloudwatch, por lo que no hay cambio significativo.
- El rol de tarea es el que permite al contenedor acceder a servicios de AWS como S3, RDS o SSM.
- Por ejemplo, si la tarea requiere poner un archivo en S3, se debe ir a la definición de su rol de tarea y habilitar la acción AWS s3:PutObject para ejecutar la función.
- La documentación sobre cómo crear roles de tareas para el servicio de ECS se puede encontrar aquí.
Imagen Docker
Lo primero que debe hacer es configurar un nuevo archivo de imágenes en el servicio AWS ECR. El proceso es bastante sencillo y se documenta aquí.
También se necesitará crear un clúster de Fargate aquí, seleccionar la opción “solo redes”, y agregarle un nombre; eso es todo lo que se necesita para que el clúster de Fargate esté listo. Se puede seleccionar la VPC en el momento de inicio del contenedor.
Una vez que su archivo esté listo para recibir la imagen de docker, se trabaja en la imagen en sí. Esta imagen consta de 3 elementos: el Dockerfile, el punto de entrada y los scripts que representan la tarea a ejecutar en la nube.
Un Dockerfile para este caso puede verse así:
------------------------------------------------------------Dockerfile
FROM alpine:3.8
RUN apk add --no-cache bash
RUN apk add --no-cache python & \
python -m ensurepip && \
rm -r /usr/lib/python*/ensurepip && \
pip install --upgrade pip setuptools && \
rm -r /root/.cache
RUN pip install awscli
RUN pip install boto3
WORKDIR /usr/src/app
COPY ./scripts ./scripts
COPY entrypoint.sh ./
ENTRYPOINT ["./entrypoint.sh"]
CMD []
---------------------------------------------------------------------------------------------------
[3]
Luego se crea un punto de acceso; un script que se ejecuta en el inicio del contenedor y por el cual pasan las variables. Con este punto de acceso se puede seleccionar cuál script ejecutar y qué parámetros usar para la ejecución del contenedor.
------------------------------------------------------------entrypoint.sh
#!/bin/bash
parameters=$(echo "$3" | tr "'" " ")
$1 /usr/src/app/scripts/$2 $parameters
echo "Finished execution!"
---------------------------------------------------------------------------------------------------
[4]
Este punto de acceso sencillo funcionará como un contenedor, capaz de llamar a cualquier script bash o python que pongamos en usr/ src/ app/ scripts/ con los parámetros deseados. Para llamarlo, simplemente ejecuta los siguientes comandos:
$./entrypoint.sh python test.py ‘param1 param2’
$./entrypoint.sh bash test.sh ‘param1 param2’
[5]
Finalmente se crean los scripts que describen la tarea por ejecutar.
Supongamos que tenemos los scripts "test.sh" y "test.py" copiados en el contenedor (como se describe en la definición anterior de Dockerfile). En un escenario real, estos scripts estarían a cargo de ejecutar una tarea más compleja, como crear un clúster. Estos archivos de script deben ser ejecutables.
------------------------------------------------------scripts/test.sh
#!/bin/bash
echo Hello World From a Container
echo $# parameters passed
------------------------------------------------------------
------------------------------------------------------scripts/test.py
import sys
print "Hello World From a Container"
print len(sys.argv) - 1, "parameters passed"
-------------------------------------------------------------
El ejemplo hasta ahora ha descrito el proceso como si se estuviera ejecutando todo desde una consola. Para mover el escenario al contexto de Docker, primero se requiere construir su imagen con
docker build . -t toolbox.
Una vez que se completa la imagen, se puede ejecutar el script del contenedor de esta manera:
$docker run toolbox [now add what we would have passed to the entrypoint so ...]
$docker run toolbox bash test.sh 'param1 param2'
$docker run toolbox python test.py 'param1 param2'
Una vez probado, se está listo para poner la imagen en ECR.
Se puede seguir este proceso para iniciar sesión al repositorio ECR creado anteriormente y subir la imagen allí. En un ejemplo real, probablemente se usaría algunos servicios de AWS (RDS, S3, etc.) y quizá se necesite configurar sus claves secretas y de acceso en el contenedor para poder ejecutarlas localmente.
Una vez que se ha subido la imagen, se debe definir la tarea en ECS para ejecutar el script deseado en AWS. Esto se puede hacer aquí.
Se cambia a la respectiva región y se desarrolla la tarea desde allí:
- Seleccione "Fargate" como el tipo de inicio y agregue los parámetros restantes para su tarea.
- Aquí es donde se utilizará el rol de tarea definido que se creó anteriormente.
- En la sección "Agregar contenedor":
- Asigne un nombre a su contenedor y agregue el URL del repositorio, que se parece a 1111111111111.dkr.ecr.us-east-1.amazonaws.com/your-repo-name:latest
- En caso de ser necesario puede seleccionar las variables de entorno, controles de estado,etc.
- Añada el punto de entrada y el directorio de trabajo.
- Establezca ECS para seleccionar su script + los parámetros separados por una coma. Así:
- También se pueden mapear los volúmenes si fuera necesario.
Se debe tener en cuenta que Fargate realiza un cobro automático basado en el CPU y la memoria utilizada, por lo que se recomienda darles un uso moderado. También se pueden configurar límites definidos para restringir y delimitar los recursos de tareas.
Se verá la tarea creada en el panel de tareas. Puede tener varias revisiones para una tarea, de modo que al editarla se sumará al número de revisión. Al ejecutarla, se mostrarán más opciones de ejecución, como VPC y subredes.
Finalmente, puede ejecutar su script y los registros caerán automáticamente en Cloudwatch y en la página de ejecución de tareas. También se puede configurar ejecuciones programadas con Fargate, para tareas de mantenimiento similares a las de cron.
Múltiples beneficios
Este enfoque trae los siguientes beneficios:
- Brinda control total de los scripts, lo cual ofrece un tipo de experiencia local en la nube; desde los parámetros y la gestión del flujo de ejecución, hasta los paquetes binarios y sus dependencias.
- Estas ejecuciones no solo ayudan a tener límites bien definidos, sino que también reducen los montos de las facturas mensuales.
- Nadie tendrá que estar a cargo del mantenimiento del servicio de instancia de docker, EKS, o bien, orquestando ejecuciones Lambda.
- Una vez que se construye la solución, los desarrolladores solo tendrán que enfocarse en crear el script, no en las implementaciones.
- Es seguro al utilizarse los servicios de seguridad integrados de AWS.
El sistema de registros (logs) de AWS, por otra parte, no muestra el output del contenedor de una forma inmediata y en ocasiones los registros (logs) aparecen desordenados. Para obtener registros (logs) adecuados, se debe ir a Cloudwatch y buscar los registros de ejecución. Además, probar los scripts fuera de la nube de AWS se maneja en una forma distinta en términos de permisos. Dentro de la nube se utilizan roles, mientras que desde fuera de la nube se utilizan usuarios.
En resumen, si se encuentra con la necesidad de ejecutar scripts que consumen mucho tiempo en cuanto a seguridad de infraestructura y servicios, pero no se desea agregar o mantener nuevas instancias solo para ese propósito y Lambda no es la mejor opción, Fargate podría ser una buena alternativa a considerar.