CloudBridge

Los primeros contenedores

Buenas prácticas y troubleshooting

Escribir templates que se puedan mantener

Un template funciona o no funciona, pero entre dos templates que funcionan hay una gran diferencia de calidad: uno se entiende y se modifica con confianza, el otro es un campo minado. Estas son las prácticas que separan a uno del otro.

Nombres lógicos descriptivos

El nombre lógico de un recurso es para las personas que leen el template. TablaApp o ServicioApp dicen qué es el recurso; Resource1 o MyTable2 no dicen nada. Como el nombre lógico es además cómo el resto del template se refiere al recurso con !Ref, un buen nombre hace legible cada conexión.

Dejar que AWS genere los nombres físicos

Salvo que haya una razón concreta, no se fija el nombre físico de un recurso (TableName, RoleName, etc.). Si se deja sin especificar, CloudFormation genera uno único. Esto evita un problema común: lanzar el mismo template dos veces y que falle porque el nombre físico ya existe.

Parámetros con valores por defecto

Un parámetro con Default documenta el valor habitual y permite lanzar el stack sin tener que completarlo cada vez. Se reservan los parámetros sin default para lo que de verdad cambia entre lanzamientos —como el ImageUri del template.

Parameters:
  DesiredCount:
    Type: Number
    Default: 1
    Description: Número de tareas en ejecución.

DeletionPolicy para lo que no debe perderse

Por defecto, borrar un stack borra todos sus recursos. Para los que guardan datos —una tabla, un bucket— eso puede ser un desastre. DeletionPolicy: Retain indica a CloudFormation conservar el recurso aunque se borre el stack.

  TablaApp:
    Type: AWS::DynamoDB::Table
    DeletionPolicy: Retain

Nunca modificar a mano, desde la consola, un recurso que gestiona un stack. El template y la realidad dejan de coincidir —eso es drift— y la próxima actualización del stack puede revertir el cambio sin avisar. Si un recurso lo gestiona un stack, cambiarlo solo a través del stack.

Los outputs son un contrato

La sección Outputs es la interfaz pública del stack: lo que expone para que otros lo usen. La URL del ALB es un output porque alguien —otro stack, un script, una persona— necesita ese valor sin tener que entrar a buscarlo. Los outputs son un contrato: se nombran con claridad y se expone lo que realmente se consume desde afuera.

Buenas prácticas, en una línea

Troubleshooting: leer un fallo

Tarde o temprano un stack falla. Saber leer el fallo es lo que convierte media hora de frustración en dos minutos de diagnóstico.

El primer evento fallido es la causa

Cuando un stack entra en ROLLBACK_IN_PROGRESS, la pestaña Events se llena de mensajes: el recurso que falló, y luego todos los que se deshacen en el rollback. El ruido del rollback puede esconder la causa real.

La técnica: ordene los eventos por tiempo y busque el primer evento con estado CREATE_FAILED (o UPDATE_FAILED). Ese, y no los posteriores, contiene el motivo real —el resto son consecuencias. La columna de razón (status reason) suele decir exactamente qué pasó.

Fallos comunes y qué los causa

SíntomaCausa habitual
requires capabilities: [CAPABILITY_IAM]El template crea roles de IAM; falta marcar la casilla de capacidades al lanzar.
already existsColisión de nombre físico: el recurso ya existe (a menudo, por fijar un nombre a mano).
is not authorized to performPermisos insuficientes en el usuario o rol que lanza el stack.
limit exceededSe alcanzó un límite de la cuenta (por ejemplo, número de VPC o de EIP).

La primera fila explica la casilla de capacidades que marcó en la Semana 1: no era un trámite, era CloudFormation pidiendo permiso explícito para crear roles de IAM.

Validar el template antes de lanzarlo

La herramienta de línea de comandos cfn-lint revisa un template en busca de errores de sintaxis, propiedades inválidas, y referencias rotas, sin necesidad de lanzar nada. Integrada en el editor o en el pipeline, atrapa la mayoría de los errores antes de llegar a la consola. La consola también ofrece un botón Validate que hace una verificación básica de sintaxis al subir el template.


Los primeros contenedores — ECS y Fargate

Del recurso en el template al contenedor en ejecución

En el template se ven tres recursos relacionados: un clúster, un servicio, y una task definition. Esta sección los explica como lo que son cuando el stack ya corre: las piezas que mantienen el contenedor vivo y accesible. Al terminar, se los reconoce en la consola de ECS y se entiende qué hace cada uno.

El modelo de ECS

Amazon ECS (Elastic Container Service) es el orquestador de contenedores de AWS: decide dónde corren los contenedores, los mantiene en ejecución, y los reemplaza si fallan. Tres conceptos lo estructuran.

ECS en tres piezas

PiezaQué es
ClústerEl espacio lógico donde corren las tareas.
Task definitionLa plantilla de ejecución de un contenedor (imagen, CPU, memoria, puertos).
ServiceEl controlador que mantiene N tareas vivas y las reemplaza si caen.

