在 OpenShift 中的 vSphere CSI 迁移
这篇文章是关于OpenShift Advent Calendar 2022和vExpert Advent Calendar 2022,发表在12月23日的帖子。
首先
如果在 vSphere 环境中使用 OpenShift,今后将推荐使用 CSI 驱动作为用于使用 PV/PVC 的卷插件,并计划在将来删除 In-Tree 驱动程序。通过启用 CSI 迁移,我们可以确认当前使用的由 In-Tree 卷插件创建的 PV/PVC 资源将如何处理。
树内卷插件和容器存储接口(CSI)
在Kubernetes环境中,可以使用嵌入式In-Tree Volume Plugin和CSI作为Persistent Volume的卷插件。目前,推荐使用CSI,并且已经删除了一些In-Tree Volume Plugin。通过实现Container Storage Interface (CSI)而不是In-Tree卷插件,第三方存储供应商可以在不更改Kubernetes代码的情况下使用标准接口提供存储插件。
- CSI Volume Plugins in Kubernetes Design Doc
在vSphere环境中使用In-Tree Volume Plugin和vSphere CSI
vSphere环境中,默认可以使用vsphereVolume(kubernetes.io/vsphere-volume)作为In-Tree卷插件,但该插件已被废弃,推荐使用vSphere CSI。在OpenShift中,vSphere CSI在4.8版本中是TechPreview,在4.10版本中变为GA。如果在2022年12月的最新版本4.11中使用IPI进行安装,则In-Tree驱动程序(kubernetres.io/vsphere-volume)和CSI驱动程序(csi.vsphere.vmware.com)都将配置为StorageClass,且默认标志为thin(In-Tree驱动程序)。
$ oc version
Client Version: 4.11.0-202210262118.p0.g142cb44.assembly.stream-142cb44
Kustomize Version: v4.5.4
Server Version: 4.11.13
Kubernetes Version: v1.24.6+5157800
$ oc get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
thin (default) kubernetes.io/vsphere-volume Delete Immediate false 37m
thin-csi csi.vsphere.vmware.com Delete WaitForFirstConsumer true 35m
$ oc get csidrivers.storage.k8s.io
NAME ATTACHREQUIRED PODINFOONMOUNT STORAGECAPACITY TOKENREQUESTS REQUIRESREPUBLISH MODES AGE
csi.vsphere.vmware.com true false false <unset> false Persistent 37m
在OpenShift 4.11的文档中,关于”VMware vSphere CSI 驱动程序 Operator”的描述中指出,未来计划明确删除In-Tree驱动程序。
OpenShift Container Platform 在默认情况下会设置使用 in-tree 或者非 CSI 驱动的方式来进行 vSphere 存储的供给。
在未来的 OpenShift Container Platform 版本中,通过现有的 in-tree 插件进行供给的容量将会迁移到相应的 CSI 驱动上。CSI 自动迁移将会无缝进行。迁移后,使用永久卷、永久卷请求、存储类等现有的 API 对象的方式将不会发生变化。有关迁移的详细信息,请参阅 CSI 的自动迁移。
在完全迁移之后,in-tree 插件最终将在 OpenShift Container Platform 未来的版本中被删除。
CSI移民
CSI Migration是一种功能,它将对In-Tree驱动程序的操作转换为等效的CSI API,并通过替代的CSI驱动程序来实现。当在Kubernetes集群中启用CSI Migration时,用户可以直接使用现有的StorageClass、PersistentVolume和PersistentVolumeClaim,但Kubernetes会将对In-Tree驱动程序的存储操作传递给CSI驱动程序。通过CSI Migration,用户可以平滑地迁移至CSI驱动程序,最终可以从Kubernetes的核心二进制文件中移除In-Tree存储驱动程序。
OpenShift 4.11(Kubernetes v1.24)ではAzure DiskとOpenStack CinderのAutomatic CSI Migrationが利用可能になっています。
-
- Kubernetes 1.24 Stargazer : Storage Plugin Migration
OpenShift 4.11 : Automatic CSI migration for OpenStack Cinder is generally available / Automatic CSI migration for Microsoft Azure Disk is generally available
vSphere向けのIn-Treeプラグインであるkubernetes.io/vsphere-volumeをvSphere CSI (csi.vsphere.vmware.com)として利用可能にするための、vSphere CSI Migrationは今月リリースのKubernetes v1.26でStable になっています。
- vSphere in-tree to CSI driver migration #1491
据称,vSphere的In-Tree驱动程序将在Kubernetes v1.28中被移除。
- Kubernetes 1.25: Kubernetes In-Tree to CSI Volume Migration Status Update
在OpenShift 4.11中启用vSphere CSI迁移
OpenShift 4.11でPVCを作成して、vSphere CSI Migrationを有効化して挙動を確認してみます。

