AWS DevOps Infrastructure Code: as 9 etapas-chave para passar de zero a operacional
AWS DevOps Infrastructure Code: o essencial em um artigo — código real, diagramas e etapas concretas, extratos de um curso de 39 lições.
Todos podem aprender AWS DevOps Infrastructure Code — desde que sigam as etapas na ordem correta. Condensamos um curso completo de 39 lições em um percurso claro, com os trechos de código mais úteis.
- Introdução e Configuração AWS
- DevOps e Infraestrutura como Código
- AWS CloudFormation
- AWS CDK Cloud Development Kit
- CICD com AWS CodePipeline
Introdução ao AWS CDK — Cloud Development Kit
Capítulo 03 — Lição 01 · AWS DevOps : Infraestrutura como Código
1. O que é o AWS CDK ?
CloudFormation é como preencher manualmente um formulário administrativo CERFA, campo por campo, seguindo regras de sintaxe rigorosas. É cansativo, mas funciona. O CDK é ter um programa que preenche esse formulário para você: você diz em Python “quero um servidor de tamanho médio com um banco de dados” e ele gera automaticamente o formulário CERFA completo, corretamente preenchido, com todos os campos obrigatórios. Você escreve muito menos, faz muito mais e aproveita todo o poder de uma linguagem de programação real, como loops, funções e reutilização de código.
O AWS Cloud Development Kit (CDK) é um framework open-source que permite definir sua infraestrutura AWS com uma linguagem de programação real: Python, TypeScript, Java, C# ou Go. O CDK gera automaticamente templates CloudFormation a partir do seu código.
CDK vs CloudFormation — comparação
| Critério | CloudFormation (YAML) | AWS CDK (Python) |
|---|---|---|
| Linguagem | YAML / JSON declarativo | Python, TypeScript, Java, C#, Go |
| Reutilização | Copiar-colar, Nested Stacks | Classes, módulos, herança |
| Autocompletar no IDE | Limitado (YAML) | Completo com tipos e documentação |
| Lógica | Condições e mappings limitados | if/else, loops for, funções completas |
| Testes | Difícil | Testes unitários com pytest, jest |
| Curva de aprendizado | Baixa para YAML, mas verboso | Exige conhecimento de uma linguagem de programação |
| Por baixo dos panos | Executado diretamente pelo CloudFormation | Gera CloudFormation e depois implanta |
Os quatro conceitos fundamentais do CDK
App (Aplicação CDK)
O ponto de entrada de todo projeto CDK. Um App contém uma ou mais Stacks. É o contêiner raiz da sua infraestrutura.
Stack (Stack CDK)
Corresponde a uma stack CloudFormation. Contém Constructs (recursos AWS). Um App pode ter várias Stacks para diferentes ambientes.
Construct
O bloco de construção básico do CDK. Representa um recurso AWS (ou um grupo de recursos). Existe em três níveis: L1, L2, L3.
Environment (Env)
A combinação de conta AWS + região de destino para a implantação. Permite implantar a mesma stack em vários ambientes.
2. Instalação — Node.js, CDK CLI e Python
O CDK CLI é uma ferramenta Node.js. Mesmo programando em Python, você precisa ter o Node.js instalado.
Pré-requisitos
# 1. Verificar Node.js (versão 18+ recomendada) node --version
# Bootstrap na região atual cdk bootstrap # Bootstrap em uma região específica cdk bootstrap aws://123456789012/eu-west-1
Os Constructs são os blocos básicos do CDK. Existem em três níveis de abstração, cada um oferecendo um compromisso diferente entre controle e simplicidade.
L1 — Constructs de baixo nível (CfnXxx)
Os constructs L1 (prefixados com Cfn) são wrappers diretos em torno dos recursos CloudFormation. Eles dão acesso a todas as propriedades, mas sem valores padrão — você deve configurar tudo explicitamente.
from aws_cdk import aws_s3 as s3
import aws_cdk as cdk
class MaStack(cdk.Stack):
def __init__(self, scope, id, **kwargs):
super().__init__(scope, id, **kwargs)
# L1 : CfnBucket = wrapper direto CloudFormation AWS::S3::Bucket
bucket_l1 = s3.CfnBucket(self, "BucketL1",
bucket_name="mon-bucket-l1",
versioning_configuration=s3.CfnBucket.VersioningConfigurationProperty(
status="Enabled"
),
lifecycle_configuration=s3.CfnBucket.LifecycleConfigurationProperty(
rules=[s3.CfnBucket.RuleProperty(
id="expiration-anciens-objets",
status="Enabled",
expiration_in_days=90
)]
)
)L2 — Constructs de alto nível (recomendados)
Nested Stacks, StackSets, Change Sets e Boas Práticas
Capítulo 02 — Lição 03 · AWS DevOps : Infraestrutura como Código
1. Nested Stacks — decompor grandes infraestruturas
Imagine a construção de um prédio de escritórios. Em vez de um único empreiteiro fazer tudo do zero e ficar sobrecarregado, recorremos a especialistas independentes: um eletricista para toda a rede elétrica, um encanador para a hidráulica, um carpinteiro para as divisórias, um técnico de rede para a TI. Cada um trabalha em sua área, produz seu relatório e um mestre de obras coordena o conjunto. As Nested Stacks funcionam da mesma forma: cada módulo (rede, segurança, banco de dados, aplicação) é um template independente gerenciado por equipes diferentes, e uma stack pai coordena todos.
Quando uma infraestrutura se torna complexa (VPC, bancos de dados, aplicações, segurança...), agrupar tudo em um único template fica inviável. As Nested Stacks (stacks aninhadas) permitem dividir a infraestrutura em módulos reutilizáveis, cada um em seu próprio template.
Arquitetura em camadas com as Nested Stacks
infrastructure/ ├── stack-parent.yaml # Stack racine — orchestre tout ├── modules/ │ ├── reseau.yaml # VPC, subnets, Internet Gateway │ ├── securite.yaml # Security Groups, IAM Roles │ ├── base-de-donnees.yaml # RDS, cache ElastiCache │ └── application.yaml # EC2, Load Balancer, Auto Scaling
A stack pai que referencia os módulos
AWSTemplateFormatVersion: "2010-09-09"
Description: "Stack parent — orchestre toute l'infrastructure"
Parameters:
Environnement:
Type: String
AllowedValues: [dev, prod]
URLTemplates:
Type: String
Description: "URL S3 de base où sont stockés les templates"
Default: "https://s3.amazonaws.com/mon-bucket-templates/v1"
Resources:
# Module réseau
StackReseau:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Sub "${URLTemplates}/reseau.yaml"
Parameters:
Environnement: !Ref Environnement
CIDRVpc: "10.0.0.0/16"
TimeoutInMinutes: 15
# Module sécurité — dépend du réseau
StackSecurite:
Type: AWS::CloudFormation::Stack
DependsOn: StackReseau
Properties:
TemplateURL: !Sub "${URLTemplates}/securite.yaml"
Parameters:
Environnement: !Ref Environnement
VpcId: !GetAtt StackReseau.Outputs.VpcId
# Module base de données
StackBDD:
Type: AWS::CloudFormation::Stack
DependsOn: StackSecurite
Properties:
TemplateURL: !Sub "${URLTemplates}/base-de-donnees.yaml"
Parameters:
Environnement: !Ref Environnement
VpcId: !GetAtt StackReseau.Outputs.VpcId
SubnetIds: !GetAtt StackReseau.Outputs.SubnetsPrives
SGBaseDeDonnees: !GetAtt StackSecurite.Outputs.SGBaseDeDonnees
TimeoutInMinutes: 30
# Module application
StackApplication:
Type: AWS::CloudFormation::Stack
DependsOn: StackBDD
Properties:
TemplateURL: !Sub "${URLTemplates}/application.yaml"
Parameters:
Environnement: !Ref Environnement
VpcId: !GetAtt StackReseau.Outputs.VpcId
SubnetPublics: !GetAtt StackReseau.Outputs.SubnetsPublics
URLBDD: !GetAtt StackBDD.Outputs.EndpointBDD
SGApplication: !GetAtt StackSecurite.Outputs.SGApplication
Outputs:
URLApplication:
Description: "URL du Load Balancer de l'application"
Value: !GetAtt StackApplication.Outputs.URLLoadBalancerExemplo do template módulo reseau.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "Module réseau — VPC, subnets publics et privés"
Parameters:
Environnement:
Type: String
CIDRVpc:
Type: String
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref CIDRVpc
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub "vpc-${Environnement}"
SubnetPublic1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.1.0/24"
AvailabilityZone: !Select [0, !GetAZs ""]
MapPublicIpOnLaunch: true
SubnetPrive1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.10.0/24"
AvailabilityZone: !Select [0, !GetAZs ""]
Outputs:
VpcId:
Value: !Ref VPC
Export:
Name: !Sub "${AWS::StackName}-VpcId"
SubnetsPublics:
Value: !Join [",", [!Ref SubnetPublic1]]
Export:
Name: !Sub "${AWS::StackName}-SubnetsPublics"
SubnetsPrives:
Value: !Join [",", [!Ref SubnetPrive1]]
Export:
Name: !Sub "${AWS::StackName}-SubnetsPrives"Implantar com os templates armazenados no S3
# Uploader les templates dans S3 d'abord
aws s3 sync ./modules/ s3://mon-bucket-templates/v1/ --exclude "*.md"
# Déployer la stack parent
aws cloudformation deploy \
--stack-name infra-prod \
--template-file stack-parent.yaml \
--parameter-overrides \
Environnement=prod \
URLTemplates=https://s3.amazonaws.com/mon-bucket-templates/v1 \
--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM2. StackSets — implantar em várias contas e regiões
Imagine uma rede de restaurantes que abre filiais pelo mundo. O diretor-geral cria uma receita de menu padrão, uma identidade visual e procedimentos operacionais que se aplicam em todos os restaurantes, seja em Paris, Nova York ou Tóquio. Quando uma nova regra é adicionada (nova alergia a informar, novo regulamento sanitário), ela é aplicada simultaneamente em todos os restaurantes da rede com uma única decisão central. Os StackSets funcionam da mesma forma: você define sua infraestrutura uma única vez e a implanta em todas as suas contas AWS e todas as regiões em uma única operação.
Os StackSets permitem implantar o mesmo template CloudFormation em várias contas AWS e/ou várias regiões em uma única operação. É a ferramenta ideal para organizações com múltiplas contas (Landing Zone, Control Tower).
Casos de uso típicos
Governança centralizada
Implantar regras AWS Config, CloudTrail, GuardDuty em todas as contas da organização automaticamente.
Conformidade uniforme
Aplicar as mesmas políticas IAM, grupos de segurança básicos e notificações de alerta em cada conta.
Multi-região
Implantar uma infraestrutura idêntica em us-east-1, eu-west-1 e ap-southeast-1 para redundância global.
Pré-requisito: configurar as permissões
# Deux modes de fonctionnement : # Mode 1 : Self-Managed (rôles IAM manuels dans chaque compte) # Créer AWSCloudFormationStackSetAdministrationRole dans le compte admin # Créer AWSCloudFormationStackSetExecutionRole dans chaque compte cible # Mode 2 : Service-Managed (via AWS Organizations — recommandé) # Activer la confiance avec Organizations dans CloudFormation aws organizations enable-aws-service-access \ --service-principal cloudformation.amazonaws.com
Criar e implantar um StackSet
Implantar e gerenciar aplicações no EKS
Capítulo 08 — Kubernetes na AWS EKS | AWS DevOps Infrastructure as Code
1. Implantar uma aplicação — Deployment YAML
Um Deployment Kubernetes é como uma cadeia de fast-food. Você define quantos “balcões” (réplicas) quer abertos ao mesmo tempo. Se um cair, o Kubernetes abre outro automaticamente sem que os clientes percebam. Quando você quer mudar o cardápio (nova versão da imagem), o Kubernetes atualiza os balcões um a um (rolling update) para nunca fechar todos os balcões ao mesmo tempo. Se o novo cardápio não agradar, é possível voltar ao anterior imediatamente (rollback).
Um Deployment Kubernetes declara o estado desejado da sua aplicação: qual imagem usar, quantas réplicas, como realizar as atualizações. O Kubernetes mantém esse estado permanentemente.
Deployment completo com todas as boas práticas
apiVersion: apps/v1
kind: Deployment
metadata:
name: mon-api-fastapi
namespace: mon-application
labels:
app: mon-api-fastapi
version: "1.0.0"
equipe: backend
spec:
replicas: 3
selector:
matchLabels:
app: mon-api-fastapi
# Stratégie de déploiement rolling update
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1 # Au plus 1 Pod indisponible pendant la mise à jour
maxSurge: 1 # Au plus 1 Pod en surplus pendant la mise à jour
template:
metadata:
labels:
app: mon-api-fastapi
version: "1.0.0"
spec:
serviceAccountName: sa-mon-api # IRSA — IAM Role for Service Account
terminationGracePeriodSeconds: 30
# Sécurité au niveau du Pod
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containers:
- name: mon-api-fastapi
image: 123456789012.dkr.ecr.ca-central-1.amazonaws.com/mon-api-fastapi:1.0.0
ports:
- containerPort: 8080
protocol: TCP
# Limites de ressources obligatoires en production
resources:
requests:
cpu: "250m" # 0.25 vCPU garanti
memory: "256Mi" # 256 Mo garantis
limits:
cpu: "500m" # Maximum 0.5 vCPU
memory: "512Mi" # Maximum 512 Mo
# Variables d'environnement depuis ConfigMap et Secret
env:
- name: ENVIRONNEMENT
value: production
- name: PORT
value: "8080"
envFrom:
- configMapRef:
name: config-mon-api
- secretRef:
name: secrets-mon-api
# Sondes de santé
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
startupProbe:
httpGet:
path: /health
port: 8080
failureThreshold: 30
periodSeconds: 5
# Sécurité du conteneur
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
# Distribution entre les zones de disponibilité
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: mon-api-fastapiComandos essenciais de implantação
# Appliquer le manifeste kubectl apply -f deployment.yaml -n mon-application # Suivre le déploiement en temps réel kubectl rollout status deployment/mon-api-fastapi -n mon-application # Voir l'historique des déploiements kubectl rollout history deployment/mon-api-fastapi -n mon-application # Mettre à jour l'image (déclenche un rolling update) kubectl set image deployment/mon-api-fastapi \ mon-api-fastapi=123456789012.dkr.ecr.ca-central-1.amazonaws.com/mon-api-fastapi:1.1.0 \ -n mon-application # Revenir à la version précédente (rollback) kubectl rollout undo deployment/mon-api-fastapi -n mon-application # Revenir à une révision spécifique kubectl rollout undo deployment/mon-api-fastapi --to-revision=2 -n mon-application
2. Serviços Kubernetes : ClusterIP, NodePort, LoadBalancer
No Kubernetes, os Services são como endereços postais estáveis em um prédio cujos inquilinos mudam com frequência. ClusterIP é como uma sala interna no prédio: ninguém de fora pode acessá-la, é para comunicação entre funcionários. LoadBalancer é a porta de entrada principal do prédio com um agente de segurança (o Load Balancer AWS) que direciona os visitantes externos para a sala correta disponível. Mesmo que os inquilinos mudem (os Pods reiniciem), o endereço do prédio permanece o mesmo.
Um Service expõe um conjunto de Pods por meio de um IP estável e um nome DNS interno, independentemente do ciclo de vida dos Pods individuais.
| Tipo | Acessibilidade | Caso de uso |
|---|---|---|
| ClusterIP | Apenas dentro do cluster | Comunicação entre serviços (banco de dados, cache) |
| NodePort | De fora via IP do Node + porta fixa (30000-32767) | Testes, desenvolvimento (não recomendado em produção) |
| LoadBalancer | De fora via Load Balancer AWS (CLB/NLB) provisionado automaticamente | Expor um serviço diretamente (sem Ingress) |
| ExternalName | Resolve para um nome DNS externo | Acessar serviços RDS, ElastiCache via nome interno |
---
# Service ClusterIP — pour la communication interne
apiVersion: v1
kind: Service
metadata:
name: svc-mon-api
namespace: mon-application
labels:
app: mon-api-fastapi
spec:
type: ClusterIP
selector:
app: mon-api-fastapi # Correspond aux labels du Deployment
ports:
- name: http
port: 80 # Port du Service (interne)
targetPort: 8080 # Port du conteneur
protocol: TCP
---
# Service LoadBalancer — expose via un NLB AWS
apiVersion: v1
kind: Service
metadata:
name: svc-mon-api-public
namespace: mon-application
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
spec:
type: LoadBalancer
selector:
app: mon-api-fastapi
ports:
- name: http
port: 80
targetPort: 80803. ConfigMaps e Secrets Kubernetes
ConfigMap — configuração não sensível
apiVersion: v1
kind: ConfigMap
metadata:
name: config-mon-api
namespace: mon-application
data:
# Variables d'environnement
LOG_LEVEL: "info"
WORKERS: "4"
TIMEOUT: "30"
DATABASE_HOST: "rds-mon-app.ca-central-1.rds.amazonaws.com"
DATABASE_NAME: "production"
# Fichier de configuration complet
application.yaml: |
server:
host: 0.0.0.0
port: 8080
database:
pool_size: 10
max_overflow: 5
cache:
backend: redis
ttl: 300Secret Kubernetes
apiVersion: v1 kind: Secret metadata: name: secrets-mon-api namespace: mon-application type: Opaque stringData: # stringData accepte les valeurs en clair — K8s les encode en base64 automatiquement DATABASE_PASSWORD: "MonMotDePasseSecret" API_KEY: "sk-abc123..." JWT_SECRET: "ma-cle-jwt-super-secrete"
External Secrets Operator — sincronizar a partir do Secrets Manager
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: secrets-aws-synchronises
namespace: mon-application
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: secrets-mon-api # Nom du Secret Kubernetes à créer
creationPolicy: Owner
data:
- secretKey: DATABASE_PASSWORD
remoteRef:
key: "mon-app/production/secrets"
property: "database_password"
- secretKey: API_KEY
remoteRef:
key: "mon-app/production/secrets"
property: "api_key"Este artigo cobre os trechos mais úteis — o curso completo AWS DevOps Infrastructure Code (10 capítulos, 39 lições, exercícios corrigidos e projeto final) leva você até o fim.
./acceder-au-cours-complet cours gratuit : Maîtriser Claude CodeFAQ
Quanto tempo para aprender AWS DevOps Infrastructure Code ?
É preciso ter pré-requisitos ?
Por onde começar na prática ?
📬 Quer receber este tipo de guia toda semana? Inscreva-se gratuitamente — código real, zero enrolação.