- Classificação de Armazenamento no Kubernetes
No ecossistema Kubernetes, os dados podem ser categorizados em duas classes principais: metadados e dados de aplicação reais.
- Metadados: Incluem configurações de aplicações, credenciais e informações do próprio Pod. São gerenciados através de
ConfigMap,SecreteDownward API. - Dados Reais: Arquivos de usuário, bancos de dados e logs. São gerenciados através de
Volumesefêmeros ouPersistentVolumes(PV).
- ConfigMaps: Injeção de Configurações
O ConfigMap permite desacoplar configurações das imagens de contêiner, promovendo portabilidade. As configurações podem ser injetadas como variáveis de ambiente, argumentos de linha de comando ou mnotadas como arquivos no sistema de arquivos do contêiner.
2.1 Criação e Injeção como Variáveis de Ambiente
# Criando um ConfigMap a partir de literais
kubectl create configmap db-credentials \
--from-literal=DB_USER=admin \
--from-literal=DB_PASS=supersecret
# Criando a partir de um arquivo de propriedades
cat <<EOF > app.properties
LOG_LEVEL=debug
MAX_CONNECTIONS=100
EOF
kubectl create configmap app-settings --from-file=app.properties
Consumindo os dados no Pod:
apiVersion: v1
kind: Pod
metadata:
name: config-env-pod
spec:
containers:
- name: app-container
image: nginx:alpine
command: ["/bin/sh", "-c", "env"]
env:
- name: DATABASE_USER
valueFrom:
configMapKeyRef:
name: db-credentials
key: DB_USER
envFrom:
- configMapRef:
name: app-settings
restartPolicy: Never
2.2 Montagem como Volume e Atualização Dinâmica
Ao montar um ConfigMap como volume, o Kubernetes utiliza links simbólicos para permitir atualizações sem corromper arquivos em uso. No entanto, a aplicação deve ser capaz de recarregar a configuração internamente (ex: nginx -s reload), pois o Kubelet apenas atualiza os arquivos no disco, não reinicia o processo do contêiner.
apiVersion: v1
kind: Pod
metadata:
name: config-volume-pod
spec:
containers:
- name: web-server
image: nginx:alpine
volumeMounts:
- name: config-vol
mountPath: /etc/nginx/conf.d
volumes:
- name: config-vol
configMap:
name: nginx-config
Nota: ConfigMaps podem ser marcados como immutable: true para melhorar a performance do cluster (reduzindo a carga no kube-apiserver) e evitar alterações acidentais.
- Secrets: Proteção de Dados Sensíveis
Os Secrets funcionam de maneira similar aos ConfigMaps, mas são destinados a dados sensíveis. Os valores devem ser codificados em Base64 no manifesto YAML (embora o Kubernetes também suporte o campo stringData para texto plano que é codificado automaticamente na criação).
apiVersion: v1
kind: Secret
metadata:
name: api-tokens
type: Opaque
data:
# echo -n 'my-secret-key' | base64
api-key: bXktc2VjcmV0LWtleQ==
Os Secrets são armazenados em memória nos nós (tmpfs) e, se configurado o cluster, criptografados em repouso no etcd. Podem ser montados como volumes com permissões restritas (ex: defaultMode: 256 para 0400 em octal).
- Downward API: Metadados do Pod
A Downward API expõe informações do próprio Pod (como nome, namespace, IP, limites de CPU e Memória) para os contêineres. Isso é fundamental para aplicações que precisam estar cientes de seu contexto de execução ou limites de recursos impostos pelo cluster.
apiVersion: v1
kind: Pod
metadata:
name: downward-env-pod
spec:
containers:
- name: main-app
image: busybox
command: ["sh", "-c", "echo Pod IP: $POD_IP, CPU Limit: $CPU_LIMIT"]
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: CPU_LIMIT
valueFrom:
resourceFieldRef:
resource: limits.cpu
- Volumes: emptyDir e hostPath
5.1 emptyDir
Um volume emptyDir é criado quando um Pod é atribuído a um nó e existe apenas enquanto o Pod estiver em execução naquele nó. É ideal para cache, compartilhamento de dados entre contêineres no mesmo Pod (padrão sidecar) ou espaço temporário. Pode ser configurado para usar memória RAM (medium: Memory), consumindo a cota de memória do contêiner e oferecendo alta performance de I/O.
5.2 hostPath
Monta um arquivo ou diretório do sistema de arquivos do nó host diretamente no contêiner. É útil para daemons que precisam acessar logs do host ou o socket do Docker (/var/run/docker.sock). Deve ser usado com extrema cautela devido a implicações de segurança e falta de portabilidade entre nós.
- Persistência com PV, PVC e StatefulSets
O modelo de armazenamento persistente no Kubernetes separa o provisionamento da infraestrutura (PV - PersistentVolume) do consumo pela aplicação (PVC - PersistentVolumeClaim).
- PV: Recurso de cluster provisionado por um administrador ou dinamicamente.
- PVC: Solicitação de armazenamento feita pelo usuário ou pelo controlador do Pod.
6.1 StatefulSet com volumeClaimTemplates
Para aplicações com estado (como bancos de dados distribuídos), o StatefulSet utiliza volumeClaimTemplates. Isso garante que cada réplica do Pod receba seu próprio PVC e PV exclusivo, mantendo a identidade de rede e a persistência de dados mesmo após reinicializações ou reschedulements.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: database-cluster
spec:
serviceName: "db-headless"
replicas: 3
selector:
matchLabels:
app: database
template:
metadata:
labels:
app: database
spec:
containers:
- name: db-engine
image: postgres:15
volumeMounts:
- name: db-data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: db-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "fast-ssd"
resources:
requests:
storage: 10Gi
- Provitionamento Dinâmico com StorageClass
O provisionamento estático exige que administradores criem PVs manualmente para cada demanda. O StorageClass resolve isso permitindo o provisionamento dinâmico. Quando um PVC é criado referenciando um StorageClass, um provisionador (como o nfs-subdir-external-provisioner ou APIs de provedores de nuvem) cria automaticamente o volume de backend e o objeto PV correspondente.
7.1 Configuração do NFS Provisioner
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
archiveOnDelete: "false"
pathPattern: "${.PVC.namespace}/${.PVC.name}"
reclaimPolicy: Delete
volumeBindingMode: Immediate
Com essa configuração, ao criar um PVC solicitando managed-nfs-storage, o provisionador cria um subdiretório isolado no servidor NFS e o vincula dinamicamente ao Pod, eliminando a necessidade de intervenção manual e acelerando o ciclo de desenvolvimento.
- Otimização de CLI: Autocomplete para kubectl
Para melhorar a produtividade ao interagir com o cluster via terminal, habilite o autocompletar do bash para o kubectl:
# Instale o pacote de completamento (se necessário)
sudo apt-get install bash-completion # Debian/Ubuntu
# ou
sudo yum install bash-completion # RHEL/CentOS
# Adicione as regras ao seu ~/.bashrc
echo 'source <(kubectl completion bash)' >> ~/.bashrc
echo 'complete -o default -F __start_kubectl k' >> ~/.bashrc # Habilita para o alias 'k'
# Recarregue a sessão do shell
source ~/.bashrc