制作测试PV/PVC
vSphere IPIでインストールした環境でStorageClassthinとthin-csiを利用してPVCを作成してみます。
$ oc get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
vsphere-csi-pvc Bound pvc-cfd35e01-9b4c-41d9-a229-ffaca40c5496 10Gi RWO thin-csi 126m
vsphere-pvc Bound pvc-188bdcc2-943b-4788-8c33-297c917bbd77 10Gi RWO thin 126m
vSphere Clientで確認すると、thin-csiとして作成したPVC(pvc-cfd35e01-9b4c-41d9-a229-ffaca40c5496)はコンテナボリュームとして認識されていますが、thinを指定して作成したPVC(pvc-188bdcc2-943b-4788-8c33-297c917bbd77)はコンテナボリュームとして認識されていません。

govcでCNS Volumesを確認すると、thin-csiとして作成したボリュームだけが表示されています。
$ govc volume.ls -l
098ea18d-457d-4349-b8b3-8e86c525a652 pvc-cfd35e01-9b4c-41d9-a229-ffaca40c5496 10.0GB KUBERNETES nvaie-9pfjt
启用特性门闸
Feature Gate是以featuregates.config.openshift.io资源的形式进行管理的。
$ oc get featuregates.config.openshift.io
NAME AGE
cluster 20h
featuregates.config.openshift.ioリソースを以下のように修正します。
apiVersion: config.openshift.io/v1
kind: FeatureGate
metadata:
name: cluster
spec:
featureSet: CustomNoUpgrade
customNoUpgrade:
enabled:
- CSIMigrationvSphere
启用CSIMigrationvSphere并更新featuregates.config.openshift.io资源。
$ oc apply -f featuregate.yaml
Warning: resource featuregates/cluster is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by oc apply. oc apply should only be used on resources created declaratively by either oc create --save-config or oc apply. The missing annotation will be patched automatically.
featuregate.config.openshift.io/cluster configured
しばらくすると各ノードの設定が変更されます。Masterのkubee-schedulerとkube-controller-managerでは、–feature-gatess=CSIMigrationvSPhere=tureが追加されています。
sh-4.4# hostname
nvaie-9pfjt-master-0
sh-4.4# ps ax | grep -i CSIMigrationvSphere
1946 ? Ssl 0:06 kube-controller-manager --openshift-config=/etc/kubernetes/static-pod-resources/configmaps/config/config.yaml --kubeconfig=/etc/kubernetes/static-pod-resources/configmaps/controller-manager-kubeconfig/kubeconfig --authentication-kubeconfig=/etc/kubernetes/static-pod-resources/configmaps/controller-manager-kubeconfig/kubeconfig --authorization-kubeconfig=/etc/kubernetes/static-pod-resources/configmaps/controller-manager-kubeconfig/kubeconfig --client-ca-file=/etc/kubernetes/static-pod-certs/configmaps/client-ca/ca-bundle.crt --requestheader-client-ca-file=/etc/kubernetes/static-pod-certs/configmaps/aggregator-client-ca/ca-bundle.crt -v=2 --tls-cert-file=/etc/kubernetes/static-pod-resources/secrets/serving-cert/tls.crt --tls-private-key-file=/etc/kubernetes/static-pod-resources/secrets/serving-cert/tls.key --allocate-node-cidrs=false --cert-dir=/var/run/kubernetes --cloud-config=/etc/kubernetes/static-pod-resources/configmaps/cloud-config/cloud.conf --cloud-provider=vsphere --cluster-cidr=10.128.0.0/14 --cluster-name=nvaie-9pfjt --cluster-signing-cert-file=/etc/kubernetes/static-pod-certs/secrets/csr-signer/tls.crt --cluster-signing-duration=720h --cluster-signing-key-file=/etc/kubernetes/static-pod-certs/secrets/csr-signer/tls.key --configure-cloud-routes=false --controllers=* --controllers=-bootstrapsigner --controllers=-tokencleaner --controllers=-ttl --enable-dynamic-provisioning=true --feature-gates=CSIMigrationvSphere=true --flex-volume-plugin-dir=/etc/kubernetes/kubelet-plugins/volume/exec --kube-api-burst=300 --kube-api-qps=150 --leader-elect-resource-lock=configmapsleases --leader-elect-retry-period=3s --leader-elect=true --pv-recycler-pod-template-filepath-hostpath=/etc/kubernetes/static-pod-resources/configmaps/recycler-config/recycler-pod.yaml --pv-recycler-pod-template-filepath-nfs=/etc/kubernetes/static-pod-resources/configmaps/recycler-config/recycler-pod.yaml --root-ca-file=/etc/kubernetes/static-pod-resources/configmaps/serviceaccount-ca/ca-bundle.crt --secure-port=10257 --service-account-private-key-file=/etc/kubernetes/static-pod-resources/secrets/service-account-private-key/service-account.key --service-cluster-ip-range=172.30.0.0/16 --use-service-account-credentials=true --tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 --tls-min-version=VersionTLS12
10209 ? Ssl 0:06 kube-scheduler --config=/etc/kubernetes/static-pod-resources/configmaps/config/config.yaml --cert-dir=/var/run/kubernetes --authentication-kubeconfig=/etc/kubernetes/static-pod-resources/configmaps/scheduler-kubeconfig/kubeconfig --authorization-kubeconfig=/etc/kubernetes/static-pod-resources/configmaps/scheduler-kubeconfig/kubeconfig
--feature-gates=CSIMigrationvSphere=true -v=2 --tls-cert-file=/etc/kubernetes/static-pod-resources/secrets/serving-cert/tls.crt --tls-private-key-file=/etc/kubernetes/static-pod-resources/secrets/serving-cert/tls.key --tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 --tls-min-version=VersionTLS12
93836 ? S+ 0:00 grep -i CSIMigrationvSphere
在kubelet的设置中添加了”CSIMigrationvSphere”: true作为featureGates的配置。
sh-4.4# cat /etc/kubernetes/kubelet.conf
{
"kind": "KubeletConfiguration",
"apiVersion": "kubelet.config.k8s.io/v1beta1",
"staticPodPath": "/etc/kubernetes/manifests",
...
"featureGates": {
"APIPriorityAndFairness": true,
"CSIMigrationAzureFile": false,
"CSIMigrationvSphere": true,
"DownwardAPIHugePages": true,
"RotateKubeletServerCertificate": true
},
...
}
在包含vSphere CSI配置的ConfgMap中,csi-migration的值也被设置为”true”。
$ oc get cm -n openshift-cluster-csi-drivers internal-feature-states.csi.vsphere.vmware.com -oyaml
apiVersion: v1
data:
csi-auth-check: "true"
csi-migration: "true"
online-volume-extend: "true"
kind: ConfigMap
metadata:
creationTimestamp: "2022-12-21T05:38:50Z"
name: internal-feature-states.csi.vsphere.vmware.com
namespace: openshift-cluster-csi-drivers
resourceVersion: "8652"
uid: e5199f4e-b962-4802-9798-b8256a42376f
确认移民
当检查使用In-Tree驱动程序创建的PVC时,可以看到Annotations中带有pv.kubernetes.io/migrated-to: csi.vsphere.vmware.com。
$ oc describe pvc vsphere-pvc
Name: vsphere-pvc
Namespace: masanara
StorageClass: thin
Status: Bound
Volume: pvc-188bdcc2-943b-4788-8c33-297c917bbd77
Labels: <none>
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
pv.kubernetes.io/migrated-to: csi.vsphere.vmware.com
volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/vsphere-volume
volume.kubernetes.io/storage-provisioner: kubernetes.io/vsphere-volume
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 10Gi
Access Modes: RWO
VolumeMode: Filesystem
Used By: vsphere-pod-dc88dd678-wtqpv
Events: <none>
PVのAnnotationsにもpv.kubernetes.io/migrated-to: csi.vsphere.vmware.comがついていますが、Volumeはkubernetes.io/vsphere-volumeとして作成したものが参照されています。
$ oc describe pv pvc-188bdcc2-943b-4788-8c33-297c917bbd77
Name: pvc-188bdcc2-943b-4788-8c33-297c917bbd77
Labels: <none>
Annotations: kubernetes.io/createdby: vsphere-volume-dynamic-provisioner
pv.kubernetes.io/bound-by-controller: yes
pv.kubernetes.io/migrated-to: csi.vsphere.vmware.com
pv.kubernetes.io/provisioned-by: kubernetes.io/vsphere-volume
Finalizers: [kubernetes.io/pv-protection external-attacher/csi-vsphere-vmware-com]
StorageClass: thin
Status: Bound
Claim: masanara/vsphere-pvc
Reclaim Policy: Delete
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 10Gi
Node Affinity: <none>
Message:
Source:
Type: vSphereVolume (a Persistent Disk resource in vSphere)
VolumePath: [Unity-Tanzu] kubevols/nvaie-9pfjt-dynamic-pvc-188bdcc2-943b-4788-8c33-297c917bbd77.vmdk
FSType: ext4
StoragePolicyName:
Events: <none>
当使用vSphere Client进行确认时,我们发现以thin指定创建的PVC(pvc-188bdcc2-943b-4788-8c33-297c917bbd77)也已经被迁移至vSphere CSI进行管理,被识别为容器卷。

