Migrate statically provisioned OSS volumes from FlexVolume to CSI
Migrate statically provisioned OSS volumes from FlexVolume to CSI by recreating PVCs and PVs on an existing ACK cluster.
Applies only to clusters with statically provisioned OSS volumes on FlexVolume. If your cluster also has disk volumes on FlexVolume, see Use csi-compatible-controller to migrate from FlexVolume to CSI.
How CSI and FlexVolume differ
Plugin | Components | kubelet parameter |
CSI | CSI-Provisioner (Deployment): handles volume creation, snapshots, Container Network File System (CNFS) storage, and data restoration after accidental deletion. CSI-Plugin (DaemonSet): mounts and unmounts disk, NAS, and OSS volumes. | Set |
FlexVolume | Disk-Controller (Deployment): handles volume creation. FlexVolume (DaemonSet): mounts and unmounts disk, NAS, and OSS volumes. | Set |
Usage notes
PVCs are recreated during migration, which restarts pods and interrupts workloads. Perform migration during off-peak hours.
Prerequisites
An ACK cluster with FlexVolume installed and at least one statically provisioned OSS volume
kubectl access to create, get, list, and delete PVCs, PVs, Deployments, and DaemonSets in the
kube-systemnamespaceAccess to OpenAPI Explorer to call UnInstallClusterAddons and InstallClusterAddons
Migrate statically provisioned OSS volumes from FlexVolume to CSI
The following example uses a StatefulSet workload to migrate a statically provisioned OSS volume from FlexVolume to CSI.

