AWS Certified CloudOps Engineer - Associate
CloudFormation StackSets
Implantar um template em muitas contas e Regiões com uma operação só: stack sets e stack instances, permissões self-managed contra service-managed, targets de implantação e filtros de conta, concorrência e tolerância a falhas, drift, e as falhas que se escondem atrás de um status SUCCEEDED.
- Distinguir stack set, stack instance e stack, e explicar por que uma stack instance pode existir sem stack
- Escolher entre permissões self-managed e service-managed, e nomear as roles que cada modelo exige
- Apontar para uma organização, para OUs específicas ou para contas filtradas, e prever quais contas recebem uma stack
- Ajustar tolerância a falhas, máximo de contas concorrentes e concorrência de Regiões conforme o risco da implantação
- Interpretar os códigos de status de stack set e de stack instance, incluindo OUTDATED e INOPERABLE
- Explicar como a detecção de drift em um stack set difere da detecção em uma stack individual
- Diagnosticar as falhas comuns de StackSets, incluindo uma operação que reporta SUCCEEDED com stacks falhadas
Um time de segurança precisa de uma role IAM só de leitura, um recorder do Config e uma regra de envio de logs em 40 contas e 4 Regiões. São 160 stacks. A versão em script é um loop que assume uma role em cada conta e chama create-stack, e funciona até a conta 23 bater em um service quota, o loop seguir em frente e ninguém perceber por três semanas que quatro contas estão sem recorder do Config.
O problema não é o loop. É que o loop não tem memória. Nada registra que aquelas 160 stacks deveriam ser a mesma coisa, então nada consegue te dizer quais estão atualizadas, quais falharam e quais alguém editou na mão.
StackSets é essa memória. Você define o template uma vez, nomeia as contas e as Regiões, e o CloudFormation rastreia cada stack resultante como parte de um conjunto gerenciado.
Stack set, stack instance, stack
Três palavras que parecem intercambiáveis e não são.
Um stack set é o contêiner: um template, um conjunto de parameters e a configuração de implantação. Ele vive na conta administradora e é um recurso regional. Crie um stack set em eu-west-1 e você não vai vê-lo com o console em us-east-1, o que surpreende quem assume que um recurso multi-Região precisa ser global.
Uma stack instance é uma referência a uma stack em uma conta alvo dentro de uma Região. Três contas em duas Regiões dão 6 stack instances, e cada uma carrega o próprio status.
Uma stack é a stack comum do CloudFormation que de fato guarda recursos, na conta alvo.
A separação entre instance e stack parece preciosismo de nomenclatura até a primeira falha. Uma stack instance pode existir sem stack: se a criação falhou, não existe stack, mas a instance sobrevive e guarda o motivo. É isso que torna um rollout falhado diagnosticável em vez de invisível.
aws cloudformation list-stack-instances --stack-set-name org-baseline \
--filters Name=DETAILED_STATUS,Values=FAILED
Dois modelos de permissão, uma escolha real
Implantar em outra conta significa assumir uma role lá. O StackSets te dá dois jeitos de organizar isso, e a prova testa qual deles um cenário obriga.
Permissões self-managed significam que você monta o elo de confiança na mão, com duas roles cujos nomes importam:
AWSCloudFormationStackSetAdministrationRolena conta administradora. A trust policy dela permite quecloudformation.amazonaws.coma assuma, e a permissions policy permitests:AssumeRolena execution role dos alvos.AWSCloudFormationStackSetExecutionRoleem cada conta alvo, confiando na conta administradora. Essa role precisa de permissão total no CloudFormation mais permissão para tudo que o template cria.
Use exatamente esses nomes e o StackSets os encontra sozinho. Use nomes customizados e toda operação precisa nomear as roles explicitamente. Os templates de exemplo que a AWS publica para essas roles dão "Action": "*" na execution role, o que serve para um primeiro teste e está errado para qualquer coisa permanente. Reduza a execution role para os tipos de recurso que o seu template realmente cria, porque aquela role é o teto do que qualquer operação de stack set consegue fazer naquela conta.
Permissões service-managed entregam o problema das roles para o CloudFormation. Você ativa o trusted access entre o CloudFormation e o AWS Organizations e, dali em diante, o CloudFormation cria e mantém as roles nas contas membro para você. Você aponta para OUs em vez de listar account IDs, e ganha implantação automática.
| Self-managed | Service-managed | |
|---|---|---|
| Contas alvo | Qualquer conta onde você consiga criar uma role | Só contas da sua organização |
| Configuração das roles | Você cria as duas | O CloudFormation cria |
| Alvos informados como | Account IDs | Raiz da organização ou IDs de OU |
| Conta nova entra na OU | Nada acontece | A implantação automática adiciona uma stack |
| Roda de onde | Qualquer conta | Conta de gerenciamento ou um delegated administrator |
| Nested stacks, macros, transforms | Aceitos | Não aceitos |
Duas restrições do modelo service-managed valem decorar, porque contradizem o que as pessoas supõem.
A conta de gerenciamento nunca recebe uma stack. Aponte para a organização inteira e o CloudFormation ainda pula ela. Se a conta de gerenciamento precisa do mesmo baseline, ela ganha a própria stack ou o próprio stack set self-managed.
Delegated administrators não podem ser limitados. A conta de gerenciamento pode registrar até 5 contas membro como delegated administrators, então um time central de plataforma roda stack sets em toda a organização sem ter credenciais da conta de gerenciamento. Mas um delegated administrator alcança todas as contas da organização. Não existe uma configuração do tipo "este time só pode implantar na OU Sandbox".
aws organizations register-delegated-administrator \
--service-principal member.org.stacksets.cloudformation.amazonaws.com \
--account-id 444455556666
Da conta delegated administrator, todo comando carrega --call-as DELEGATED_ADMIN. Deixe isso de fora e a CLI procura stack sets self-managed na própria conta membro, não acha nada e devolve uma lista vazia que parece problema de permissão.
Escolher quem recebe uma stack
Com permissões service-managed, os targets de implantação são a raiz da organização ou uma lista de IDs de OU. Apontar para uma OU pai inclui as filhas automaticamente, que é o comportamento desejado para um baseline de segurança e o comportamento que te pega quando uma OU de sandbox aninhada herda uma policy de produção.
Por padrão, toda conta de uma OU alvo recebe uma stack. Os filtros de conta estreitam isso:
| Tipo de filtro | Significado |
|---|---|
NONE (padrão) | Todas as contas das OUs listadas |
INTERSECTION | Só as contas listadas, e só se estiverem nas OUs listadas |
DIFFERENCE | Todas as contas das OUs listadas, exceto as contas listadas |
UNION | Todas as contas das OUs listadas, mais as contas 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 é o que se paga na prática. Um baseline vale para a OU Workloads inteira, menos a única conta legada que quebraria, e você expressa essa exceção na implantação em vez de tirar a conta da OU dela.
Concorrência e tolerância a falhas
Empurrar um template para 160 lugares de uma vez é um jeito eficiente de quebrar 160 lugares de uma vez. Quatro configurações controlam o raio de impacto, e elas interagem.
Máximo de contas concorrentes limita quantas contas alvo uma operação toca ao mesmo tempo, em número ou percentual. Percentuais arredondam para baixo: 25 por cento de 10 contas é 2, não 3.
Tolerância a falhas é o número ou percentual de falhas permitidas por Região antes de o CloudFormation parar. Também arredonda para baixo.
Concorrência de Regiões é SEQUENTIAL (o padrão, uma Região por vez na ordem de implantação que você definiu) ou PARALLEL (todas as Regiões de uma vez).
Concurrency mode decide o que acontece com a concorrência quando as falhas começam. STRICT_FAILURE_TOLERANCE mantém o máximo de contas concorrentes em no máximo tolerância a falhas mais 1, e desacelera conforme as falhas acumulam. SOFT_FAILURE_TOLERANCE mantém o seu nível de concorrência de qualquer forma.
Vamos andar por uma operação. Você implanta em 10 contas em eu-west-1, us-east-1 e ap-southeast-2, nessa ordem de implantação, com tolerância a falhas de 20 por cento, máximo de contas concorrentes de 50 por cento e Regiões sequenciais.
- 20 por cento de 10 arredonda para baixo e dá 2 falhas permitidas por Região. 50 por cento de 10 dá 5 contas por vez.
eu-west-1roda 5 contas, depois as outras 5. Duas falham. É exatamente a tolerância, então a Região termina e a operação segue.us-east-1roda e uma terceira conta falha naquela Região. A tolerância foi excedida ali, então o status da operação viraFAILEDeap-southeast-2é cancelada inteira.
A tolerância a falhas reinicia por Região. É isso que faz da implantação sequencial um mecanismo de segurança útil: um template quebrado em todo lugar falha na primeira Região e nunca chega nas outras.
Os padrões são deliberadamente tímidos, MaxConcurrentCount=1 e FailureToleranceCount=0 nos exemplos da CLI, o que significa uma conta por vez e parada na primeira falha. Para o primeiro rollout de um template novo, é a escolha certa. Aumente depois que o template provar que funciona.
Status, e o que engana
As operações de stack set reportam RUNNING, SUCCEEDED, FAILED, QUEUED, STOPPING ou STOPPED. QUEUED aparece com implantação automática: mova uma conta entre OUs e o StackSets roda um delete da stack da OU antiga e enfileira um create para a nova.
As stack instances têm os próprios status, e dois deles significam trabalho esperando por você:
OUTDATEDsignifica que a stack não está atualizada em relação ao stack set, quase sempre porque um create ou update falhou ali, ou porque a operação parou antes de alcançá-la.INOPERABLEsignifica que uma operação de delete de instances falhou e deixou a stack em estado instável. Instances nesse estado são excluídas de futuros updates do stack set, então elas silenciosamente param de receber suas mudanças. Recuperar significa apagar a instance comRetainStacksem true e depois limpar a stack na mão.
Agora o erro de leitura que custa cobertura de verdade. Uma operação SUCCEEDED não significa que toda stack deu certo. Significa que a tolerância a falhas nunca foi excedida. Coloque tolerância a falhas em 10 para 10 contas e uma operação em que absolutamente toda stack falha ainda devolve SUCCEEDED, porque você disse ao CloudFormation que aquele número de falhas era aceitável.
O número que você quer de verdade está nos detalhes de status:
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 com FailedStackInstancesCount diferente de zero é a assinatura de um baseline implantado pela metade. Trate esse campo, e não o status da operação, como a definição de pronto.
Drift em um stack set
A detecção de drift no nível do stack set roda a detecção de drift de stack em cada stack instance e agrega as respostas. Um recurso em drift deixa a stack dele em drift, uma stack em drift deixa a instance em drift, e uma instance em drift deixa o stack set inteiro DRIFTED.
aws cloudformation detect-stack-set-drift --stack-set-name org-baseline
A operação devolve um ID porque é longa, e describe-stack-set-operation reporta as contagens conforme ela avança: DriftedStackInstancesCount, InSyncStackInstancesCount, InProgressStackInstancesCount, FailedStackInstancesCount, sobre TotalStackInstancesCount. Só uma operação de detecção de drift roda por vez em um stack set, e você para ela com stop-stack-set-operation.
Dois limites decidem quanto vale um resultado limpo:
- Mudanças feitas pelo CloudFormation nunca são drift. Atualize a stack de uma conta alvo direto para um template diferente e a detecção de drift ainda reporta
IN_SYNC, porque a stack bate com a própria configuração esperada. Aquela stack agora está inconsistente com as irmãs, o que é um problema legítimo, e a detecção de drift não é a ferramenta que encontra isso. - A detecção no nível da stack não sobe. Rode a detecção em uma stack individual da conta alvo e o resultado nunca aparece na página de StackSets do console. Comece a detecção no nível do stack set ou o status de drift do stack set fica velho.
Overrides de parameter são tratados corretamente: como a detecção roda por stack, uma instance com valores de parameter sobrescritos é comparada com as próprias expectativas sobrescritas, não com o padrão do stack set.
Quando as operações falham
As falhas se concentram em uma lista curta, e o status reason normalmente nomeia a causa direto.
| Sintoma | Causa |
|---|---|
should have 'AWSCloudFormationStackSetExecutionRole' role with trust relationship... | Elo de confiança self-managed ausente ou com nome errado no alvo |
| Falha em uma conta só, template ok nas outras | Permissão insuficiente na execution role para um tipo de recurso naquela conta |
| Falhas em muitas contas em um nome global | O template cria um recurso globalmente único, como um bucket S3 com nome fixo |
| Erro de quota só em algumas contas | A conta alvo já tem o máximo de um recurso que o template cria, como roles IAM |
| Delete falha em uma stack | Proteção contra exclusão está ligada naquela stack |
Instance travada em INOPERABLE depois de um import | O import falhou; apague a instance com RetainStacks, corrija e tente de novo |
Tentar de novo não é uma API especial. Você corrige a causa e roda um update no stack set com o mesmo template ou um corrigido, e as instances OUTDATED se atualizam.
As quotas que importam em escala: 1.000 stack sets por conta administradora, 100.000 stack instances por stack set e 10.000 operações de stack instance rodando ao mesmo tempo por Região por conta administradora, somando todos os stack sets. Bater na última é o que deixa um rollout grande misteriosamente lento em vez de falhado.
Dicas para a prova
- "Implantar o mesmo template em muitas contas e Regiões de um lugar só" é StackSets. Uma resposta que descreve um script em loop pelas contas está errada mesmo que funcionasse.
- "Contas gerenciadas pelo AWS Organizations" mais "contas novas devem receber automaticamente" é service-managed com implantação automática. "Contas fora da organização" ou "sem organização" força self-managed.
AWSCloudFormationStackSetAdministrationRolefica na conta administradora,AWSCloudFormationStackSetExecutionRoleem cada alvo. Um status reason que nomeia a execution role é problema de confiança self-managed, nunca de trusted access.- A conta de gerenciamento nunca recebe uma stack instance service-managed. Fique atento a cenários em que a conta faltante é a de gerenciamento.
- A tolerância a falhas é por Região e arredonda para baixo. Excedê-la em uma Região cancela as Regiões restantes.
- Status
SUCCEEDEDcom recursos faltando significa que a tolerância a falhas absorveu as falhas. OlheFailedStackInstancesCount. - Retain stacks mantém os recursos e derruba a associação com o stack set. Não apaga nada.
OUTDATEDsignifica operação falhada ou pulada.INOPERABLEsignifica que a instance está fora dos updates futuros até você apagá-la.- Stack sets service-managed não aceitam nested stacks, macros nem transforms, incluindo
AWS::Serverless. - A detecção de drift em um stack set nunca trata uma mudança feita pelo CloudFormation como drift.
Leve uma regra desta lição: com StackSets, "implantado" é um fato por instance, não por operação. Antes de considerar um rollout completo, olhe os status das instances e a contagem de instances falhadas, porque o status da operação foi feito para te dizer algo mais estreito do que você quer saber.
O StackSets empurra recursos idênticos para dentro das contas. A próxima lição cobre o movimento oposto: manter um recurso em uma conta e deixar outras contas usarem ele, com o AWS RAM.
