Guía definitiva de StatefulSet de Kubernetes – CodesCode

Explora la gestión de aplicaciones de estado con StatefulSets de Kubernetes cuándo utilizarlos, cómo implementar MongoDB, limitaciones y mejores prácticas para su implementación.

StatefulSet es una API de carga de trabajo de Kubernetes específicamente utilizada para administrar aplicaciones con estado. Esta es una guía completa para configurar y usar StatefulSets, donde veremos los siguientes temas:

  1. ¿Qué es un StatefulSet y cuándo deberías usarlo?
  2. Ejemplo: Configuración y ejecución de MongoDB como StatefulSet
  3. Límites de los StatefulSets y lo que hay que tener en cuenta
  4. Mejores prácticas al implementar StatefulSets

Aplicaciones con y sin estado

Comencemos distinguiendo aplicaciones con y sin estado. Una aplicación sin estado es aquella en la que cada solicitud se trata como una transacción nueva e independiente de cualquier transacción anterior. No almacena datos específicos de la sesión entre solicitudes, ya sea en el lado del cliente o en el lado del servidor.

Kubernetes es conocido por ser excelente en el manejo de servicios sin estado. Para una aplicación sin estado, las cápsulas son completamente intercambiables: escalar hacia arriba y hacia abajo no resultará en ninguna pérdida de datos. Kubernetes utiliza el Despliegue para administrar cápsulas de aplicaciones sin estado.

En contraste, las aplicaciones con estado mantienen datos entre sesiones y transacciones. Recuerdan actividades pasadas y personalizan las interacciones del usuario en función de este estado recordado. Por ejemplo, todas las bases de datos son con estado.

Entonces, ¿cómo gestionamos aplicaciones con estado en Kubernetes, dado que no podemos reiniciar o matar cápsulas al azar? Aquí es donde entran en juego los StatefulSets.

¿Qué es un StatefulSet?

Un StatefulSet es un objeto de API de carga de trabajo de Kubernetes diseñado para administrar aplicaciones con estado que requieren identidades de red estables y almacenamiento persistente.

Proporciona ciertas garantías sobre el orden y la unicidad de las cápsulas y cómo se implementan y escalan (ver más abajo).

  • Garantías de orden: Cuando desplegamos usando un StatefulSet, las cápsulas se crean secuencialmente y en orden (a diferencia de Despliegues o Conjuntos de Réplicas). Esto es relevante para sistemas donde el orden de inicio es importante, como bases de datos distribuidas.
  • Identificadores persistentes: Cada cápsula en un StatefulSet tiene un nombre de host estable y predecible, típicamente en el formato <nombre-de-cápsula>-<número-ordinal>. Incluso si una cápsula cambia de ubicación, su identificador permanece inalterado.
  • Almacenamiento estable: Cuando usamos un StatefulSet, cada cápsula está asociada con un almacenamiento persistente. Este almacenamiento permanece conectado a la cápsula específica aunque esta se mueva a otro nodo.
  • Escala y actualización controlada: Un StatefulSet permite escalar y actualizar aplicaciones de forma controlada, asegurando que operaciones como las actualizaciones graduales no comprometan la integridad de la aplicación.

Controlador de StatefulSet

El Controlador de StatefulSet es un controlador de Kubernetes responsable de la supervisión y gestión del ciclo de vida de las cápsulas creadas en función de una especificación de cápsula de StatefulSet. Se encuentra en el plano de control y se encarga de orquestar la creación, escalado y eliminación de cápsulas en el orden exacto establecido en la definición de StatefulSet.

Ventajas de los StatefulSets

  1. Predictibilidad: StatefulSet garantiza un orden predecible en el despliegue, escalado y eliminación de cápsulas, lo cual es fundamental para aplicaciones como bases de datos donde importa la secuencia de operaciones.
  2. Estabilidad: Incluso si una cápsula en un StatefulSet se bloquea o el nodo que la aloja falla, la identidad de la cápsula (nombre, nombre del host y almacenamiento) se mantiene consistente.
  3. Seguridad de los datos: Junto con las reclamaciones de volumen persistente, un StatefulSet garantiza que los datos de cada cápsula estén protegidos. Si se reprograma una cápsula, sus datos permanecen intactos.
  4. Fácil descubrimiento y comunicación: Cada cápsula tiene su propio DNS, lo que facilita el descubrimiento de servicios y la comunicación dentro de las cápsulas.
  5. Provisiones para intervención manual: Para aquellos casos especiales en los que se necesita más control, un StatefulSet permite la intervención manual sin que el sistema intente “corregir” automáticamente de inmediato.

El diseño y las ventajas de un StatefulSet ofrecen una clara distinción respecto a otros objetos de Kubernetes, lo que lo convierte en la opción preferida para administrar aplicaciones con estado.

