Este proyecto es una plantilla que permite generar un proyecto "serverless" básico, que sirva como punto inicial a proyectos pequeños de un solo repositorio.
Si requieres crear un proyecto más complejo: multiples repositorios, más de 3 desarrolladores o la plantilla ya tiene demasidadas lambdas contacta al equipo de CI/CD.
Diagrama:
Tipo: API
Descripción: Esta API le permite a un zoológico llevar el control de sus animales.
Si quieres pulir tus habilidades en AWS puedes contribuir agregando más funcionalidades.
Lenguaje: Python 3.9
Dependencias:
Servicios:
Herramientas:
Crear proyecto: Cookiecutter
AWS tiene varios servicios administrados que se cobran por uso, los más comunes: colas de mensajes, bus de eventos, administración de APIs, orquestación de servicios y envío de notificaciones. No es necesario instalar un producto en un servidor y mantenerlo actualizado, AWS se encarga de estas tareas y así nos concentramos en elegir la mejor herramienta para nuestro caso de uso.
También permite ejecutar código sin necesidad de un servidor dedicado: al recibir un evento que cumple ciertas condiciones AWS crea una instancia que ejecuta nuestro código, según la demanda puede crear más instancias. El cobro es por el tiempo que duró la ejecución del código y el número de instancias creadas.
Se pueden diseñar soluciones completas utilizando estas herramientas y a este tipo de aplicaciones se les conoce como "serverless" (sin servidor).
https://aws.amazon.com/serverless/
Es posible habilitar y configurar todos estos servicios de distintas maneras:
Todas son útiles en distintos escenarios pero AWS ha creado otro servicio que permite tener estas definiciones en archivos de texto (YAML o JSON) que pueden ser agregados a un repositorio de código como este y utilizarlo para crear y modificar recursos en AWS. De esta manera se puede tener una trazabilidad sobre los cambios que se han realizado en un sistema, colaborar y realizar modificaciones modificando esta definición (infraestructura como código).
¿Cómo funciona CloudFormation?: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-howdoesitwork.html
Las plantillas de CloudFormation pueden crecer rápidamente y definir todos los recursos de una aplicación puede ser una tarea repetitiva y tardada, para solucionar esto AWS ha creado un framework que permite definir la mayoría de recursos de una aplicación "serverless" de una forma simple y con menos líneas.
Especificación de plantilas SAM: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification.html
Estas definiciones cortas soportan la mayoría de servicios utilizados en una aplicación "serverless" como:
AWS::Serverless::Api Crea una función lambda que recibe peticiones a traves del API Gateway, permite agregar un documento de OpenAPI para la configuración del API REST. Comparación entre API REST y HTTP API
AWS::Serverless::Function Crea una función lambda y un rol de IAM asociado a ella. La función puede ser iniciada por distintos eventos (S3 | SNS | Kinesis | DynamoDB | SQS | Api | Schedule | CloudWatchEvent | EventBridgeRule | CloudWatchLogs | IoTRule | AlexaSkill)
AWS::Serverless::HttpApi Crea una función lambda que recibe peticiones a traves del API Gateway. Comparación entre API REST y HTTP API
AWS::Serverless::LayerVersion Si multiples funciones requieren las mismas librerías es posible crear una capa reutilizables que incluya estas librerías.
AWS::Serverless::SimpleTable Permite crear tablas de DynamoDB.
AWS::Serverless::StateMachine SAM también tiene soporte para agregar a tu proyecto Step Functions y orquestar distintas lambdas o incluso otros servicios de AWS.
SAM también ofrece un CLI que permite inicializar proyectos basados en plantillas, construir y desplegar una plantilla de SAM, crear eventos de pruebas, ejecutar localmente el proyecto y obtener logs los componentes luego de desplegados en AWS.
Inciando con el CLI de SAM: https://www.sqlshack.com/getting-started-with-the-aws-sam-cli/
sam init
Usando Docker (No requiere que tengas Python instalado)
sam build --use-container
Usando Docker y una imagen en especifico (No requiere que tengas Python instalado)
sam build --use-container --build-image public.ecr.aws/sam/build-python3.8:1.32.0
Si necesitas ver un ejemplo de la estructura del evento que recibe tu lambda puede utilizar estos comandos.
Para SQS
sam local generate-event sqs receive-message
API Gateway:
sam local generate-event apigateway aws-proxy --method GET --path document --body "{"test": "1", "tests2": "2"}"
Para visualizar la lista de servicios de los que se pueden generar eventos favor de visitar: sam local generate-event - AWS Serverless Application Model
sam local start-api
Si necesitas validar el funcionamiento de tu lambda puede pasarle un evento en formato json si necesidad de desplegar. (Requiere Docker instalado)
sam local invoke -e events/event.json
Para mayor información de comandos de CLI de SAM: AWS SAM CLI command reference - AWS Serverless Application Model
Si quieres aprender a crear aplicaciones con herramientas "serverless" de AWS puedes tomar alguno de estos cursos (en negritas están los recomendados):
AWS ofrece extensiones para distintos IDEs, los relevantes para este repositorio son:
Utilizar alguna de estas extensiones en tu IDE favorito te facilitará el desarrollo de aplicaciones SAM.
Estas referencias pueden ser útiles cuando estás desarrollando una aplicación con SAM:
Github inicio como una plataforma para subir repositorios de código basados en Git, con el tiempo ha ido agregando más funcionalidades al punto de volverse una plataforma para administrar todo el ciclo de vida de una aplicación:
Todo repositorio de código debe tener definidas algunas reglas para trabajar y colaborar. Trunk base development es la estrategia que mejor nos ha funcionado pues reduce la cantidad de conflicto al reducir la cantidad de "merges" o "pull requests":
Trunk based development: https://trunkbaseddevelopment.com/
La rama main es la rama principal (trunk en el diagrama) todo el código se sube directamente ahí, si se agrego un nuevo desarrollador que aún no está familiarizado con el código se puede solicitar que introduzca sus cambios mediante "pull request" para que sean revisados por su mentor o guía en el proyecto, eventualmente podrá introducir cambios directamente en main.
Una vez que se libera el código a producción se genera una rama de release, estas ramas están protegidas (ya no se pueden modificar) y deben utilizar versionado semántico para indicar la versión.
Ejemplo: releases/1.0.0
Recuerda que las ramas releases/x.x.x están protegidas.
En caso de que ocurra un bug en producción, hay dos posibles caminos:
Workflow reusables (Como los workflows hacen llamados a los workflows reusables para completar tareas y liga a la administración de workflows)
Agregar nota: Si el proyecto crece y se crean multiples repositorios, se debe crear un repo independiente en el que puedan guardarse los workflows reusables y otras utilerías
Crea un proyecto (Crear proyecto a partir de plantilla de cookiecutter y agregar los número de cuenta de los ambientes como secretos en Github)
Contar con las siguientes herramientas instaladas:
graph TD;
AWS-->1_IAM;
1_IAM-->crear_identity_provider;
crear_identity_provider-->crear_rol_despliegue;
crear_rol_despliegue-->agregar_politicas_requeridas;
agregar_politicas_requeridas-->agregar_tags_del_proyecto;
agregar_tags_del_proyecto-->copiar_account_id;
copiar_account_id-->agregar_account_id;
AWS-->2_KMS;
2_KMS-->crear_llave_simetrica_multiregion_SSM;
crear_llave_simetrica_multiregion_SSM-->copiar_ARN;
2_KMS-->crear_llave_simetrica_multiregion_DynamoDB;
crear_llave_simetrica_multiregion_DynamoDB-->copiar_ARN;
crear_llave_simetrica_multiregion_SSM-->configurar_regionalidad_en_region_dr;
crear_llave_simetrica_multiregion_DynamoDB-->configurar_regionalidad_en_region_dr;
configurar_regionalidad_en_region_dr-->copiar_ARN;
copiar_ARN-->ingresarlos_al_inicializar_cookiecutter;
3_GitHub-->crear_repositorio;
crear_repositorio-->crear_ambientes;
crear_ambientes-->configurar_secretos_ambiente;
agregar_account_id-->configurar_secretos_ambiente;
Para poder realizar los despliegues a una cuenta AWS, es importante generar un rol en lugar de un usuario en las cuentas AWS destino. Esto para ejercer mejores prácticas de seguridad en AWS.
Nota: este paso debe realizarse en las cuentas de AWS de todos los ambientes.
Para crear un identity provider es necesario ingresar a IAM daremos clic en la opción de la barra lateral izquierda "identity providers" y daremos clic en el botón azul de "Add provider".
En provider URL ingresaremos: https://token.actions.githubusercontent.com En "Audience" ingresaremos: sts.amazonaws.com
Posteriormente daremos clic en "get thumbprint"
y para terminar daremos clic en "Add provider"
En esta sección se sugiere nombrar el rol con identificador-del-proyecto-github-actions-role (sin agregarle el sufijo de ambiente. Para crear el rol, nos iremos en la sección de IAM > Roles y daremos clic en "Create role", en el tipo de entidad confiable daremos clic en "Web identity" y seleccionaremos el identity provider y audience que acabamos de crear en el paso anterior y daremos clic en "Next":
En este punto es indispensable que el rol que desplegará, cuente con acceso a Cloudformation y los servicios que estará desplegando:
Estos permisos se sugieren habilitar para poder realizar su despliegue. Salvo que haya alguno que sobre o alguno que falte deberá ser agregado/eliminado:
La siguiente política puede insertarse directamente al rol para poder desplegar:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"iam:UntagRole",
"iam:TagRole",
"iam:UpdateRoleDescription",
"iam:CreateRole",
"iam:DeleteRole",
"iam:AttachRolePolicy",
"iam:PutRolePolicy",
"iam:TagPolicy",
"iam:CreatePolicy",
"iam:DetachRolePolicy",
"iam:DeleteRolePolicy",
"iam:UntagPolicy",
"iam:UpdateRole"
],
"Resource": "*"
}
]
}
Por acá estaremos agregando el tag "Proyecto" con el nombre del proyecto para el que se utilizará este rol:
Una vez que el rol haya sido creado, abriremos el rol que creamos y daremos clic en "Edit trust policy":
En este bloque agregaremos lo siguiente sustituyendo los siguientes valores:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<NUMERO_CUENTA_AWS>:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:<ORGANIZACION_GITHUB>/<NOMBRE_REPOSITORIO>:*"
}
}
}
]
}
NUMERO_CUENTA_AWS = Número de cuenta de la cuenta AWS donde se estará desplegando, en este caso podemos obtenerla en la parte superior derecha de la consola AWS.
ORGANIZACION_GITHUB = Organización o usuario de GitHub a la que pertenece el repositorio.
NOMBRE_REPOSITORIO = Nombre del repositorio.
Por último daremos clic en "Update Policy".
Recursos: https://www.automat-it.com/post/using-github-actions-with-aws-iam-roles
Como prerequisito es importante crear 2 llaves KMS simétricas "multiregión", una para SSM y otra para DynamoDB. La región de creación de la llave será la región principal. Y la secundaría será la destinada para DR.
El nombrado debe seguir el siguiente estándar: identificador_del_proyecto-servicio_de_aws-ambiente
Ejemplo de llave SSM:
Identificador = proyectonuevo\ Servicio = ssm\ Ambiente = dev
Ejemplo de llave DynamoDB:
Identificador = proyectonuevo\ Servicio = dynamo\ Ambiente = dev
NOTA: Este proceso debe realizarse en ambas cuentas (desarrollo y producción). Cuando inicialicemos el proyecto con cookiecutter nos solicitará los ARN's de las llaves llaves. Por lo que es importante tenerlas a la mano cuando se inicialice el proyecto.
Se debe crear un repositorio nuevo. El repositorio debe ser creado vacío, para que se pueda inicializar correctamente el proyecto.
Es necesario crear 2 ambientes en el repositorio para poder inicializar el proyecto, develop y production
Para ello nos dirigiremos a "Settings" > "Environments" > "New environment":
Agregaremos el ambiente "develop" y daremos clic en "Configure environment":
Posteriormente, daremos clic em "Save protection rules".:
Sería el mismo paso que seguimos en el ambiente develop:
Esta vez se nombrará como production:
Por último, agregaremos a los equipos o personas que pueden aprobar despliegues en este ambiente:
Una vez creados los ambientes:
Seleccionaremos el ambiente develop, y en la parte inferior daremos clic en "add secret":
Agregaremos los números de cuenta en los secretos del repositorio de GitHub. Esto será para ambos ambientes:
Número de cuenta AWS del ambiente develop:
Acto seguido procederemos a dirigirnos al ambiente production:
Número de cuenta AWS del ambiente production:
Una vez concluidos los pasos anteriores podemos proseguir a inicializar el proyecto, nos moveremos hacia la carpeta donde se alojará el repositorio y ejecutaremos el siguiente comando:
cookiecutter https://github.com/spsdevops/aws_sam_github_quickstart_template
Ingresaremos los valores que nos pide la plantilla. Algunas opciones cuentan con valores default.
A continuación se describen cada una de las opciones:
Es importante que no incluya el identificador o sufijo del proyecto.
Pueden ser las iniciales de la empresa o nombre del proyecto. Se utilizará como sufijo para los recursos del proyecto.
Ejemplo: us-east-1
Ejemplo: us-west-2
Es una de las llaves que creamos para la región principal en Creación de llaves KMS para el ambiente de Desarrollo.
Es una de las llaves que creamos para la región principal en Creación de llaves KMS para el ambiente de Desarrollo.
Es una de las llaves que creamos para la región DR en Creación de llaves KMS para el ambiente de Desarrollo.
Es una de las llaves que creamos para la región DR en Creación de llaves KMS para el ambiente de Desarrollo.
Es una de las llaves que creamos para la región principal en Creación de llaves KMS para el ambiente de QA/Preproducción.
Es una de las llaves que creamos para la región principal en Creación de llaves KMS para el ambiente de QA/Preproducción.
Es una de las llaves que creamos para la región principal en Creación de llaves KMS para el ambiente de Producción.
Es una de las llaves que creamos para la región principal en Creación de llaves KMS para el ambiente de Producción.
Es una de las llaves que creamos para la región DR en Creación de llaves KMS para el ambiente de Producción.
Es una de las llaves que creamos para la región DR en Creación de llaves KMS para el ambiente de Producción.
Es el contenedor que construye la aplicación, en esta caso está como default uno de Python. Pero de ser requerido usar una lambda de otro lenguaje se puede especificar en esta opción.
Es el bucket que necesita SAM para realizar los despliegues.
Aquí se deja por default este valor, salvo se haya especificado uno diferente en la configuración de secretos por ambiente
Aquí se deja por default este valor, salvo se haya especificado uno diferente en la configuración de secretos por ambiente
Aquí se deja por default este valor, salvo se haya especificado uno diferente en la configuración de secretos por ambiente
Es el nombre del rol que creamos en la sección de creando rol para el ambiente de desarrollo.
Es el nombre del rol que creamos en la sección de creando rol para el ambiente de QA/preproducción.
Es el nombre del rol que creamos en la sección de creando rol para el ambiente de producción.
Al terminar de generar el proyecto, por medio de un script se vincula el repo generado con el repo remoto que creamos en GitHub. Por lo tanto ya es posible comenzar a trabajar en él. Pero antes, se recomienda agregar alguna modificación en el archivo template.yaml para desplegar el proyecto Hello world por primera vez y evitar que se tengan problemas relacionados con un primer despliegue fallido.
Lista de deseos: