7. Migrar MongoDB a StatefulSet
Motivo
Un Deployment gestiona Pods intercambiables. Un StatefulSet proporciona identidad estable y almacenamiento asociado.
Deployment:
db-<hash>-<hash>
StatefulSet:
db-0
Services de MongoDB
Se utilizan dos Services:
db
-> Service ClusterIP normal
-> lo utiliza la API
db-headless
-> Service sin ClusterIP
-> proporciona identidad de red al StatefulSet
La API continúa utilizando:
mongodb://db/mern-crud
El Service normal db ofrece una IP virtual estable y redirige hacia los endpoints disponibles.
El Service headless tiene:
clusterIP: None
Y permite resolver el Pod por un nombre estable:
db-0.db-headless.mern.svc.cluster.local
La IP del Pod puede cambiar, pero el nombre db-0 permanece.
StatefulSet reutilizando el PVC existente
Crear k8s/05-db-statefulset.yaml:
apiVersion: v1
kind: Service
metadata:
name: db
namespace: mern
spec:
type: ClusterIP
selector:
app: db
ports:
- name: mongodb
port: 27017
targetPort: 27017
---
apiVersion: v1
kind: Service
metadata:
name: db-headless
namespace: mern
spec:
clusterIP: None
selector:
app: db
ports:
- name: mongodb
port: 27017
targetPort: 27017
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: db
namespace: mern
spec:
serviceName: db-headless
replicas: 1
selector:
matchLabels:
app: db
template:
metadata:
labels:
app: db
spec:
terminationGracePeriodSeconds: 30
containers:
- name: mongo
image: mongo:7.0
imagePullPolicy: IfNotPresent
ports:
- name: mongodb
containerPort: 27017
volumeMounts:
- name: mongo-data
mountPath: /data/db
volumes:
- name: mongo-data
persistentVolumeClaim:
claimName: mongo-data
Migrar
Eliminar el Deployment anterior:
kubectl delete deployment db -n mern
El PVC no se elimina.
Crear el StatefulSet:
kubectl apply -f k8s/05-db-statefulset.yaml
Comprobar:
kubectl get statefulset,pods,pvc -n mern -w
El Pod debe llamarse:
db-0
Probar identidad estable
kubectl delete pod db-0 -n mern
El nuevo Pod vuelve a llamarse db-0 y conserva los datos del PVC.
No escalar MongoDB a varias réplicas todavía. Un StatefulSet no convierte automáticamente MongoDB en un replica set.
Separar los manifiestos
El archivo inicial k8s/01-db-api.yaml también contenía la API. Después de migrar MongoDB:
- Renombrar el archivo antiguo para no aplicarlo accidentalmente.
- Crear
k8s/01-api.yamlcopiando únicamente el Deployment y el Service de la API. - Mantener el Service
db, el Servicedb-headlessy el StatefulSet enk8s/05-db-statefulset.yaml.
Una estructura final recomendada es:
k8s/
├── 01-api.yaml
├── 02-web.yaml
├── 03-ingress.yaml
├── 04-db-pvc.yaml
└── 05-db-statefulset.yaml
No volver a aplicar el manifiesto antiguo de Deployment de MongoDB.
Pruebas a realizar
-
Comparar los recursos que gestionan MongoDB antes y después de la
migración:kubectl get deployment,statefulset,pods,services,pvc -n mern -
Describir el StatefulSet y comprobar que utiliza el Service headless:
kubectl describe statefulset db -n mern kubectl get service db-headless -n mern -o yaml -
Resolver desde un Pod temporal el Service normal y el nombre estable del
Pod:kubectl run debug-dns -n mern --rm -it --restart=Never \ --image=busybox:1.36 -- shDentro del Pod:
nslookup db nslookup db-headless nslookup db-0.db-headless.mern.svc.cluster.local exit -
Eliminar
db-0y observar que el StatefulSet crea otro Pod con el mismo
nombre y el mismo PVC:kubectl delete pod db-0 -n mern kubectl get pods,pvc -n mern -w -
Comprobar que los datos siguen disponibles después de la recreación del
Pod y revisar los endpoints de ambos Services:kubectl get endpointslice -n mern \ -l kubernetes.io/service-name=db -o wide kubectl get endpointslice -n mern \ -l kubernetes.io/service-name=db-headless -o wide -
Revisar que no exista todavía un Deployment de MongoDB activo:
kubectl get deployment db -n mernEl resultado esperado es que no se encuentre ese Deployment; MongoDB debe
estar gestionado por el StatefulSet.
Aprendizajes del despliegue
- Un StatefulSet proporciona identidad estable a sus Pods.
- El nombre
db-0vuelve a utilizarse aunque el Pod sea eliminado y recreado. - El PVC puede reutilizarse durante la migración sin perder los datos.
- El Service normal ofrece una dirección estable para la API.
- El Service headless permite descubrir los Pods por identidad y nombre DNS estable.
- La dirección IP de un Pod puede cambiar, mientras que su identidad lógica permanece.
- Un StatefulSet no convierte automáticamente MongoDB en un clúster replicado ni en un replica set.
- El orden y la identidad de los Pods son responsabilidades distintas de la disponibilidad de la aplicación.
- Separar los manifiestos reduce el riesgo de volver a crear accidentalmente el Deployment antiguo.