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.