Pular para o conteúdo
vibe coding

Automatizando a Infraestrutura com Terraform e Kubernetes

Admin5 min de leitura
Automatizando a Infraestrutura com Terraform e Kubernetes

Automatizando a Infraestrutura com Terraform e Kubernetes

Tecnologia e Inovação

Resumo: Este artigo mostra como combinar Terraform e Kubernetes para criar ambientes de produção e teste totalmente declarativos. Você verá a estrutura de um repositório GitOps, exemplos de código Terraform, manifests Kubernetes e um pequeno chart Helm. Ao final, será possível reproduzir todo o fluxo em poucos minutos.


Introdução

A prática de Infraestrutura como Código (IaC) tem mudado a forma como equipes de tecnologia entregam valor. Em vez de configurar servidores manualmente, declaramos recursos em arquivos versionados, permitindo:

Reprodutibilidade – o mesmo código gera o mesmo ambiente em diferentes regiões ou contas. Auditoria – cada mudança fica registrada no histórico do Git. Escalabilidade – recursos podem ser criados ou destruídos em massa com poucos comandos.

Dois pilares dessa revolução são Terraform (para provisionamento de recursos de nuvem) e Kubernetes (para orquestração de containers). Quando usados em conjunto, eles permitem que a camada de infraestrutura (máquinas virtuais, redes, bancos) e a camada de plataforma (pods, serviços, ingressos) sejam geridas de forma unificada.

