top of page
  • Foto do escritorRan Isenberg

AWS CDK - Melhores práticas das trincheiras


AWS CDK - Melhores práticas das trincheiras

O que é AWS CDK?

O AWS CDK permite que você crie aplicativos confiáveis, escaláveis e econômicos na nuvem com o considerável poder expressivo de uma linguagem de programação

Acredito que o AWS CDK revolucionou a maneira como criamos recursos na nuvem.

O AWS CDK permite que os desenvolvedores escrevam infraestrutura como código e se sintam em casa.

É uma ferramenta tão flexível e poderosa que é fácil cometer erros.

Alguns erros podem custar muito caro.


Algumas semanas atrás, perguntei aos desenvolvedores no LinkedIn e no Twitter por que eles não estavam usando o AWS CDK (exceto multicloud) e recebi muitas respostas e preocupações: Obrigado por compartilhar suas experiências!

Eu me vejo como um defensor do AWS CDK; dei palestras sobre o CDK internamente no meu local de trabalho, organizei umwebinar e dei uma palestra no primeiroAWS CDK Day 2020 .


Então decidi que a melhor maneira de abordar essas preocupações e converter as pessoas para o CDK era:

1. Escrever minha opinião sobre um guia de práticas recomendadas do CDK reunido ao longo de quase três anos de desenvolvimento com o CDK.

2. Forneça um projeto de modelo CDK funcional que implemente essas práticas que podem ser encontradas aqui .

 

Melhores práticas do AWS CDK

Logotipo CDK

Estas diretrizes expandem as melhores práticas oficiais do AWS CDK .

Observe que esta postagem do blog pressupõe que você tenha conhecimento básico do AWS CDK e entenda os conceitos de pilha e construções.

Essas diretrizes são divididas em várias categorias:

  1. Estrutura do projeto e diretrizes de pilha

  2. Diretrizes de construções

  3. Diretrizes CI/CD

  4. Resiliência e Segurança

  5. Dicas gerais de desenvolvimento

Se você quiser a versão em vídeo, ela está disponível abaixo:


 

Estrutura do projeto e diretrizes da pilha

Estas diretrizes discutem uma estrutura de projeto recomendada.


Um repositório, uma aplicação, uma pilha

“Cada aplicação começa com uma única pilha em um único repositório” — Guia de práticas recomendadas do AWS CDK

De acordo com as práticas recomendadas oficiais do AWS CDK, seu repositório de código não deve conter mais de um aplicativo CDK, uma pilha com uma ou muitas construções mantidas por uma equipe.

Concordo com essa prática.

Adicionar mais pilhas e aplicativos ao repositório aumentará o tempo de implantação e o raio de alcance em caso de erros.

Em vez de várias pilhas, use inúmeras construções.

Entretanto, como saber quando dividir uma pilha em várias pilhas?

Minha regra geral é dividir quando:

  1. A nova pilha é um serviço ou microsserviço diferente com requisitos ou estratégias de implantação adicionais (implantação em várias regiões etc.).

  2. Uma equipe diferente manterá a nova pilha.

  3. A nova pilha tem um domínio de negócios diferente.

  4. A implantação se tornou muito longa ou muito complexa na pilha. Divida a pilha em microsserviços espalhando vários repositórios. A dependência/contrato entre os microsserviços será definido com REST API/SQS/EventBridge/SNS etc.

Estrutura do repositório de serviços SaaS da AWS

O código do AWS CDK e o manipulador do serviço AWS Lambda residem no mesmo repositório, mas em pastas diferentes como módulos Python separados.

O projeto é construído a partir de dois projetos internos: o projeto CDK de infraestrutura como código e o código de serviço (código do manipulador AWS Lambda com testes).

Esses dois projetos internos são separados para reduzir o raio de explosão em caso de erros e melhorar a facilidade de testabilidade de cada projeto.

Como desenvolvo serviços Serverless, o exemplo descreve um projeto Serverless. No entanto, a estrutura permanece a mesma para quaisquer serviços não Serverless.


