O que é o AWS CDK, e para que serve?

Olá, pessoal. Tudo bem?

Quem já trabalhou com CloudFormation, Terraform ou outra ferramenta de IaC, que forneça uma linguagem declarativa para escrevermos infraestrutura como código, sabe o quão útil elas são, mas também sabe o quão complexos e inflexível os templates criados por estas linguagens podem se tornar.

O AWS CDK (Cloud Development Kit) foi criado para endereçar estes problemas. O framework está disponível hoje em algumas das linguagens mais usadas no mercado (atualmente C#, Python, Java, Javascript e Typescript), permitindo a construção de estruturas de IaC com maior flexibilidade, utilizando todo o poder destas linguagens (loops, estruturas condicionais, etc).

Como o CDK funciona?

Basicamente, o CDK é formado por três estruturas elementares:

  • Constructs: Constructs são a base de todos os componentes do CDK;
  • Stacks: São constructs que permitem o provisionamento de coleções de recursos de forma unitária (Cloudformation stacks);
  • Apps: Permitem o agrupamento e deploy de stacks dentro de um mesmo contexto e ciclo de vida.
AWS CDK

O CDK fornece uma CLI para podermos gerir nossos projetos de infraestrutura. Alguns dos principais comandos são:

  • init: Cria um projeto do CDK baseado em um template;
  • synth: Sintetiza templates do CloudFormation a partir do app;
  • deploy: Efetua o deploy do app na AWS, através do CloudFormation;
  • destroy: Destrói as stacks na AWS.

Abaixo segue um exemplo para facilitar a visualização. Ele pode parecer pouco comum, visto que usei C# (minha linguagem favorita) para escrever meu projeto, mas é só por diversão. 😁

var vpc = new Vpc(this, "MainVPC", new VpcProps
{
    Cidr = "192.168.0.0/16"
});

var loadBalancer = new ApplicationLoadBalancer(this, "PublicALB", new ApplicationLoadBalancerProps
{
    InternetFacing = true,
    Vpc = vpc
});

var listener = loadBalancer.AddListener("MyListener", new ApplicationListenerProps
{
    Port = 80
});

var userData = UserData.ForLinux(new LinuxUserDataOptions
{
    Shebang = "#!/bin/bash"
});

userData.AddCommands(
    "yum update -y",
    "yum install httpd -y",
    "echo \"Hello World\" >> /var/www/html/index.html",
    "service httpd start",
    "chkconfig httpd on");


var ec2SG =  new SecurityGroup(this, "Ec2SecurityGroup", new SecurityGroupProps
{
  Vpc  = vpc,
  SecurityGroupName = "Ec2SG"
});

ec2SG.Connections.AllowFrom(loadBalancer, Port.Tcp(80), "FROM ALB");

var instanceIds = new List<string>();
for(var ix = 0; ix < vpc.PrivateSubnets.Length;ix++)
{
    var instance = new Instance_(this, $"Instance-{ix}", new InstanceProps
    {
        InstanceType = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.MICRO),
        VpcSubnets = new SubnetSelection()
        {
            SubnetType = SubnetType.PRIVATE
        },
        AvailabilityZone = vpc.PrivateSubnets[ix].AvailabilityZone,
        Vpc = vpc,
        MachineImage = new AmazonLinuxImage(),
        UserData = userData,
        KeyName = "test-cdk",
        SecurityGroup = ec2SG
    } );
    
    instanceIds.Add(instance.InstanceId);
}

listener.AddTargets("Targets", new AddApplicationTargetsProps
{
    Port = 80,
    Targets = instanceIds.Select(i => new InstanceIdTarget(i, 80)).ToArray()
});

No exemplo acima, construiremos a estrutura abaixo:

Estrutura gerada pelo exemplo acima

Um ponto interessante que acredito valer a pena comentar, é que na primeira linha, quando críamos a VPC, o CDK já cria subnets públicas e privadas nas AZs disponíveis, faz o deploy de um NAT Gateway em cada uma das subnet públicas, e também do Internet Gateway, das Route Tables, etc, criando uma estrutura padrão para utilizarmos. O melhor é que podemos customizar tudo isso, caso este modelo não sirva para o nosso propósito.

Gostaria também de ressaltar a linha 39, onde utilizamos um for loop para criar uma instância EC2 em cada subnet privada. Essa é uma construção que as linguagens declarativas existentes (ao menos as que conheço) não possibilitam.

Para quem quiser ver mais, o exemplo está no Github. Sugiro mandar sintetizar o CloudFormation, e verificar a quantidade de linhas geradas no template (A diferença é enorme).

E se a biblioteca do CDK não possuir o construct para o serviço que necessito?

Ok, sem problemas. É possível incorporar código do CloudFormation diretamente dentro do CDK. Exemplo:

new CfnResource(this, "SSLCertificate", new CfnResourceProps
{
    Type = "AWS::CertificateManager::Certificate",
    Properties = new Dictionary<string, object>
    {
        ["DomainName"] = "mydomain.com"
    }
});     

Ok, mas eu não poderia utilizar o SDK da AWS diretamente?

Se alguém está se perguntando se poderíamos usar o SDK da AWS sem o CDK, a resposta é, sim, você pode construir seus próprios artefatos usando o SDK. Contudo, o CDK traz algumas vantagens em relação a isso, como:

  1. Uma série de comandos prontos criados pela AWS, que permitem o provisionamento de estruturas complexas com poucas linhas de comando;
  2. Como vimos, no final ele transforma tudo em templates do CloudFormation, a ferramenta oficial da AWS para IaC. Por isso herdamos todas as vantagens do mesmo em relação ao provisionamento através da SDK, como rastreabilidade, gerenciamento dos recursos de forma unitária e detecção de drifts na infraestrutura;

Não tive a oportunidade de utilizar o CDK exaustivamente ainda, mas até o momento a experiência está sendo muito boa, com bastante praticidade e produtividade.

Para aqueles que já utilizam, o que vocês estão achando? Deixem seus comentários abaixo.

Forte abraço e até a próxima.

Postado em AWS

Deixe uma resposta