Маємо Helm-чарт VictoriaLogs, в якому заданий PVC з розміром в 30 GB, якого нам стало вже замало, і його треба збільшити.
Але проблема полягає в тому, що .spec.volumeClaimTemplates[*].spec.resources.requests.storage
в STS являється immutable, тобто ми не можемо просто змінити size через values.yaml
, бо це призведе до помилки “Forbidden: updates to statefulset spec for fields other than ‘replicas’, ‘ordinals’, ‘template’, ‘updateStrategy’, ‘revisionHistoryLimit’, ‘persistentVolumeClaimRetentionPolicy’ and ‘minReadySeconds’ are forbidden“.
Values чарту виглядають зараз так:
victoria-logs-single: server: persistentVolume: enabled: true storageClassName: gp2-retain size: 30Gi retentionPeriod: 7d
І при дефолтному типі StatefulSet в чарті для створення PVC використовується volumeClaimTemplates
:
... volumeClaimTemplates: - apiVersion: v1 kind: PersistentVolumeClaim metadata: name: server-volume ... spec: ... resources: requests: storage: {{ $app.persistentVolume.size }} ...
Якби замість STS був тип Deployment – то в чарті VictoriaLogs це призвело б до створення окремого PVC – pvc.yaml
.
Можна було б просто самому створити окремий PVC, і підключати його через value existingClaim
, аде PersistentVolume вже є, створювати новий і переносити дані не хочеться (хоча при потребі – можна, див. VictoriaMetrics: міграція даних VMSingle та VictoriaLogs між кластерами Kubernetes, але буде даунтайм), тому подивимось, як ми можемо це вирішити інакше – без видалення Pods і без зупинки сервісу.
Зміст
storageClassName
та AllowVolumeExpansion
storageClass
, який використовується для створення Persistent Volume має підтримувати AllowVolumeExpansion
– див. Volume expansion:
$ kk describe storageclass gp2-retain Name: gp2-retain ... Provisioner: kubernetes.io/aws-ebs Parameters: <none> AllowVolumeExpansion: True MountOptions: <none> ReclaimPolicy: Retain VolumeBindingMode: WaitForFirstConsumer ...
У нас цей storageClass
створюється при створенні EKS кластеру з простого маніфесту:
... resource "kubectl_manifest" "storageclass_gp2_retain" { yaml_body = <<YAML apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: gp2-retain provisioner: kubernetes.io/aws-ebs reclaimPolicy: Retain allowVolumeExpansion: true volumeBindingMode: WaitForFirstConsumer YAML } ...
Хоча для Terraform є окремий ресурс storage_class
.
Та й kubernetes.io/aws-ebs
вже deprecated (OMG, since Kubernetes 1.17!), пора б оновити на ebs.csi.aws.com
.
Але це будемо фіксити пізніше, зараз задача – просто збільшити диск.
Reproducing the issue
Для тесту напишемо власний STS з volumeClaimTemplates
:
apiVersion: apps/v1 kind: StatefulSet metadata: name: demo-sts spec: serviceName: demo-sts-svc replicas: 1 selector: matchLabels: app: demo template: metadata: labels: app: demo spec: containers: - name: app image: busybox command: ["sh", "-c", "sleep 3600"] volumeMounts: - name: data mountPath: /data volumeClaimTemplates: - metadata: name: data spec: accessModes: ["ReadWriteOnce"] storageClassName: gp2-retain resources: requests: storage: 1Gi
В volumeClaimTemplates
задаємо storageClassName
та розмір 1 гігабайт.
Деплоїмо:
$ kk apply -f test-sts-pvc.yaml statefulset.apps/demo-sts created
Перевіряємо PVC:
$ kk get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE data-demo-sts-0 Bound pvc-31a9a547-7547-4d34-bb2d-2c7015b9e0f3 1Gi RWO gp2-retain <unset> 15s
Тепер, якщо ми захочемо збільшити розмір через volumeClaimTemplates
з 1Gi до 2Gi:
... volumeClaimTemplates: ... resources: requests: storage: 2Gi
То отримаємо помилку:
$ kk apply -f test-sts-pvc.yaml The StatefulSet "demo-sts" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'ordinals', 'template', 'updateStrategy', 'revisionHistoryLimit', 'persistentVolumeClaimRetentionPolicy' and 'minReadySeconds' are forbidden
The Fix
Але ми можемо це обійти дуже просто:
- редагуємо PVC вручну – задаємо новий розмір
- видаляємо STS з
--cascade=orphan
– див. Delete owner objects and orphan dependents - створюємо STS заново
- …
- profit!
Спробуємо.
Note: перед змінами в дисках – не забуваємо про бекапи!
Редагуємо PVC вручну – міняємо resources.requests.storage
з 1Gi
на 2Gi
:
Перевіряємо Events цього PVC:
$ kk describe pvc data-demo-sts-0 ... Normal ExternalExpanding 40s volume_expand CSI migration enabled for kubernetes.io/aws-ebs; waiting for external resizer to expand the pvc Normal Resizing 40s external-resizer ebs.csi.aws.com External resizer is resizing volume pvc-31a9a547-7547-4d34-bb2d-2c7015b9e0f3 Normal FileSystemResizeRequired 35s external-resizer ebs.csi.aws.com Require file system resize of volume on node
І ще через кілька секунд – готово:
... Normal FileSystemResizeSuccessful 19s kubelet
Перевіряємо CAPACITY
:
$ kk get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE data-demo-sts-0 Bound pvc-31a9a547-7547-4d34-bb2d-2c7015b9e0f3 2Gi RWO gp2-retain <unset> 4m7s
2Gi
, все ОК.
І в самому Pod тепер теж маємо 2 гігабайти:
$ kk exec -ti demo-sts-0 -- df -h /data Filesystem Size Used Available Use% Mounted on /dev/nvme7n1 1.9G 24.0K 1.9G 0% /data
Але якщо ми спробуємо задеплоїти зміни в volumeClaimTemplates.spec.resources.requests.storage
ще раз – все одно будемо ловити помилку:
$ kk apply -f test-sts-pvc.yaml The StatefulSet "demo-sts" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'ordinals', 'template', 'updateStrategy', 'revisionHistoryLimit', 'persistentVolumeClaimRetentionPolicy' and 'minReadySeconds' are forbidden
Тому видаляємо сам STS, але залишаємо всі його dependent об’єкти:
$ kubectl delete statefulset demo-sts --cascade=orphan statefulset.apps "demo-sts" deleted
Перевіряємо чи живий Pod:
$ kk get pod NAME READY STATUS RESTARTS AGE demo-sts-0 1/1 Running 0 3m13s
І тепер просто створюємо STS заново, вже з новим значенням в volumeClaimTemplates.spec.resources.requests.storage
:
$ kk apply -f test-sts-pvc.yaml statefulset.apps/demo-sts created
Готово.