As principais pastas do projeto são:

  1. Pasta CDK : sob a pasta 'cdk'. Um aplicativo CDK implanta uma pilha que consiste em uma ou mais construções CDK. As construções CDK contêm recursos AWS e suas conexões/relações. Leia mais sobre os detalhes do projeto CDK aqui e aqui.

  2. Pasta Docs : pasta de documentação do serviço GitHub Pages (opcional).

  3. Pasta de serviço : arquivos de projeto do AWS Lambda: handler, esquemas de entrada/saída e pasta de utilitários. Cada handler tem sua própria pasta de esquemas. A pasta de utilitários armazenava código compartilhado entre vários handlers.

  4. Pasta de testes : testes unitários/de integração e E2E. Ao separar o código de serviço da infra, executar os testes localmente no IDE é mais direto.

Você pode encontrar meu projeto de modelo Serverless aqui e o blog sobre ele aqui .


Criar Projetos de Modelo

Para acelerar a adoção do Serverless e o uso do CDK, você pode criar um projeto de modelo que forneça um novo serviço e equipe com um projeto CDK implantável em funcionamento com um pipeline funcional e manipuladores do AWS Lambda que contenham todas as práticas recomendadas.

Como arquiteto em um grupo de plataforma de nuvem, entendemos que é importante compartilhar construções e fornecer guias de instruções do CDK, incluindo um projeto de modelo.


Você pode encontrar meu projeto de modelo Serverless aqui e o blog sobre ele aqui .


 

Diretrizes de construções

Esta seção contém práticas recomendadas para o desenvolvimento de construções.


Composição da pilha

Use construções para modelar os domínios de infraestrutura do seu aplicativo.

Esforce-se para manter os recursos não-construídos definidos pela pilha no mínimo.

Se duas construções tiverem a mesma dependência de recursos:

  1. Coloque o recurso em uma nova construção e forneça-o como um parâmetro de entrada para ambos

  2. Decida qual constructo tem o direito de “possuí-lo” e criá-lo internamente. Forneça-o como um parâmetro de entrada para o outro constructo.


Construções orientadas ao domínio empresarial

Não acho que exista uma abordagem certa ou errada para selecionar recursos em construções, desde que faça sentido para você e você consiga encontrar recursos e configurações facilmente.

No entanto, acredito que escolher uma abordagem orientada ao domínio de negócios para selecionar quais recursos devem ser incluídos em uma construção faz mais sentido.

É mais fácil encontrar recursos e entender suas conexões simplesmente olhando para o diagrama de arquitetura de serviço. Também é mais fácil compartilhar padrões de design entre equipes em organizações que podem exigir a mesma arquitetura.

Vamos supor que eu tenha um serviço de "reservas" sem servidor contendo dois domínios comerciais:

  1. Fornecer API REST para ações CRUD para um sistema de reservas a ser usado pelos clientes.

  2. Envie dados de reserva entre vários serviços internos (compartilhe e envie informações de reserva em um método assíncrono de serviço para serviço).

Vamos supor que eu tenha projetado a seguinte arquitetura:


arquitetura de serviço de reserva
arquitetura de serviço de reserva

  1. API GW com funções CRUD AWS Lambda.

  2. Banco de dados AWS Aurora usado pelas funções CRUD para consultas de leitura/gravação.

  3. Os fluxos do AWS Aurora acionam uma função do AWS Lambda que envia dados por meio de um tópico do AWS SNS para outros serviços externos.

  4. AWS SNS — uma implementação central de pub/sub de serviços cruzados. Ela permite que tanto o serviço de 'reserva' quanto os serviços externos enviem mensagens uns aos outros por meio do tópico de reserva.

  5. O AWS SQS assinou o tópico SNS e um destino de função AWS Lambda do SQS. Esta função Lambda obtém um evento de solicitação do SNS e consulta o banco de dados Aurora e envia uma resposta via SNS.

Observação: o banco de dados AWS Aurora é acessado pela API CRUD e pelas funções Lambda SQS/streams. No entanto, o uso de CRUD é de leitura/gravação, enquanto as lambdas SQS/streams são somente leitura.


