O Kubernetes (frequentemente abreviado como k8s) atua como uma plataforma de código aberto dedicada à orquestração de contêineres. Seu propósito central é automatizar o ciclo de vida de aplicações conteinerizadas, incluindo provisionamento, escalabilidade e operações de rede, abstraindo a complexidade inerente à execução de cargas de trabalho distribuídas em múltiplos hosts e garentindo alta disponibilidade.
Componentes da Arquitetura
A infraestrutura do Kubernetes é dividida em dois planos principais que operam em conjunto para manter o estado desejado do cluster:
- Plano de Controle (Control Plane): Responsável pela tomada de decisões globais e pela detecção e resposta a eventos do cluster. Seus componentes essenciais incluem o
kube-apiserver(ponto de entrada para todas as chamadas de API), oetcd(banco de dados chave-valor para persistência de estado), okube-scheduler(que define em qual nó os Pods serão executados) e okube-controller-manager(que executa os controladores de ciclo de vida). - Nós de Trabalho (Worker Nodes): São as máquinas que efetivamente executam as cargas de aplicação. Cada nó possui um
kubelet(agente que garante a execução dos contêineres), umkube-proxy(responsável pelas regras de rede e roteamento) e um ambiente de execução (como containerd ou CRI-O).
Abstrações Fundamentais
- Pod: A menor unidade de computação implantável. Um Pod encapsula um ou mais contêineres que compartilham o mesmo namespace de rede e volumes de armazenamento.
- Deployment: Um controlador declarativo que gerencia o estado de réplicas de Pods, facilitando atualizações contínuas (rolling updates) e reversões (rollbacks).
- Service: Uma abstração de rede que define um endpoint lógico estável e políticas de acesso para um conjunto dinâmico de Pods, atuando também como balanceador de carga interno ou externo.
Provisionamento de Cargas de Trabalho
Criação de um Pod Independente
Para instanciar uma unidade básica de processamento, define-se um manifesto YAML. O exemplo abaixo configura um servidor web Apache leve:
apiVersion: v1
kind: Pod
metadata:
name: web-server-pod
labels:
environment: staging
spec:
containers:
- name: apache-instance
image: httpd:2.4-alpine
ports:
- containerPort: 8080
Para aplicar esta configuração ao cluster e verificar seu status, utilizam-se os seguintes comandos via CLI:
kubectl apply -f web-pod.yaml
kubectl get pods -l environment=staging
Gerenciamento de Réplicas com Deployment
Em ambientes de produção, os Pods são raramente criados de forma isolada. O Deployment garante a resiliência e a escalabilidade. O manifesto a seguir provisiona um cluster de cache em memória com quatro réplicas:
apiVersion: apps/v1
kind: Deployment
metadata:
name: cache-cluster
spec:
replicas: 4
selector:
matchLabels:
tier: backend
component: cache
template:
metadata:
labels:
tier: backend
component: cache
spec:
containers:
- name: memcached-node
image: memcached:1.6-alpine
ports:
- containerPort: 11211
A implantação e a inspeção dos recursos são realizaads através do kubectl:
kubectl apply -f cache-deploy.yaml
kubectl rollout status deployment/cache-cluster
kubectl get pods -l component=cache
Exposição de Rede via Service
Para permitir que o tráfego externo ou interno alcance os Pods de forma consistente, utiliza-se um Service. O exemplo abaixo cria um gateway de acesso do tipo NodePort para uma aplicação frontend:
apiVersion: v1
kind: Service
metadata:
name: frontend-gateway
spec:
type: NodePort
selector:
tier: frontend
ports:
- port: 80
targetPort: 3000
nodePort: 30080
protocol: TCP
kubectl apply -f frontend-svc.yaml
Injeção de Configurações e Dados Sensíveis
O desacoplamento entre o código da aplicação e suas configurações é uma prática essencial. O Kubernetes oferece recursos nativos para isso.
ConfigMaps para Dados Não Confidenciais
Um ConfigMap armazena pares de chave-valor que podem ser injetados como variáveis de ambiente ou arquivos. Abaixo, definimos parâmetros de conexão e nível de log:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-settings
data:
DATABASE_HOST: "db.internal.local"
LOG_LEVEL: "debug"
Diferente da montagem de volumes, podemos injetar esses dados diretamente no ambiente de execução do contêiner:
apiVersion: v1
kind: Pod
metadata:
name: api-backend
spec:
containers:
- name: api-container
image: node:18-alpine
envFrom:
- configMapRef:
name: app-settings
Secrets para Credenciais
Para dados sensíveis, como senhas e tokens, utiliza-se o recurso Secret. Os valores devem ser codificados em Base64 no manifesto (ou utilizar o campo stringData para conversão automática):
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
DB_USER: cm9vdA==
DB_PASS: cGFzczEyMw==
Para consumir o Secret de forma segura, ele pode ser montado como um sistema de arquivos em memória (tmpfs) dentro do Pod, garantindo que as credenciais não sejam expostas em variáveis de ambiente:
apiVersion: v1
kind: Pod
metadata:
name: secure-worker
spec:
containers:
- name: worker-process
image: python:3.11-slim
volumeMounts:
- name: auth-vol
mountPath: "/var/secrets/auth"
readOnly: true
volumes:
- name: auth-vol
secret:
secretName: db-credentials