容器引擎CCE

    使用文件存储CFS

    准备工作

    用户做好以下准备,才能在容器中挂载CFS实例。

    创建容器集群

    1. 创建一个容器集群,操作步骤参考创建集群
    2. 下载命令行客户端kubectl,并连接集群,操作步骤参考通过kubectl连接Kubernetes集群

    创建CFS实例和挂载点

    1. 创建CFS实例,操作步骤请参考创建文件系统
    2. 添加CFS挂载点,操作步骤请参考添加挂载点

    注意: 创建的cfs实例和挂载点须和集群节点在同一vpc内。

    1. 获取CFS挂载地址,操作步骤请参考获取挂载地址

    本操作假设CFS挂载点地址为 cfs-test.baidubce.com

    操作指南

    静态PV/PVC方式挂载CFS

    1.在集群中创建PV和PVC资源

    使用kubectl,执行 kubectl create -f pv-cfs.yaml 完成PV的创建

    对应的pv-cfs.yaml文件如下所示:

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-cfs
    spec:
      capacity:
        storage: 8Gi
      accessModes:
        - ReadWriteMany
      persistentVolumeReclaimPolicy: Retain
      mountOptions:
        - hard
        - nfsvers=4.1
        - nordirplus
      nfs:
        path: /
        server: cfs-test.baidubce.com

    注意: yaml中server字段对应的是CFS挂载点地址

    注意: yaml中path字段对应的是CFS挂载目录,该目录需要在挂载前预先存在

    创建PV后,输入kubectl get pv可以看见一个available状态的PV,如下所示:

    $ kubectl get pv
    NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGE
    pv-cfs    8Gi        RWX            Retain           Available                                      3s

    建立一个能够与该PV绑定的PVC

    使用kubectl,执行 kubectl create -f pvc-cfs.yaml完成PVC的创建

    对应的pvc-cfs.yaml文件如下所示:

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: pvc-cfs
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 8Gi

    绑定前,PVC为pending状态

    $ kubectl get pvc
    NAME      STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    pvc-cfs   Pending                                                      2s                                                  2s

    绑定后,PV和PVC状态变为Bound

    $ kubectl get pv
    NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM             STORAGECLASS   REASON    AGE
    pv-cfs    8Gi        RWX            Retain           Bound     default/pvc-cfs                            36s
    $ kubectl get pvc
    NAME      STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    pvc-cfs   Bound     pv-cfs    8Gi        RWX                           1m

    有关PV和PVC的更多设置和字段说明,见k8s官方文档

    2.在Pod内挂载PVC

    在Pod spec内指定相应的PVC名称即可,使用kubectl,执行 kubectl create -f demo-cfs-rc.yaml 完成rc的创建

    对应的demo-cfs-rc.yaml文件如下所示:

    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: nginx
    spec:
      replicas: 20
      selector:
        app: nginx
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx
            ports:
            - containerPort: 80
            volumeMounts:
            - mountPath: "/cfs-volume"
              name: mycfs
          volumes:
          - name: mycfs
            persistentVolumeClaim:
              claimName: pvc-cfs

    Pod创建后,可以读写容器内的/cfs-volume路径来访问相应的CFS存储上的内容。

    由于创建PV和PVC时指定了accessModesReadWriteMany,该PVC可以被多节点上的Pod挂载读写。

    3.释放PV和PVC资源

    完成存储资源的使用后,可以释放PVC和PV资源

    使用以下命令可以释放PVC

    $ kubectl delete -f  pvc-cfs.yaml

    释放PVC后,原来与之绑定的PV状态会变为Release,如下所示:

    NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM             STORAGECLASS   REASON    AGE
    pv-cfs    8Gi        RWX            Retain           Released   default/pvc-cfs                            16m

    输入以下指令释放PV资源

    $ kubectl delete -f  pv-cfs.yaml

    动态PV/PVC方式挂载CFS

    1.创建StorageClass和Provisioner

    dynamic-cfs-template.yaml是一个yaml文件模板,包含了需要创建的集群资源信息。

    dynamic-cfs-template.yaml文件内容如下:

    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: nfs-client-provisioner-runner
    rules:
      - apiGroups: [""]
        resources: ["persistentvolumes"]
        verbs: ["get", "list", "watch", "create", "delete"]
      - apiGroups: [""]
        resources: ["persistentvolumeclaims"]
        verbs: ["get", "list", "watch", "update"]
      - apiGroups: ["storage.k8s.io"]
        resources: ["storageclasses"]
        verbs: ["get", "list", "watch"]
      - apiGroups: [""]
        resources: ["events"]
        verbs: ["create", "update", "patch"]
    ---
    kind: ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: run-nfs-client-provisioner
    subjects:
      - kind: ServiceAccount
        name: nfs-client-provisioner
        namespace: kube-system
    roleRef:
      kind: ClusterRole
      name: nfs-client-provisioner-runner
      apiGroup: rbac.authorization.k8s.io
    ---
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: leader-locking-nfs-client-provisioner
      namespace: kube-system
    rules:
      - apiGroups: [""]
        resources: ["endpoints"]
        verbs: ["get", "list", "watch", "create", "update", "patch"]
    ---
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: leader-locking-nfs-client-provisioner
      namespace: kube-system
    subjects:
      - kind: ServiceAccount
        name: nfs-client-provisioner
        # replace with namespace where provisioner is deployed
        namespace: kube-system
    roleRef:
      kind: Role
      name: leader-locking-nfs-client-provisioner
      apiGroup: rbac.authorization.k8s.io
    
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: nfs-client-provisioner
      namespace: kube-system
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-cfs
    spec:
      capacity:
        storage: 5Gi
      accessModes:
        - ReadWriteMany
      persistentVolumeReclaimPolicy: Retain
      mountOptions:
        - hard
        - nfsvers=4.1
        - nordirplus
      nfs:
        path: {{NFS_PATH}}
        server: {{NFS_SERVER}}
    ---
    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: pvc-cfs
      namespace: kube-system
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 5Gi
    ---
    kind: Deployment
    apiVersion: extensions/v1beta1
    metadata:
      name: nfs-client-provisioner
      namespace: kube-system
    spec:
      replicas: 1
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: nfs-client-provisioner
        spec:
          serviceAccountName: nfs-client-provisioner
          containers:
            - name: nfs-client-provisioner
              image: hub.baidubce.com/jpaas-public/nfs-client-provisioner:latest
              imagePullPolicy: Always
              volumeMounts:
                - name: nfs-client-root
                  mountPath: /persistentvolumes
              env:
                - name: PROVISIONER_NAME
                  value: {{PROVISIONER_NAME}}
                - name: NFS_SERVER
                  value: {{NFS_SERVER}}
                - name: NFS_PATH
                  value: {{NFS_PATH}}
                - name: SHARE_PATH
                  value: "{{SHARE_PATH}}"
          volumes:
            - name: nfs-client-root
              persistentVolumeClaim:
                claimName: pvc-cfs
    
    ---
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: {{STORAGE_CLASS_NAME}}
    provisioner: {{PROVISIONER_NAME}}
    parameters:
      archiveOnDelete: "{{ARCHIVE_ON_DELETE}}"
    mountOptions:
      - hard
      - nfsvers=4.1
      - nordirplus

    dynamic-cfs-template.yaml模板文件中可自定义的选项如下:

    • NFS_SERVER: CFS挂载点地址。
    • NFS_PATH: CFS远程挂载目录,注意该目录在使用前需要预先存在,如果目录不存在会导致provisioner插件启动失败。
    • SHARE_PATH: 不同PVC的CFS挂载目录是否隔离,true-不隔离,false-隔离。若指定隔离,则会在CFS挂载目录下为每个PVC创建一个子目录,对应PVC使用该子目录作为挂载目录;否则所有PVC共享挂载目录。
    • ARCHIVE_ON_DELETE: 删除PVC后是否保留对应数据,仅当PVC挂载目录隔离时生效,true-保留,false-不保留;PVC挂载目录共享时,删除PVC不会删除任何数据。设置为不保留则直接删除对应PVC的子目录,否则仅将原子目录名加上archive-前缀后保留。
    • STORAGE_CLASS_NAME: 创建的StorageClass名称。
    • PROVISIONER_NAME: Provisioner名称。

    支持shell的系统中,可以直接使用下面的replace.sh脚本进行yaml模板中模板变量的替换操作。

    #!/bin/sh
    # user defined vars
    
    NFS_SERVER="cfs-test.baidubce.com"
    NFS_PATH="/cce/shared"
    SHARE_PATH="true" # 不同PVC的挂载目录是否隔离,true-不隔离,false-隔离
    ARCHIVE_ON_DELETE="false" # 删除PVC是否保留对应数据,仅当PVC挂载目录隔离时生效,true-保留,false-不保留
    STORAGE_CLASS_NAME="sharedcfs" # StorageClass名称
    PROVISIONER_NAME="baidubce/$STORAGE_CLASS_NAME" # provisioner名称
    
    YAML_FILE="./dynamic-cfs-template.yaml"
    
    # replace template vars in yaml file
    
    sed -i "s#{{SHARE_PATH}}#$SHARE_PATH#" $YAML_FILE
    sed -i "s#{{ARCHIVE_ON_DELETE}}#$ARCHIVE_ON_DELETE#" $YAML_FILE
    sed -i "s#{{STORAGE_CLASS_NAME}}#$STORAGE_CLASS_NAME#" $YAML_FILE
    sed -i "s#{{PROVISIONER_NAME}}#$PROVISIONER_NAME#" $YAML_FILE
    sed -i "s#{{NFS_SERVER}}#$NFS_SERVER#" $YAML_FILE
    sed -i "s#{{NFS_PATH}}#$NFS_PATH#" $YAML_FILE

    将脚本中前半段中的shell变量替换为期望值,将replace.sh脚本和dynamic-cfs-template.yaml文件放置在同一个目录下,执行sh replace.sh即可。

    或者采用其他方式,将模板yaml文件中的模板变量替换为期望值。

    最后,使用kubectl工具,执行 kubectl create -f dynamic-cfs-template.yaml 完成StorageClass和Provisioner的创建。

    $ kubectl create -f dynamic-cfs-template.yaml
    clusterrole "nfs-client-provisioner-runner" created
    clusterrolebinding "run-nfs-client-provisioner" created
    role "leader-locking-nfs-client-provisioner" created
    rolebinding "leader-locking-nfs-client-provisioner" created
    serviceaccount "nfs-client-provisioner" created
    persistentvolume "pv-cfs" created
    persistentvolumeclaim "pvc-cfs" created
    deployment "nfs-client-provisioner" created
    storageclass "sharedcfs" created
    $ kubectl get pod --namespace kube-system  | grep provisioner
    nfs-client-provisioner-c94494f6d-dlxmj   1/1       Running   0          26s

    如果相应的Pod进入Running状态,则动态绑定PV所需的资源已经建立成功。

    2.创建PVC时动态生成PV并绑定

    在PVC Spec中指定上面创建的StorageClass名称,则在创建PVC时,会自动调用相应StorageClass绑定的的Provisioner生成相应的PV进行绑定。

    使用kubectl,执行 kubectl create -f dynamic-pvc-cfs.yaml 完成PVC的创建。

    假设创建的StorageClass名称为sharedcfs,对应的 dynamic-pvc-cfs.yaml 文件如下所示

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: dynamic-pvc-cfs
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: sharedcfs
      resources:
        requests:
          storage: 5Gi

    创建PVC后,可以看见相应的PV自动创建,PVC状态变为Bound,即PVC已经与新创建的PV绑定。

    $ kubectl create -f dynamic-pvc-cfs.yaml
    persistentvolumeclaim "dynamic-pvc-cfs" created
    $ kubectl get pvc
    NAME              STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    dynamic-pvc-cfs   Bound     pvc-6dbf3265-bbe0-11e8-bc54-fa163e08135d   5Gi        RWX            sharedcfs      4s
    $ kubectl get pv
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                     STORAGECLASS   REASON    AGE
    pv-cfs                                     5Gi        RWX            Retain           Bound     kube-system/pvc-cfs                                21m
    pvc-6dbf3265-bbe0-11e8-bc54-fa163e08135d   5Gi        RWX            Delete           Bound     default/dynamic-pvc-cfs   sharedcfs                7s

    3.在Pod内挂载PVC

    在Pod spec内指定相应的PVC名称即可,使用kubectl,执行 kubectl create -f dynamic-cfs-pod.yaml 完成资源的创建。

    对应的dynamic-cfs-pod.yaml文件如下所示:

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pvc-pod
      labels:
        app: test-pvc-pod
    spec:
      containers:
      - name: test-pvc-pod
        image: nginx
        volumeMounts:
          - name: cfs-pvc
            mountPath: "/cfs-volume"
      volumes:
        - name: cfs-pvc
          persistentVolumeClaim:
            claimName: dynamic-pvc-cfs

    Pod创建后,可以读写容器内的/cfs-volume路径来访问相应的CFS存储上的内容。

    4.释放PVC时动态销毁绑定PV

    删除PVC时,与之绑定的动态PV会被一同删除,其中的数据则根据用户定义的SHARE_PATHARCHIVE_ON_DELETE选项进行相应的保留或删除处理。

    $ kubectl get pvc
    NAME              STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    dynamic-pvc-cfs   Bound     pvc-6dbf3265-bbe0-11e8-bc54-fa163e08135d   5Gi        RWX            sharedcfs      9m
    $ kubectl get pv
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                     STORAGECLASS   REASON    AGE
    pv-cfs                                     5Gi        RWX            Retain           Bound     kube-system/pvc-cfs                                31m
    pvc-6dbf3265-bbe0-11e8-bc54-fa163e08135d   5Gi        RWX            Delete           Bound     default/dynamic-pvc-cfs   sharedcfs                9m
    $ kubectl delete -f dynamic-pvc-cfs.yaml
    persistentvolumeclaim "dynamic-pvc-cfs" deleted
    $ kubectl get pv
    NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                 STORAGECLASS   REASON    AGE
    pv-cfs    5Gi        RWX            Retain           Bound     kube-system/pvc-cfs                            31m
    $ kubectl get pvc
    No resources found.
    上一篇
    使用云盘CDS
    下一篇
    使用对象存储BOS