Como criamos as construções?

Eu modelaria o serviço em duas construções de domínio de negócios: CRUD e Mensagens .


construções de serviços de reserva
construções de serviços de reserva

A construção CRUD criará uma instância dos seguintes recursos:

  1. Funções do AWS Lambda e suas funções.

  2. Construção Aurora — O AWS Aurora é relativamente complexo de definir no CDK (VPC, bancos de dados, permissões, etc.) e deve ser manipulado em sua própria construção instanciada dentro da construção CRUD.

A construção de mensagens criará:

  1. Tópico do AWS SNS.

  2. AWS SQS com uma assinatura do tópico AWS SNS.

  3. Função e função do AWS Lambda acionadas pelo AWS SQS. A função do Lambda tem acesso somente leitura ao AWS Aurora DB e pode enviar eventos ao AWS SNS.

  4. Função do AWS Lambda acionada por fluxos do Aurora que envia dados de reserva para serviços externos por meio do tópico do AWS SNS.

A construção de mensagens também obterá a construção Aurora como um parâmetro de entrada para definir as permissões e configurações necessárias para as funções do AWS Lambda.

Regra prática: qualquer recurso compartilhado usado em todas as construções (fila de mensagens mortas, SQS ou mecanismo de tratamento de erros) deve ser definido como uma construção independente e passado como entrada para as outras construções.


Construções Compartilhadas

Crie repositórios de bibliotecas de construção CDK que podem ser usados como uma dependência de projeto em toda a organização. Essas construções são recursos seguros e testados ou até mesmo padrões.


Você pode ter uma equipe de engenharia de nuvem ou DevOps criando tais construções compatíveis. Você pode ler sobre engenharia de plataforma de nuvem aqui .

Por exemplo:

  1. Regras do WAF para distribuições do AWS API Gateway/CloudFront.

  2. Padrão de gatilho SNS -> SQS onde SNS e SQS têm criptografia em repouso definida com CMKs necessárias.

  3. Construção de configuração dinâmica do AWS AppConfig.

 

Diretrizes CI/CD

Esta seção descreve diretrizes para implantação correta de pilha, modelagem de ambiente e experiência do desenvolvedor em relação a testes e desenvolvimento locais.


Implantação de pilha

“As equipes de desenvolvimento devem ser capazes de usar suas próprias contas para testes e ter a capacidade de implantar novos recursos nessas contas conforme necessário. Desenvolvedores individuais podem tratar esses recursos como extensões de sua própria estação de trabalho de desenvolvimento” — Guia do AWS CDK

Várias opções vêm à mente; escolha a que faz mais sentido para você, considerando o tamanho da empresa, o orçamento e a sobrecarga de gerenciamento de contas da AWS.

Certifique-se de usar as diretrizes e práticas recomendadas para gerenciar essas contas com o AWS Organizations e o AWS ControlTower.


Empresas menores usam estratégias como conta por desenvolvedor, onde você pode implantar TODA a linha de produtos e sua infinidade de microsserviços em uma conta para desenvolver localmente, fazer alterações, enviá-las e testar imediatamente em versões estáveis locais.

  1. Experiência em desenvolvimento local é excelente.

  2. Os testes de integração são mais diretos e podem ser feitos localmente. No entanto, imitar dados de serviço reais por conta AWS pode ser desafiador e reduz a praticidade do teste.

  3. É difícil manter a observabilidade em muitas contas.

  4. Gerenciar um grande número de contas considerando o pequeno porte da empresa.

Quando os desenvolvedores abrem um PR, o pipeline é implantado em uma conta diferente. Conta por estágio é a abordagem recomendada, pois reduz o raio de explosão em caso de violação ou erros.


No entanto, empresas maiores podem escolher uma abordagem diferente.

Às vezes, implantar todo o portfólio da empresa em uma única conta é impossível devido à complexidade, às cotas de recursos e ao conhecimento necessário para implantar os serviços.

