Cómo cambiar el tamaño de los volúmenes de un StatefulSet de Kubernetes

logotipo de Kubernetes

Los Kubernetes StatefulSets se utilizan para implementar aplicaciones con estado dentro de su clúster. Cada Pod en el StatefulSet puede acceder volúmenes persistentes locales que se adhieren incluso después de que se reprograme. Esto permite que los pods mantengan un estado individual separado de sus vecinos en el conjunto.

Desafortunadamente, estos volúmenes vienen con una gran limitación: Kubernetes no proporciona una forma de cambiar su tamaño desde el objeto StatefulSet. los spec.resources.requests.storage propiedad de StatefulSet volumeClaimTemplates campo es inmutable, impidiéndole aplicar los aumentos de capacidad que necesite. Este artículo le mostrará cómo solucionar el problema.

Creación de un StatefulSet

Copie este YAML y guárdelo en ss.yaml:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  ports:
  - name: nginx
    port: 80
  clusterIP: None
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  serviceName: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - name: web
          containerPort: 80
        volumeMounts:
        - name: data
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi

Aplique YAML a su clúster con Kubectl:

$ kubectl apply -f ss.yaml
service/nginx created
statefulset.apps/nginx created

necesitarás un clase de almacenamiento y aprovisionador en su clúster para ejecutar este ejemplo. Crea un StatefulSet que ejecuta tres réplicas de un servidor web NGINX.

Si bien esto no es representativo de cuándo se deben usar StatefulSets, es adecuado como demostración de los problemas de volumen que puede enfrentar. Se monta una reclamación de volumen con 1 Gi de almacenamiento en el directorio de datos de NGINX. Su contenido web podría superar esta asignación relativamente pequeña a medida que escala su servicio. Sin embargo, tratar de modificar el volumeClaimTemplates.spec.resources.requests.storage campo a 10Gi informará el siguiente error cuando ejecute kubectl apply:

$ kubectl apply -f ss.yaml
service/nginx unchanged
The StatefulSet "nginx" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'template', 'updateStrategy', 'persistentVolumeClaimRetentionPolicy' and 'minReadySeconds' are forbidden

Esto ocurre porque casi todos los campos del manifiesto de un StatefulSet son inmutables después de la creación.

Cambiar manualmente el tamaño de los volúmenes StatefulSet

Puede omitir la restricción cambiando manualmente el tamaño de la reclamación de volumen persistente (PVC). Luego deberá volver a crear el StatefulSet para liberar y volver a vincular el volumen de sus Pods. Esto activará el evento de cambio de tamaño de volumen real.

Primero use Kubectl para encontrar los PVC asociados con su StatefulSet:

$ kubectl get pvc
NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES
data-nginx-0   Bound    pvc-ccb2c835-e2d3-4632-b8ba-4c8c142795e4   1Gi        RWO         
data-nginx-1   Bound    pvc-1b0b27fe-3874-4ed5-91be-d8e552e515f2   1Gi        RWO         
data-nginx-2   Bound    pvc-4b7790c2-3ae6-4e04-afee-a2e1bae4323b   1Gi        RWO

Hay tres PVC porque hay tres réplicas en StatefulSet. Cada Pod tiene su propio volumen individual.

Ahora usa kubectl edit para ajustar la capacidad de cada volumen:

$ kubectl edit pvc data-nginx-0

El manifiesto YAML de PVC aparecerá en su editor. Encuentra el spec.resources.requests.storage campo y cámbielo a su nueva capacidad deseada:

# ...
spec:
  resources:
    requests:
      storage: 10Gi
# ...

Guarde y cierre el archivo. Kubectl debería informar que el cambio se ha aplicado a su clúster.

persistentvolumeclaim/data-nginx-0 edited

Ahora repita estos pasos para los PVC restantes de StatefulSet. La lista de volúmenes persistentes de su clúster debería mostrar el nuevo tamaño contra cada uno:

$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               
pvc-0a0d0b15-241f-4332-8c34-a24b61944fb7   10Gi       RWO            Delete           Bound    default/data-nginx-2
pvc-33af452d-feff-429d-80cd-a45232e700c1   10Gi       RWO            Delete           Bound    default/data-nginx-0
pvc-49f3a1c5-b780-4580-9eae-17a1f002e9f5   10Gi       RWO            Delete           Bound    default/data-nginx-1