Step 1: Install CSI manually
Deploy the CSI components alongside the existing FlexVolume installation.
Create two files:
csi-plugin.yamlandcsi-provisioner.yaml. csi-plugin.yaml--- apiVersion: v1 kind: ServiceAccount metadata: name: csi-admin namespace: kube-system --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: alicloud-csi-plugin rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "create", "list"] - apiGroups: [""] resources: ["persistentvolumes"] verbs: ["get", "list", "watch", "update", "create", "delete", "patch"] - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get", "list", "watch", "update"] - apiGroups: [""] resources: ["persistentvolumeclaims/status"] verbs: ["get", "list", "watch", "update", "patch"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] - apiGroups: ["storage.k8s.io"] resources: ["csinodes"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["events"] verbs: ["get", "list", "watch", "create", "update", "patch"] - apiGroups: [""] resources: ["endpoints"] verbs: ["get", "watch", "list", "delete", "update", "create"] - apiGroups: [""] resources: ["configmaps"] verbs: ["get", "watch", "list", "delete", "update", "create"] - apiGroups: [""] resources: ["nodes"] verbs: ["get", "list", "watch", "update"] - apiGroups: ["csi.storage.k8s.io"] resources: ["csinodeinfos"] verbs: ["get", "list", "watch"] - apiGroups: ["storage.k8s.io"] resources: ["volumeattachments"] verbs: ["get", "list", "watch", "update", "patch"] - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshotclasses"] verbs: ["get", "list", "watch", "create"] - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshotcontents"] verbs: ["create", "get", "list", "watch", "update", "delete"] - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshots"] verbs: ["get", "list", "watch", "update", "create"] - apiGroups: ["apiextensions.k8s.io"] resources: ["customresourcedefinitions"] verbs: ["create", "list", "watch", "delete", "get", "update", "patch"] - apiGroups: ["coordination.k8s.io"] resources: ["leases"] verbs: ["get", "create", "list", "watch", "delete", "update"] - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshotcontents/status"] verbs: ["update"] - apiGroups: ["storage.k8s.io"] resources: ["volumeattachments/status"] verbs: ["patch"] - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshots/status"] verbs: ["update"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["namespaces"] verbs: ["get", "list"] - apiGroups: [""] resources: ["pods","pods/exec"] verbs: ["create", "delete", "get", "post", "list", "watch", "patch", "update"] - apiGroups: ["storage.alibabacloud.com"] resources: ["rules"] verbs: ["get"] - apiGroups: ["storage.alibabacloud.com"] resources: ["containernetworkfilesystems"] verbs: ["get","list", "watch"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: alicloud-csi-plugin subjects: - kind: ServiceAccount name: csi-admin namespace: kube-system roleRef: kind: ClusterRole name: alicloud-csi-plugin apiGroup: rbac.authorization.k8s.io --- apiVersion: storage.k8s.io/v1 kind: CSIDriver metadata: name: diskplugin.csi.alibabacloud.com spec: attachRequired: true podInfoOnMount: true --- apiVersion: storage.k8s.io/v1 kind: CSIDriver metadata: name: nasplugin.csi.alibabacloud.com spec: attachRequired: false podInfoOnMount: true --- apiVersion: storage.k8s.io/v1 kind: CSIDriver metadata: name: ossplugin.csi.alibabacloud.com spec: attachRequired: false podInfoOnMount: true --- kind: DaemonSet apiVersion: apps/v1 metadata: name: csi-plugin namespace: kube-system spec: selector: matchLabels: app: csi-plugin template: metadata: labels: app: csi-plugin spec: tolerations: - operator: Exists affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: type operator: NotIn values: - virtual-kubelet nodeSelector: kubernetes.io/os: linux serviceAccount: csi-admin priorityClassName: system-node-critical hostNetwork: true hostPID: true dnsPolicy: ClusterFirst containers: - name: disk-driver-registrar image: registry.cn-hangzhou.aliyuncs.com/acs/csi-node-driver-registrar:v2.3.1-038aeb6-aliyun resources: requests: cpu: 10m memory: 16Mi limits: cpu: 500m memory: 1024Mi args: - "--v=5" - "--csi-address=/var/lib/kubelet/csi-plugins/diskplugin.csi.alibabacloud.com/csi.sock" - "--kubelet-registration-path=/var/lib/kubelet/csi-plugins/diskplugin.csi.alibabacloud.com/csi.sock" volumeMounts: - name: kubelet-dir mountPath: /var/lib/kubelet - name: registration-dir mountPath: /registration - name: nas-driver-registrar image: registry.cn-hangzhou.aliyuncs.com/acs/csi-node-driver-registrar:v2.3.1-038aeb6-aliyun resources: requests: cpu: 10m memory: 16Mi limits: cpu: 500m memory: 1024Mi args: - "--v=5" - "--csi-address=/var/lib/kubelet/csi-plugins/nasplugin.csi.alibabacloud.com/csi.sock" - "--kubelet-registration-path=/var/lib/kubelet/csi-plugins/nasplugin.csi.alibabacloud.com/csi.sock" volumeMounts: - name: kubelet-dir mountPath: /var/lib/kubelet/ - name: registration-dir mountPath: /registration - name: oss-driver-registrar image: registry.cn-hangzhou.aliyuncs.com/acs/csi-node-driver-registrar:v2.3.1-038aeb6-aliyun resources: requests: cpu: 10m memory: 16Mi limits: cpu: 500m memory: 1024Mi args: - "--v=5" - "--csi-address=/var/lib/kubelet/csi-plugins/ossplugin.csi.alibabacloud.com/csi.sock" - "--kubelet-registration-path=/var/lib/kubelet/csi-plugins/ossplugin.csi.alibabacloud.com/csi.sock" volumeMounts: - name: kubelet-dir mountPath: /var/lib/kubelet/ - name: registration-dir mountPath: /registration - name: csi-plugin securityContext: privileged: true allowPrivilegeEscalation: true image: registry.cn-hangzhou.aliyuncs.com/acs/csi-plugin:v1.24.6-55c95dd-aliyun args: - "--endpoint=$(CSI_ENDPOINT)" - "--v=2" - "--driver=oss,nas,disk" env: - name: KUBE_NODE_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - name: CSI_ENDPOINT value: unix://var/lib/kubelet/csi-plugins/driverplugin.csi.alibabacloud.com-replace/csi.sock - name: MAX_VOLUMES_PERNODE value: "15" - name: SERVICE_TYPE value: "plugin" resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 1024Mi livenessProbe: httpGet: path: /healthz port: healthz scheme: HTTP initialDelaySeconds: 10 periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 5 readinessProbe: httpGet: path: /healthz port: healthz initialDelaySeconds: 10 periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 5 ports: - name: healthz containerPort: 11260 volumeMounts: - name: kubelet-dir mountPath: /var/lib/kubelet/ mountPropagation: "Bidirectional" - name: etc mountPath: /host/etc - name: host-log mountPath: /var/log/ - name: ossconnectordir mountPath: /host/usr/ - name: container-dir mountPath: /var/lib/container mountPropagation: "Bidirectional" - name: host-dev mountPath: /dev mountPropagation: "HostToContainer" - mountPath: /var/addon name: addon-token readOnly: true - mountPath: /host/var/run/ name: fuse-metrics-dir volumes: - name: fuse-metrics-dir hostPath: path: /var/run/ type: DirectoryOrCreate - name: registration-dir hostPath: path: /var/lib/kubelet/plugins_registry type: DirectoryOrCreate - name: container-dir hostPath: path: /var/lib/container type: DirectoryOrCreate - name: kubelet-dir hostPath: path: /var/lib/kubelet type: Directory - name: host-dev hostPath: path: /dev - name: host-log hostPath: path: /var/log/ - name: etc hostPath: path: /etc - name: ossconnectordir hostPath: path: /usr/ - name: addon-token secret: defaultMode: 420 optional: true items: - key: addon.token.config path: token-config secretName: addon.csi.token updateStrategy: rollingUpdate: maxUnavailable: 30% type: RollingUpdatecsi-provisioner.yaml
--- kind: Deployment apiVersion: apps/v1 metadata: name: csi-provisioner namespace: kube-system spec: selector: matchLabels: app: csi-provisioner strategy: rollingUpdate: maxSurge: 0 maxUnavailable: 1 type: RollingUpdate replicas: 2 template: metadata: labels: app: csi-provisioner spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: node-role.kubernetes.io/master operator: Exists requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: type operator: NotIn values: - virtual-kubelet podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - csi-provisioner topologyKey: kubernetes.io/hostname tolerations: - effect: NoSchedule operator: Exists key: node-role.kubernetes.io/master - effect: NoSchedule operator: Exists key: node.cloudprovider.kubernetes.io/uninitialized serviceAccount: csi-admin hostPID: true priorityClassName: system-node-critical containers: - name: external-disk-provisioner image: registry.cn-hangzhou.aliyuncs.com/acs/csi-provisioner:v3.0.0-080f01e64-aliyun resources: requests: cpu: 10m memory: 16Mi limits: cpu: 500m memory: 1024Mi args: - "--csi-address=$(ADDRESS)" - "--feature-gates=Topology=True" - "--volume-name-prefix=disk" - "--strict-topology=true" - "--timeout=150s" - "--leader-election=true" - "--retry-interval-start=500ms" - "--extra-create-metadata=true" - "--default-fstype=ext4" - "--v=5" env: - name: ADDRESS value: /var/lib/kubelet/csi-provisioner/diskplugin.csi.alibabacloud.com/csi.sock volumeMounts: - name: disk-provisioner-dir mountPath: /var/lib/kubelet/csi-provisioner/diskplugin.csi.alibabacloud.com - name: external-disk-attacher image: registry.cn-hangzhou.aliyuncs.com/acs/csi-attacher:v3.3-72dd428b-aliyun resources: requests: cpu: 10m memory: 16Mi limits: cpu: 500m memory: 1024Mi args: - "--v=5" - "--csi-address=$(ADDRESS)" - "--leader-election=true" env: - name: ADDRESS value: /var/lib/kubelet/csi-provisioner/diskplugin.csi.alibabacloud.com/csi.sock volumeMounts: - name: disk-provisioner-dir mountPath: /var/lib/kubelet/csi-provisioner/diskplugin.csi.alibabacloud.com - name: external-disk-resizer image: registry.cn-hangzhou.aliyuncs.com/acs/csi-resizer:v1.3-ca84e84-aliyun resources: requests: cpu: 10m memory: 16Mi limits: cpu: 500m memory: 8Gi args: - "--v=5" - "--csi-address=$(ADDRESS)" - "--leader-election" env: - name: ADDRESS value: /var/lib/kubelet/csi-provisioner/diskplugin.csi.alibabacloud.com/csi.sock volumeMounts: - name: disk-provisioner-dir mountPath: /var/lib/kubelet/csi-provisioner/diskplugin.csi.alibabacloud.com - name: external-nas-provisioner image: registry.cn-hangzhou.aliyuncs.com/acs/csi-provisioner:v3.0.0-080f01e64-aliyun resources: requests: cpu: 10m memory: 16Mi limits: cpu: 500m memory: 1024Mi args: - "--csi-address=$(ADDRESS)" - "--volume-name-prefix=nas" - "--timeout=150s" - "--leader-election=true" - "--retry-interval-start=500ms" - "--default-fstype=nfs" - "--v=5" env: - name: ADDRESS value: /var/lib/kubelet/csi-provisioner/nasplugin.csi.alibabacloud.com/csi.sock volumeMounts: - name: nas-provisioner-dir mountPath: /var/lib/kubelet/csi-provisioner/nasplugin.csi.alibabacloud.com - name: external-nas-resizer image: registry.cn-hangzhou.aliyuncs.com/acs/csi-resizer:v1.3-ca84e84-aliyun resources: requests: cpu: 10m memory: 16Mi limits: cpu: 500m memory: 8Gi args: - "--v=5" - "--csi-address=$(ADDRESS)" - "--leader-election" env: - name: ADDRESS value: /var/lib/kubelet/csi-provisioner/nasplugin.csi.alibabacloud.com/csi.sock volumeMounts: - name: nas-provisioner-dir mountPath: /var/lib/kubelet/csi-provisioner/nasplugin.csi.alibabacloud.com - name: external-oss-provisioner args: - --csi-address=$(ADDRESS) - --volume-name-prefix=oss - --timeout=150s - --leader-election=true - --retry-interval-start=500ms - --default-fstype=ossfs - --v=5 env: - name: ADDRESS value: /var/lib/kubelet/csi-provisioner/ossplugin.csi.alibabacloud.com/csi.sock image: registry.cn-hangzhou.aliyuncs.com/acs/csi-provisioner:v3.0.0-080f01e64-aliyun resources: limits: cpu: 500m memory: 1Gi requests: cpu: 10m memory: 16Mi volumeMounts: - mountPath: /var/lib/kubelet/csi-provisioner/ossplugin.csi.alibabacloud.com name: oss-provisioner-dir - name: external-csi-snapshotter image: registry.cn-hangzhou.aliyuncs.com/acs/csi-snapshotter:v4.0.0-a230d5b3-aliyun resources: requests: cpu: 10m memory: 16Mi limits: cpu: 500m memory: 1024Mi args: - "--v=5" - "--csi-address=$(ADDRESS)" - "--leader-election=true" - "--extra-create-metadata=true" env: - name: ADDRESS value: /csi/csi.sock volumeMounts: - name: disk-provisioner-dir mountPath: /csi - name: external-snapshot-controller image: registry.cn-hangzhou.aliyuncs.com/acs/snapshot-controller:v4.0.0-a230d5b3-aliyun resources: requests: cpu: 10m memory: 16Mi limits: cpu: 500m memory: 1024Mi args: - "--v=5" - "--leader-election=true" - name: csi-provisioner securityContext: privileged: true image: registry.cn-hangzhou.aliyuncs.com/acs/csi-plugin:v1.24.6-55c95dd-aliyun args: - "--endpoint=$(CSI_ENDPOINT)" - "--v=2" - "--driver=nas,disk,oss" env: - name: CSI_ENDPOINT value: unix://var/lib/kubelet/csi-provisioner/driverplugin.csi.alibabacloud.com-replace/csi.sock - name: MAX_VOLUMES_PERNODE value: "15" - name: SERVICE_TYPE value: "provisioner" - name: "CLUSTER_ID" value: "CLUSTER_ID" livenessProbe: httpGet: path: /healthz port: healthz scheme: HTTP initialDelaySeconds: 10 periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 5 readinessProbe: httpGet: path: /healthz port: healthz initialDelaySeconds: 5 periodSeconds: 20 ports: - name: healthz containerPort: 11270 volumeMounts: - name: host-log mountPath: /var/log/ - name: disk-provisioner-dir mountPath: /var/lib/kubelet/csi-provisioner/diskplugin.csi.alibabacloud.com - name: nas-provisioner-dir mountPath: /var/lib/kubelet/csi-provisioner/nasplugin.csi.alibabacloud.com - name: oss-provisioner-dir mountPath: /var/lib/kubelet/csi-provisioner/ossplugin.csi.alibabacloud.com - mountPath: /var/addon name: addon-token readOnly: true - mountPath: /mnt mountPropagation: Bidirectional name: host-dev - mountPath: /host/etc name: etc resources: limits: cpu: 500m memory: 1024Mi requests: cpu: 100m memory: 128Mi volumes: - name: disk-provisioner-dir emptyDir: {} - name: nas-provisioner-dir emptyDir: {} - name: oss-provisioner-dir emptyDir: {} - name: host-log hostPath: path: /var/log/ - name: etc hostPath: path: /etc type: "" - name: host-dev hostPath: path: /mnt type: "" - name: addon-token secret: defaultMode: 420 optional: true items: - key: addon.token.config path: token-config secretName: addon.csi.tokenDeploy both components:
kubectl apply -f csi-plugin.yaml -f csi-provisioner.yamlVerify that CSI is running:
kubectl get pods -nkube-system | grep csiExpected output:
csi-plugin-577mm 4/4 Running 0 3d20h csi-plugin-k9mzt 4/4 Running 0 41d csi-provisioner-6b58f46989-8wwl5 9/9 Running 0 41d csi-provisioner-6b58f46989-qzh8l 9/9 Running 0 6d20h
Step 2: Check the current volume status
Record the current state of your workload before converting PVCs and PVs.
Check pod status:
kubectl get podExpected output:
NAME READY STATUS RESTARTS AGE oss-sts-1 1/1 Running 0 11mIdentify the PVC used by the pod:
kubectl describe pod oss-sts-1 |grep ClaimNameExpected output:
ClaimName: oss-pvcCheck the PVC status:
kubectl get pvcExpected output:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE oss-pvc Bound oss-pv 5Gi RWX 7m23s
Step 3: Create CSI-managed PVC and PV for the OSS volume
Choose one of the following methods:
Method 1: Automated (Flexvolume2CSI CLI) | Method 2: Manual YAML editing | |
Best for | Clusters with many PVs to convert | Clusters with a small number of PVs, or when you want full control |
Effort | Low — the CLI generates the CSI YAML | Higher — edit YAML definitions by hand |
Risk | Low — logical conversion only; original PV/PVC objects remain intact until you delete them | Low — same data, new PV/PVC definitions; original objects remain until cleanup |
Downtime | Pod restarts when you update the application reference | Pod restarts when you update the application reference |
Method 1: Automated conversion with the Flexvolume2CSI CLI
Convert FlexVolume PVs and PVCs to CSI definitions with the Flexvolume2CSI CLI. The CLI generates
oss-pv-pvc-csi.yaml.Apply the generated file:
kubectl apply -f oss-pv-pvc-csi.yamlVerify that both the old and new PVCs are bound:
kubectl get pvcExpected output:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE oss-pvc-csi Bound oss-pv-csi 5Gi RWO 7m15s oss-pvc Bound oss-pv 5Gi RWX 52m
Method 2: Manual conversion by editing PVC and PV configurations
Save the existing FlexVolume PVC definition:
kubectl get pvc oss-pvc -oyaml > oss-pvc-flexvolume.yaml cat oss-pvc-flexvolume.yamlExpected output:
apiVersion: v1 kind: PersistentVolumeClaim name: oss-pvc namespace: default spec: accessModes: - ReadWriteMany resources: requests: storage: 5Gi volumeMode: Filesystem volumeName: oss-pvSave the PV:
kubectl get pv oss-pv -oyaml > oss-pv-flexvolume.yaml cat oss-pv-flexvolume.yamlExpected output:
apiVersion: v1 kind: PersistentVolume metadata: name: oss-pv spec: accessModes: - ReadWriteMany capacity: storage: 5Gi claimRef: apiVersion: v1 kind: PersistentVolumeClaim name: oss-pvc namespace: default flexVolume: driver: alicloud/oss nodePublishSecretRef: name: oss-secret namespace: default options: bucket: xxx otherOpts: -o max_stat_cache_size=0 -o allow_other url: xxx.aliyuncs.com persistentVolumeReclaimPolicy: Retain volumeMode: FilesystemCreate
oss-pv-pvc-csi.yamlwith CSI PVC and PV definitions. Replace***with your OSS bucket name and endpoint.apiVersion: v1 kind: PersistentVolumeClaim metadata: name: oss-pvc-csi spec: accessModes: - ReadWriteMany resources: requests: storage: 5Gi selector: matchLabels: alicloud-pvname: oss-pv-csi --- apiVersion: v1 kind: PersistentVolume metadata: name: oss-pv-csi labels: alicloud-pvname: oss-pv-csi spec: capacity: storage: 5Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain csi: driver: ossplugin.csi.alibabacloud.com volumeHandle: oss-pv-csi nodePublishSecretRef: name: oss-secret namespace: default volumeAttributes: bucket: "***" url: "***.aliyuncs.com" otherOpts: "-o max_stat_cache_size=0 -o allow_other"Apply the file:
kubectl apply -f oss-pv-pvc-csi.yamlVerify that both PVCs are bound:
kubectl get pvcExpected output:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE oss-pvc-csi Bound oss-pv-csi 5Gi RWO 7m15s oss-pvc Bound oss-pv 5Gi RWX 52m
Step 4: Update the application to use the CSI-managed PVC
Edit the StatefulSet configuration:
kubectl edit sts oss-stsUpdate the volume reference to the CSI PVC:
volumes: - name: oss persistentVolumeClaim: claimName: oss-pvc-csiVerify the pod restarted:
kubectl get podExpected output:
NAME READY STATUS RESTARTS AGE oss-sts-1 1/1 Running 0 70sVerify the volume uses CSI (ossfs):
kubectl exec oss-sts-1 -- mount |grep ossfsExpected output:
***:/ on /var/lib/kubelet/pods/ac02ea3f-125f-4b38-9bcf-9b117f62eaf0/volumes/kubernetes.io~csi/oss-pv-csi/mount type ossfs (rw,relatime,max_stat_cache_size=0,allow_other)The mount path
kubernetes.io~csiconfirms CSI is active.
Step 5: Uninstall FlexVolume
Call UnInstallClusterAddons in OpenAPI Explorer to uninstall FlexVolume. See Uninstall components from a cluster.
ClusterId: The cluster ID from the Basic Information tab.
name: Set to
flexvolume.
Delete the FlexVolume controller components:
kubectl delete deploy -n kube-system alicloud-disk-controller alicloud-nas-controllerVerify that FlexVolume is fully removed:
kubectl get pods -n kube-system | grep 'flexvolume\|alicloud-disk-controller\|alicloud-nas-controller'No output means FlexVolume is fully removed.
Delete the FlexVolume StorageClasses (provisioner:
alicloud/disk):kubectl delete storageclass alicloud-disk-available alicloud-disk-efficiency alicloud-disk-essd alicloud-disk-ssdExpected output:
storageclass.storage.k8s.io "alicloud-disk-available" deleted storageclass.storage.k8s.io "alicloud-disk-efficiency" deleted storageclass.storage.k8s.io "alicloud-disk-essd" deleted storageclass.storage.k8s.io "alicloud-disk-ssd" deleted
Step 6: Install CSI by using the API
Replace the manually deployed CSI components with the officially managed add-on.
Call InstallClusterAddons in OpenAPI Explorer to install CSI. See Install a component in an ACK cluster.
ClusterId: Your cluster ID.
name:
csi-provisionerversion: Applied automatically. See csi-provisioner for available versions.
Verify that the CSI plug-in is running:
kubectl get pods -nkube-system | grep csiExpected output:
csi-plugin-577mm 4/4 Running 0 3d20h csi-plugin-k9mzt 4/4 Running 0 41d csi-provisioner-6b58f46989-8wwl5 9/9 Running 0 41d csi-provisioner-6b58f46989-qzh8l 9/9 Running 0 6d20h
Step 7: Update kubelet parameters on existing nodes
CSI requires --enable-controller-attach-detach set to true on each node. The following DaemonSet applies this automatically.
This DaemonSet restarts kubelet on each node, which may briefly interrupt pod scheduling. Drain nodes one at a time before deploying, or verify your workloads tolerate a brief kubelet restart. Delete the DaemonSet after this step.
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: kubelet-set
spec:
selector:
matchLabels:
app: kubelet-set
template:
metadata:
labels:
app: kubelet-set
spec:
tolerations:
- operator: "Exists"
hostNetwork: true
hostPID: true
containers:
- name: kubelet-set
securityContext:
privileged: true
capabilities:
add: ["SYS_ADMIN"]
allowPrivilegeEscalation: true
image: registry.cn-hangzhou.aliyuncs.com/acs/csi-plugin:v1.26.5-56d1e30-aliyun
imagePullPolicy: "Always"
env:
- name: enableADController
value: "true"
command: ["sh", "-c"]
args:
- echo "Starting kubelet flag set to $enableADController";
ifFlagTrueNum=`cat /host/etc/systemd/system/kubelet.service.d/10-kubeadm.conf | grep enable-controller-attach-detach=$enableADController | grep -v grep | wc -l`;
echo "ifFlagTrueNum is $ifFlagTrueNum";
if [ "$ifFlagTrueNum" = "0" ]; then
curValue="true";
if [ "$enableADController" = "true" ]; then
curValue="false";
fi;
sed -i "s/enable-controller-attach-detach=$curValue/enable-controller-attach-detach=$enableADController/" /host/etc/systemd/system/kubelet.service.d/10-kubeadm.conf;
restartKubelet="true";
echo "current value is $curValue, change to expect "$enableADController;
fi;
if [ "$restartKubelet" = "true" ]; then
/nsenter --mount=/proc/1/ns/mnt systemctl daemon-reload;
/nsenter --mount=/proc/1/ns/mnt service kubelet restart;
echo "restart kubelet";
fi;
while true;
do
sleep 5;
done;
volumeMounts:
- name: etc
mountPath: /host/etc
volumes:
- name: etc
hostPath:
path: /etcAfter all nodes have enable-controller-attach-detach=true, delete the DaemonSet:
kubectl delete daemonset kubelet-set