Uma opção viável para grandes empresas consiste no seguinte:

  1. Diferentes equipes de serviço obtêm contas AWS separadas, reduzindo atritos, conflitos e chances de atingir cotas de serviço AWS por conta AWS.

  2. Cada estágio do pipeline de CI/CD obtém sua conta AWS (desenvolvimento, teste, preparação, produção, etc.).

  3. Os desenvolvedores desenvolvem na conta dev juntos. Eles implantam suas pilhas de CDK de serviço na mesma conta. No entanto, cada pilha tem um nome/prefixo diferente para remover possíveis conflitos de implantação.

  4. Os desenvolvedores testam serviços reais implantados em outras contas.

  5. Testes de integração em várias contas às vezes podem exigir confiança entre contas e podem ser mais desafiadores.

Como você pode ver, cada método tem seus prós e contras, e não existe uma solução mágica.


Modele seus estágios de pipeline de CI/CD em código

Use arquivos de configuração local e variáveis de ambiente em conjunto com condições de código ('instruções if') para implantar diferentes configurações de recursos em várias contas e estágios.

Por exemplo:

  1. Uma conta de desenvolvimento pode ter políticas diferentes (manter a política definida para destruir, por exemplo), mas uma conta de produção praticará uma configuração resiliente.

  2. Cada estágio terá segredos e chaves de API diferentes – reduza o raio de explosão se uma conta for violada.

  3. A conta de produção definirá maior simultaneidade reservada do AWS Lambda ou habilitará a simultaneidade provisionada para remover inicializações a frio.

  4. Diferentes modelos de faturamento para AWS DynamoDB em vários estágios. Reduza custos em contas dev e maximize o desempenho em produção.

 

Diretrizes de resiliência e segurança


Definir políticas de retenção

Em um ambiente de produção, é essencial definir políticas de remoção em recursos com estado ou críticos (bancos de dados) como "Reter" para que você não exclua e reconstrua os dados que eles contêm.

No ambiente de desenvolvimento, não há problema em excluir os recursos depois que a pilha for removida ou o ID do recurso for alterado.

Essa prática reduzirá seus custos e recursos órfãos a longo prazo.


Testes do AWS CDK

Use testes do AWS CDK para garantir que recursos vitais não sejam excluídos e que conexões de recursos significativas permaneçam intactas.

Esses testes são feitos em tempo de sintetização, então não há como você implantar uma versão quebrada.

Veja exemplos de testes de infraestrutura no meu modelo de CDK aqui .

Os testes verificam em tempo de síntese, antes da implantação, se o recurso GW da API existe.


Veja mais exemplos aqui .


Os padrões de segurança não são bons o suficiente

Sempre se esforce para ter as menores permissões e funções de privilégio. Cada AWS Lambda deve ter sua própria função com seu subconjunto mínimo de permissões.

Há muitas diretrizes de segurança para diferentes recursos. Às vezes, elas são refletidas nos valores padrão do AWS CDK, como o S3 bloqueia o acesso público por padrão. No entanto, às vezes, não são.

Depende de você ter sempre a segurança em mente:

Esse recurso deve residir em uma VPC? Devo colocar autorização IAM desse caminho de gateway de API? Talvez transformá-lo em um Gateway de API privado?

Felizmente, há ferramentas para ajudar você a cobrir seus rastros. Você deve usar ferramentas como CFN Nag e CDK-nag.


Confira os testes nag do CDK que implementei no meu projeto de modelo do CDK aqui .

As verificações de CDK nag são adicionadas à pilha e executadas durante a implantação. Qualquer potencial violação de segurança falhará na implantação.


Segredos em CDK

Não armazene segredos no seu código, seja CDK ou manipulador AWS Lambda. Use strings criptografadas AWS SSM ou AWS Secrets Manager para mantê-los seguros.

No entanto, como você passa os segredos para o CDK, para que eles sejam implantados no AWS Secrets Manager?

