AWS Admin

O que Todo Dev Deve Saber sobre AWS CDK Avançado: Constructs, Stacks e Pipelines com CDK Pipelines Já leu

Fundamentos do AWS CDK: Constructs e Stacks O AWS CDK (Cloud Development Kit) é um framework que permite definir infraestrutura como código usando linguagens de programação familiar. Um Construct é 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. Uma Stack é um container que agrupa Constructs e mapeia para um CloudFormation template. Cada Stack pode ser deployada independentemente. Vamos ver como estruturar isso: Observe como exportamos o bucket para reutilização em outras Stacks. Isso é essencial para composição. Constructs Avançados e Composição 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 base. O padrão aqui é aceitar um interface para configurabilidade. Isso permite que sua Stack seja parametrizada e reutilizável em múltiplos contextos. CDK Pipelines: CI/CD Declarativo O CDK Pipelines é o padrão mais

Fundamentos do AWS CDK: Constructs e Stacks

O AWS CDK (Cloud Development Kit) é um framework que permite definir infraestrutura como código usando linguagens de programação familiar. Um Construct é 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.

Uma Stack é um container que agrupa Constructs e mapeia para um CloudFormation template. Cada Stack pode ser deployada independentemente. Vamos ver como estruturar isso:

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);
  }
}

Observe como exportamos o bucket para reutilização em outras Stacks. Isso é essencial para composição.

Constructs Avançados e Composição

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 Construct base.

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,
    });
  }
}

O padrão aqui é aceitar um props interface para configurabilidade. Isso permite que sua Stack seja parametrizada e reutilizável em múltiplos contextos.

CDK Pipelines: CI/CD Declarativo

O CDK Pipelines é 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.

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);
  }
}

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.

Boas Práticas e Patterns

Separação de Responsabilidades

Organize seu código em múltiplos arquivos: uma Stack por arquivo, Constructs customizados isolados, configurações centralizadas. Isso torna projetos escaláveis.

Contexto e Configuração

Use valores de contexto para parametrizar comportamentos sem hardcode:

const isDev = this.node.tryGetContext('env') === 'dev';
const bucketRetention = isDev ? cdk.RemovalPolicy.DESTROY : cdk.RemovalPolicy.RETAIN;

Validação em Tempo de Síntese

Valide Constructs durante a síntese para falhar rápido:

if (!props.domainName) {
  throw new Error('domainName é obrigatório');
}

Conclusão

Dominar AWS CDK exige entender três pilares: Constructs como blocos reutilizáveis com responsabilidades bem definidas, Stacks como unidades de deployment lógicas e compostas, e CDK Pipelines 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.

Referências


Artigos relacionados