Bom pessoal, como eu já adiantei na aula anterior, nessa aula nós criaremos o projeto que será a reescrita daquilo que nós fizemos em Terraform. Então nós vamos criar ali o módulo de Network e o módulo de Cluster. O objetivo dessa aula é que a gente consiga pelo menos fazer o deploy da nossa page. Beleza? Mas antes de nós começarmos de fato, eu gostaria simplesmente de complementar a aula anterior mostrando como nós conseguimos excluir aquele que nós provisionamos utilizando o cdk. Isso é bem simples, tá? Nós temos aqui o comando cdk deploy, que nós já vimos como funciona. Agora, para nós excluirmos uma stack, basta nós substituirmos deploy por destroy. E dessa forma, nós vamos excluir essa stack específica. Caso haja somente uma stack, você nem mesmo precisa especificar o nome da stack. Então, vamos excluir aqui essa stack. Vamos navegar até o CloudFormation para nós vermos. Na verdade, primeiro nós precisamos te dar uma confirmação aqui no nosso comando. Então, nós vamos colocar aqui um yes. Opa, yes. Beleza, agora sim está sendo excluído esse recurso. Nós podemos acompanhar os eventos aqui na nossa própria stack E aqui nós já temos algo interessante, tá? Que é o status de delete skipped para o nosso bucket Isso quer dizer que o bucket não foi excluído Nós excluímos a stack, porém o bucket permaneceu Existem alguns recursos que quando nós criamos através do CDK Ele adiciona uma flag, uma marcação, dizendo que aquele recurso, mesmo quando a stack for criada, ou for excluída, melhor dizendo, esse recurso não pode ser excluído, ele deve ser mantido, o que em muitos casos faz sentido. Então, às vezes nós temos um bucket onde nós colocamos várias informações que precisam ser mantidas ali por um período de 5 anos, por exemplo, por questões legais, mas nós já não estamos utilizando aqueles recursos provisionados. E nós precisamos simplesmente manter os arquivos que estão no bucket. Então, manter esta flag aqui faz sentido, porque nós excluímos todos os recursos e mantemos os nossos dados, as nossas informações. Se eu não me engano, quando nós criamos banco de dados através dessas stacks, acontece a mesma coisa. Apesar de que muitas vezes não é recomendado nós criarmos banco de dados através do CloudFormation, por exemplo, porque geralmente o ciclo de vida de um banco de dados é diferente do ciclo de vida dos recursos da aplicação. Então, nós precisamos estar atentos a isso. No nosso caso aqui, o bucket foi mantido, mas o metadata, por exemplo, aqui do CDK foi excluído e a própria stack foi excluída. Se nós tivéssemos outros recursos, também seriam excluídos. Nós podemos observar isso aqui no nosso template. Então, nós podemos navegar até template, onde nós temos o template CloudFormation em JSON e aqui nós temos o deletionPolicy igual a retain. Quando nós temos aqui esse cara, quer dizer que o recurso ele será mantido mesmo após a exclusão da stack e esse deletionPolicy é adicionado automaticamente pelo CDK. Bom, nesse caso, basta nós navegarmos aqui até o nosso serviço S3, procurarmos pelo bucket e fazermos a exclusão manual, tá? Então, vamos excluir, para isso nós precisamos informar o nome do bucket e confirmar. E beleza, agora nós já não temos mais esses recursos provisionados aqui. Agora nós vamos voltar aqui ao nosso VS Code e nós vamos trabalhar no nosso novo projeto, tá? Eu já criei um projeto, fazendo ali o mesmo que eu fiz na aula anterior, executando os mesmos passos, faça aí do seu lado, o nome que eu dei para o projeto é website, e aqui dentro nós temos já a nossa stack, tá? O website stack, que está vazio, na verdade eu até já excluí aqueles comentários, sugiro que você faça o mesmo, e excluir aqueles comentários, sugiro que você faça o mesmo, e excluir também os comentários aqui do arquivo app.py. Beleza? Então vamos lá. Bom, primeiro nós vamos criar ali os recursos de network, os recursos de rede. E nós vamos seguir o mesmo padrão que nós seguimos no Terraform, nós vamos criar um módulo. E uma forma que nós podemos representar aquele módulo em Terraform aqui em Python, utilizando o CDK, é criando uma classe. Então, nós faremos isso, tá? Eu vou adicionar aqui um novo diretório dentro de websites e nós teremos aqui modules. Beleza. E aqui nós teremos um novo arquivo que será o arquivo network.py e eu vou colocar aqui também um arquivo network.py e eu vou colocar aqui também um arquivo init. Beleza, temos aqui já este arquivo network e nós vamos criar agora uma classe. E essa classe vai receber todos os parâmetros que nós esperamos receber aqui para este módulo, assim como nós fizemos também no Terraform. Então, para nós relembrarmos, vamos só dar uma olhada aqui, antes de nós começarmos a codificar, como nós criamos o nosso módulo de network. Nós temos aqui primeiras variáveis que nós recebemos, tá? Então, nós recebemos um prefixo que vai ser ali simplesmente o nome que nós vamos adicionar ao nome de cada um dos recursos provisionados, para que a gente não confunda os recursos quando nós reutilizarmos este módulo em outras stacks ou em outros projetos. Então nós temos este prefixo, nós vamos ter aqui o CIDER block da VPC e o CIDER block das nossas subnets. Então temos estas três variáveis e aqui no nosso módulo nós temos o seguinte vamos abrir aqui mem.tf nós provisionamos uma vpc nós provisionamos aqui subnet de acordo com a lista que nós enviamos de CIDER Blocks então se essa lista possui cinco CIDER Blocks nós teremos cinco subnets, fazemos associação com a vpc, associamos também com uma availability zone específica, nós criamos o Internet Gateway, porque nós precisamos de acesso à internet, nós criamos uma route table que já possui uma rota que direciona todo o tráfego para esse Internet Gateway, nós temos aqui também uma associação dessa route table com a nossa subnet, com cada uma das nossas subnets, na verdade, para que todas elas tenham acesso à internet. Em seguida, nós criamos um security group, que vai permitir tanto o tráfego na porta 22, como também na porta 80, e nós temos aqui as regras de saída, permitindo saída para qualquer IP. Então, beleza, temos esses recursos e precisamos de provisioná-los agora em CDK. Então, aqui nós vamos criar a definição da nossa classe e nós teremos um construtor onde nós iremos receber todos esses argumentos. Então, eu vou copiar aqui para nós darmos uma olhada, para nós entendermos. Temos aqui, então, o Class Network. Nós temos aqui a nossa stack, tá? Porque a ideia é nós reutilizarmos essa classe, utilizarmos este módulo de network. Então nós teremos os nossos recursos sendo associados a diferentes stacks. Agora nós vamos criar aqui uma network para a nossa stack de website, mas nós podemos ter ali uma outra stack chamada worker, por exemplo e nós queremos criar uma network específica também para este worker na verdade e aí nós teremos aqui uma outra stack nós vamos ter aqui o prefixo o bloco sider da nossa VPC e os blocos siders das nossas subnets deixa eu já fazer aqui o import de tudo aquilo que nós vamos precisar. Beleza? Nós vamos aqui utilizar stack, AWS EC2, o FN e o CFM tag. Daqui a pouco nós falaremos sobre cada um desses carinhas aqui. Bom, em primeiro lugar, nós criaremos então a nossa VPC. Será da seguinte forma. Eu já vou copiar aqui o código para nós não perdermos muito tempo, e nós utilizamos aqui o CFN VPC dentro deste módulo EC2, e nós passamos aqui a nossa stack, que vem como parâmetro, passamos o identificador do nosso recurso, lembrando que este aqui não é o nome do recurso, ele é o identificador que depois é colocado lá no arquivo CloudFormation, então se nós olharmos, por exemplo, o template CloudFormation que nós criamos, este ID é o ID aqui da linha 5, que identifica o recurso mais que arbitrário, ele não tem nenhum significado para o recurso em si, mas sim para o template para identificar o recurso dentro deste template. Então, temos aqui, estamos concatenando o prefix com o VPC, passamos o CIDR block, informamos a tag name, e é exatamente aquilo que nós fizemos também na nossa VPC aqui no Terraform. Aqui nós colocamos, nós chamamos de VPC, nós estamos passando o CIDER block e estamos criando uma tag. Então, bem semelhante. E nós veremos que todos os recursos que nós provisionamos utilizando o CDK, eles seguem esse mesmo padrão. Primeiro nós informamos da stack, se nós estivermos criando dentro da própria stack, nós passaremos o self aqui, por exemplo, mas não é esse o caso. Então, nós colocamos stack aqui Um id e depois os atributos Então, perfeito, já temos aqui a nossa VPC Em seguida nós criaremos o nosso Internet Gateway, tá? Então nós faremos aqui a criação do nosso Internet Gateway Que é bem simples Basta nós informarmos a stack e o id, tá? Aqui nós não conseguimos associar diretamente com a VPC. Para isso, nós precisamos de um outro recurso. E este recurso é justamente o CFNVPCGatewayAttachment. Então, nós precisamos de criar este recurso simplesmente para associar o Internet Gateway com a nossa VPC. Aqui nós passamos a VPC e aqui nós passamos qual é o Internet Gateway com a nossa VPC. Aqui nós passamos a VPC e aqui nós passamos qual que é o Internet Gateway. Você pode observar que eu não estou atribuindo esse cara a nenhuma variável porque nós não precisamos de referenciar esse attachment em outro lugar, tá? E aqui também eu não estou colocando essa variável como sendo uma propriedade porque nós não vamos precisar referenciar o Internet Gateway fora aqui do módulo, tá? Então, nós podemos deixar aqui como sendo privado deste método. Já a VPC, nós colocamos aqui self.vpc, e aqui nós expomos esta propriedade para que a gente consiga referenciar depois, já que nós vamos precisar dessa VPC. Em seguida, nós vamos criar a nossa Route Table, tá? É bem simples, nós temos aqui simplesmente uma associação com a VPC, basta nós dizermos a qual VPC essa Route Table pertence, beleza? E temos, claro, a stack e o ID seguindo sempre o mesmo padrão, tá? E temos, claro, a stack e o ID seguindo sempre o mesmo padrão. Em seguida, nós vamos criar aquela rota default que direciona todo o tráfego para o Internet Gateway. Então, aqui nós informamos qual é a route table que nós acabamos de criar. Nós informamos qual é o Internet Gateway que nós criamos aqui anteriormente. E nós colocamos também o CIDR Block Destination. Então, nós estamos dizendo aqui que qualquer tráfego deve ser direcionado para a Internet Gateway. Beleza. Agora chegou a hora de nós, de fato, criarmos as nossas subnets. Nós faremos o seguinte. Como nós estamos trabalhando com Python, como nós estamos trabalhando com linguagem de código imperativo, nós utilizaremos um for da seguinte forma. Teremos aqui o nosso índice e o nosso bloco, o nosso cyberblock. E nós vamos dar um enumerate aqui nos blocos que nós recebemos como parâmetro. E para cada um desses blocos nós teremos uma subnet. Então será bem simples. nós teremos uma subnet. Então será bem simples. Mas primeiro nós precisamos de identificar ou de obter a AZ a qual nós iremos associar essa subnet. E nós fazemos isso da seguinte forma. Aqui vai ser um pouquinho diferente do que nós vamos identificar a forma onde nós chamamos os data providers. Aqui nós temos o que nós chamamos de funções intrínsecas, onde nós conseguimos ter acesso às nossas subnets. E para isso, nós vamos acessar aqui, então, fn get azes. Esse cara aqui, ele vai nos retornar todas as azes, todas as availability zones da nossa região, da região na qual nós estamos rodando a nossa stack, onde nós criamos a nossa stack. Mas, para nós acessarmos uma dessas azes específicas, nós precisamos aqui do select, desse fn select, onde nós informamos o índice, que pode ser esse índex aqui, e nós podemos atribuir uma variável. Então, essa aqui será a nossa AZ. Provavelmente você já viu um problema, que é o seguinte, e se eu tiver mais blocos do que subnets? Se eu tiver, por exemplo, seis blocos, mas só três subnets? Isso de fato é um problema, e nós utilizamos ali o módulo para nós conseguirmos trabalhar aqui com esses cenários, mas aqui eu não encontrei uma forma simples de nós obtermos a quantidade de azis. Apesar de nós termos aqui esse get azis, que deveria retornar uma lista de todas as azis, o comportamento dessas funções intrínsecas é um pouco complicado de nós trabalharmos com eles, porque essas funções são chamadas no momento em que o deploy da stack está sendo realizado, então após a sintetização do arquivo CloudFormation. Então, para isso, eu vou colocar aqui uma variável que eu vou chamar de maxAz E eu vou atribuir 3, tá? Então, eu sei que na região que eu vou fazer o deploy, eu tenho pelo menos 3 Az Na verdade, eu tenho 4, mas eu vou colocar que nós criaremos subnets Nessas 3 diferentes zonas de disponibilidade, tá? E aí eu vou fazer um módulo aqui de index por eixo max aziz, tá? Então, teremos esse valor aqui, hardcode, então você verifique a região onde você está fazendo o deploy, verifique a sua necessidade e coloque aqui a quantidade de aziz máxima com a qual você irá trabalhar, tá? Então, já temos aqui a nossa aziz, agora basta nós criarmos a nossa subnet, tá? Nós faremos isso. Nós criaremos aqui uma variável subnet, utilizamos esse construtor, esse CFN subnet, passamos aqui agora o nosso ID, mas colocando também o índice, tá? Já que nós iremos criar várias subnets, nós informamos a AZ, o VPC, o nosso CIDR Block, informamos também um nome para a nossa subnet. Além disso, nós faremos uma associação com a nossa route table. Nós precisamos dizer que esses dois componentes estão associados, a nossa route table e a nossa subnet. Dessa forma, nós garantimos que a subnet terá acesso à internet. nós garantimos que a subnet terá acesso à internet. E por fim, nós teremos aqui também uma propriedade subnets, para que a gente consiga expor essas subnets, para que a stack que estiver utilizando esse módulo consiga acessar essas subnets. Então nós vamos adicionar dentro dessa lista, nós vamos dar um append aqui, e vamos adicionar a nossa subnet que nós acabamos de criar. Beleza, já temos aqui então as nossas subnets. E agora por fim nós precisamos de criar o nosso security group. Relembrando, esse security group permite acesso na porta 22, na porta 80 e também permite acesso de saída para qualquer endereço IP. Então, nós vamos aqui ter um self-security group. Utilizamos o CFN Security Group. Damos um nome para o nosso security group e uma descrição. Aqui eu coloquei o prefixo, alá o SSH e HTTP, que são os dois protocolos que nós estamos aqui permitindo. E nós temos a nossa VPC, a associação com a VPC. E agora nós temos as regras de fato. Temos aqui o nosso CIDR block, temos a liberação da porta 22, o protocolo IP é o TCP. E damos uma descrição aqui de ALAU SSH. É o TCP e damos uma descrição aqui de ALAU SSH e a mesma coisa também para a porta 80 e a descrição é ALAU HTTP. E por fim nós permitimos acesso de saída para qualquer endereço. E beleza, temos aqui já o nosso módulo, já temos tudo criado. Agora para nós utilizarmos esse mulo, basta nós instanciarmos ele na nossa stack, o que é algo bem simples. Então, nós teremos aqui network, vamos importar este cara, né? Então, from modules.network, nós vamos importar aqui a nossa classe network e vamos instanciá-la. Aqui nós precisamos passar na nossa stack, que é a própria classe, nós vamos passar um prefixo, nós podemos receber como parâmetro, tá? Vamos colocar aqui como sendo um parâmetro, eu vou colocar aqui prefixo, beleza? E aqui, agora sim, nós podemos passar prefixo igual a prefixo. Nós precisamos informar também o nosso bloco. Nós vamos colocar aqui como sendo 10.0.0.0.16. Teremos um barra 16. E aqui nós teremos também a lista de blocos das nossas subnetas. Nós teremos primeiro 10.0.0.0.24, teremos um outro barra 24 aqui, beleza, porém a máscara será diferente. Perfeito, temos aqui já todos os parâmetros definidos. Vamos voltar até o nosso app.py, agora nós precisamos aqui de informar um parâmetro adicional, que é o nosso prefixo, e aqui nós vamos colocar website. Dessa forma. E aparentemente nós já temos aqui tudo o que nós precisamos. Nós não precisamos importar este carinha aqui. Beleza. Agora nós podemos testar. Beleza, agora nós podemos testar, então eu vou aqui criar um novo terminal, perfeito, vou navegar até cdk-website e agora nós vamos rodar primeiro cdk-ls para nós listarmos as stacks que nós temos, nós temos uma única stack, website stack, beleza, confirmamos que está tudo certo. E agora nós podemos também dar uma olhada no CloudFormation gerado por este projeto. Então nós podemos aqui direcionar o output da nossa sintetização para o arquivo template.yaml. Nós já temos aqui, não nesse diretório, né? Então vamos aqui criar este arquivo beleza, vamos esperar agora sim, nós já temos aqui o nosso arquivo CloudFormation que foi sintetizado a partir do nosso projeto CDK aqui nós estamos criando a nossa VPC com o CiderBlock especificado com o nome especificado temos aqui o nosso Internet Gateway bem simples, não tem nenhuma propriedade, agora nós fazemos o attachment, nós anexamos esse internet gateway na nossa VPC, então aqui nós informamos o internet gateway e informamos a VPC, criamos uma route table, criamos aqui uma rota para a internet, para direcionar todo o tráfego para o nosso internet gateway, e criamos as nossas subnets. Então, nós selecionamos aqui primeiro a subnet no índice, ou melhor dizendo, a availability zone no índice 0, para nós pegarmos a primeira AZ. Aqui o nosso slider block está correto, nós temos um nome também para a nossa subnet, aqui nós temos a associação da subnet com a route table, e em seguida nós fazemos a mesma coisa, porém agora para outra subnet, tá? Aqui nós selecionamos a segunda AZ, o índice 1, e temos o nosso ciberblock também corretamente definido. Temos a associação da route table com a subnet, e por fim nós criamos o nosso security group com todas as regras de egress e ingress e é isso, logo depois nós temos os metadata do nosso projeto CDK e os conditions sobre os quais nós não precisamos nos preocupar, tá? Beleza, nós podemos inclusive excluir aqui esse arquivo template, não precisamos dele foi simplesmente para nós verificarmos. Mas, agora é a hora da verdade. Nós precisamos aqui fazer o deploy desse stack. Temos um único stack. Não vou colocar o nome. Vou só especificar o meu profile. Default. Beleza. E, como sempre, o deploy desses componentes costuma demorar um pouquinho. Então, eu vou pausar a aula e depois nós voltamos quando o deploy foi finalizado. Aqui está, após 43 segundos o deploy foi finalizado, nós podemos navegar aqui até o nosso CloudFormation e verificar a nossa stack, tá? Então nós temos aqui inclusive o template, temos todos os eventos, nós podemos ver que todos eles são de sucesso e nós temos também todos os recursos criados. Vamos navegar até a nossa VPC, nós podemos navegar por aqui. Vamos clicar aqui, temos já a nossa VPC, podemos clicar, nós temos o nosso Resource Map que mostra aqui as duas subnets que nós criamos, essas subnets estão associadas a uma Route Table. Quando nós criamos aqui a nossa subneta, já temos uma route table por default, ou melhor, quando nós criamos a VPC já temos uma route table por default, mas nós criamos uma outra que direciona para o nosso Internet Gateway. E nós temos também o nosso Security Group, tá? Então, vamos verificar aqui, cadê o Security Group? Beleza, Security Group. nosso security group, tá? Então, vamos verificar aqui, cadê o security group, beleza, security group, e aqui nós temos o website allow SSH e HTTP com dois inbound rules permitindo aqui o SSH e o HTTP e com um outbound rules permitindo todo o tráfego, beleza? Então, dessa forma nós vimos como nós podemos criar um módulo em CDK e como nós conseguimos utilizá-lo. Então se nós criássemos ali outras stacks, outras aplicações nesse mesmo projeto, nós poderíamos simplesmente instanciar essa classe network passando os parâmetros necessários e todos esses recursos já estariam disponíveis para nós. Espero que você tenha gostado e vejo você na nossa próxima aula.