はじめに
PersistenVolumeClaim(PVC)を使っているPodに対してストレージサイズ拡張に伴う再起動が必要ない、すなわちゼロダウンタイムで拡張を行える方法をDeploymentとStatefulSetの2パターンで説明します。
環境はEKS、外部ストレージはEBSを前提としています。
手順
kubeletの設定、StorageClassの設定、PVCの拡張、の順に説明していきます。
kubeletの設定
Cloudformationのワーカーノード起動時の設定に「BootstrapArguments」の項目があるので、そこにkubeletの設定を加えます。
--kubelet-extra-args "--feature-gates=ExpandInUsePersistentVolumes=true"
ワーカーノードの設定はあらかじめ入れておかないと意味がないことに注意しましょう。例えばワーカーノード作成後にSSHして設定を変えたとしても、自動復旧で立ち上がった新たなワーカーノードにはその設定が反映されません。
StorageClassの設定
EKSにはあらかじめgp2
というStorageClassが用意されています。
デフォルトではストレージ拡張のためのパラメータallowVolumeExpansion
がfalse
になっているので変更する必要があります。
## "allowVolumeExpansion: true"を追記する。
$ kubectl edit storageclass gp2
## 変更内容を確認する。
$ kubectl get storageclass gp2 -o yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"storage.k8s.io/v1","kind":"StorageClass","metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"},"name":"gp2"},"parameters":{"fsType":"ext4","type":"g p2"},"provisioner":"kubernetes.io/aws-ebs"}
storageclass.kubernetes.io/is-default-class: "true"
creationTimestamp: 2019-08-13T03:34:59Z
name: gp2
resourceVersion: "70681"
selfLink: /apis/storage.k8s.io/v1/storageclasses/gp2
uid: 53ddc7e2-bd7b-11e9-a365-0a4781fb1e78
parameters:
fsType: ext4
type: gp2
provisioner: kubernetes.io/aws-ebs
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true
PVCの拡張
DeploymentとStatefulSetの2パターン説明します。両方ともDynamic ProvisioningでPVを動的に生成することを前提とします。
拡張を行う際には下記2点に注意しましょう。
- AWSでは1つのボリュームの拡張変更を行えるのは6時間に1度だけ
- ボリュームサイズを元の値より小さくすることはできない
Deploymentの場合
手順は次のようになります。
- PVCのマニフェストファイル
pvc.yaml
のspec.resources.requests.storage
の値を変更する。 -
$ kubectl apply -f pvc.yaml
で変更を反映させる。
実験として、あるPVCを8Giから9Giに変更してみます。この作業を行うと自動的にEBSのリサイズが始まります。下の画像を見るとボリュームの状態がin-use
となっていることが分かります。
このときPVCを確認してもサイズは8Giのままです。
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
sample Bound pvc-1a94f083-bdd3-11e9-adc6-0ed3a87e16f4 8Gi RWO gp2 20h
PVCを確認してみます。サイズが9Giに変わっていることが分かります。
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
sample Bound pvc-1a94f083-bdd3-11e9-adc6-0ed3a87e16f4 9Gi RWO gp2 20h
StatefulSetの場合
PVCのリソーススペックはStatefulSetのマニフェストにおけるspec.volumeClaimTemplates
で定義しているものとします。
このもとで、手順は次のようになります。
-
$ kubectl edit pvc <PVC>
でspec.resources.requests.storage
の値を変更する。 -
$ kubectl delete statefulset <STATEFULSET> --cascade=false
でPodを削除せずStatefulSetのみ削除する。 - 1で変更した
spec.resources.requests.storage
の値を、StatefulSetのマニフェストファイルstatefulset.yaml
のspec.volumeClaimTemplates[].spec.resources.requests.storage
に記述する。 -
$ kubectl apply -f statefulset.yaml
で変更を反映させる。
StatefulSetを途中で削除しています。これは、PVCのマニフェストで定義されている内容とStatefulSetのマニフェストに相違がないようにするためです。
直接StatefulSetのspec.volumeClaimTemplates[].spec.resources.requests.storage
に変更を加えてkubectl apply
しても下記のエラーが発生します。
$ kubectl apply -f statefulset.yaml
* spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'template', and 'updateStrategy' are forbidden
まとめ
EKSにデプロイしたDeployment、StatefulSetにアタッチされているEBSのボリューム拡張をゼロダウンタイムで行う方法を説明しました。
StatefulSetは冪等性を保たせるために無理やりな方法を取っていますが、今の所他の方法がなさそうです。