All Products
Search
Document Center

Container Service for Kubernetes:Use CSI to take over the statically provisioned NAS volumes that are managed by FlexVolume

最終更新日:Nov 01, 2024

The FlexVolume plug-in is deprecated. New Container Service for Kubernetes (ACK) clusters no longer support FlexVolume. For existing clusters, we recommend that you upgrade from FlexVolume to Container Storage Interface (CSI). This topic describes how to use CSI to take over the statically provisioned File Storage NAS (NAS) volumes that are managed by FlexVolume.

Table of contents

Differences between FlexVolume and CSI

The following table describes the differences between CSI and FlexVolume.

Plug-in

Component

kubelet parameter

References

CSI

  • CSI-Provisioner (deployed as a Deployment)

    This component is used to implement automatic volume creation and automatic snapshot creation. This component also supports Container Network File System (CNFS) storage and data restoration after data is accidentally deleted.

  • CSI-Plugin (deployed as a DaemonSet)

    This component is used to implement automatic volume mounting and unmounting. By default, this component supports disk volumes, File Storage NAS (NAS) volumes, and Object Storage Service (OSS) volumes.

The kubelet parameters required by the CSI plug-in are different from those required by the FlexVolume plug-in.

To run the CSI plug-in, you must set the kubelet parameter enable-controller-attach-detach to true on each node.

CSI overview

FlexVolume

  • Disk-Controller (deployed as a Deployment)

    This component is used to implement automatic volume creation.

  • FlexVolume (deployed as a DaemonSet)

    This component is used to implement volume mounting and unmounting. By default, this component supports disk volumes, NAS volumes, and OSS volumes.

The kubelet parameters required by the FlexVolume plug-in are different from those required by the CSI plug-in.

To tun the FlexVolume plug-in, you must set the kubelet parameter enable-controller-attach-detach to true on each node.

FlexVolume overview

Scenarios

FlexVolume is installed in your cluster and used to mount statically provisioned NAS volumes. If you also have disk volumes managed by FlexVolume in the cluster, see Use csi-compatible-controller to migrate from FlexVolume to CSI.

Usage notes

When you upgrade from FlexVolume to CSI, persistent volume claims (PVCs) are recreated. As a result, pods are recreated and your business is interrupted. We recommend that you upgrade to CSI, recreate PVCs, modify applications, or perform other operations that result in pod restarts during off-peak hours.

Preparations

Manually install CSI

  1. Create files named csi-plugin.yaml and csi-provisioner.yaml.

    View the csi-plugin.yaml file

    ---
    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", "udpate"]
      - 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: RollingUpdate

    View the csi-provisioner.yaml file

    ---
    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.token
  2. Run the following command to deploy csi-plugin and csi-provisioner in the cluster:

    kubectl apply -f csi-plugin.yaml -f csi-provisioner.yaml
  3. Run the following command to check whether CSI runs as normal:

    kubectl get pods -nkube-system | grep csi

    Expected 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

    If the preceding output is returned, CSI runs as normal.

In this example, FlexVolume is used to mount a statically provisioned NAS volume to a pod created by a StatefulSet. This example shows how to use CSI to take over the NAS volume that is mounted by using FlexVolume. The following figure shows the procedure.nas

Step 1: Check the status of the volume in the cluster

  1. Run the following command to query the status of the pod:

    kubectl get pod

    Expected output:

    NAME           READY   STATUS    RESTARTS   AGE
    nas-static-1   1/1     Running   0          11m
  2. Run the following command to query the status of the PVC used by the pod:

    kubectl describe pod nas-static-1 |grep ClaimName

    Expected output:

    ClaimName:  nas-pvc
  3. Run the following command to query the status of the PVC:

    kubectl get pvc

    Expected output:

    NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    nas-pvc   Bound    nax-pv   512Gi        RWX                         7m23s

Step 2: Create a statically provisioned NAS volume managed by CSI by defining a PVC and PV

Method 1: Use the Flexvolume2CSI CLI to convert PVs and PVCs

  1. Convert PVs and PVCs managed by FlexVolume to PVs and PVCs managed by CSI.

  2. Run the following command to create a PVC and PV for the NAS volume:

    nas-pv-pvc-csi.yaml is the YAML file that defines the PVC and PV managed by CSI after you use the Flexvolume2CSI CLI to convert the original PVC and PV.

    kubectl apply -f nas-pv-pvc-csi.yaml
  3. Run the following command to query the status of the PVC:

    kubectl get pvc

    Expected output:

    NAME          STATUS   VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    nas-pvc       Bound    nas-pv       512Gi      RWX            nas            30m
    nas-pvc-csi   Bound    nas-pv-csi   512Gi      RWX            nas            2s