Uma opção viável é armazenar o segredo como um segredo do GitHub/Jenkins/CI e injetá-lo como um parâmetro do CDK ou variável de ambiente durante o processo de implantação.


Pense sempre em resiliência

Evite alterar o ID lógico de recursos com estado.

"Evite alterar o id lógico de recursos com estado. Alterar o ID lógico do recurso resulta na substituição do recurso por um novo na próxima implantação. O ID lógico é derivado do id que você especifica ao instanciar a construção.." — Melhores práticas oficiais do AWS CDK.

É sempre melhor prevenir do que remediar. Erros podem acontecer.

É necessária uma refatoração ingênua em um recurso CDK com estado (mover construções, renomear ID lógico, etc.) para excluir um banco de dados de produção inteiro e dados de clientes.


Cópias de segurança

Crie backups para seus recursos com estado; use backups integrados, como a recuperação de ponto no tempo do DynamoDB, ou use o AWS Backup para criar backups personalizados.


Altera a visibilidade

Você pode usar uma ferramenta chamada ' Notificador CDK ' para fornecer mais visibilidade ao seu pipeline em cada PR.

Agora, antes de cada PR merge, você pode entender visualmente as mudanças na sua infraestrutura. Verde são recursos que são adicionados, e vermelho são excluídos.

Desenvolvedores conscientes agora podem entender visualmente se há uma catástrofe iminente no PR.

Obrigado, Roy Ben Yosef, por esta dica valiosa!

 

Dicas gerais de desenvolvimento


RTFM

Ao usar construções e recursos internos do CDK, leia a documentação. Certifique-se de entender cada parâmetro e sua definição antes de começar a trabalhar.

Esses parâmetros opcionais geralmente contêm políticas de segurança ou de recursos que você deve definir explicitamente.


Escreva suas próprias políticas de IAM

Uma capacidade poderosa das construções CDK é a abundância de funções internas relacionadas ao IAM que abstraem as políticas reais do IAM. Por exemplo: Uma construção de tabela do DynamoDB pode conceder a uma função permissões de leitura e gravação (' grant_read_write_data ').

Embora isso abstraia as políticas do IAM que são adicionadas à função do beneficiário, o efeito colateral é esse.

  1. Os desenvolvedores não entendem as políticas do IAM e o que suas alterações concedem à função. Sim, eles podem ler a documentação da função, mas muitos desenvolvedores não vão além.

  2. Algumas dessas funções adicionam permissões que sua função não exige, o que vai contra o princípio de segurança de "privilégio mínimo".


No exemplo, a função define que o AWS AppConfig obtém permissões de configuração. É fácil de escrever e muito legível.


Conclusão: defina seu próprio documento de política do AWS IAM. Você pode definir políticas inline ou políticas JSON IAM completas. Quando possível, tente limitar a seção de recursos a um recurso específico: um bucket específico, uma tabela específica do AWS DynamoDB, etc.

Embora menos intuitivo, você aprenderá sobre IAM e criará serviços mais seguros, e a política se tornará mais precisa e menos abstrata a longo prazo.


Veja este blog para mais exemplos.


Leia mais sobre isso aqui .


Abordagem do Console First

Ao desenvolver o CFN, tente usar o console primeiro, entenda os relacionamentos entre os itens e, então, tente criar os objetos CFN e conectá-los.


Não abstraia demais

Escrever AWS CDK é escrever código. Como engenheiros, prosperamos e nos orgulhamos de abstrações e truques legais. No entanto, como em tudo na vida, por favor, não exagere, especialmente com código de infraestrutura. Eu aceitaria uma pequena duplicação de código — definição de função AWS Lambda com uma definição e configuração de variáveis de ambiente claras em vez de um método de fábrica complicado que cria várias funções Lambda.

O código de infraestrutura é crítico, então ele deve ser legível e organizado o máximo possível. No entanto, isso não significa que a duplicação de código seja sempre aceita. Encontre o equilíbrio que funciona para você entre abstração e legibilidade.

 

Obrigado Alon Sadovsk por ajudar com esta postagem.



Comments


bottom of page