
[!] この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
Oracle Cloud Infrastructure (以下 OCI) の Kubernetes のサービスである Container Engine for Kubernetes (以下 OKE) を利用しています。OKE で永続ボリュームとして PersistentVolume (以下 PV) を利用していますが、Kubernetes v1.23 で、今まで利用してきたボリュームプラグインの FlexVolume が Deprecated になりました。あわせて OKE でも v1.24 からデフォルトのボリュームプラグインが FlexVolume から CSI に変更になりました (Release Note ⧉)。今回は OKE 上で PV のボリュームプラグインを FlexVolume から CSI へ移行した手順を紹介します。
移行前の構成
- Deployment や StatefulSet で管理している Pod に永続ボリュームを接続している
- 永続ボリュームは PersistentVolumeClaim (以下 PVC) から FlexVolume の PV を動的プロビジョニングで払い出して利用している
また、検証で利用したそれぞれのツールのバージョンは以下のとおりです。
- OKE ⧉ (Kubernetes ⧉)
- v1.23.4
- OCI CLI ⧉
- 3.15.2
- jq ⧉
- jq-1.6
移行手段
移行手段の候補として以下 3 つの方法を挙げます。
- 【パターン A】Block Volume を複製して PV を静的プロビジョニングで払い出して利用する方法
- 【パターン B】Block Volume を再利用して PV を CSI で作り直す方法
- 【パターン C】パターン B+動的プロビジョニングで払い出した PV と認識させる方法
【パターン A】Block Volume を複製して PV を静的プロビジョニングで払い出して利用する方法
OCI の公式ドキュメントには FlexVolume の場合は「Creating a PVC From an Existing Block Volume or A Backup ⧉」に手順がありましたが、CSI についてはドキュメントに記載がありませんでした。OCI のサポートに問い合わせたところ、複製した Block Volume を参照して PV を静的に作成して紐づける手順の回答をいただいたため、こちらの手順を紹介します。
-
Deployment の削除
永続ボリュームへの書き込みを止めるため、一度 Deployment との接続を停止します。
Terminal window ## 永続ボリュームを使用していた旧 Deployment を削除して、PV との紐づけを解除する$ kubectl delete deployment old-deploy -
Block Volume の複製
動的プロビジョニングの設定により、PVC を削除すると、参照していた Block Volume が削除されるため、先にデータを格納した Block Volume を複製します。複製して作成した Block Volume の OCID を控えておきます。
-
旧 PVC の削除
PVC を削除すると動的プロビジョニングのため、PV および紐づく Block Volume が削除されます。
Terminal window ## 旧 PVC を削除する$ kubectl delete pvc old-pvcpersistentvolumeclaim "old-pvc" deleted## 一覧から old-pvc の削除を確認する$ kubectl get pvcNo resources found in default namespace.## PV の一覧から削除されていることを確認する$ kubectl get pvNo resources found. -
新 PV の作成
CSI のボリュームハンドルの指定で複製した Block Volume を紐づけて PV を作成します。
Terminal window ## PV のマニフェストを作成する$ vim ./new-pv.yamlapiVersion: v1kind: PersistentVolumemetadata:name: new-pvspec:storageClassName: "oci-bv" # OCI の CSI の StorageClass を選択claimRef: # 他の PVC の要求から紐づかないよう、PVC を指定する (Namespace: default の new-pvc に紐づける)namespace: defaultname: new-pvccapacity:storage: 50Gi # 複製前の PV と同じ値accessModes:- ReadWriteOncecsi:driver: blockvolume.csi.oraclecloud.com # OCI の CSI のドライバを選択volumeHandle: <Block Volume の OCID> # 複製した Block Volume の OCIDTerminal window ## PV を展開する$ kubectl apply -f ./new-pv.yamlpersistentvolume/new-pv created## 展開した PV を確認する$ kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEnew-pv 50Gi RWO Retain Available default/new-pvc oci-bv 16s -
新 PVC の作成
手順 4. で作成した PV を指定して PVC を作成します。
Terminal window ## PVC のマニフェストを作成する$ vim ./new-pvc.yamlapiVersion: v1kind: PersistentVolumeClaimmetadata:name: new-pvcspec:storageClassName: "oci-bv" # OCI の CSI の StorageClass を選択accessModes:- ReadWriteOncevolumeName: new-pv # 上で作成した PV の名前resources:requests:storage: 50GiTerminal window ## PVC を展開する$ kubectl apply -f ./new-pvc.yamlpersistentvolumeclaim/new-pvc created## 展開した PVC を確認する$ kubectl get pvcNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGEnew-pvc Bound new-pv 50Gi RWO oci-bv 27s## PV のステータスも確認する (STATUS: Bound となり、紐づいたことが確認できる)$ kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEnew-pv 50Gi RWO Retain Bound default/new-pvc oci-bv 4m49s -
Deployment の展開
作成した PVC を利用して Deployment の Pod と Block Volume を紐づけます。
Terminal window ## Deployment のマニフェストを作成する## (サンプルとして /mount-pvc に PVC をマウントした ubuntu の Pod を作成する)$ vim ./new-deploy.yamlapiVersion: apps/v1kind: Deploymentmetadata:name: new-deployspec:replicas: 1selector:matchLabels:app: new-deploytemplate:metadata:labels:app: new-deployspec:containers:- name: ubuntuimage: ubuntu:20.04command: [ "/bin/bash", "-c", "--" ]args: [ "while true; do sleep 30; done;" ] # sleep を繰り返して稼働したままにするvolumeMounts:- name: pvcmountPath: "/mount-pvc"volumes:- name: pvcpersistentVolumeClaim:claimName: new-pvc # 上で作成した PVC の名前に変更するTerminal window ## Deployment (Pod) を展開する$ kubectl apply -f ./new-deploy.yamldeployment.apps/new-deploy created## Pod の展開を確認する$ kubectl get podNAME READY STATUS RESTARTS AGEnew-deploy-xxxxxxxxxx-yyyyy 1/1 Running 0 4m43s## Pod のコンテナにアクセスしてデータが復元されているか確認する$ kubectl exec -it new-deploy-xxxxxxxxxx-yyyyy -- /bin/bashTerminal window ## PVC の中のファイルを確認するroot@new-deploy-xxxxxxxxxx-yyyyy:/# ls /mount-pvc/test.txt## ファイルの中身を確認するroot@new-deploy-xxxxxxxxxx-yyyyy:/# cat /mount-pvc/test.txttest## 確認できたため、コンテナからログアウトするroot@new-deploy-xxxxxxxxxx-yyyyy:/# exitexit
これで FlexVolume から CSI に移行することができました。
【パターン B】Block Volume を再利用して PV を CSI で作り直す方法
次に、Block Volume を複製する手間を省き、再利用できるようにパターン A の手順を変更します。PVC の削除時に PV および Block Volume も削除されてしまう原因は、動的プロビジョニングで払い出した PV の ReclaimPolicy が Delete に設定されているためです。ReclaimPolicy を Retain にすることで動的プロビジョニングで払い出した PV でも削除されないようにすることが可能です。
-
旧 PV の修正
Terminal window ## 動的プロビジョニングで払い出した PV を確認する## (RECLAIM POLICY が Delete になっている)$ kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaa 50Gi RWO Delete Bound default/old-pvc oci 69s## 一時的に ReclaimPolicy を Delete から Retain に変更する (マニフェストの該当部分以外は一部省略)$ kubectl edit pv ocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaaapiVersion: v1kind: PersistentVolumemetadata:name: ocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaaspec:flexVolume:driver: oracle/ocifsType: ext4# persistentVolumeReclaimPolicy: Delete # Retain に変更するpersistentVolumeReclaimPolicy: RetainstorageClassName: oci # FlexVolumeTerminal window ## 保存すると設定が更新されるpersistentvolume/ocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaa edited## PV のポリシーを確認する## (RECLAIM POLICY が Retain になっている)$ kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaa 50Gi RWO Retain Bound default/old-pvc oci 8m43s -
旧 PV, PVC の削除
PV の設定を変更し、PVC, PV それぞれを削除しても Block Volume は残るようになりました。 それぞれ削除して確認します。
Terminal window ## PVC を削除する$ kubectl delete pvc old-pvcpersistentvolumeclaim "old-pvc" deleted## PV を削除する$ kubectl delete pv ocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaapersistentvolume "ocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaa" deleted## PV の削除を確認する$ kubectl get pvNo resources found.## OCI の Block Volume 一覧を確認する## aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee という名前の Block Volume が削除されず残っている$ oci bv volume list --compartment-id <コンパートメント OCID> --sort-order DESC | jq -r '.data[] | [."display-name", ."id"] | @csv'"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee","ocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaa" -
新 PV の作成、新 PVC の作成、Deployment の修正
以順はパターン A と同じ手順となります。
【パターン C】パターン B+動的プロビジョニングで払い出した PV と認識させる方法
当社の運用では静的プロビジョニングで BV を残して運用する手順となりました。FlexVolume から CSI への移行にあたり、動的プロビジョニングの削除時のように PVC 削除時に BV まで一緒に削除される挙動に戻すとなると工夫が必要なため、その手順について紹介します。
-
旧 PV の修正、PV, PVC の削除
旧 PV の修正、PV, PVC の削除まではパターン B と同じ手順となります。
-
新 PV の作成
動的プロビジョニングで払い出した PV と自分で Block Volume と紐づけた静的プロビジョニングで払い出した PV の差分を確認すると、Annotation にフラグが付いていることに気づきました。新 PV を作成する際、以下の修正をすることで動的プロビジョニングで払い出した場合と同様になることを確認しました。
Terminal window ## パターン A (および、手順を省略したパターン B) で利用した PV のマニフェストを修正する$ vim ./new-pv.yamlapiVersion: v1kind: PersistentVolumemetadata:name: new-pvannotations:pv.kubernetes.io/provisioned-by: blockvolume.csi.oraclecloud.com # 追加 (動的プロビジョニングで作成した場合のフラグ)spec:storageClassName: "oci-bv"persistentVolumeReclaimPolicy: Delete # 修正 (動的プロビジョニングと同様に、PV 削除時に Block Volume も削除するポリシーに変更する)claimRef:namespace: defaultname: new-pvccapacity:storage: 50GiaccessModes:- ReadWriteOncecsi:driver: blockvolume.csi.oraclecloud.comvolumeHandle: <Block Volume の OCID>Terminal window ## PV を展開する$ kubectl apply -f ./new-pv.yamlpersistentvolume/new-pv created## PV の展開を確認する$ kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEnew-pv 50Gi RWO Delete Available default/new-pvc oci-bv 6s -
新 PVC の作成、Deployment の修正
新 PVC の作成 以降の手順もパターン A、パターン B と同じ手順になります。
PVC 削除時に動的プロビジョニングと同じ挙動をするか確認
最後に、検証として、パターン C で作成した PV が動的プロビジョニングで払い出した場合と同様に、紐づいた Block Volume が削除されるかを確認するため、PVC を削除します。
## 対象のリソースを確認する$ kubectl get pvcNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGEnew-pvc Bound new-pv 50Gi RWO oci-bv 19m$ kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEnew-pv 50Gi RWO Delete Bound default/new-pvc oci-bv 19m
## PV の情報を確認する$ kubectl get pv new-pv -o yamlapiVersion: v1kind: PersistentVolumemetadata: annotations: pv.kubernetes.io/provisioned-by: blockvolume.csi.oraclecloud.com # 追加したアノテーション name: new-pvspec: csi: driver: blockvolume.csi.oraclecloud.com volumeHandle: ocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaa # 紐づく Block Volume の OCID persistentVolumeReclaimPolicy: Delete
## OCI の Block Volume 一覧を確認する$ oci bv volume list --compartment-id <コンパートメント OCID> --sort-order DESC | jq -r '.data[] | [."display-name", ."id"] | @csv'"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee","ocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaa"
## Block Volume の情報を取得する (該当箇所以外は一部省略して表記)$ oci bv volume get --volume-id ocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaa{ "data": { "id": "ocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaa", "lifecycle-state": "AVAILABLE", # ステータスが使用可能になっている },}
## Deployment を削除して Pod と PV との紐づきを解除する$ kubectl get podNAME READY STATUS RESTARTS AGEnew-deploy-xxxxxxxxxx-yyyyy 1/1 Running 0 19m
$ kubectl delete deploy new-deploydeployment.apps "new-deploy" deleted
## それぞれリソース一覧から削除されていることを確認する$ kubectl get deploymentNo resources found in default namespace.$ kubectl get podNo resources found in default namespace.
## PVC を削除してみる$ kubectl delete pvc new-pvcpersistentvolumeclaim "new-pvc" deleted
## PVC 一覧から削除を確認する$ kubectl get pvcNo resources found in default namespace.
## 削除した PVC に紐づいた PV の削除も確認する$ kubectl get pvNo resources found.
## 削除した PV に紐づいた Block Volume の情報を確認する (該当箇所以外は一部省略して表記)$ oci bv volume get --volume-id ocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaa{ "data": { "id": "ocid1.volume.oc1.ap-tokyo-1.aaaaaaaaaa", "lifecycle-state": "TERMINATED", # ステータスが削除済になる (OCI コンソール上はステータスが「終了済」と表記) },}
以上で動的プロビジョニングで作成した場合と同様に、PVC の削除のみで、紐づく PV および Block Volume が削除されるようになりました。
おわりに
今回は OKE のバージョンアップにあたり、Deprecated になった FlexVolume の PV を CSI に移行する手順を紹介しました。CSI を利用した PV のリストア手順や、動的プロビジョニングと静的プロビジョニングとの切り替えは OCI 公式のドキュメントにも記載が今のところないため、同じような悩みを抱えている方の手助けになれれば幸いです。