Despliegue vs. StatefulSet

Veamos cómo difiere un StatefulSet de un Despliegue:

1. Nombre e identidad de la cápsula

Despliegue: Las cápsulas tienen una ID que contiene el nombre del despliegue y un hash aleatorio

StatefulSet: Cada cápsula recibe una identidad persistente con el nombre del StatefulSet y un número de secuencia

2. Secuencia de creación de cápsulas

Implementación: Los pods se crean y eliminan al azar

StatefulSet: Los pods creados en secuencia no se pueden eliminar al azar

3. Interchangeability

Implementación:Todos los pods son idénticos y se pueden intercambiar

StatefulSet: Los pods no son idénticos y no se pueden intercambiar

4. Reasignación

Implementación: En cualquier momento, un pod puede ser reemplazado por una nueva réplica

StatefulSet: Los pods conservan su identidad al reprogramarse en otro nodo

5. Reclamación de Volumen

Implementación: Todas las réplicas comparten la misma Reclamación de Volumen Persistente (PVC) y un volumen

StatefulSet: Cada pod obtiene un PVC y volumen únicos

6. Interacción de Pod

Implementación: Necesita un servicio para interactuar con los pods

StatefulSet: El servicio sin cabeza maneja las identidades de red de los pods

Cuándo usar StatefulSet

Use StatefulSets cuando su aplicación tenga estado. Pregúntese: ¿Su aplicación requiere identidades estables para sus pods? ¿Su sistema se verá interrumpido cuando se reemplace una réplica de pod?

Las bases de datos replicadas son un buen ejemplo de cuándo se necesita un StatefulSet. Un pod actúa como nodo de base de datos principal, manejando tanto la lectura como la escritura, mientras que los otros pods son réplicas de solo lectura. Cada pod puede ejecutar la misma imagen del contenedor, pero cada uno necesita una configuración para establecer si está en modo principal o de solo lectura.

Algo como esto:

  • mongodb-0: Nodo principal (lectura y escritura).
  • mongodb-1: Réplica de solo lectura.
  • mongodb-2: Réplica de solo lectura.

Si reduce el tamaño de un ReplicaSet o Deployment, se eliminan pods arbitrarios, lo que podría incluir al nodo principal en este sistema de MongoDB.

Sin embargo, cuando usamos un StatefulSet, Kubernetes termina los pods en el orden opuesto a su creación, lo que asegura que mongodb-2 se destruye primero en este ejemplo.

Ejemplo de StatefulSet: Ejecutando MongoDB en Kubernetes

Ahora, veamos un ejemplo y ejecutemos un clúster de MongoDB en Kubernetes utilizando un StatefulSet.

Paso 1: Configurar un servicio sin cabeza

La identidad de los pods en un StatefulSet está estrechamente relacionada con su identidad de red estable, por lo que un servicio sin cabeza es vital.

Un servicio sin cabeza se define configurando su clusterIP a None, lo que garantiza identidades de red estables para los pods.

Este es un archivo YAML para nuestro servicio de MongoDB:

    apiVersion: v1kind: Servicemetadata:  name: mongodb  labels:    app: mongodbspec:  ports:    - name: mongodb      port: 27017  clusterIP: None  selector:    app: mongodb

Implementemos el servicio en el clúster:

$ kubectl apply -f mongodb-service.yamlservice/mongodb created

Paso 2: Desplegar el StatefulSet de MongoDB

El siguiente archivo YAML es para el StatefulSet. Describe la ejecución de tres réplicas de la imagen de MongoDB:

    apiVersion: apps/v1kind: StatefulSetmetadata:  name: mongodbspec:  selector:    matchLabels:      app: mongodb  serviceName: mongodb  replicas: 3  template:    metadata:      labels:        app: mongodb    spec:      containers:        - name: mongodb          image: mongo:latest          ports:          - name: mongodb            containerPort: 27017          volumeMounts:          - name: data            mountPath: /data/db  volumeClaimTemplates:  - metadata:      name: data    spec:      accessModes: ["ReadWriteOnce"]      resources:        requests:          storage: 1Gi

Ahora, apliquemos la configuración del StatefulSet:

$ kubectl apply -f mongodb-statefulset.yamlstatefulset.apps/mongodb created

Verifiquemos los nuevos pods para verlos en acción:

Estado de los pods

Podemos ver que los tres pods se crean secuencialmente, asegurando la inicialización de uno antes de que lo haga el siguiente pod.

Cada nuevo pod en este StatefulSet de MongoDB tendrá su propio Volumen Persistente y Reclamación de Volumen Persistente. Estas reclamaciones se generan a partir del campo volumeClaimTemplates del StatefulSet.

