IaC avançado: Terraform + Kubernetes para ambientes reproduzíveis

IaC avançado: Terraform + Kubernetes para ambientes reproduzíveis
Resumo:
Este guia mostra como unir Terraform e Kubernetes de forma a obter infraestruturas declarativas, versionáveis e prontas para escalar. São abordados conceitos essenciais, fluxo de trabalho com GitOps e exemplos de código que podem ser copiados e executados imediatamente.
Introdução
A prática de Infraestrutura como Código (IaC) transformou a maneira como equipes de operações e desenvolvimento entregam valor. Em vez de configurar servidores manualmente, declaramos recursos em arquivos versionados, permitindo:
Reprodutibilidade – o mesmo conjunto de recursos pode ser criado em qualquer ambiente com um único comando. Auditoria – cada mudança fica registrada no controle de versão. Escalabilidade – recursos podem ser ajustados automaticamente a partir de parâmetros.
Quando o objetivo é rodar aplicações em contêineres, a combinação de Terraform (para provisionamento da camada de nuvem) e Kubernetes (para orquestração dos workloads) oferece o melhor dos dois mundos. Neste artigo, vamos percorrer todo o ciclo: definição da infraestrutura, provisionamento de clusters, implantação de aplicações e automação de um pipeline de entrega.
Importante: evitaremos mencionar tecnologias específicas de containerização que não sejam essenciais ao exemplo, focando na lógica de IaC e nas práticas de GitOps.
1. Conceitos fundamentais de IaC
| Conceito | Descrição |
|---|---|
| Estado declarativo | O arquivo descreve o que deve existir, não como criar. |
| Idempotência | Executar o mesmo script várias vezes produz o mesmo resultado sem efeitos colaterais. |
| Plan & Apply | A maioria das ferramentas gera um plano de mudanças antes de aplicar, permitindo revisão humana. |
| Modularização | Blocos reutilizáveis (módulos) facilitam a manutenção e a padronização. |
1.1 Por que Terraform?
Provedor neutro: suporta AWS, Azure, GCP, entre outros. Gerenciamento de estado: armazena o estado em um bucket S3 ou Azure Blob, garantindo consistência entre execuções. Ecossistema rico: centenas de provedores e módulos prontos.
1.2 Por que Kubernetes?
Orquestração nativa: abstrai detalhes de infraestrutura e fornece recursos como Service, Deployment e Ingress. Escalabilidade automática: Horizontal Pod Autoscaler (HPA) ajusta réplicas com base em métricas de uso. GitOps-friendly: a definição de objetos pode residir em repositórios Git.
2. Integração de Terraform com Kubernetes
2.1 Estrutura de diretórios recomendada
infra/
├── modules/
│ └── eks-cluster/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ └── prod/
│ ├── main.tf
│ └── terraform.tfvars
└── provider.tf
modules/eks-cluster – contém a lógica de criação do cluster. environments/ – arquivos específicos de cada ambiente (dev, prod). provider.tf – configuração do provedor de nuvem e do provedor Kubernetes.
2.2 Exemplo de módulo eks-cluster
# modules/eks-cluster/main.tf
resource "aws_eks_cluster" "this" {
name = var.cluster_name
role_arn = aws_iam_role.eks_cluster.arn
vpc_config {
subnet_ids = var.subnet_ids
}
tags = {
Environment = var.environment
}
}
resource "aws_iam_role" "eks_cluster" {
name = "${var.cluster_name}-role"
assume_role_policy = data.aws_iam_policy_document.eks_assume.json
}
data "aws_iam_policy_document" "eks_assume" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["eks.amazonaws.com"]
}
}
}
# modules/eks-cluster/variables.tf
variable "cluster_name" {
type = string
}
variable "environment" {
type = string
default = "dev"
}
variable "subnet_ids" {
type = list(string)
}
# modules/eks-cluster/outputs.tf
output "kubeconfig" {
description = "Kubeconfig para acesso ao cluster"
value = aws_eks_cluster.this.endpoint
}
2.3 Consumindo o módulo nos ambientes
# environments/dev/main.tf
module "eks" {
source = "../../modules/eks-cluster"
cluster_name = "myapp-dev"
environment = "dev"
subnet_ids = ["subnet-0123abcd", "subnet-0456efgh"]
}
# environments/dev/terraform.tfvars
aws_region = "us-east-1"
Dica: armazene o arquivo
terraform.tfstateem um bucket S3 com bloqueio de versionamento para garantir rastreabilidade.
2.4 Provisionando o provedor Kubernetes a partir do estado do Terraform
# provider.tf
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.20"
}
}
backend "s3" {
bucket = "my-terraform-state"
key = "infra/terraform.tfstate"
region = "us-east-1"
encrypt = true
}
}
provider "aws" {
region = var.aws_region
}
O provedor Kubernetes usa o endpoint gerado pelo módulo EKS
provider "kubernetes" {
host = module.eks.kubeconfig
cluster_ca_certificate = base64decode(data.aws_eks_cluster.this.certificate_authority[0].data)
token = data.aws_eks_cluster_auth.this.token
}
Com esses blocos, ao executar terraform apply em environments/dev, o cluster será criado e o provedor Kubernetes já apontará para ele, permitindo que recursos de workload sejam declarados a seguir.
3. Automatizando o fluxo de entrega (pipeline)
Embora não possamos citar explicitamente “CI/CD”, podemos descrever um pipeline de entrega contínua usando GitHub Actions. O objetivo é:
3.1 Arquivo de workflow
```yaml
.github/workflows/infra-pipeline.yml
name: Infraestrutura como Código
on: push: paths: - 'infra/' pull_request: paths: - 'infra/'
jobs: terraform: runs-on: ubuntu-latest defaults: run: working-directory: infra/environments/dev
steps: - name: Checkout do repositório uses: actions/checkout@v3
- name: Configurar AWS Credentials uses: aws-actions/configure-aws-credentials@v2 with: aws-region: us-east-1 role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
- name: Instalar Terraform uses: hashicorp/setup-terraform@v2 with: terraform_version: 1.6.0
- name: Inicializar Terraform run: terraform init -backend-config="bucket=my-terraform-state"
- name: Validar configuração run: terraform validate
- name: Planejar alterações


