¿Qué es CloudFormation?
CloudFormation es, ante todo, un servicio gestionado por AWS que ayuda a organizar las soluciones creadas en la nube; es una pieza fundamental para replicar configuraciones entre entornos de desarrollo, homologación y producción de los clientes, pero también puede utilizarse para replicar soluciones reutilizables entre diversos clientes.
Suelo decir que CloudFormation sintetiza conocimiento, provisionamiento de infraestructura y horas de troubleshooting en plantillas de soluciones.
Técnicamente, CloudFormation es la forma oficial de definir infraestructura como código en la nube de AWS, por lo tanto, es una pieza fundamental para posibilitar procesos de entrega continua y DevOps.
Organización de una plantilla
Una plantilla de cloudformation puede definirse en un archivo yaml o json. Inicialmente mis plantillas se definían en json, pero a lo largo de los últimos 2 años utilicé solo yaml debido a la facilidad de lectura.
Ejemplo: Infraestrutura Deployment
En todas las cuentas AWS que CloudDog provisiona ejecutamos esta plantilla o alguna derivada de ella, creando un stack que crea 3 buckets S3 que se comparten entre los demás stacks.
Los recursos provisionados por este stack son:
- LogsBucket: para almacenar logs de Amazon CloudFront u otro servicio gestionado que genere logs.
- DeployBucket: utilizado en los procesos de continuous deployment para almacenar copias de las plantillas de CloudFormation y binarios de aplicaciones que eventualmente se acceden durante los deployments.
- BackupBucket: guarda archivos de backup que pueden ser generados por otros procesos.
CloudFormation template.yml
AWSTemplateFormatVersion: '2010-09-09' Description: Infraestrutura Deployment Resources: LogsBucket: Type: AWS::S3::Bucket
Properties: AccessControl: LogDeliveryWrite DeployBucket: Type: AWS::S3::Bucket
BackupBucket: Type: AWS::S3::Bucket
Outputs: LogsBucketName: Value: !Ref LogsBucket Description: Bucket to store logging in general Export: Name: !Sub ${AWS::StackName}-LogsBucketName DeployBucketName: Value: !Ref DeployBucket Description: Bucket to store deployment artifacts Export: Name: !Sub ${AWS::StackName}-DeployBucketName BackupBucketName: Value: !Ref BackupBucket Description: Bucket to store RDS or any other backup Export: Name: !Sub ${AWS::StackName}-BackupBucketName
Las Secciones de la plantilla
La estructura completa de una plantilla puede volverse más compleja que esta, pero en este ejemplo ya tenemos las secciones más importantes, que son:
- AWSTemplateFormatVersion: declara la versión de la plantilla
- Description: define la descripción de la plantilla, que puede ayudar a comprender cuando existe una gran cantidad de stacks
- Resources: donde se declaran todos los recursos que deben ser provisionados
- Outputs: permite la visualización rápida de atributos de recursos creados utilizando la línea de comando y la consola de aws. Cuando se utiliza el parámetro export además permite que otros stacks hagan referencia a esos atributos, permitiendo un encadenamiento de stacks.
Ejecutando el template.yml vía consola
##Seleccionar el Servicio CloudFormation Buscar en el menú de la consola el servicio CloudFormation; en caso de no haber creado ningún stack, mostrará una pantalla parecida a la de abajo:
Crear un Stack
Selecciona la opción ‘Create Stack’ y sigue a la próxima pantalla.
A continuación deja configurada la primera opción: ‘Template is Ready’, selecciona en template source la opción para cargar una plantilla ‘Upload a template file’, selecciona el archivo conforme la configuración anterior y haz clic en ‘Next’.
Configura el ‘Stack Name’; en nuestro ejemplo utilizamos infra-deployment pero podría ser cualquiera que cumpla los requisitos de la expresión regular descrita debajo del campo, y haz clic en ‘Next’ nuevamente.
Ahora deja todas las opciones como están, sin ninguna alteración, y haz clic en ‘Next’ nuevamente.
Podrás en el último paso revisar todas las configuraciones y seleccionar la opción ‘Create Stack’; luego verás una pantalla parecida a la imagen de abajo con la lista de eventos que fueron generados por CloudFormation. En caso de que ocurra algún problema, como por ejemplo una configuración inválida, se realiza el rollback automáticamente de todo el stack.
Seleccionando la pestaña ‘Resources’, podrás consultar de forma resumida todos los recursos provisionados.
Seleccionando la pestaña ‘Output’, podrás consultar todas las variables configuradas en la sección ‘Output’ de la plantilla, donde el ‘Export Name’ corresponderá a los nombres que podrán ser referenciados en otros stacks.
Verificar Recursos Creados
Tras la finalización de la creación del ‘Stack’, en la pestaña ‘Stack Info’ deberá aparecer el Status como CREATE_COMPLETE; a continuación será posible consultar los recursos creados.
Para ello busca en el menú de servicios de AWS por S3 o Simple Storage Service; en ese momento deberás visualizar una pantalla similar a la de abajo:
Nota que además de los 3 buckets creados por la plantilla, también se creó un bucket llamado cf-template--us-east-1; ese bucket fue creado por el propio CloudFormation en el momento en que se hizo el upload de la plantilla; en caso de entrar al bucket podrás consultar algo como
Volviendo al listado de buckets y seleccionando el bucket de logs, podrás consultar que fue creado con una configuración de ‘Permissions’ y ‘Access Control List’ diferenciada donde el S3 Log Delivery Group consta con ambos permisos ‘Write Objects’ y ‘Read Bucket Permissions’ como ‘yes’, conforme puedes consultar en la próxima imagen:
Nomenclatura
La nomenclatura adoptada en los buckets es ${StackName}-${LogicalName}-${HashCode}, donde el StackName es el nombre del stack conforme definido en el proceso de creación, el LogicalName es el nombre lógico atribuido en la sección ‘Resources’ de la plantilla y el HashCode se genera automáticamente durante la ejecución.
Esta nomenclatura a priori puede parecer un poco extraña, pero ayuda a mantener la organización. Existen algunos servicios, como por ejemplo el propio bucket S3 que utiliza un namespace común, lo que imposibilita la utilización de nombres fijos en diferentes cuentas.
Actualizando el stack creado anteriormente
Imagina que olvidaste colocar alguna configuración en ese stack o evolucionaste alguna cosa y necesitas replicarla en los entornos.
Para mantener la infraestructura como código y dejar las plantillas alineadas con los stacks, debemos hacer la actualización en la plantilla y a continuación crear un ‘Change Set’ en el stack.
Ajustando la plantilla
Utilizaremos el mismo escenario del ejemplo anterior; como habrás notado a esta altura, el LogsBucket tiene una configuración diferenciada para permitir la recepción de archivos de log; sin embargo, en los otros buckets BackupBucket y DeployBucket no se hicieron las configuraciones correctamente.
CloudFormation template.yml ajustada
Es necesario agregar las siguientes properties en la plantilla original.
DeployBucket: Type: AWS::S3::Bucket
Properties: LoggingConfiguration: DestinationBucketName: !Ref LogsBucket LogFilePrefix: !Sub ${AWS::StackName}/deploy-bucket/ BackupBucket: Type: AWS::S3::Bucket
Properties: LoggingConfiguration: DestinationBucketName: !Ref LogsBucket LogFilePrefix: !Sub ${AWS::StackName}/backup-bucket/
Creando un Change Set
En el servicio CloudFormation en la consola de AWS, selecciona el stack creado anteriormente, en nuestro caso infra-deployment; en el menú ‘Stack Actions’ selecciona la opción ‘Create change set for current stack’, conforme la imagen de abajo:
Luego selecciona la opción ‘Replace current template’, para posibilitar la carga de la plantilla actualizada, y realiza la carga de la plantilla utilizando ‘Upload a template file’ y seleccionando el archivo template.yml.
A continuación haz clic en ‘Next’ aceptando las configuraciones estándar hasta que aparezca el popup de abajo para configurar el nombre del change set; puedes dejar el nombre sugerido y luego hacer clic en ‘Create Change Set’.
Tras la creación del change set, será posible consultar qué recursos serán alterados por ese change set; si todo salió bien, deberán aparecer en la lista solo el BackupBucket y el DeployBucket. Es importante notar que la columna ‘Replacement’ está con valor ‘false’ para ambos recursos, lo que significa que no habrá pérdida de datos. En ese momento, podrás ejecutar el change set con seguridad haciendo clic en el botón ‘Execute’
El change set comenzará a ejecutarse y volverá a la pestaña de eventos del Stack; puedes hacer clic en el botón refresh hasta que aparezca en la parte superior la línea ‘infra-deployment’ con status ‘UPDATE_COMPLETE’, conforme la imagen de abajo.
Validando el Change Set
Siempre es importante entrar a los recursos actualizados y verificar que el ajuste se hizo de forma satisfactoria.
Protegiendo un Stack
Tras la creación y actualización del stack ya tenemos una base sólida para dar continuidad y pasa a ser importante evitar que alguien elimine ese stack de forma accidental.
Por eso es necesario hacer la configuración seleccionando el stack, accede a la opción ‘Edit termination protection’ en el menú ‘Stack Actions’
Selecciona la opción ‘Enable’ y confirma haciendo clic en ‘Save’.
Podrás consultar a continuación la notificación en verde diciendo que la alteración se hizo con éxito. Como esa alteración no generó cambios en los recursos, no hubo alteración en el status del stack y no se lanzó ningún evento nuevo.
Resumen
En este artículo descubrimos lo básico de una plantilla de AWS CloudFormation, creamos un Stack y lo actualizamos utilizando un Change Set, y por último protegimos el stack contra eliminación.


