Introdução ao Kubernetes e orquestração de containers

1. Fundamentos da orquestração de containers

A orquestração de containers é o processo de gerenciar automaticamente o ciclo de vida de containers em ambientes distribuídos. Ela resolve problemas fundamentais como escalabilidade, resiliência e gerenciamento de recursos que surgem quando operamos múltiplos containers em produção.

Gerenciar containers manualmente apresenta diversos desafios:
- Falhas: um container pode cair inesperadamente, exigindo reinicialização automática
- Balanceamento de carga: distribuir tráfego entre múltiplas instâncias de uma aplicação
- Rede: comunicação entre containers espalhados por diferentes máquinas
- Armazenamento: dados persistentes que precisam sobreviver ao ciclo de vida dos containers

Comparando ferramentas de orquestração:

Docker Compose:
- Ideal para desenvolvimento local e ambientes simples
- Gerenciamento de containers em um único host
- Configuração declarativa simples (docker-compose.yml)
- Sem suporte nativo a clusters ou alta disponibilidade

Docker Swarm:
- Orquestração nativa do Docker
- Clusterização simples e integrada
- Menos recursos avançados que Kubernetes
- Adequado para equipes pequenas com necessidades moderadas

Kubernetes:
- Padrão da indústria para orquestração
- Alta disponibilidade, auto-recuperação e escalonamento avançado
- Ecossistema extenso de ferramentas e extensões
- Curva de aprendizado mais íngreme, mas mais poderoso

2. Arquitetura principal do Kubernetes

Um cluster Kubernetes é composto por dois tipos principais de componentes:

Control Plane (Plano de Controle):
- API Server: ponto central de comunicação, expõe a API REST do Kubernetes
- Scheduler: decide em qual nó worker cada Pod será executado
- Controller Manager: executa controladores que monitoram e ajustam o estado do cluster
- etcd: banco de dados chave-valor que armazena todo o estado do cluster

Nós Workers:
- kubelet: agente que executa em cada nó, garante que os containers estejam rodando
- kube-proxy: gerencia regras de rede e balanceamento de carga
- Container Runtime: executa os containers (Docker, containerd, CRI-O)

A comunicação segue um fluxo centralizado onde o API Server coordena todas as operações. O conceito fundamental é o estado desejado versus estado atual:

# Exemplo de manifesto declarativo
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80

O Kubernetes constantemente reconcilia o estado atual com o estado desejado definido no manifesto.

3. Pods: a unidade mínima de execução

O Pod é o menor objeto que pode ser criado e gerenciado no Kubernetes. Um Pod pode conter um ou mais containers que compartilham:
- Rede: mesmo endereço IP e namespace de rede
- Armazenamento: volumes montados que podem ser compartilhados entre containers
- Ciclo de vida: containers são iniciados e parados juntos

Ciclo de vida de um Pod:

Status do Pod:
- Pending: aguardando recursos e agendamento
- Running: pelo menos um container em execução
- Succeeded: todos os containers terminaram com sucesso
- Failed: containers terminaram com erro
- CrashLoopBackOff: container falha repetidamente
- Unknown: estado do Pod não pode ser determinado

Padrão Sidecar (uso de múltiplos containers em um Pod):

apiVersion: v1
kind: Pod
metadata:
  name: app-com-sidecar
spec:
  containers:
  - name: app-principal
    image: minha-aplicacao:1.0
    ports:
    - containerPort: 8080
  - name: sidecar-log
    image: fluentd:latest
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/app
  volumes:
  - name: shared-logs
    emptyDir: {}

4. Workloads: controladores para gerenciar Pods

Deployments: ideais para aplicações stateless, oferecem atualizações rolling update e rollback:

# Rolling update com estratégia personalizada
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 1
  template:
    spec:
      containers:
      - name: app
        image: app:2.0

StatefulSets: para aplicações que precisam de identidade estável e armazenamento persistente:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: banco-de-dados
spec:
  serviceName: "db"
  replicas: 3
  template:
    spec:
      containers:
      - name: postgres
        image: postgres:14
        volumeMounts:
        - name: dados
          mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
  - metadata:
      name: dados
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi

DaemonSets e Jobs: DaemonSets executam um Pod em cada nó (útil para agentes de monitoramento), Jobs executam tarefas temporárias até a conclusão.

5. Serviços e descoberta de rede

Tipos de Service:

# ClusterIP (comunicação interna)
apiVersion: v1
kind: Service
metadata:
  name: api-interna
spec:
  type: ClusterIP
  selector:
    app: api
  ports:
  - port: 80
    targetPort: 8080

# NodePort (acesso externo básico)
apiVersion: v1
kind: Service
metadata:
  name: web-externo
spec:
  type: NodePort
  ports:
  - port: 80
    nodePort: 30080

Ingress: roteamento avançado baseado em domínio e path:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
spec:
  rules:
  - host: app.exemplo.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

O DNS interno do Kubernetes resolve automaticamente nomes como meu-servico.namespace.svc.cluster.local.

6. Armazenamento e volumes

Volumes efêmeros vs persistentes:

# emptyDir (efêmero)
apiVersion: v1
kind: Pod
metadata:
  name: pod-temporario
spec:
  volumes:
  - name: cache
    emptyDir: {}
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: cache
      mountPath: /cache

# PersistentVolumeClaim (persistente)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dados-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: standard

ConfigMaps e Secrets:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  config.yaml: |
    ambiente: producao
    timeout: 30
---
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  password: c2VuaGExMjM=  # base64

7. Gerenciamento de recursos e escalabilidade

Requests e Limits:

apiVersion: v1
kind: Pod
metadata:
  name: pod-recursos
spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:
        memory: "256Mi"
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "500m"

Horizontal Pod Autoscaler (HPA):

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app-deployment
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

8. Observabilidade e troubleshooting inicial

Comandos essenciais para debugging:

# Visualizar logs de um Pod
kubectl logs pod/app-pod-xyz

# Logs de container específico em multi-container Pod
kubectl logs pod/app-pod -c container-sidecar

# Descrever detalhes de um recurso
kubectl describe pod app-pod-xyz

# Executar comando dentro de um container
kubectl exec -it pod/app-pod -- /bin/sh

# Encaminhar porta local para um Pod
kubectl port-forward pod/app-pod 8080:80

# Visualizar eventos do cluster
kubectl get events --sort-by='.lastTimestamp'

Ferramentas de monitoramento:
- Prometheus: coleta e armazenamento de métricas
- Grafana: dashboards visuais para métricas do cluster
- Fluentd/Loki: agregação e análise de logs centralizados

Referências