<h2>Fundamentos do AWS CDK: Constructs e Stacks</h2>
<p>O AWS CDK (Cloud Development Kit) é um framework que permite definir infraestrutura como código usando linguagens de programação familiar. Um <strong>Construct</strong> é o bloco de construção fundamental — representa um componente de nuvem (EC2, S3, Lambda) ou um agrupamento lógico deles. Você combina Constructs para criar aplicações complexas.</p>
<p>Uma <strong>Stack</strong> é um container que agrupa Constructs e mapeia para um CloudFormation template. Cada Stack pode ser deployada independentemente. Vamos ver como estruturar isso:</p>
<pre><code class="language-typescript">import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as lambda from 'aws-cdk-lib/aws-lambda';
export class StorageStack extends cdk.Stack {
public readonly bucket: s3.Bucket;
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Criando um S3 bucket customizado
this.bucket = new s3.Bucket(this, 'DataBucket', {
versioned: true,
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
removalPolicy: cdk.RemovalPolicy.RETAIN,
});
// Lambda para processar arquivos
const processor = new lambda.Function(this, 'Processor', {
runtime: lambda.Runtime.NODEJS_18_X,
handler: 'index.handler',
code: lambda.Code.fromAsset('lambda'),
});
this.bucket.grantReadWrite(processor);
}
}</code></pre>
<p>Observe como exportamos o bucket para reutilização em outras Stacks. Isso é essencial para composição.</p>
<h2>Constructs Avançados e Composição</h2>
<p>Constructs de alto nível (L3) encapsulam lógica complexa em abstrações reutilizáveis. Em vez de gerenciar IAM, VPC e segurança manualmente, você constrói Constructs customizados que herdam de <code>Construct</code> base.</p>
<pre><code class="language-typescript">import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as iam from 'aws-cdk-lib/aws-iam';
interface SecureWebServerProps extends cdk.StackProps {
instanceType: ec2.InstanceType;
machineImage: ec2.IMachineImage;
}
export class SecureWebServer extends cdk.Stack {
constructor(scope: cdk.App, id: string, props: SecureWebServerProps) {
super(scope, id, props);
const vpc = new ec2.Vpc(this, 'VPC', {
maxAzs: 2,
cidrMask: 24,
});
const securityGroup = new ec2.SecurityGroup(this, 'SG', {
vpc,
description: 'Security group for web server',
allowAllOutbound: true,
});
securityGroup.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(80),
'Allow HTTP'
);
const instance = new ec2.Instance(this, 'Instance', {
vpc,
instanceType: props.instanceType,
machineImage: props.machineImage,
securityGroup,
});
new cdk.CfnOutput(this, 'InstanceIP', {
value: instance.instancePublicIp,
});
}
}</code></pre>
<p>O padrão aqui é aceitar um <code>props</code> interface para configurabilidade. Isso permite que sua Stack seja parametrizada e reutilizável em múltiplos contextos.</p>
<h2>CDK Pipelines: CI/CD Declarativo</h2>
<p>O <strong>CDK Pipelines</strong> é o padrão mais poderoso: você define seu pipeline de deployment como código. O pipeline é autossuficiente — ele se autodeploya e sincroniza com seu repositório.</p>
<pre><code class="language-typescript">import * as cdk from 'aws-cdk-lib';
import * as codepipeline from 'aws-cdk-lib/aws-codepipeline';
import * as codepipeline_actions from 'aws-cdk-lib/aws-codepipeline-actions';
import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines';
export class PipelineStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const pipeline = new CodePipeline(this, 'Pipeline', {
pipelineName: 'MyAppPipeline',
synth: new ShellStep('Synth', {
input: CodePipelineSource.gitHub('seu-user/seu-repo', 'main', {
authentication: cdk.SecretValue.secretsManager('github-token'),
}),
commands: [
'npm install',
'npm run build',
'npx cdk synth',
],
}),
});
// Estágio de desenvolvimento
const devStage = pipeline.addStage(
new ApplicationStage(this, 'Dev', {
env: { account: '111111111111', region: 'us-east-1' },
})
);
devStage.addPost(
new ShellStep('TestDev', {
commands: [
'npm install',
'npm test',
],
})
);
// Estágio de produção com aprovação manual
const prodStage = pipeline.addStage(
new ApplicationStage(this, 'Prod', {
env: { account: '222222222222', region: 'us-east-1' },
})
);
prodStage.addPre(
new codepipeline_actions.ManualApprovalAction({
actionName: 'ApproveProduction',
}) as any
);
}
}
export class ApplicationStage extends cdk.Stage {
constructor(scope: cdk.Construct, id: string, props?: cdk.StageProps) {
super(scope, id, props);
new StorageStack(this, 'Storage');
new SecureWebServer(this, 'WebServer', {
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO),
machineImage: ec2.AmazonLinuxImage.latestAmazonLinux2(),
} as any);
}
}</code></pre>
<p>O pipeline sincroniza automaticamente com seu repositório GitHub. Quando você faz push, o synth executa, gera o CloudFormation e deploya os estágios sequencialmente. Adicione testes, aprovações manuais e validações conforme necessário.</p>
<h2>Boas Práticas e Patterns</h2>
<h3>Separação de Responsabilidades</h3>
<p>Organize seu código em múltiplos arquivos: uma Stack por arquivo, Constructs customizados isolados, configurações centralizadas. Isso torna projetos escaláveis.</p>
<h3>Contexto e Configuração</h3>
<p>Use valores de contexto para parametrizar comportamentos sem hardcode:</p>
<pre><code class="language-typescript">const isDev = this.node.tryGetContext('env') === 'dev';
const bucketRetention = isDev ? cdk.RemovalPolicy.DESTROY : cdk.RemovalPolicy.RETAIN;</code></pre>
<h3>Validação em Tempo de Síntese</h3>
<p>Valide Constructs durante a síntese para falhar rápido:</p>
<pre><code class="language-typescript">if (!props.domainName) {
throw new Error('domainName é obrigatório');
}</code></pre>
<h2>Conclusão</h2>
<p>Dominar AWS CDK exige entender três pilares: <strong>Constructs</strong> como blocos reutilizáveis com responsabilidades bem definidas, <strong>Stacks</strong> como unidades de deployment lógicas e compostas, e <strong>CDK Pipelines</strong> como a ferramenta que automatiza e torna repetível todo o ciclo de infraestrutura-como-código. Comece com Stacks simples, evolua para Constructs customizados de alto nível, e implemente pipelines quando sua infraestrutura crescer. O poder real vem da composição: Constructs dentro de Stacks dentro de Stages dentro de Pipelines.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://docs.aws.amazon.com/cdk/" target="_blank" rel="noopener noreferrer">AWS CDK Documentation</a></li>
<li><a href="https://docs.aws.amazon.com/cdk/v2/guide/cdk_pipeline.html" target="_blank" rel="noopener noreferrer">AWS CDK Pipelines Guide</a></li>
<li><a href="https://github.com/aws-samples/aws-cdk-examples" target="_blank" rel="noopener noreferrer">CDK Examples Repository</a></li>
<li><a href="https://www.oreilly.com/library/view/infrastructure-as-code/9781491924334/" target="_blank" rel="noopener noreferrer">Infrastructure as Code: Dynamic Systems for the Cloud Age - Kief Morris</a></li>
</ul>