O autor selecionou a Fundação Wikimedia para receber uma doação como parte do programa Escreva para Doações.
Introdução
A Infraestrutura como Código (IaC) é uma prática de automatização da implantação e modificações da infraestrutura, definindo os estados dos recursos e suas relações em código. A execução desse código então cria ou modifica os recursos reais na nuvem. A IaC permite aos engenheiros utilizar uma ferramenta de IaC como o Terraform (da HashiCorp) para o provisionamento da infraestrutura.
Com a IaC, as mudanças em sua infraestrutura podem passar pelo mesmo processo de revisão de código que o código de sua aplicação. Você pode armazenar o código em controle de versão (como o Git) para manter um histórico do estado de sua infraestrutura, e pode automatizar ainda mais o processo de implantação com ferramentas de nível superior, como uma plataforma interna de desenvolvimento self-service (IDP).
Terraform é uma ferramenta popular de IaC (Infraestrutura como Código) agnóstica de plataforma devido ao seu amplo suporte para muitas plataformas, incluindo o GitHub, Cloudflare e DigitalOcean. A maioria das configurações do Terraform é escrita usando uma linguagem declarativa chamada de HashiCorp Configuration Language (HCL).
O Kit de Desenvolvimento em Nuvem para Terraform (CDKTF) é uma ferramenta construída em cima do Terraform que permite definir infraestrutura usando uma linguagem de programação familiar (como TypeScript, Python ou Go) em vez de HCL. Esta ferramenta pode proporcionar uma curva de aprendizado mais suave para desenvolvedores não familiarizados com HCL, ao mesmo tempo em que permite que os desenvolvedores usem recursos nativos de programação como loops, variáveis e funções.
Neste tutorial, você começará instalando a ferramenta de linha de comando (CLI) cdktf
. Em seguida, você criará um projeto CDKTF em TypeScript e definirá o projeto com dois servidores NGINX balanceados por um balanceador de carga. Em seguida, você usará o cdktf
para implantar a infraestrutura. No final deste tutorial, você terá um projeto CDKTF a partir do qual poderá expandir sua infraestrutura.
Observação: Este tutorial foi testado com CDKTF 0.11.2
e Terraform 1.2.2
.
Pré-requisitos
Para concluir este tutorial, você precisará de:
- A good understanding of Infrastructure-as-Code (IaC). You can learn about IaC in Infrastructure as Code Explained.
- A DigitalOcean account. If you do not have one, sign up for a new account.
- A DigitalOcean Personal Access Token, which you can create via the DigitalOcean console. Instructions on how to do that can be found at How to Generate a Personal Access Token.
- A password-less SSH key added to your DigitalOcean account. You can add that by following How To Use SSH Keys with DigitalOcean Droplets. When you add the key to your account, remember the name you give it, as you will need it in this tutorial. For CDKTF to accept the name of your key, it must start with a letter or underscore and may contain only letters, digits, underscores, and dashes.
- O Terraform instalado em sua máquina local, o qual você pode configurar com o “Passo 1 – Instalando o Terraform” em Como Usar o Terraform com a DigitalOcean.
- O Node.js instalado em sua máquina local. Você pode encontrar instruções para isso na série Como Instalar o Node.js e Criar um Ambiente de Desenvolvimento Local.
- Se sentir confortável programando em JavaScript. Para desenvolver suas habilidades, confira a série Como Programar em JavaScript.
- Se sentir confortável usando os recursos básicos do TypeScript. Se você não estiver familiarizado com TypeScript, o tutorial da série Como Programar em TypeScript é um bom recurso para ajudá-lo a se familiarizar.
- A code editor or integrated development environment (IDE) that supports TypeScript. If you are not currently using one, try Visual Studio Code. You can also read up on How To Work With TypeScript in Visual Studio Code.
Passo 1 — Instalando a CLI cdktf
Para começar, você irá instalar a ferramenta de linha de comando cdktf
.
A CLI cdktf
está disponível como um pacote NPM. Se você pesquisar por cdktf
no npmjs.com, encontrará dois pacotes com nomes semelhantes: cdktf
e cdktf-cli
.
Conceitualmente, o CDKTF é uma camada de abstração sobre o Terraform. Ele consiste em duas partes:
- uma biblioteca contendo um conjunto de construções nativas da linguagem (como funções e classes) para definir infraestrutura. Esta parte é encapsulada dentro do pacote npm
cdktf
. Por exemplo, você pode ver o uso das classesApp
eTerraformStack
do pacotecdktf
no seguinte projeto de exemplo CDKTF: -
Um adaptador que analisa os construtos dentro do projeto CDKTF e os reduz a um conjunto de documentos JSON, que são então inseridos no Terraform da mesma forma que o HCL é inserido. Este adaptador é encapsulado em uma ferramenta CLI chamada
cdktf
, fornecida pelo pacotecdktf-cli
.
Para instalar a ferramenta CLI cdktf
, você precisa do pacote cdktf-cli
. Você pode instalar este pacote globalmente usando npm
, yarn
, ou um gerenciador de pacotes de sua escolha.
Para instalar o cdktf-cli
com o npm
, execute o seguinte:
Observação: Provavelmente haverá uma versão mais recente do pacote cdktf-cli
após a publicação deste artigo. Você pode tentar seguir o tutorial com a versão mais recente executando npm install --global cdktf-cli@latest
em vez disso, mas esteja ciente de que algumas saídas podem diferir ligeiramente.
Alternativamente, você pode usar o Homebrew no macOS ou Linux para instalar a CLI cdktf
como a fórmula cdktf
:
Para verificar se a instalação foi bem-sucedida, execute o comando cdktf
sem argumentos:
Você verá uma saída semelhante ao seguinte:
OutputPlease pass a command to cdktf, here are all available ones:
cdktf
Commands:
cdktf init Create a new cdktf project from a template.
cdktf get Generate CDK Constructs for Terraform providers and modules.
cdktf convert Converts a single file of HCL configuration to CDK for Terraform.
cdktf deploy [stacks...] Deploy the given stacks
cdktf destroy [stacks..] Destroy the given stacks
cdktf diff [stack] Perform a diff (terraform plan) for the given stack
cdktf list List stacks in app.
cdktf login Retrieves an API token to connect to Terraform Cloud.
cdktf synth Synthesizes Terraform code for the given app in a directory.
cdktf watch [stacks..] [experimental] Watch for file changes and automatically trigger a deploy
cdktf output [stacks..] Prints the output of stacks
cdktf debug Get debug information about the current project and environment
cdktf completion generate completion script
Options:
--version Mostrar número da versão
--disable-logging Não escrever arquivos de log. Suportado usando o env CDKTF_DISABLE_LOGGING.
--disable-plugin-cache-env Não definir automaticamente TF_PLUGIN_CACHE_DIR.
--log-level Qual nível de log deve ser escrito.
-h, --help Show help
Options can be specified via environment variables with the "CDKTF_" prefix (e.g. "CDKTF_OUTPUT")
A saída mostra os comandos disponíveis. No restante deste tutorial, você ganhará experiência usando cdktf init
, cdktf get
, cdktf deploy
e cdktf destroy
.
Agora que você instalou o CLI cdktf
, você pode definir infraestrutura escrevendo algum código TypeScript.
Passo 2 — Criando um Novo Projeto CDKTF
Neste passo, você usará o CLI cdktf
que acabou de instalar para criar um projeto de modelo CDKTF, no qual você irá construir nos próximos passos.
Crie um diretório que abrigará o projeto CDKTF executando o seguinte comando:
Em seguida, navegue até o diretório recém-criado:
Use o comando cdktf init
para criar um esqueleto de projeto CDKTF no qual você irá trabalhar:
CDKTF permite que os desenvolvedores definam infraestrutura usando TypeScript, Python, Java, C# ou Go. A opção --template=typescript
diz ao cdktf
para criar este projeto CDKTF usando TypeScript.
O Terraform (e, portanto, o CDKTF) acompanha os recursos que está gerenciando registrando suas definições e estados em arquivos chamados arquivos de estado do Terraform. A opção --local
diz ao CDKTF para manter esses arquivos de estado localmente na máquina em que o cdktf
está sendo executado (cada arquivo segue a estrutura de nomeação terraform.<stack>.tfstate
).
Após executar o comando, o CLI pode solicitar sua permissão para enviar relatórios de falhas para a equipe do CDKTF para ajudá-los a melhorar o produto:
Output? Do you want to send crash reports to the CDKTF team? See https://www.terraform.io/cdktf/create-and-deploy/configuration-file for
more information (Y/n)
Digite Y
se desejar consentir ou N
se discordar e pressione ENTER
.
cdktf
então criará o esqueleto do projeto e instalará os pacotes. Quando o projeto estiver esqueletizado, você verá uma saída semelhante à seguinte:
Output Your cdktf typescript project is ready!
cat help Print this message
Compile:
npm run get Import/update Terraform providers and modules (you should check-in this directory)
npm run compile Compile typescript code to javascript (or "npm run watch")
npm run watch Watch for changes and compile typescript in the background
npm run build Compile typescript
Synthesize:
cdktf synth [stack] Synthesize Terraform resources from stacks to cdktf.out/ (ready for 'terraform apply')
Diff:
cdktf diff [stack] Perform a diff (terraform plan) for the given stack
Deploy:
cdktf deploy [stack] Deploy the given stack
Destroy:
cdktf destroy [stack] Destroy the stack
Test:
npm run test Runs unit tests (edit __tests__/main-test.ts to add your own tests)
npm run test:watch Watches the tests and reruns them on change
Upgrades:
npm run upgrade Upgrade cdktf modules to latest version
npm run upgrade:next Upgrade cdktf modules to latest "@next" version (last commit)
Você também verá alguns novos arquivos adicionados ao diretório infra
. Os arquivos mais importantes são cdktf.json
e main.ts
.
cdktf.json
é o arquivo de configuração para o projeto CDKTF. Se você abrir o arquivo, ele exibirá algo como o seguinte:
A propriedade app
define o comando que será executado para sintetizar o código TypeScript em JSON compatível com o Terraform. Esta propriedade indica que main.ts
é o ponto de entrada para o projeto CDKTF.
Se você abrir o arquivo main.ts
, você verá algo semelhante ao seguinte:
Na linguagem do CDKTF, uma coleção de recursos de infraestrutura relacionados pode ser agrupada em um stack. Por exemplo, os recursos que compõem uma aplicação de API, como Droplets, balanceadores de carga e registros DNS, podem ser agrupados em um único stack chamado APIStack
. Cada stack mantém seu próprio estado e pode ser implantado, modificado ou destruído independentemente de outros stacks. Um uso comum de stacks é ter um stack para produção e um stack separado para desenvolvimento.
Uma aplicação é um contêiner para vários stacks. Por exemplo, uma aplicação pode agrupar os stacks de vários microsserviços.
O projeto CDKTF scaffold gerado em main.ts
contém uma única classe de stack chamada MyStack
, atualmente definindo nenhum recurso. Uma instância de MyStack
é criada com o nome infra
, contida dentro de uma aplicação chamada app
. Em etapas subsequentes, você definirá recursos de infraestrutura dentro do construtor de MyStack
.
Após criar o projeto, o próximo passo é configurar o projeto CDKTF com provedores.
Passo 3 — Instalando o Provedor DigitalOcean
Nesta etapa, você instalará o provedor DigitalOcean no projeto CDKTF.
Provedores são bibliotecas que fornecem instruções ao Terraform (que é usado pelo cdktf
nos bastidores) sobre como criar, atualizar e excluir recursos em provedores de nuvem, provedores de software como serviço (SaaS) e outras plataformas que expõem interfaces de programação de aplicativos (APIs). Os provedores encapsulam a lógica de chamada dessas APIs de upstream em funções padrão que o Terraform pode chamar.
Por exemplo, se você fosse criar um novo Droplet DigitalOcean sem o Terraform, teria que enviar uma solicitação POST
para o endpoint /v2/droplets
da API DigitalOcean. Com o Terraform, você instalaria o provedor DigitalOcean e definiria um recurso digitalocean_droplet
, semelhante ao seguinte trecho de código de exemplo:
Em seguida, você pode usar a ferramenta CLI cdktf
para traduzir este código TypeScript em JSON compatível com o Terraform e passá-lo para o provedor, que fará as chamadas de API apropriadas para criar o Droplet em seu nome.
Agora que você entende o que é um provedor, pode configurar o provedor DigitalOcean para o seu projeto CDKTF.
Abra o arquivo cdktf.json
e adicione a string digitalocean/digitalocean
ao array terraformProviders
:
digitalocean/digitalocean
é o identificador do provedor DigitalOcean no Registro do Terraform.
Salve e feche o arquivo.
Em seguida, execute cdktf get
para baixar e instalar o provedor.
cdktf get
irá baixar o provedor, extrair o esquema, gerar as classes TypeScript correspondentes e adicioná-lo como um módulo TypeScript em .gen/providers/
. Essa geração de código automática permite que você use qualquer provedor Terraform e módulos HCL com CDKTF, e é assim que CDKTF pode fornecer autocompletar em editores que o suportam.
Assim que cdktf get
terminar de ser executado, você verá uma saída semelhante à seguinte:
OutputGenerated typescript constructs in the output directory: .gen
Você também verá um novo diretório chamado .gen
contendo o código gerado do provedor.
Neste passo, você instalou o provedor digitalocean/digitalocean
no projeto. No próximo passo, você configurará o provedor DigitalOcean com as credenciais necessárias para autenticar o provedor com a API da DigitalOcean.
Passo 4 — Configurando o Provedor DigitalOcean
Neste passo, você configurará o provedor DigitalOcean com seu Token de Acesso Pessoal da DigitalOcean, que permite que o provedor chame a API da DigitalOcean em seu nome.
Diferentes provedores requerem e suportam credenciais diferentes para autenticar com a API upstream. Para o provedor DigitalOcean, você precisa fornecer seu Token de Acesso Pessoal da DigitalOcean. Você pode especificar o token para o provedor configurando-o como as variáveis de ambiente DIGITALOCEAN_TOKEN
ou DIGITALOCEAN_ACCESS_TOKEN
.
Execute o seguinte comando em seu terminal para definir a variável de ambiente para essa sessão do terminal.
Nota: Ao chamar export
, você está definindo a variável de ambiente apenas para essa sessão do terminal. Se você fechar e reabrir o terminal ou executar os comandos cdktf
em um terminal diferente, será necessário executar o comando export
novamente para que a variável de ambiente entre em vigor.
Em seguida, você especificará o provedor dentro da classe MyStack
, o que permitirá que você defina recursos fornecidos pelo provedor dentro do seu stack. Atualize o arquivo main.ts
para o seguinte:
O módulo para o provedor está localizado em ./.gen/providers/digitalocean
, que foi gerado automaticamente quando você executou cdktf get
.
Você configurou o provedor digitalocean/digitalocean
com credenciais neste passo. Em seguida, você começará a definir a infraestrutura que faz parte do objetivo deste tutorial.
Passo 5 — Definindo Aplicações Web em Droplets
Neste passo, você irá definir dois servidores NGINX, cada um servindo arquivos diferentes, implantados em dois Droplets Ubuntu 20.04 idênticos.
Você começa com a definição dos dois Droplets. Modifique o arquivo main.ts
com as alterações destacadas:
Você utiliza um loop nativo do JavaScript (Array.prototype.map()
) para evitar duplicações no código.
Assim como se estivesse criando o Droplet através do console, existem vários parâmetros a especificar:
image
– a distribuição Linux e a versão na qual seu Droplet será executado.region
– o data center onde o Droplet será executado.size
– a quantidade de recursos de CPU e memória a reservar para o Droplet.name
– um nome único usado para se referir ao Droplet.
Os valores para image
, region
e size
devem ser coisas que o DigitalOcean suporta. Você pode encontrar os valores válidos (chamados de slugs) para todas as imagens de distribuição Linux suportadas, tamanhos de Droplet e regiões na página de Slugs da API do DigitalOcean. Você pode encontrar uma lista completa de atributos obrigatórios e opcionais na página de documentação do digitalocean_droplet
.
Adicionando uma Chave SSH
Como parte dos pré-requisitos, você enviou uma chave pública SSH sem senha para sua conta do DigitalOcean e anotou seu nome. Agora você usará esse nome para recuperar o ID da chave SSH e passá-lo para a definição do seu Droplet.
Como a chave SSH foi adicionada manualmente à sua conta do DigitalOcean, ela não é um recurso gerenciado pela sua configuração atual do Terraform. Se você tentar definir um novo recurso digitalocean_ssh_key
, ele criará uma nova chave SSH em vez de usar a existente.
Em seguida, você irá definir um novo digitalocean_ssh_key
fonte de dados. No Terraform, fontes de dados são usadas para obter informações sobre infraestrutura que não são gerenciadas pela configuração atual do Terraform. Em outras palavras, elas fornecem uma visualização somente leitura do estado da infraestrutura externa pré-existente. Uma vez que uma fonte de dados é definida, você pode usar os dados em outros lugares da sua configuração do Terraform.
Ainda no arquivo main.ts
e dentro do construtor de MyStack
, defina uma nova fonte de dados DataDigitaloceanSshKey
, e passe o nome que você atribuiu à sua chave SSH (aqui, o nome é do_cdktf
):
Em seguida, atualize a definição do Droplet para incluir a chave SSH:
Ao ser provisionado, você pode acessar o Droplet usando uma chave SSH privada em vez de uma senha.
Especificando o Script de Dados do Usuário para Instalar o NGINX
Agora você definiu dois Droplets idênticos executando o Ubuntu, configurados com acesso SSH. A próxima tarefa é instalar o NGINX em cada Droplet.
Quando um Droplet está sendo criado, uma ferramenta chamada CloudInit inicializará o servidor. O CloudInit pode aceitar um arquivo chamado dados do usuário, que pode modificar como o servidor é inicializado. Os dados do usuário podem ser qualquer arquivo cloud-config
ou scripts que o servidor possa interpretar, como scripts Bash.
No restante deste passo, você criará um script Bash e o especificará como os dados do usuário do Droplet. O script instalará o NGINX como parte do processo de inicialização. Além disso, o script também substituirá o conteúdo do arquivo /var/www/html/index.html
(o arquivo padrão servido pelo NGINX) pelo nome do host e endereço IP do Droplet, o que fará com que os dois servidores NGINX sirvam arquivos diferentes. No próximo passo, você colocará ambos esses servidores NGINX atrás de um balanceador de carga; ao servir arquivos diferentes, ficará evidente se o balanceador de carga está distribuindo corretamente as solicitações ou não.
Ainda em main.ts
, adicione uma nova propriedade userData
ao objeto de configuração do Droplet:
Aviso: Certifique-se de que não há novas linhas antes do shebang (#!
); caso contrário, o script pode não ser executado.
Quando o Droplet é provisionado pela primeira vez, o script será executado como usuário root
. Ele usará o gerenciador de pacotes do Ubuntu, APT, para instalar o pacote nginx
. Em seguida, ele usará o Serviço de Metadados da DigitalOcean para recuperar informações sobre si mesmo e escrever o nome do host e o endereço IP em index.html
, que é servido pelo NGINX.
Neste passo, você definiu os dois Droplets executando o Ubuntu, configurou cada um com acesso SSH e instalou o NGINX usando o recurso de dados do usuário. No próximo passo, você definirá um balanceador de carga que ficará na frente desses servidores NGINX e o configurará para balanceamento de carga de forma round-robin.
Passo 6 — Definindo um Balanceador de Carga
Neste passo, você definirá um Balanceador de Carga da DigitalOcean ao definir uma instância do recurso digitalocean_loadbalancer
.
Ainda em main.ts
, adicione a seguinte definição para um balanceador de carga ao final do construtor MyStack
:
O argumento forwardingRule
indica ao balanceador de carga para escutar as solicitações HTTP na porta 80
e encaminhá-las para cada uma das instâncias no Droplet na porta 80
.
Os dropletIds
especificam os Droplets para os quais o balanceador de carga encaminhará as solicitações. Ele aceita um número, mas o valor de droplet.id
é uma string. Portanto, você utilizou a função Fn.tonumber
do Terraform para converter o valor da ID do Droplet de string para número.
Observação: Você utilizou a função Fn.tonumber
do Terraform aqui em vez do parseInt
nativo do JavaScript porque o valor de droplet.id
é desconhecido até que o Droplet seja provisionado. As funções do Terraform são projetadas para operar em valores de tempo de execução desconhecidos antes que o Terraform aplique uma configuração.
Salve e feche o arquivo.
Você agora definiu dois Droplets e um balanceador de carga que fica na frente deles. Seu arquivo main.ts
deve se parecer com isso:
No próximo passo, você usará a ferramenta de linha de comando cdktf
para atualizar seu projeto inteiro do CDKTF.
Passo 7 — Provisionamento da Sua Infraestrutura
Neste passo, você usará a ferramenta CLI cdktf
para provisionar os Droplets e os balanceadores de carga que você definiu nos passos anteriores.
Certifique-se de estar no diretório infra/
e ter definido a variável de ambiente DIGITALOCEAN_ACCESS_TOKEN
para sua sessão no terminal, então execute o comando cdktf deploy
:
Você deve ver uma saída semelhante ao seguinte:
Outputinfra Initializing the backend...
infra Initializing provider plugins...
infra - Reusing previous version of digitalocean/digitalocean from the dependency lock file
infra - Using previously-installed digitalocean/digitalocean v2.19.0
infra Terraform has been successfully initialized!
infra Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
infra # digitalocean_droplet.bar (bar) will be created
+ resource "digitalocean_droplet" "bar" {
+ backups = false
+ created_at = (known after apply)
+ disk = (known after apply)
+ graceful_shutdown = false
+ id = (known after apply)
+ image = "ubuntu-20-04-x64"
+ ipv4_address = (known after apply)
+ ipv4_address_private = (known after apply)
+ ipv6 = false
+ ipv6_address = (known after apply)
+ locked = (known after apply)
+ memory = (known after apply)
+ monitoring = false
+ name = "bar"
+ price_hourly = (known after apply)
+ price_monthly = (known after apply)
+ private_networking = (known after apply)
+ region = "lon1"
+ resize_disk = true
+ size = "s-1vcpu-1gb"
+ ssh_keys = [
+ "34377800",
]
+ status = (known after apply)
+ urn = (known after apply)
+ user_data = "f9b1d9796d069fe504ce0d89439b6b664b14b1a1"
+ vcpus = (known after apply)
+ volume_ids = (known after apply)
+ vpc_uuid = (known after apply)
}
# digitalocean_droplet.foo (foo) será criado
+ resource "digitalocean_droplet" "foo" {
+ backups = false
+ created_at = (known after apply)
+ disk = (known after apply)
+ graceful_shutdown = false
+ id = (known after apply)
+ image = "ubuntu-20-04-x64"
+ ipv4_address = (known after apply)
+ ipv4_address_private = (known after apply)
+ ipv6 = false
+ ipv6_address = (known after apply)
+ locked = (known after apply)
+ memory = (known after apply)
+ monitoring = false
+ name = "foo"
+ price_hourly = (known after apply)
+ price_monthly = (known after apply)
+ private_networking = (known after apply)
+ region = "lon1"
+ resize_disk = true
+ size = "s-1vcpu-1gb"
+ ssh_keys = [
+ "34377800",
]
+ status = (known after apply)
+ urn = (known after apply)
+ user_data = "f9b1d9796d069fe504ce0d89439b6b664b14b1a1"
+ vcpus = (known after apply)
+ volume_ids = (known after apply)
+ vpc_uuid = (known after apply)
}
# digitalocean_loadbalancer.lb (lb) será criado
+ resource "digitalocean_loadbalancer" "lb" {
+ algorithm = "round_robin"
+ disable_lets_encrypt_dns_records = false
+ droplet_ids = (known after apply)
+ enable_backend_keepalive = false
+ enable_proxy_protocol = false
+ id = (known after apply)
+ ip = (known after apply)
+ name = "default"
+ redirect_http_to_https = false
+ region = "lon1"
+ size_unit = (known after apply)
+ status = (known after apply)
+ urn = (known after apply)
+ vpc_uuid = (known after apply)
+ forwarding_rule {
+ certificate_id = (known after apply)
+ certificate_name = (known after apply)
+ entry_port = 80
+ entry_protocol = "http"
+ target_port = 80
+ target_protocol = "http"
+ tls_passthrough = false
}
+ healthcheck {
+ check_interval_seconds = (known after apply)
+ healthy_threshold = (known after apply)
+ path = (known after apply)
+ port = (known after apply)
+ protocol = (known after apply)
+ response_timeout_seconds = (known after apply)
+ unhealthy_threshold = (known after apply)
}
+ sticky_sessions {
+ cookie_name = (known after apply)
+ cookie_ttl_seconds = (known after apply)
+ type = (known after apply)
}
}
Plan: 3 to add, 0 to change, 0 to destroy.
─────────────────────────────────────────────────────────────────────────────
Saved the plan to: plan
To perform exactly these actions, run the following command to apply:
terraform apply "plan"
Please review the diff output above for infra
❯ Approve Applies the changes outlined in the plan.
Dismiss
Stop
Nota: O CDKTF ainda está em desenvolvimento, e a saída pode ser diferente da mostrada acima.
Esta exibição lista todos os recursos e propriedades que o cdktf
planeja criar, atualizar e destruir. Alguns valores, como o ID de um Droplet, só são conhecidos após o provisionamento do recurso. Para esses, você verá (known after apply)
como o valor da propriedade na saída.
Revise a lista de recursos para garantir que seja o que você espera. Em seguida, use as teclas de seta para selecionar a opção Aprovar e pressione ENTER
.
Você verá uma saída semelhante ao seguinte:
Outputinfra digitalocean_droplet.foo (foo): Creating...
digitalocean_droplet.bar (bar): Creating...
infra digitalocean_droplet.bar (bar): Still creating... [10s elapsed]
infra digitalocean_droplet.foo (foo): Still creating... [10s elapsed]
1 Stack deploying 0 Stacks done 0 Stacks waiting
Esta saída informa que o cdktf
está se comunicando com a API da DigitalOcean para criar o Droplet. O cdktf
está criando os Droplets primeiro porque o balanceador de carga depende do ID do Droplet, que é desconhecido até que os Droplets sejam provisionados.
A criação do Droplet geralmente leva menos de um minuto. Assim que os Droplets forem provisionados, o cdktf
passará a criar o balanceador de carga.
Outputinfra digitalocean_droplet.bar (bar): Creation complete after 54s [id=298041598]
infra digitalocean_droplet.foo (foo): Creation complete after 55s [id=298041600]
infra digitalocean_loadbalancer.lb (lb): Creating...
infra digitalocean_loadbalancer.lb (lb): Still creating... [10s elapsed]
O balanceador de carga pode demorar mais. Depois que o balanceador de carga for criado, você verá um resumo que mostra que o stack foi implantado com sucesso.
Outputinfra digitalocean_loadbalancer.lb (lb): Still creating... [1m30s elapsed]
infra digitalocean_loadbalancer.lb (lb): Creation complete after 1m32s [id=4f9ae2b7-b649-4fb4-beed-96b95bb72dd1]
infra
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
No outputs found.
Agora você pode visitar o console do DigitalOcean, onde você pode ver um balanceador de carga chamado default
e dois Droplets saudáveis chamados foo
e bar
, cada um servindo como um alvo para o balanceador de carga.
Você pode testar se o NGINX está em execução e servindo conteúdo corretamente visitando o endereço IP de cada Droplet. Você deve ver um texto semelhante ao seguinte:
Droplet: bar, IP Address: droplet_ip
Se você não ver essa sequência de texto ou o servidor não estiver respondendo, verifique se os dados do usuário que você especificou estão corretos e se nenhum caractere (incluindo novas linhas) precede o shebang (#!
). Você também pode fazer SSH no Droplet usando sua chave privada SSH e revisar os logs de saída gerados pelo CloudInit em /var/log/cloud-init-output.log
:
Depois de confirmar que os Droplets estão acima e servindo conteúdo, você pode começar a testar o balanceador de carga. Você faz isso enviando algumas solicitações.
Execute o seguinte comando do seu terminal para enviar dez solicitações para o balanceador de carga:
Você deve ver uma saída semelhante ao seguinte, embora os endereços IP mostrados sejam diferentes:
OutputDroplet: foo, IP Address: droplet_foo_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: foo, IP Address: droplet_foo_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: foo, IP Address: droplet_foo_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: foo, IP Address: droplet_foo_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: foo, IP Address: droplet_foo_ip
Isso mostra que as solicitações ao balanceador de carga foram encaminhadas para cada Droplet cinco vezes, indicando que o balanceador de carga está funcionando.
Observação: O balanceador de carga nem sempre equilibrará perfeitamente entre os dois Droplets; você pode descobrir que quatro solicitações foram enviadas para um Droplet e seis para o outro. Esse comportamento é normal.
Neste passo, você utilizou cdktf
para provisionar seus recursos e, em seguida, utilizou o console da DigitalOcean para descobrir os endereços IP de seus Droplets e balanceador de carga. Em seguida, enviou solicitações para cada Droplet e balanceador de carga para confirmar que eles funcionam.
No próximo passo, você obterá os endereços IP dos Droplets e do balanceador de carga sem fazer login no console da DigitalOcean.
Passo 8 — Exibindo Informações
No passo anterior, você precisou fazer login no Console da DigitalOcean para obter os endereços IP do seu Droplet e balanceador de carga. Neste passo, você modificará ligeiramente seu código para que essas informações sejam impressas na saída do comando cdktf deploy
, poupando-lhe uma viagem ao console.
O Terraform registra a configuração e o estado de seus recursos gerenciados em arquivos de estado. Para sua pilha infra
, o arquivo de estado pode ser encontrado em infra/terraform.infra.tfstate
. Você será capaz de encontrar os endereços IP dos Droplets e do balanceador de carga dentro deste arquivo de estado.
No entanto, classificar através de um arquivo grande pode ser inconveniente. O CDKTF fornece o construtor TerraformOutput
, que você pode usar para exibir variáveis e torná-las disponíveis fora da pilha. Quaisquer saídas são impressas em stdout
após a execução de cdktf deploy
. Executar cdktf output
também pode imprimir saídas a qualquer momento.
Nota: Embora você apenas use saídas para imprimir informações no console neste tutorial, seu verdadeiro poder vem de pilhas que utilizam saídas de outras pilhas como entrada, uma funcionalidade conhecida como referências entre pilhas.
Atualize o arquivo main.ts
para incluir as saídas dos endereços IP do balanceador de carga e das gotas (Droplets):
Salve e feche o arquivo.
Execute cdktf deploy
para atualizar a mudança:
Dentro da saída, você deve ver algo semelhante ao seguinte:
Output─────────────────────────────────────────────────────────────────────────────
Changes to Outputs:
+ droplet0IP = "droplet_foo_ip"
+ droplet1IP = "droplet_bar_ip"
+ loadBalancerIP = "load_balancer_ip"
You can apply this plan to save these new output values to the Terraform
state, without changing any real infrastructure.
─────────────────────────────────────────────────────────────────────────────
Esta saída informa que nenhuma alteração de infraestrutura será feita, apenas o que é produzido pela pilha.
Use as teclas de seta para selecionar Aprovar, e então pressione ENTER
. No final da saída do terminal, você deve ver algo semelhante a:
Outputinfra
droplet0IP = droplet_foo_ip
droplet1IP = droplet_bar_ip
loadBalancerIP = load_balancer_ip
Agora, cada vez que você executar cdktf deploy
ou cdktf output
, o endereço IP das gotas e dos balanceadores de carga são impressos na saída do terminal, eliminando a necessidade de acessar essas informações pelo console do DigitalOcean.
Você agora provisionou duas gotas e um balanceador de carga e confirmou que estão funcionando. Você pode usar o projeto CDKTF que desenvolveu como base para definir infraestrutura mais sofisticada (você pode encontrar uma implementação de referência em do-community / digitalocean-cdktf-typescript
).
Os recursos provisionados neste tutorial incorrerão em custos. Se você não pretende usar a infraestrutura criada, você deve destruí-la. No próximo e último passo, você limpará o projeto destruindo os recursos criados neste tutorial.
Passo 9 — Destruindo Sua Infraestrutura
Neste passo, você removerá todos os recursos criados neste tutorial.
Ainda dentro do diretório infra/
, execute cdktf destroy
:
Você deverá ver uma saída semelhante à seguinte:
Outputinfra Initializing the backend...
infra Initializing provider plugins...
infra - Reusing previous version of digitalocean/digitalocean from the dependency lock file
infra - Using previously-installed digitalocean/digitalocean v2.19.0
infra Terraform has been successfully initialized!
infra digitalocean_droplet.bar (bar): Refreshing state... [id=298041598]
digitalocean_droplet.foo (foo): Refreshing state... [id=298041600]
infra digitalocean_loadbalancer.lb (lb): Refreshing state... [id=4f9ae2b7-b649-4fb4-beed-96b95bb72dd1]
infra Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
infra # digitalocean_droplet.bar (bar) will be destroyed
- resource "digitalocean_droplet" "bar" {
- backups = false -> null
- created_at = "2022-05-02T10:04:16Z" -> null
- disk = 25 -> null
- graceful_shutdown = false -> null
- id = "298041598" -> null
- image = "ubuntu-20-04-x64" -> null
- ipv4_address = "droplet_bar_public_ip" -> null
- ipv4_address_private = "droplet_bar_private_ip" -> null
- ipv6 = false -> null
- locked = false -> null
- memory = 1024 -> null
- monitoring = false -> null
- name = "bar" -> null
- price_hourly = 0.00744 -> null
- price_monthly = 5 -> null
- private_networking = true -> null
- region = "lon1" -> null
- resize_disk = true -> null
- size = "s-1vcpu-1gb" -> null
- ssh_keys = [
- "34377800",
] -> null
- status = "active" -> null
- tags = [] -> null
- urn = "do:droplet:298041598" -> null
- user_data = "f9b1d9796d069fe504ce0d89439b6b664b14b1a1" -> null
- vcpus = 1 -> null
- volume_ids = [] -> null
- vpc_uuid = "bed80b32-dc82-11e8-83ec-3cfdfea9f3f0" -> null
}
# digitalocean_droplet.foo (foo) será destruído
- resource "digitalocean_droplet" "foo" {
- backups = false -> null
- created_at = "2022-05-02T10:04:16Z" -> null
- disk = 25 -> null
- graceful_shutdown = false -> null
- id = "298041600" -> null
- image = "ubuntu-20-04-x64" -> null
- ipv4_address = "droplet_foo_public_ip" -> null
- ipv4_address_private = "droplet_foo_private_ip" -> null
- ipv6 = false -> null
- locked = false -> null
- memory = 1024 -> null
- monitoring = false -> null
- name = "foo" -> null
- price_hourly = 0.00744 -> null
- price_monthly = 5 -> null
- private_networking = true -> null
- region = "lon1" -> null
- resize_disk = true -> null
- size = "s-1vcpu-1gb" -> null
- ssh_keys = [
- "34377800",
] -> null
- status = "active" -> null
- tags = [] -> null
- urn = "do:droplet:298041600" -> null
- user_data = "f9b1d9796d069fe504ce0d89439b6b664b14b1a1" -> null
- vcpus = 1 -> null
- volume_ids = [] -> null
- vpc_uuid = "bed80b32-dc82-11e8-83ec-3cfdfea9f3f0" -> null
}
# digitalocean_loadbalancer.lb (lb) será destruído
- resource "digitalocean_loadbalancer" "lb" {
- algorithm = "round_robin" -> null
- disable_lets_encrypt_dns_records = false -> null
- droplet_ids = [
- 298041598,
- 298041600,
] -> null
- enable_backend_keepalive = false -> null
- enable_proxy_protocol = false -> null
- id = "4f9ae2b7-b649-4fb4-beed-96b95bb72dd1" -> null
- ip = "load_balancer_ip" -> null
- name = "default" -> null
- redirect_http_to_https = false -> null
- region = "lon1" -> null
- size_unit = 1 -> null
- status = "active" -> null
- urn = "do:loadbalancer:4f9ae2b7-b649-4fb4-beed-96b95bb72dd1" -> null
- vpc_uuid = "bed80b32-dc82-11e8-83ec-3cfdfea9f3f0" -> null
- forwarding_rule {
- entry_port = 80 -> null
- entry_protocol = "http" -> nul
infra l
- target_port = 80 -> null
- target_protocol = "http" -> null
- tls_passthrough = false -> null
}
- healthcheck {
- check_interval_seconds = 10 -> null
- healthy_threshold = 5 -> null
- path = "/" -> null
- port = 80 -> null
- protocol = "http" -> null
- response_timeout_seconds = 5 -> null
- unhealthy_threshold = 3 -> null
}
- sticky_sessions {
- cookie_ttl_seconds = 0 -> null
- type = "none" -> null
}
}
Plan: 0 to add, 0 to change, 3 to destroy.
─────────────────────────────────────────────────────────────────────────────
Saved the plan to: plan
To perform exactly these actions, run the following command to apply:
terraform apply "plan"
Please review the diff output above for infra
❯ Approve Applies the changes outlined in the plan.
Dismiss
Stop
Desta vez, em vez de mostrar +
ao lado de cada recurso, ele mostra -
, indicando que o CDKTF planeja destruir o recurso. Analise as alterações propostas e, em seguida, use as teclas de seta para selecionar Aprovar e pressione ENTER
. O provedor da DigitalOcean agora irá se comunicar com a API da DigitalOcean para destruir os recursos.
Outputinfra digitalocean_loadbalancer.lb (lb): Destroying... [id=4f9ae2b7-b649-4fb4-beed-96b95bb72dd1]
infra digitalocean_loadbalancer.lb (lb): Destruction complete after 1s
infra digitalocean_droplet.bar (bar): Destroying... [id=298041598]
digitalocean_droplet.foo (foo): Destroying... [id=298041600]
O balanceador de carga foi excluído primeiro porque não possui dependências (nenhum outro recurso faz referência ao balanceador de carga em suas entradas). Como os Droplets fazem referência ao balanceador de carga, eles só podem ser destruídos após o balanceador de carga ser destruído.
Após os recursos terem sido destruídos, você verá a seguinte linha impressa na saída:
OutputDestroy complete! Resources: 3 destroyed.
Conclusão
Neste tutorial, você utilizou o CDKTF para provisionar e destruir uma página da web balanceada, composta por dois Droplets da DigitalOcean executando servidores NGINX, servidos atrás de um balanceador de carga. Você também exibiu informações sobre os recursos no terminal.
O CDKTF é uma camada de abstração acima do Terraform. Um bom entendimento do Terraform é útil para entender o CDKTF. Se você gostaria de aprender mais sobre o Terraform, pode ler a série Como Gerenciar Infraestrutura com Terraform, que cobre o Terraform em profundidade.
Você também pode conferir a documentação oficial do CDK for Terraform e os tutoriais para aprender mais sobre o CDKTF.