Los Volúmenes Persistentes proporcionan un espacio de almacenamiento en el clúster, independiente de cualquier pod individual que lo utilice. Son recursos en el clúster, al igual que los nodos son recursos del clúster. Los PV tienen un ciclo de vida independiente de cualquier pod individual que use volúmenes de almacenamiento del PV.

Echemos un vistazo a los PV.

$ kubectl get pv...

La salida muestra los Volúmenes Persistentes disponibles en el clúster. Para nuestro StatefulSet de MongoDB con tres réplicas, esto es lo que vemos:

$ kubectl get pvc...

Vemos aquí las Solicitudes de Volúmenes Persistentes realizadas por los tres pods. Tener almacenamiento dedicado garantiza que nuestra instancia de MongoDB conserve sus datos independientemente de los ciclos de vida de los pods, lo cual es vital para cualquier sistema de bases de datos.

Paso 3: Escalar el Cluster de MongoDB

Vamos a ver cómo escalar nuestras instancias de MongoDB:

$ kubectl scale sts mongodb --replicas=5statefulset.apps/mongodb escalado

Confirmemos que los pods se crean de forma secuencial.

$ kubectl get pods...

Aquí podemos ver por la edad que los pods se crearon de forma secuencial y cuándo.

De manera similar, veamos cómo reducir la escala:

$ kubectl scale sts mongodb --replicas=2statefulset.apps/mongodb escalado

Kubernetes ahora terminará los pods en el mismo volumen en el orden inverso de creación.

Como se puede ver, los últimos pods se terminan primero.

Este ejemplo muestra cómo el StatefulSet asegura que MongoDB, una aplicación con estado, se ejecute sin problemas, escalando cuando sea necesario y conservando datos importantes mediante Kubernetes.

Limitaciones de los StatefulSets

Aunque StatefulSet de Kubernetes ofrece una serie de opciones para gestionar aplicaciones con estado, existen algunas limitaciones. Entender estas limitaciones nos ayudará a tomar decisiones informadas para nuestro caso de uso específico.

1. Despliegue más lento

El proceso de escalado secuencial de un StatefulSet garantiza consistencia y orden, pero también conlleva despliegues más lentos, especialmente para aplicaciones a gran escala.

2. Intervención manual para limpiar/restaurar el estado

Si un pod en un StatefulSet se corrompe, simplemente eliminar el pod no siempre resolverá el problema. El almacenamiento persistente adjunto podría seguir conteniendo uno o más de los pods corruptos en el statefulset. En tales casos, puede ser necesario realizar una intervención manual para limpiar o restaurar el estado.

3. Cambiar el tamaño es complejo

Un StatefulSet está estrechamente ligado a los recursos de almacenamiento de sus Solicitudes de Volúmenes Persistentes (PVC). Una vez que se crea un PVC, no se puede cambiar fácilmente de tamaño. Si necesitamos ampliar los volúmenes de almacenamiento, a menudo tenemos que pasar por un proceso más complejo dependiendo del proveedor de almacenamiento que estemos utilizando.

4. Complejidad de la copia de seguridad

Hacer una copia de seguridad de los datos del pod anterior en una aplicación con estado gestionada por un StatefulSet requiere una planificación más cuidadosa. Debemos asegurarnos de la consistencia de los datos en varios pods, especialmente en bases de datos distribuidas donde los datos pueden estar particionados.

5. Desafíos con las configuraciones de red

Un StatefulSet se basa en servicios headless para la identidad de red. Si bien esto asegura un nombre de host único, introduce complejidades, especialmente cuando necesitamos configurar la comunicación entre pods o manejar escenarios donde se necesita acceder a pods específicos externamente.

Mejores prácticas de los StatefulSets

Dado lo que sabemos sobre StatefulSet, aquí hay algunas mejores prácticas a tener en cuenta

1. Utilice nombres únicos y relevantes para los pods de sus StatefulSets

Esto ayuda a identificar y gestionar los pods específicos de StatefulSets y sus recursos de manera más fácil.

2. Gestione la inicialización y el orden

Utilice contenedores de inicio para realizar tareas de preinicialización de forma secuencial. Esto garantiza que las tareas de configuración críticas, como la población de datos o la inicialización de la configuración, se completen antes de que comience el contenedor principal de la aplicación.

    spec:  template:    spec:      initContainers:      - name: init-container-1        image: init-image-1        # Agregue aquí la configuración del contenedor de inicio      - name: init-container-2        image: init-image-2        # Agregue aquí la configuración del contenedor de inicio      containers:      - name: main-container        image: main-image        # Agregue aquí la configuración del contenedor principal