El clúster

El clúster es la agrupación lógica donde viven las tareas. Con Fargate no contiene servidores que administrar —es solo el contexto bajo el cual ECS organiza lo que corre. En la consola, se accede desde ECS → Clusters.

La task definition

La task definition es la plantilla de ejecución de un contenedor: el documento que dice cómo es una tarea. Sus campos principales:

Variables de entorno vs. secretos en una task definition

La task definition tiene dos campos distintos para configurar el contenedor con valores en tiempo de ejecución:

environment — texto plano, almacenado dentro de la task definition:

"environment": [
  { "name": "CB_APPS_GATED", "value": "all" }
]

secrets — referencia a un secreto en AWS Secrets Manager (o SSM Parameter Store); ECS lo resuelve y lo inyecta al arrancar la tarea:

"secrets": [
  {
    "name": "CB_APPS_SECRET",
    "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:cb-apps-secret-AbCdEf"
  }
]

El contenedor recibe CB_APPS_SECRET igual que una variable de entorno normal, pero el valor nunca queda escrito en la task definition.

Por qué el texto plano es un problema. Una tarea definida con environment expone su valor en cualquier lugar donde la task definition sea legible:

  • aws ecs describe-task-definition lo devuelve en claro.
  • La consola de ECS lo muestra en la pestaña de configuración del contenedor.
  • Un template de CloudFormation con el valor hardcodeado queda en el repositorio.

Para un secreto de acceso —como CB_APPS_SECRET, la clave que desbloquea los escenarios del taller— el texto plano significa que cualquier persona con permiso ecs:DescribeTaskDefinition puede leerlo.

Con secrets + valueFrom, el valor vive en Secrets Manager. La task definition solo guarda el ARN. Para leerlo hace falta permiso sobre Secrets Manager, no sobre ECS.

Requisito de IAM. El execution role de la tarea debe tener permiso secretsmanager:GetSecretValue (o ssm:GetParameters) sobre el recurso referenciado. ECS usa ese rol —no el task role— al resolver secretos antes de lanzar el contenedor.

Las task definitions son versionadas: cada cambio crea una nueva revisión (taller:1, taller:2, …). Esto permite saber exactamente qué configuración está corriendo, y volver a una anterior si hace falta.

El service

El service es el controlador que mantiene el número deseado de tareas en ejecución. Es lo que cambió en la sección anterior cuando subió DesiredCount a 2. Sus responsabilidades:

La distinción clave: la task definition describe cómo es una tarea; el service decide cuántas hay y las mantiene vivas.

flowchart TD
  CL["Clúster ECS"] --> SV["Service<br/>(DesiredCount = 2)"]
  TD["Task definition<br/>imagen · CPU · memoria · puertos"] -.->|plantilla| SV
  SV --> T1["Tarea 1 (RUNNING)"]
  SV --> T2["Tarea 2 (RUNNING)"]
  SV -->|registra| TG["Target Group del ALB"]
Fargate vs. EC2: ¿quién pone los servidores?

ECS puede ejecutar tareas de dos formas. Con el tipo de lanzamiento EC2, se administra una flota de servidores donde corren los contenedores. Con Fargate, AWS pone y administra esa capacidad: se especifican CPU y memoria por tarea, y no hay servidores que mantener. Este taller usa Fargate porque elimina la administración de servidores —el foco queda en la aplicación, no en la infraestructura que la ejecuta.

Práctica guiada: reconocer las piezas en la consola

Abrir el clúster

  1. Abrir ECS y seleccionar el clúster.
  2. En la pestaña Services, aparece el servicio con la cuenta de tareas deseadas y en ejecución (ahora 2).

Inspeccionar el servicio y sus tareas

  1. Pulsar sobre el nombre del servicio.
  2. En la pestaña Tasks, aparecen las tareas en estado RUNNING. Pulsar una de ellas.
  3. En el detalle de la tarea, localizar la task definition que la originó (con su número de revisión) y el grupo de logs al que escribe.

Leer la task definition

  1. Pulsar sobre el nombre de la task definition para abrir la revisión.
  2. Identificar la imagen (el URI de ECR), la CPU y memoria, y el port mapping —los mismos valores del template.

Ejercicio 11 — Reconocer lo que está corriendo

Desde la consola de ECS, identificar para la aplicación: la tarea en ejecución, la revisión de la task definition que la originó, el URI de la imagen que ejecuta, y el grupo de CloudWatch Logs al que escribe.


Dónde estamos

Al cerrar la Semana 2, la caja negra ya no es una caja negra:

Pasó de lanzar el ambiente a entenderlo y modificarlo.

Qué sigue en la Semana 3

La próxima semana se opera y automatiza lo que ya se entiende:

Llegará al final de la Semana 3 con el ciclo de entrega automatizado y los primeros ojos puestos sobre cómo se comporta el sistema en ejecución.