Las reclamaciones mantendrán el tamaño anterior por ahora:

$ kubectl get pvc
NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES
data-nginx-0   Bound    pvc-33af452d-feff-429d-80cd-a45232e700c1   10Gi       RWO         
data-nginx-1   Bound    pvc-49f3a1c5-b780-4580-9eae-17a1f002e9f5   10Gi       RWO         
data-nginx-2   Bound    pvc-0a0d0b15-241f-4332-8c34-a24b61944fb7   10Gi       RWO

Esto se debe a que no se puede cambiar el tamaño del volumen mientras los pods todavía lo están usando.

Recreando el StatefulSet

Complete el cambio de tamaño liberando el reclamo de volumen del StatefulSet que lo contiene. Elimine el StatefulSet pero use el orphan mecanismo en cascada por lo que sus Pods permanecen en su clúster. Esto ayudará a minimizar el tiempo de inactividad.

$ kubectl delete statefulset --cascade=orphan nginx
statefulset.apps "nginx" deleted

A continuación, edite su archivo YAML original para incluir el nuevo tamaño de volumen en el spec.resources.requests.storage expediente. Entonces usa kubectl apply para recrear el StatefulSet en su clúster:

$ kubectl apply -f ss.yaml
service/nginx unchanged
statefulset.apps/nginx created

El nuevo StatefulSet asumirá la propiedad de los Pods anteriormente huérfanos porque ya cumplirán con sus requisitos. Los volúmenes pueden cambiar de tamaño en este punto, pero en la mayoría de los casos tendrá que iniciar manualmente una implementación que reinicie sus Pods:

$ kubectl rollout restart statefulset nginx

La implementación se realiza de forma secuencial, apuntando a un pod a la vez. Esto asegura que su servicio permanezca accesible en todo momento.

Ahora sus PVC deberían mostrar el nuevo tamaño:

$ kubectl get pvc
NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES
data-nginx-0   Bound    pvc-33af452d-feff-429d-80cd-a45232e700c1   10Gi       RWO         
data-nginx-1   Bound    pvc-49f3a1c5-b780-4580-9eae-17a1f002e9f5   10Gi       RWO         
data-nginx-2   Bound    pvc-0a0d0b15-241f-4332-8c34-a24b61944fb7   10Gi       RWO

Intente conectarse a uno de sus Pods para verificar que la capacidad aumentada sea visible desde adentro:

$ kubectl exec -it nginx-0 bash
root@nginx-0:/# df -h /usr/share/nginx/html
Filesystem                                                                Size  Used Avail Use% Mounted on
/dev/disk/by-id/scsi-0DO_Volume_pvc-33af452d-feff-429d-80cd-a45232e700c1  9.9G  4.5M  9.4G   1% /usr/share/nginx/html

El Pod informa los 10 Gi esperados de almacenamiento.

Resumen

Kubernetes StatefulSets le permite ejecutar aplicaciones con estado en Kubernetes con volúmenes de almacenamiento persistentes que se limitan a pods individuales. Sin embargo, la flexibilidad que esto permite termina cuando necesita cambiar el tamaño de uno de sus volúmenes. Esta es una función que falta y actualmente requiere que se completen varios pasos manuales en secuencia.

Los mantenedores de Kubernetes son conscientes del problema. hay un abierto solicitud de función para desarrollar una solución que eventualmente debería permitirle iniciar cambios de tamaño de volumen editando el manifiesto de StatefulSet. Esto será mucho más rápido y seguro que la situación actual.

Una advertencia final es que los cambios de tamaño de volumen dependen de un controlador de almacenamiento que permite la expansión dinámica. Esta característica solo estuvo disponible de forma general en Kubernetes v1.24 y no todos los controladores, las distribuciones de Kubernetes y las plataformas en la nube la admitirán. Puedes comprobar si el tuyo lo hace ejecutando kubectl get sc y buscando true en el ALLOWVOLUMEXPANSION columna del controlador de almacenamiento que está utilizando con sus StatefulSets.

Deja un comentario

En esta web usamos cookies para personalizar tu experiencia de usuario.    Política de cookies
Privacidad