CNS volumesを確認すると、thinとして作成したボリュームもCNS volumeに変換されたため一覧に表示されています。
$ govc volume.ls -l
b86b065f-bfc2-4eb7-9780-cd388b20d991 429ddb9e-7ed2-11ed-8ee7-005056ae3ff8 10.0GB KUBERNETES nvaie-9pfjt
098ea18d-457d-4349-b8b3-8e86c525a652 pvc-cfd35e01-9b4c-41d9-a229-ffaca40c5496 10.0GB KUBERNETES nvaie-9pfjt
建立新的PVC
Migrationが有効になった状態で、In-Treeドライバを指定する以下のマニフェストでPVCを作成してみます。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: vsphere-pvc2
spec:
storageClass: thin
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
PVCが作成されました。StorageClassはthinを利用しているため、kubernetes.io/vsphere-volumeが指定されることになります。
$ oc apply -f vsphere-pvc2.yaml
persistentvolumeclaim/vsphere-pvc2 created
$ oc get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
vsphere-csi-pvc Bound pvc-cfd35e01-9b4c-41d9-a229-ffaca40c5496 10Gi RWO thin-csi 3d13h
vsphere-pvc Bound pvc-188bdcc2-943b-4788-8c33-297c917bbd77 10Gi RWO thin 3d13h
vsphere-pvc2 Bound pvc-1b3e1910-94e7-4394-942a-46098f1aa550 10Gi RWO thin 4s
作成されたPVC/PVを確認すると、内部ではCSIを利用してプロビジョニングされていることがわかります。
$ oc describe pvc vsphere-pvc2
Name: vsphere-pvc2
Namespace: masanara
StorageClass: thin
Status: Bound
Volume: pvc-1b3e1910-94e7-4394-942a-46098f1aa550
Labels: <none>
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
volume.beta.kubernetes.io/storage-provisioner: csi.vsphere.vmware.com
volume.kubernetes.io/storage-provisioner: csi.vsphere.vmware.com
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 10Gi
Access Modes: RWO
VolumeMode: Filesystem
Used By: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ExternalProvisioning 2m39s persistentvolume-controller waiting for a volume to be created, either by external provisioner "csi.vsphere.vmware.com" or manually created by system administrator
Normal Provisioning 2m39s csi.vsphere.vmware.com_nvaie-9pfjt-master-2_58e8e693-9e8e-4a85-b45d-54e386a87db7 External provisioner is provisioning volume for claim "masanara/vsphere-pvc2"
Normal ProvisioningSucceeded 2m38s csi.vsphere.vmware.com_nvaie-9pfjt-master-2_58e8e693-9e8e-4a85-b45d-54e386a87db7 Successfully provisioned volume pvc-1b3e1910-94e7-4394-942a-46098f1aa550
$ oc describe pv pvc-1b3e1910-94e7-4394-942a-46098f1aa550
Name: pvc-1b3e1910-94e7-4394-942a-46098f1aa550
Labels: <none>
Annotations: pv.kubernetes.io/migrated-to: csi.vsphere.vmware.com
pv.kubernetes.io/provisioned-by: kubernetes.io/vsphere-volume
volume.kubernetes.io/provisioner-deletion-secret-name:
volume.kubernetes.io/provisioner-deletion-secret-namespace:
Finalizers: [kubernetes.io/pv-protection]
StorageClass: thin
Status: Bound
Claim: masanara/vsphere-pvc2
Reclaim Policy: Delete
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 10Gi
Node Affinity: <none>
Message:
Source:
Type: vSphereVolume (a Persistent Disk resource in vSphere)
VolumePath: [ESA] 8e5c9e63-3078-f184-2bb6-b8cef6a515b8/ba9e5f035b7943dfa38f694b4492d671.vmdk
FSType: ext4
StoragePolicyName:
Events: <none>
当您检查govc的CNS Volume时,可以确认存在由CSI创建的卷(pvc-1b3e1910-94e7-4394-942a-46098f1aa550)。
$ govc volume.ls -l
f30b40be-89ac-4a4a-8e36-e530529e7f1d pvc-1b3e1910-94e7-4394-942a-46098f1aa550 10.0GB KUBERNETES nvaie-9pfjt
b86b065f-bfc2-4eb7-9780-cd388b20d991 429ddb9e-7ed2-11ed-8ee7-005056ae3ff8 10.0GB KUBERNETES nvaie-9pfjt
098ea18d-457d-4349-b8b3-8e86c525a652 pvc-cfd35e01-9b4c-41d9-a229-ffaca40c5496 10.0GB KUBERNETES nvaie-9pfjt
总结
通过使用vSphere CSI Migration,您可以将过去通过In-Tree驱动程序创建的PV/PVC无需考虑迁移到vSphere CSI管理下。然而,目前在当前的OpenShift上启用vSphere CSI Migration似乎不是一个好主意。在即将发布的基于Kubernetes v1.26的OpenShift版本中,应该可以无问题地使用它。