Saltar al contenido principal

Capítulo 7.1 - StatefulSets en Profundidad

Objetivos de Aprendizaje​

Al finalizar este capítulo, usted será capaz de:

  • Comprender los StatefulSets en profundidad
  • Desplegar bases de datos con StatefulSets
  • Gestionar el scaling y las actualizaciones
  • Comprender los init containers en StatefulSets
  • Implementar la replicación maestro-esclavo
  • Gestionar quorums y la elección de líder

Introducción​

Los StatefulSets son esenciales para las aplicaciones stateful. Este capítulo profundiza en los conceptos y presenta casos de uso avanzados.


Arquitectura de un StatefulSet​

Componentes​


Ejemplo: Base de Datos PostgreSQL​

Paso 1: Service Headless​

apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
clusterIP: None
selector:
app: postgres
ports:
- port: 5432
name: postgres

Paso 2: ConfigMap para Configuración​

apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
data:
postgresql.conf: |
max_connections = 200
shared_buffers = 256MB
effective_cache_size = 1GB

Paso 3: Secret para Credenciales​

apiVersion: v1
kind: Secret
metadata:
name: postgres-secret
type: Opaque
data:
postgres-password: cG9zdGdyZXM= # base64
replication-password: cmVwbGljYXRpb24= # base64

Paso 4: StatefulSet​

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
initContainers:
- name: init-postgres
image: postgres:14
command:
- /bin/bash
- -c
- |
set -e
if [[ $HOSTNAME == "postgres-0" ]]; then
echo "Initializing primary database..."
else
echo "Waiting for primary to be ready..."
until pg_isready -h postgres-0.postgres; do
sleep 1
done
fi
env:
- name: PGHOST
value: postgres-0.postgres
containers:
- name: postgres
image: postgres:14
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: postgres-password
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
ports:
- containerPort: 5432
name: postgres
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
- name: postgres-config
mountPath: /etc/postgresql
volumes:
- name: postgres-config
configMap:
name: postgres-config
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "fast-ssd"
resources:
requests:
storage: 50Gi

Init Containers​

Los init containers se ejecutan antes de los contenedores principales y pueden:

  • Inicializar la base de datos
  • Esperar a que otros servicios estén listos
  • Configurar el entorno
  • Verificar dependencias

Ejemplo:

spec:
template:
spec:
initContainers:
- name: wait-for-db
image: busybox:1.35
command:
- sh
- -c
- |
until nc -z postgres-0.postgres 5432; do
echo "Waiting for database..."
sleep 2
done
containers:
- name: app
image: my-app:1.0

Replicación Maestro-Esclavo​

Arquitectura​

Configuración:

spec:
template:
spec:
containers:
- name: postgres
env:
- name: POSTGRES_REPLICATION_MODE
value: "master" # Para postgres-0
- name: POSTGRES_MASTER_HOST
value: "postgres-0.postgres" # Para postgres-1, postgres-2

Quorum y Elección de Líder​

Para aplicaciones que requieren un quorum (ej: etcd, Consul):

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: etcd
spec:
serviceName: etcd
replicas: 3 # Quorum: (3/2) + 1 = 2
template:
spec:
containers:
- name: etcd
image: quay.io/coreos/etcd:v3.5.0
env:
- name: ETCD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: ETCD_INITIAL_CLUSTER
value: "etcd-0=http://etcd-0.etcd:2380,etcd-1=http://etcd-1.etcd:2380,etcd-2=http://etcd-2.etcd:2380"

Quorum: (N/2) + 1, donde N = número de replicas


Scaling​

Scaling Up​

kubectl scale statefulset postgres --replicas=5

Proceso:

  1. Crea postgres-3
  2. Espera a que postgres-3 esté Ready
  3. Crea postgres-4
  4. Espera a que postgres-4 esté Ready

Scaling Down​

kubectl scale statefulset postgres --replicas=2

Proceso:

  1. Elimina postgres-4 (último)
  2. Espera a que postgres-4 esté terminado
  3. Elimina postgres-3
  4. Espera a que postgres-3 esté terminado

Importante: Para bases de datos, asegúrese de que los datos estén respaldados antes de hacer scaling down.


Actualizaciones​

Rolling Update​

spec:
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0 # Actualizar todos los Pods

Proceso:

  1. Actualización de postgres-2 (último)
  2. Actualización de postgres-1
  3. Actualización de postgres-0 (primero)

Actualización Parcial (Canary)​

spec:
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 2 # Mantiene postgres-0 y postgres-1 en la versión anterior

Resultado: Solo postgres-2 es actualizado.


Comandos Útiles​

Gestión​

# Ver los StatefulSets
kubectl get statefulset
kubectl get sts

# Detalles
kubectl describe statefulset postgres

# Ver los Pods
kubectl get pods -l app=postgres

# Logs de un Pod específico
kubectl logs postgres-0

Scaling​

# Scaling up
kubectl scale statefulset postgres --replicas=5

# Scaling down
kubectl scale statefulset postgres --replicas=2

Actualizaciones​

# Actualización de la imagen
kubectl set image statefulset/postgres postgres=postgres:15

# Ver el estado de la actualización
kubectl rollout status statefulset/postgres

# Rollback
kubectl rollout undo statefulset/postgres

Buenas Prácticas​

1. Respaldos Regulares​

Implemente respaldos automáticos de los volúmenes.

2. Monitoreo​

Supervise el estado de cada Pod y las métricas de rendimiento.

3. Quorum Apropiado​

Utilice un número impar de replicas para evitar empates.

4. Init Containers​

Utilice init containers para la inicialización y verificaciones.

5. Service Headless​

Siempre cree un service headless para el descubrimiento DNS.


Resumen​

En este capítulo, usted ha aprendido:

StatefulSets en profundidad: Aplicaciones stateful con identidades estables
Bases de datos: Despliegue de PostgreSQL con replicación
Init containers: Inicialización antes de los contenedores principales
Replicación: Configuración maestro-esclavo
Quorum: Cálculo y configuración para aplicaciones distribuidas
Scaling: Orden garantizado (ascendente/descendente)
Actualizaciones: RollingUpdate y actualizaciones parciales
Buenas prácticas: Respaldos, monitoreo, quorum


Próximos Pasos​

Capítulo 7.2: DaemonSets
Capítulo 7.3: Jobs
Capítulo 7.4: CronJobs


Capítulo creado el: Diciembre 2024