AWS Certified CloudOps Engineer - Associate
CloudFormation StackSets
Desplegar un template a muchas cuentas y regiones desde una sola operación: stack sets y stack instances, permisos self-managed contra service-managed, targets de despliegue y filtros de cuenta, concurrencia y tolerancia a fallas, drift, y las fallas que se esconden detrás de un estado SUCCEEDED.
- Distinguir un stack set, una stack instance y un stack, y explicar por qué una stack instance puede existir sin stack
- Elegir entre permisos self-managed y service-managed, y nombrar los roles que exige cada modelo
- Apuntar a una organización, a OUs específicas o a cuentas filtradas, y predecir qué cuentas reciben un stack
- Ajustar tolerancia a fallas, máximo de cuentas concurrentes y concurrencia de regiones según el riesgo del despliegue
- Interpretar los códigos de estado de stack set y de stack instance, incluidos OUTDATED e INOPERABLE
- Explicar en qué difiere la detección de drift de un stack set respecto de la de un stack individual
- Diagnosticar las fallas comunes de StackSets, incluida una operación que reporta SUCCEEDED mientras hubo stacks fallidos
Un equipo de seguridad necesita un rol IAM de solo lectura, un recorder de Config y una regla de envío de logs en 40 cuentas y 4 regiones. Eso son 160 stacks. La versión con script es un loop que asume un rol en cada cuenta y llama a create-stack, y funciona hasta que la cuenta 23 choca contra un service quota, el loop sigue igual, y nadie nota durante tres semanas que cuatro cuentas se quedaron sin recorder de Config.
El problema no es el loop. Es que el loop no tiene memoria. Nada registra que esos 160 stacks se supone que son la misma cosa, así que nada te puede decir cuáles están al día, cuáles fallaron y cuáles editó alguien a mano.
StackSets es esa memoria. Defines el template una vez, nombras las cuentas y las regiones, y CloudFormation rastrea cada stack resultante como parte de un conjunto administrado.
Stack set, stack instance, stack
Tres palabras que suenan intercambiables y no lo son.
Un stack set es el contenedor: un template, un conjunto de parameters y la configuración de despliegue. Vive en la cuenta administradora, y es un recurso regional. Crea un stack set en eu-west-1 y no lo vas a ver cuando la consola esté en us-east-1, cosa que sorprende a quien asume que una función multi-región tiene que ser global ella misma.
Una stack instance es una referencia a un stack en una cuenta destino dentro de una región. Tres cuentas en dos regiones te dan 6 stack instances, y cada una lleva su propio estado.
Un stack es el stack común de CloudFormation que realmente contiene los recursos, y está en la cuenta destino.
La separación entre instance y stack parece pedantería contable hasta la primera falla. Una stack instance puede existir sin stack: si la creación falló, no hay stack, pero la instance sobrevive y guarda el motivo. Eso es lo que hace que un rollout fallido sea diagnosticable en vez de invisible.
aws cloudformation list-stack-instances --stack-set-name org-baseline \
--filters Name=DETAILED_STATUS,Values=FAILED
Dos modelos de permisos, una sola elección real
Desplegar en otra cuenta significa asumir un rol ahí. StackSets te da dos maneras de armar eso, y el examen evalúa cuál te obliga a usar cada escenario.
Los permisos self-managed significan que armas la cadena de confianza tú, con dos roles cuyos nombres importan:
AWSCloudFormationStackSetAdministrationRoleen la cuenta administradora. Su trust policy permite quecloudformation.amazonaws.comlo asuma, y su permissions policy permitests:AssumeRolesobre el execution role de los destinos.AWSCloudFormationStackSetExecutionRoleen cada cuenta destino, confiando en la cuenta administradora. Este rol necesita permisos completos de CloudFormation más permisos para todo lo que crea el template.
Usa esos nombres exactos y StackSets los toma solo. Usa nombres propios y cada operación tiene que nombrarlos explícitamente. Los templates de ejemplo que AWS publica para estos roles le dan "Action": "*" al execution role, que está bien para una primera prueba y mal para cualquier cosa permanente. Acota el execution role a los tipos de recurso que tu template realmente crea, porque ese rol es el techo de lo que cualquier operación del stack set puede hacer en esa cuenta.
Los permisos service-managed le pasan el problema de los roles a CloudFormation. Activas el trusted access entre CloudFormation y AWS Organizations, y desde ahí CloudFormation crea y mantiene los roles en las cuentas miembro por ti. Apuntas a OUs en vez de listar account IDs, y obtienes despliegue automático.
| Self-managed | Service-managed | |
|---|---|---|
| Cuentas destino | Cualquier cuenta donde puedas crear un rol | Solo cuentas de tu organización |
| Armado de roles | Los creas tú, los dos | Los crea CloudFormation |
| Los targets se indican como | Account IDs | Raíz de la organización o IDs de OU |
| Una cuenta nueva entra a la OU | No pasa nada | El despliegue automático agrega un stack |
| Se corre desde | Cualquier cuenta | Cuenta de administración, o un delegated administrator |
| Nested stacks, macros, transforms | Soportados | No soportados |
Dos restricciones del modelo service-managed conviene memorizarlas, porque contradicen lo que la gente asume.
La cuenta de administración nunca recibe un stack. Apunta a toda la organización y CloudFormation igual la saltea. Si la cuenta de administración necesita el mismo baseline, le toca su propio stack o su propio stack set self-managed.
Los delegated administrators no se pueden acotar. La cuenta de administración puede registrar hasta 5 cuentas miembro como delegated administrators, así un equipo central de plataforma corre stack sets a nivel de organización sin tener credenciales de la cuenta de administración. Pero un delegated administrator tiene alcance total sobre todas las cuentas de la organización. No existe un ajuste que diga "este equipo solo puede desplegar en la OU Sandbox".
aws organizations register-delegated-administrator \
--service-principal member.org.stacksets.cloudformation.amazonaws.com \
--account-id 444455556666
Desde la cuenta delegated administrator, cada comando lleva --call-as DELEGATED_ADMIN. Si lo omites, la CLI busca stack sets self-managed en la propia cuenta miembro, no encuentra nada, y devuelve una lista vacía que parece un problema de permisos.
Elegir qué recibe un stack
Con permisos service-managed, los targets de despliegue son la raíz de la organización o una lista de IDs de OU. Apuntar a una OU padre incluye automáticamente a sus hijas, que es el comportamiento que quieres para un baseline de seguridad y el que te sorprende cuando una OU sandbox anidada se lleva una política de producción.
Por defecto, todas las cuentas de una OU apuntada reciben un stack. Los filtros de cuenta acotan eso:
| Tipo de filtro | Significado |
|---|---|
NONE (default) | Todas las cuentas de las OUs listadas |
INTERSECTION | Solo las cuentas listadas, y solo si están en las OUs listadas |
DIFFERENCE | Todas las cuentas de las OUs listadas menos las cuentas listadas |
UNION | Todas las cuentas de las OUs listadas, más las cuentas listadas |
aws cloudformation create-stack-instances --stack-set-name org-baseline \
--deployment-targets OrganizationalUnitIds=ou-rcuk-1x5j1lwo,Accounts=111122223333,AccountFilterType=DIFFERENCE \
--regions eu-west-1 us-east-1
DIFFERENCE es el que se gana su lugar en la práctica. Un baseline aplica a toda la OU Workloads salvo la única cuenta heredada que se rompería, y expresas esa excepción en el despliegue en vez de sacar la cuenta de su OU.
Concurrencia y tolerancia a fallas
Empujar un template a 160 lugares a la vez es una buena forma de romper 160 lugares a la vez. Cuatro ajustes controlan el radio de impacto, y se combinan entre ellos.
El máximo de cuentas concurrentes limita cuántas cuentas destino toca una operación al mismo tiempo, como número o como porcentaje. Los porcentajes se redondean hacia abajo: 25 por ciento de 10 cuentas es 2, no 3.
La tolerancia a fallas es el número o porcentaje de fallas permitidas por región antes de que CloudFormation se detenga. También redondea hacia abajo.
La concurrencia de regiones es SEQUENTIAL (el default, una región por vez en el orden de despliegue que indicaste) o PARALLEL (todas las regiones a la vez).
El modo de concurrencia decide qué pasa con la concurrencia cuando empiezan las fallas. STRICT_FAILURE_TOLERANCE mantiene el máximo de cuentas concurrentes en no más que la tolerancia a fallas más 1, y baja el ritmo a medida que las fallas se acumulan. SOFT_FAILURE_TOLERANCE sostiene tu nivel de concurrencia pase lo que pase.
Sigue una operación de punta a punta. Despliegas a 10 cuentas en eu-west-1, us-east-1 y ap-southeast-2, en ese orden, con tolerancia a fallas de 20 por ciento, máximo de cuentas concurrentes de 50 por ciento y regiones secuenciales.
- 20 por ciento de 10 se redondea hacia abajo a 2 fallas permitidas por región. 50 por ciento de 10 son 5 cuentas por vez.
eu-west-1corre 5 cuentas, y después las otras 5. Fallan dos. Es exactamente la tolerancia, así que la región termina y la operación sigue.us-east-1corre y falla una tercera cuenta en esa región. Ahí se excede la tolerancia, el estado de la operación pasa aFAILEDyap-southeast-2se cancela por completo.
La tolerancia a fallas se reinicia en cada región. Eso es lo que hace del despliegue secuencial un mecanismo de seguridad útil: un template que está roto en todas partes falla en la primera región y nunca llega al resto.
Los ajustes por defecto son deliberadamente tímidos, MaxConcurrentCount=1 y FailureToleranceCount=0 en los ejemplos de la CLI, o sea una cuenta por vez y freno en la primera falla. Para el primer rollout de un template nuevo, es la elección correcta. Súbelos cuando el template ya se haya probado.
Los estados, y el que miente
Las operaciones de stack set reportan RUNNING, SUCCEEDED, FAILED, QUEUED, STOPPING o STOPPED. QUEUED aparece con el despliegue automático: mueve una cuenta entre OUs y StackSets corre un delete del stack de la OU vieja y encola un create para la nueva.
Las stack instances llevan sus propios estados, y dos de ellos significan que hay trabajo esperándote:
OUTDATEDsignifica que el stack no está al día con el stack set, casi siempre porque ahí falló un create o un update, o porque la operación se detuvo antes de llegar.INOPERABLEsignifica que una operación de borrado de instances falló y dejó el stack en un estado inestable. Las instances en este estado quedan excluidas de los updates siguientes del stack set, así que dejan de recibir tus cambios en silencio. Recuperarlas implica borrar la instance conRetainStacksen true, y después limpiar el stack a mano.
Ahora la idea equivocada que le cuesta cobertura real a la gente. Una operación SUCCEEDED no significa que todos los stacks salieron bien. Significa que nunca se superó la tolerancia a fallas. Pon la tolerancia en 10 sobre 10 cuentas y una operación donde falla absolutamente cada stack igual devuelve SUCCEEDED, porque le dijiste a CloudFormation que esa cantidad de fallas era aceptable.
El número que de verdad quieres está en los detalles de estado:
aws cloudformation describe-stack-set-operation \
--stack-set-name org-baseline --operation-id 5550e62f-c822-4331-88fa-21c1d7bafc60
{
"StackSetOperation": {
"Status": "SUCCEEDED",
"StatusDetails": { "FailedStackInstancesCount": 3 }
}
}
SUCCEEDED con un FailedStackInstancesCount distinto de cero es la firma de un baseline desplegado a medias. Trata ese campo, y no el estado de la operación, como la definición de terminado.
Drift a lo largo de un stack set
La detección de drift a nivel de stack set corre la detección de drift a nivel de stack sobre cada stack instance y sube las respuestas. Un recurso con drift vuelve a su stack con drift, un stack con drift vuelve a su instance con drift, y una instance con drift deja al stack set entero en DRIFTED.
aws cloudformation detect-stack-set-drift --stack-set-name org-baseline
La operación devuelve un ID porque es de larga duración, y describe-stack-set-operation va reportando los conteos mientras avanza: DriftedStackInstancesCount, InSyncStackInstancesCount, InProgressStackInstancesCount, FailedStackInstancesCount, sobre TotalStackInstancesCount. Solo puede correr una detección de drift por stack set a la vez, y la puedes frenar con stop-stack-set-operation.
Dos límites deciden cuánto vale un resultado limpio:
- Los cambios hechos por CloudFormation nunca son drift. Actualiza directo el stack de una cuenta destino a un template distinto y la detección de drift igual reporta
IN_SYNC, porque el stack coincide con su propia configuración esperada. Ese stack ahora es inconsistente con sus hermanos, que es un problema genuino, y la detección de drift no es la herramienta que lo encuentra. - La detección a nivel de stack no sube. Corre la detección sobre un stack individual en una cuenta destino y esos resultados nunca aparecen en la página de StackSets de la consola. Arranca la detección a nivel de stack set o el estado de drift del stack set se queda viejo.
Los overrides de parameters se manejan bien: como la detección corre por stack, una instance con valores de parameter sobrescritos se compara contra sus propias expectativas sobrescritas, no contra el default del stack set.
Cuando las operaciones fallan
Las fallas se agrupan en una lista corta, y el motivo de estado suele nombrar la causa directo.
| Síntoma | Causa |
|---|---|
should have 'AWSCloudFormationStackSetExecutionRole' role with trust relationship... | Falta la cadena de confianza self-managed en el destino, o los nombres no coinciden |
| Falla en una cuenta, el template anda bien en las demás | Permisos insuficientes en el execution role para un tipo de recurso en esa cuenta |
| Fallas en muchas cuentas sobre un nombre global | El template crea un recurso de nombre único global, por ejemplo un bucket de S3 con nombre fijo |
| Un error de quota solo en algunas cuentas | La cuenta destino ya tiene el máximo de un recurso que el template crea, por ejemplo roles IAM |
| El delete falla en un stack | Ese stack tiene termination protection activada |
Instance trabada en INOPERABLE después de un import | El import falló; borra la instance con RetainStacks, arregla y reintenta |
Reintentar no es una API especial. Arreglas la causa de fondo, después corres un update sobre el stack set con el mismo template o uno corregido, y las instances OUTDATED se ponen al día.
Las quotas que importan a escala: 1.000 stack sets por cuenta administradora, 100.000 stack instances por stack set, y 10.000 operaciones de stack instance corriendo a la vez por región por cuenta administradora, sumando todos los stack sets. Chocar contra la última es lo que vuelve misteriosamente lento a un rollout grande, en vez de fallido.
Consejos para el examen
- "Desplegar el mismo template a muchas cuentas y regiones desde un solo lugar" es StackSets. Una respuesta que describa un script que recorre cuentas está mal incluso si funcionaría.
- "Cuentas administradas por AWS Organizations" más "las cuentas nuevas deberían recibirlo automáticamente" es service-managed con despliegue automático. "Cuentas fuera de la organización" o "sin organización" te obliga a self-managed.
AWSCloudFormationStackSetAdministrationRolevive en la cuenta administradora,AWSCloudFormationStackSetExecutionRoleen cada destino. Un motivo de estado que nombra el execution role es un problema de confianza self-managed, nunca un problema de trusted access.- La cuenta de administración nunca recibe una stack instance service-managed. Fíjate en los escenarios donde la cuenta faltante es la de administración.
- La tolerancia a fallas es por región y redondea hacia abajo. Excederla en una región cancela las regiones restantes.
- Un estado de operación
SUCCEEDEDcon recursos faltantes significa que la tolerancia a fallas absorbió las fallas. MiraFailedStackInstancesCount. - Retain stacks conserva los recursos y suelta la asociación al stack set. No borra nada.
OUTDATEDsignifica una operación fallida o saltada.INOPERABLEsignifica que la instance queda excluida de futuros updates hasta que la borres.- Los stack sets service-managed no soportan nested stacks, macros ni transforms, incluido
AWS::Serverless. - La detección de drift sobre un stack set nunca trata como drift un cambio hecho por CloudFormation.
Llévate una regla de esta lección: con StackSets, "desplegado" es un hecho por instance, no por operación. Antes de dar un rollout por completo, mira los estados de las instances y el conteo de instances fallidas, porque el estado de la operación está diseñado para decirte algo más angosto que lo que quieres saber.
StackSets empuja recursos idénticos hacia adentro de las cuentas. La próxima lección cubre el movimiento opuesto: dejar un recurso en una cuenta y permitir que otras lo usen, con AWS RAM.