Neste artigo vamos:

  • Definir a arquitetura de um repositório GitOps.
  • Escrever um módulo Terraform que cria um cluster Kubernetes na nuvem.
  • Deployar uma aplicação simples usando um chart Helm.
  • Automatizar tudo com um workflow de automação.
  • Dica: Embora o exemplo use a AWS, o mesmo conceito se aplica a GCP, Azure ou provedores on‑premises.


    1. Estrutura de um repositório GitOps

    Organizar o código em diretórios claros facilita a colaboração e a revisão de mudanças. A seguir, um modelo de repositório:

    infra/
    

    ├── terraform/ │ ├── modules/ │ │ └── eks-cluster/ │ │ ├── main.tf │ │ ├── variables.tf │ │ └── outputs.tf │ └── env/ │ ├── dev/ │ │ ├── backend.tf │ │ └── main.tf │ └── prod/ │ ├── backend.tf │ └── main.tf apps/ ├── helm/ │ └── hello-world/ │ ├── Chart.yaml │ ├── values.yaml │ └── templates/ │ ├── deployment.yaml │ └── service.yaml │ .github/ └── workflows/ └── deploy.yml

    infra/terraform – contém todo o código Terraform, incluindo módulos reutilizáveis. apps/helm – charts Helm que descrevem a aplicação a ser executada no cluster. .github/workflows – workflow de automação que roda o Terraform e o Helm.

    Essa separação deixa claro onde cada equipe deve atuar: infra cuida da nuvem, apps cuida das workloads.


    2. Provisionando o cluster Kubernetes com Terraform

    Vamos criar um módulo simples que provisiona um Amazon EKS (Elastic Kubernetes Service). O módulo pode ser adaptado para outros provedores.

    2.1 variables.tf

    variable "cluster_name" {
    

    description = "Nome do cluster EKS" type = string }

    variable "region" { description = "Região da AWS" type = string default = "us-east-1" }

    variable "node_instance_type" { description = "Tipo de instância para os nós de trabalho" type = string default = "t3.medium" }

    2.2 main.tf

    provider "aws" {
    

    region = var.region }

    resource "aws_eks_cluster" "this" { name = var.cluster_name role_arn = aws_iam_role.eks_cluster.arn

    vpc_config { subnet_ids = aws_subnet.private[].id }

    depends_on = [aws_iam_role_policy_attachment.eks_cluster_AmazonEKSClusterPolicy] }

    resource "aws_eks_node_group" "workers" { cluster_name = aws_eks_cluster.this.name node_group_name = "${var.cluster_name}-workers" node_role_arn = aws_iam_role.eks_node.arn subnet_ids = aws_subnet.private[].id

    scaling_config { desired_size = 2 max_size = 4 min_size = 1 }

    instance_types = [var.node_instance_type] }

    Observação: O exemplo omite recursos auxiliares (VPC, sub‑nets, IAM). Em projetos reais, recomenda‑se usar módulos oficiais da comunidade, como terraform-aws-modules/vpc/aws.

    2.3 outputs.tf

    output "cluster_endpoint" {
    

    description = "Endpoint do cluster EKS" value = aws_eks_cluster.this.endpoint }

    output "kubeconfig_certificate_authority_data" { description = "CA data para gerar kubeconfig" value = aws_eks_cluster.this.certificate_authority[0].data }

    2.4 Executando o Terraform

    # Inicializa o backend (ex.: S3 + DynamoDB para lock)
    

    terraform init -backend-config="bucket=my-terraform-state" \ -backend-config="key=eks/prod/terraform.tfstate" \ -backend-config="region=us-east-1"

    Planeja a criação

    terraform plan -var="cluster_name=prod-eks"

    Aplica

    terraform apply -auto-approve -var="cluster_name=prod-eks"

    Ao final, o output cluster_endpoint pode ser usado para gerar um kubeconfig:

    aws eks update-kubeconfig --name prod-eks --region us-east-1

    3. Deploy de uma aplicação com Helm

    Com o cluster pronto, vamos colocar em execução um Hello World escrito em Go. Usaremos um chart Helm para tornar o processo declarativo.

    3.1 Chart.yaml

    apiVersion: v2
    

    name: hello-world description: Aplicação mínima que responde "Hello, World!" via HTTP type: application version: 0.1.0 appVersion: "1.0"

    3.2 values.yaml

    replicaCount: 2
    

    image: repository: ghcr.io/example/hello-world tag: "1.0.0" pullPolicy: IfNotPresent

    service: type: LoadBalancer port: 80

    resources: limits: cpu: 100m memory: 128Mi requests: cpu: 50m memory: 64Mi

    3.3 templates/deployment.yaml

    apiVersion: apps/v1
    

    kind: Deployment metadata: name: {{ include "hello-world.fullname" . }} labels: {{- include "hello-world.labels" . | nindent 4 }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: {{- include "hello-world.selectorLabels" . | nindent 6 }} template: metadata: labels: {{- include "hello-world.selectorLabels" . | nindent 8 }} spec: containers: - name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" ports: - containerPort: 8080 resources: {{- toYaml .Values.resources | nindent 12 }}

    3.4 templates/service.yaml

    apiVersion: v1
    

    kind: Service metadata: name: {{ include "hello-world.fullname" . }} labels: {{- include "hello-world.labels" . | nindent 4 }} spec: type: {{ .Values.service.type }} ports: - port: {{ .Values.service.port }} targetPort: 8080 selector: {{- include "hello-world.selectorLabels" . | nindent 4 }}

    3.5 Instalando o chart

    helm repo add my-charts https://example.com/charts
    

    helm upgrade --install hello-world ./apps/helm/hello-world \ --namespace production --create-namespace

    O comando cria um Deployment com duas réplicas e um Service do tipo LoadBalancer. O provedor de nuvem provisiona automaticamente um IP público que pode ser testado:

    curl http://<load-balancer-ip>
    

    => Hello, World!


    4. Automatizando tudo com um workflow de automação

    Para garantir que a infraestrutura e a aplicação sejam mantidas sincronizadas, criamos um workflow que:

  • Executa o Terraform sempre que há mudança nos arquivos infra/terraform.
  • Executa o Helm quando houver alteração nos charts.
  • 4.1 Arquivo .github/workflows/deploy.yml

    ```yaml name: Deploy Infra + App

    on: push: paths: - 'infra/terraform/' - 'apps/helm/'

    jobs: terraform: runs-on: ubuntu-latest defaults: run: working-directory: infra/terraform steps: - name: Checkout repository uses: actions/checkout@v3

    - name: Setup Terraform uses: hashicorp/setup-terraform@v2 with: terraform_version: "1.5.0"

    - name: Terraform Init & Apply env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: | terraform init terraform apply -auto-approve -var="cluster_name=prod-eks"

    helm: needs: terraform runs-on: ubuntu-latest steps: -

    Artigos relacionados