Method 2: Save PVCs and PVs managed by FlexVolume and change the volume plug-in

  1. Save the PV and PVC objects managed by FlexVolume.

    1. Run the following command to save the PVC object managed by FlexVolume:

      kubectl get pvc nas-pvc -oyaml > nas-pvc-flexvolume.yaml
      cat nas-pvc-flexvolume.yaml

      Expected output:

      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: nas-pvc
        namespace: default
      spec:
        accessModes:
        - ReadWriteMany
        resources:
          requests:
            storage: 512Gi
        selector:
          matchLabels:
            alicloud-pvname: nas-pv
        storageClassName: nas
    2. Run the following command to save the persistent volume (PV) object managed by FlexVolume:

      kubectl get pv nas-pv -oyaml > nas-pv-flexvolume.yaml
      cat nas-pv-flexvolume.yaml

      Expected output:

      apiVersion: v1
      kind: PersistentVolume
      metadata:
        labels:
          alicloud-pvname: nas-pv
        name: nas-pv
      spec:
        accessModes:
        - ReadWriteMany
        capacity:
          storage: 512Gi
        flexVolume:
          driver: alicloud/nas
          options:
            path: /aliyun
            server: ***.***.nas.aliyuncs.com
            vers: "3"
        persistentVolumeReclaimPolicy: Retain
        storageClassName: nas
  2. Create a statically provisioned NAS volume managed by CSI by defining a PVC and PV.

    1. Create a file named nas-pv-pvc-csi.yaml and add the following YAML content to the file to create a statically provisioned NAS volume managed by CSI:

      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: nas-pvc-csi
        namespace: default
      spec:
        accessModes:
        - ReadWriteMany
        resources:
          requests:
            storage: 512Gi
        selector:
          matchLabels:
            alicloud-pvname: nas-pv-csi
        storageClassName: nas
      ---
      apiVersion: v1
      kind: PersistentVolume
      metadata:
        labels:
          alicloud-pvname: nas-pv-csi
        name: nas-pv-csi
      spec:
        accessModes:
        - ReadWriteMany
        capacity:
          storage: 512Gi
        csi:
          driver: nasplugin.csi.alibabacloud.com
          volumeHandle: nas-pv-csi
          volumeAttributes:
            server: "***.***.nas.aliyuncs.com"  
            path: "/aliyun"
        mountOptions:
        - nolock,tcp,noresvport
        - vers=3
        persistentVolumeReclaimPolicy: Retain
        storageClassName: nas
    2. Run the following command to create a PVC and PV for the NAS volume:

      kubectl apply -f nas-pv-pvc-csi.yaml
    3. Run the following command to query the status of the PVC:

      kubectl get pvc

      Expected output:

      NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
      nas-pvc   Bound    nax-pv   512Gi        RWX                         7m23s

Step 3: Change the PVC associated with the application

  1. Run the following command to modify the configuration file of the application:

    kubectl edit sts nas-static
  2. Change the PVC to the one managed by CSI.

          volumes:
          - name: pvc-nas
            persistentVolumeClaim:
              claimName: nas-pvc-csi
  3. Run the following command to check whether the pod is restarted:

    kubectl get pod

    Expected output:

    NAME           READY   STATUS    RESTARTS   AGE
    nas-static-1   1/1     Running   0          70s
  4. Run the following command to query the mount information:

    kubectl exec nas-static-1 -- mount |grep nas

    Expected output:

    # View the mount information 
    ***.***.nas.aliyuncs.com:/aliyun on /var/lib/kubelet/pods/ac02ea3f-125f-4b38-9bcf-9b117f62***/volumes/kubernetes.io~csi/nas-pv-csi/mount type nfs (rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,nolock,noresvport,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=192.168.XX.XX,mountvers=3,mountport=2049,mountproto=tcp,local_lock=all,addr=192.168.XX.XX)

    If the preceding output is returned, the pod is migrated.

Step 4: Uninstall FlexVolume

  1. Log on to the OpenAPI Explorer console and call the UnInstallClusterAddons operation to uninstall the FlexVolume plug-in.

    • ClusterId: Set the value to the ID of your cluster. You can view the cluster ID on the Basic Information tab of the cluster details page of your cluster.

    • name: Set the value to Flexvolume.

    For more information, see Uninstall components from a cluster.

  2. Run the following command to delete the alicloud-disk-controller and alicloud-nas-controller components:

    kubectl delete deploy -nkube-system alicloud-disk-controller alicloud-nas-controller
  3. Run the following command to check whether the FlexVolume plug-in is uninstalled from your cluster:

    kubectl get pods -n kube-system | grep 'flexvolume\|alicloud-disk-controller\|alicloud-nas-controller'

    If no output is displayed, the FlexVolume plug-in is uninstalled from your cluster.

  4. Run the following command to delete the StorageClass that uses FlexVolume from the cluster. The provisioner of the StorageClass that uses FlexVolume is alicloud/disk.

    kubectl delete storageclass alicloud-disk-available alicloud-disk-efficiency alicloud-disk-essd alicloud-disk-ssd

    Expected 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

    If the preceding output is displayed, the StorageClass is deleted from your cluster.

Step 5: Call the API to install CSI

  1. Log on to the OpenAPI Explorer console and call the InstallClusterAddons to install the CSI plug-in.

    • ClusterId: Set the value to the ID of your cluster.

    • name: Set the value to csi-provisioner.

    • version: The latest version is automatically specified. For more information about CSI versions, see csi-provisioner.

    For more information about how to install the CSI plug-in, see Install a component in an ACK cluster.

  2. Run the following command to check whether the CSI plug-in runs as expected in your cluster:

    kubectl get pods -nkube-system | grep csi

    Expected 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

    If the preceding output is displayed, the CSI plug-in runs as expected in the cluster.

Step 6: Modify the configurations of existing nodes

Create a YAML file based on the following code block. Then, deploy the YAML file to modify the kubelet parameters on which the CSI plug-in relies. This DaemonSet can change the value of the kubelet parameter --enable-controller-attach-detach of an existing node to true. After this step is complete, you can delete the DaemonSet.

Important

When you deploy the YAML file, kubelet is restarted. We recommend that you evaluate the impact on the applications before you deploy the YAML file.

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: /etc