Si su StatefulSet requiere un orden específico para la inicialización del pod (por ejemplo, el primario de una base de datos debe iniciarse antes que las réplicas), puede implementar lógica personalizada dentro de sus contenedores de inicio o utilizar herramientas como wait-for-it o wait-for para gestionar la disponibilidad del pod.

3. Manejar el escalado cuidadosamente

Asegúrate de entender las dependencias y requisitos de tu aplicación con estado antes de escalar un StatefulSet. Escalar hacia arriba debe preservar la consistencia de los datos, mientras que escalar hacia abajo puede requerir estrategias adecuadas de migración o respaldo de datos. Utiliza estrategias como la replicación basada en quórum o la partición para mantener la integridad de los datos durante el escalado.

4. Definir presupuestos de interrupción de Pods (PDBs)

Los PDBs te permiten establecer políticas que limitan la cantidad de pods que pueden ser interrumpidos simultáneamente durante eventos como el escalado hacia abajo o el mantenimiento. Para definir un presupuesto de interrupción de Pods para tu StatefulSet, crea un recurso PodDisruptionBudget y especifica el campo maxUnavailable, que determina el número máximo de pods no disponibles en cualquier momento dado. Por ejemplo, para asegurar que como máximo un pod esté no disponible durante el escalado o mantenimiento, establece maxUnavailable: 1.

Aquí tienes una guía rápida:

A. Crea un archivo YAML de presupuesto de interrupción de Pods (por ejemplo, pdb.yaml) para tu StatefulSet

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: ejemplo-pdb
spec:
  maxUnavailable: 1  # Ajusta este valor según tus necesidades
  selector:
    matchLabels:
      app: tu-etiqueta-de-StatefulSet

B. Agrega el PDB a tu clúster de Kubernetes

kubectl apply -f pdb.yaml

5. Respaldar y restaurar datos

Implementa mecanismos de respaldo y restauración para los datos almacenados en volúmenes persistentes. Esto asegura disponibilidad y resiliencia de los datos en caso de fallas o situaciones de recuperación ante desastres. Puedes utilizar alguna de las muchas herramientas de respaldo o escribir scripts personalizados.

Observabilidad y solución de problemas para StatefulSets

En general, la observabilidad de un StatefulSet en Kubernetes es bastante similar a la de un Deployment (ambos pueden ser instrumentados con las mismas soluciones de métricas y registro, como Prometheus y FluentD), pero hay algunas diferencias a tener en cuenta.

En ciertos aspectos, es más fácil hacer un seguimiento de los pods individuales con un StatefulSet, ya que los StatefulSets asignan nombres estables y predecibles a sus pods, como pod-0, pod-1, etc. Esto nos permite solucionar problemas y depurar más fácilmente. En contraste, los Deployments utilizan nombres aleatorios para los pods, por lo que necesitamos confiar más en etiquetas y selectores.

Sin embargo, es posible que deseemos realizar un seguimiento de algunas métricas y registros adicionales para los StatefulSets, como métricas que capturan el estado de los pods individuales, la distribución de datos, la replicación de datos, la sincronización y la consistencia entre los pods. También podríamos querer monitorear los diferentes estados de los pods a medida que escalamos hacia arriba o hacia abajo, como “Pending” (pendiente), “Running” (ejecutándose) o “Terminating” (terminando), para asegurarnos de que los datos se muevan o repliquen correctamente durante estas transiciones.

Del mismo modo, para las alertas, probablemente querremos incluir alertas adicionales relacionadas con el comportamiento específico de los pods o las transiciones de estado, como cambios en el recuento de réplicas, identidad o utilización de almacenamiento.

Para obtener una lectura más completa sobre cómo configurar la observabilidad de manera adecuada, puedes consultar este artículo.

A menudo, los problemas más molestos son causados por StatefulSets y son más difíciles de simular y depurar. Si estás en ambiente de preparación y estás tratando de determinar si un problema es causado por una aplicación con estado, en lugar de intentar simular el estado del StatefulSet, puedes utilizar herramientas de código abierto como Klone para evitar por completo la simulación y depurar más rápidamente. También existe una categoría de productos de IA emergentes, como ZeroK.ai, que ayudan automáticamente a identificar posibles causas utilizando IA mediante la ejecución de investigaciones automatizadas en tus datos de observabilidad, lo cual podría valer la pena explorar.

Resumen

En este artículo, examinamos cómo funcionan los StatefulSets y cómo son diferentes a un Deployment. Configuramos y ejecutamos MongoDB como un StatefulSet y examinamos las limitaciones y las mejores prácticas al implementar StatefulSets. Los StatefulSets son de gran utilidad para reducir la complejidad de la implementación y administración de aplicaciones con estado en Kubernetes.


Leave a Reply

Your email address will not be published. Required fields are marked *