
# 通过静态存储卷使用已有并行文件系统
本文介绍如何使用已有的并行文件系统静态创建PV和PVC，并在工作负载中实现数据持久化与共享性。
#### 前提条件
- 已设置[并行文件系统卷挂载设置访问密钥（AK/SK）](https://support.huaweicloud.com/usermanual-cci2/cci_01_0336.html)。
- 您需要通过命令行创建，需要使用ccictl连接到CCI 2.0，详情请参见[ccictl配置指南](https://support.huaweicloud.com/devg-cci2/cci_ccictl_02.html)。
 
#### 约束与限制
- 使用并行文件系统时，挂载点不支持修改属组和权限。
- 使用PVC挂载并行文件系统时，负载每挂载一个并行文件系统卷，后端会产生一个常驻进程。当负载使用并行文件系统数过多或大量读写并行文件系统文件时，常驻进程会占用大量内存，为保证负载稳定运行，建议负载使用的并行文件系统卷数量不超过其申请的内存GiB数量，如负载的申请的内存规格为4GiB，则建议其使用的并行文件系统数**不超过**4个。
- 使用并行文件系统，不支持只读挂载，如果需要指定并行文件系统的权限，请参考[并行文件系统权限配置](https://support.huaweicloud.com/usermanual-obs/obs_13_0012.html#section1)章节配置并行文件系统权限。

- 支持多个PV挂载同一个并行文件系统，但有如下限制：
  - 多个不同的PVC/PV使用同一个底层并行文件系统卷时，如果挂载至同一Pod使用，会因为PV的volumeHandle参数值相同导致无法挂载，请避免该使用场景。
  
  - PV中persistentVolumeReclaimPolicy参数必须设置为Retain，否则可能存在一个PV删除时，级联删除底层卷，其他关联这个底层卷的PV会由于底层存储被删除导致使用出现异常。
  
  - 重复用底层存储时，数据一致性由您自行维护。建议在应用层做好多读多写的隔离保护，合理规划文件使用时间，避免出现多个客户端写同一个文件的情况，防止产生数据覆盖和丢失。
   
- 在使用并行文件系统挂载时，如果配置了subPath（子路径），请勿在OBS控制台或通过API删除该subPath对应的存储目录。否则，将导致挂载点无法清理，进而使Pod无法正常删除（长期处于Terminating 状态）。
- CCI 2.0当前支持在西南-贵阳一使用并行文件系统。
 
#### 通过ccictl命令行使用已有对象存储
1. 使用ccictl连接CCI2.0。
2. 创建PV。 
   1. 创建pv-obs.yaml文件。
      ```
      apiVersion: cci/v2
      kind: PersistentVolume
      metadata:
        name: pv-obs                                  # PV的名称
      spec:
        accessModes:
        - ReadWriteMany                                # 访问模式，并行文件系统必须为ReadWriteMany
        capacity:
          storage: 1Gi                                # 存储容量大小，此处仅为校验需要（不能为空和0），设置的大小不起作用
        csi:
          driver: obs.csi.everest.io                   # 挂载依赖的存储驱动
          fsType: obsfs                              # 实例类型
          volumeHandle: <your_file_system_name>   # 并行文件系统的名称
          nodePublishSecretRef:                       # 设置并行文件系统的密钥
            name: <your_secret_name>                  # Secret的名称
            namespace: <your_namespace>               # Secret的命名空间
        persistentVolumeReclaimPolicy: Retain         # 回收策略
        storageClassName: csi-obs                  # 存储类名称
        mountOptions: []                             # 挂载参数
      ```
       表1关键参数说明 
      | 参数                            | 是否必选 | 参数类型   | 描述                                                                                                                                                                                                                                                                  |
      |:---|:---|:---|:---|
      | accessModes                   | 是    | List   | 参数解释：存储访问模式 约束限制：并行文件系统必须为ReadWriteMany                                                                                                                                                                                               |
      | driver                        | 是    | String | 参数解释：挂载依赖的存储驱动 约束限制：并行文件系统必须为obs.csi.everest.io                                                                                                                                                                                       |
      | fsType                        | 是    | String | 参数解释：存储实例类型 约束限制：支持"obsfs"，即并行文件系统                                                                                                                                                                                                      |
      | volumeHandle                  | 是    | String | 参数解释：并行文件系统的名称 约束限制：必须为已创建的并行文件系统的名称                                                                                                                                                                                                  |
      | nodePublishSecretRef          | 是    | Object | 参数解释：并行文件系统卷挂载支持设置访问密钥（AK/SK），您可以使用AK/SK创建一个Secret，然后挂载到PV。详细说明请参见[并行文件系统卷挂载设置访问密钥（AK/SK）](https://support.huaweicloud.com/usermanual-cci2/cci_01_0336.html) 示例如下： ``` nodePublishSecretRef: name: secret-demo namespace: default ``` |
      | mountOptions                  | 否    | List   | 参数解释：挂载参数，具体请参见[设置并行文件系统挂载参数](https://support.huaweicloud.com/usermanual-cci2/cci_01_0631.html)                                                                                                                                                                     |
      | persistentVolumeReclaimPolicy | 是    | String | 参数解释：PV卷回收策略 约束限制：目前只支持Retain回收策略 **Retain**：删除PVC，PV资源与底层存储资源均不会被删除，需要手动删除回收。PVC删除后PV资源状态为"已释放（Released）"，不能直接再次被PVC绑定使用。                                                                                  |
      | storage                       | 是    | String | 参数解释：存储容量，单位为Gi 约束限制：对于并行文件系统来说，此处仅为校验需要（不能为空和0），设置的大小不起作用，此处设定为固定值1Gi                                                                                                                                                              |
      | storageClassName              | 是    | String | 参数解释：并行文件系统对应的存储类名称 约束限制：并行文件系统对应的存储类名称为csi-obs                                                                                                                                                                                          |
         
      
   
   2. 执行以下命令，创建PV。
      ```
      ccictl apply -f pv-obs.yaml
      ```
      
   
   
   
   
3. 创建PVC。 
   1. 创建pvc-obs.yaml文件。
      ```
      apiVersion: cci/v2
      kind: PersistentVolumeClaim
      metadata:
        name: pvc-obs
        namespace: test-obs-v1
        annotations:
          csi.storage.k8s.io/fstype: obsfs
          csi.storage.k8s.io/node-publish-secret-name: <your_secret_name>           # Secret的名称
          csi.storage.k8s.io/node-publish-secret-namespace: <your_namespace>        # Secret的命名空间
      spec:
        accessModes:
        - ReadWriteMany                                                             # 并行文件系统必须为ReadWriteMany
        resources:
          requests:
            storage: 1Gi
        storageClassName: csi-obs                                                # 存储类名称，必须与PV的存储类一致。
        volumeName: pv-obs                                                        # PV的名称
      ```
      表2关键参数说明 
      | 参数                                               | 是否必填 | 参数类型   | 描述                                                                                                                                                                                                                                                                                                                                                        |
      |:---|:---|:---|:---|
      | fsType                                           | 是    | String | 参数解释：存储实例类型 约束限制：支持"obsfs"，即并行文件系统                                                                                                                                                                                                                                                                                         |
      | csi.storage.k8s.io/node-publish-secret-name      | 是    | String | 参数解释：PV中指定Secret的名称                                                                                                                                                                                                                                                                                                                                       |
      | csi.storage.k8s.io/node-publish-secret-namespace | 是    | String | 参数解释：PV中指定Secret的命名空间                                                                                                                                                                                                                                                                                                                                     |
      | storage                                          | 是    | String | 参数解释：PVC申请容量，单位为Gi 约束限制： - 对于并行文件系统来说，此处仅为校验需要（不能为空和0），设置的大小不起作用，此处设定为固定值1Gi  - 与[表1]中PV设置的容量值相同。   |
      | storageClassName                                 | 是    | String | 参数解释：存储类名称 约束限制：必须与[表1]中PV的存储类一致，并行文件系统对应的存储类名称为csi-obs                                                                                                                                                                                                                                  |
      | volumeName                                       | 是    | String | 参数解释：PV的名称 约束限制：必须与[表1]中PV名称一致                                                                                                                                                                                                                                                             |
         
      
   
   2. 执行以下命令，创建PVC。
      ```
      ccictl apply -f pvc-obs.yaml
      ```
      
   
   
   
   
4. 创建应用。 
   1. 创建web-demo.yaml文件，本示例中将并行文件系统挂载至/data路径。
      ```
      apiVersion: cci/v2
      kind: Deployment
      metadata:
        name: web-demo
        namespace: test-obs-v1
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: web-demo
        template:
          metadata:
            labels:
              app: web-demo
          spec:
            containers:
            - name: container-1
              image: nginx:latest
              resources:
                limits:
                  cpu: 500m
                  memory: 1Gi
                requests:
                  cpu: 500m
                  memory: 1Gi
              volumeMounts:
              - name: pvc-obs-volume    #卷名称，需与volumes字段中的卷名称对应
                mountPath: /data  #存储卷挂载的位置
            imagePullSecrets:
              - name: imagepull-secret
            volumes:
              - name: pvc-obs-volume    #卷名称，可自定义
                persistentVolumeClaim:
                  claimName: pvc-obs    #已创建的PVC名称
      ```
      
   
   2. 执行以下命令，创建一个挂载并行文件系统的应用。
      ```
      ccictl apply -f web-demo.yaml
      ```
      工作负载创建成功后，您可以尝试[验证数据持久化及共享性]。
      
   
   
   
   
 
 #### 验证数据持久化及共享性
1. 查看部署的应用及文件。 
   1. 执行以下命令，查看已创建的Pod。
      ```
      ccictl get pod -n test-obs-v1| grep web-demo
      ```
      预期输出如下：
      ```
      web-demo-7864446874-6d4lp   1/1     Running   0             52s
      web-demo-7864446874-xx6qh   1/1     Running   0             52s
      ```
      
   
   2. 依次执行以下命令，查看Pod的/data路径下的文件。
      ```
      ccictl exec web-demo-7864446874-6d4lp -n test-obs-v1 -- ls /data
      ccictl exec web-demo-7864446874-xx6qh -n test-obs-v1 -- ls /data
      ```
      两个Pod均无返回结果，说明/data路径下无文件。
      
   
   
   
   
2. 执行以下命令，在/data路径下创建static文件。 
   ```
   ccictl exec web-demo-7864446874-6d4lp -n test-obs-v1 --  touch /data/static
   ```
   
   
3. 执行以下命令，查看/data路径下的文件。 
   ```
   ccictl exec web-demo-7864446874-6d4lp -n test-obs-v1 -- ls /data
   ```
   预期输出如下：
   ```
   static
   ```
   
   
4. **验证数据持久化**
   
   1. 执行以下命令，删除名称为web-demo-7864446874-6d4lp的Pod。
      ```
      ccictl delete pod web-demo-7864446874-6d4lp -n test-obs-v1
      ```
      预期输出如下：
      ```
      pod "web-demo-7864446874-6d4lp" deleted
      ```
      删除后，Deployment控制器会自动重新创建一个副本。
      
   
   2. 执行以下命令，查看已创建的Pod。
      ```
      ccictl get pod -n test-obs-v1 | grep web-demo
      ```
      预期输出如下，web-demo-7864446874-84slz为新建的Pod：
      ```
      web-demo-7864446874-84slz   1/1     Running   0             110s
      web-demo-7864446874-xx6qh    1/1     Running   0             8m47s
      ```
      
   
   3. 执行以下命令，验证新建的Pod中/data路径下的文件是否更改。
      ```
      ccictl exec web-demo-7864446874-84slz -n test-obs-v1 -- ls /data
      ```
      预期输出如下：
      ```
      static
      ```
      static文件仍然存在，则说明数据可持久化保存。
      
   
   
   
   
5. **验证数据共享性**
   
   1. 执行以下命令，查看已创建的Pod。
      ```
      ccictl get pod -n test-obs-v1 | grep web-demo
      ```
      预期输出如下：
      ```
      web-demo-7864446874-84slz   1/1     Running   0             6m3s
      web-demo-7864446874-xx6qh   1/1     Running   0             13m
      ```
      
   
   2. 执行以下命令，在任意一个Pod的/data路径下创建share文件。本例中选择名为web-demo-7864446874-84slz的Pod。
      ```
      ccictl exec web-demo-7864446874-84slz -n test-obs-v1 --  touch /data/share
      ```
      并查看该Pod中/data路径下的文件。
      ```
      ccictl exec web-demo-7864446874-84slz -n test-obs-v1 -- ls /data
      ```
      预期输出如下：
      ```
      share
      static
      ```
      
   
   3. 由于写入share文件的操作未在名为web-demo-7864446874-xx6qh的Pod中执行，在该Pod中查看/data路径下是否存在文件以验证数据共享性。
      ```
      ccictl exec web-demo-7864446874-xx6qh -n test-obs-v1 -- ls /data
      ```
      预期输出如下：
      ```
      share
      static
      ```
      如果在任意一个Pod中的/data路径下创建文件，其他Pod下的/data路径下均存在此文件，则说明两个Pod共享一个存储卷。
      
   
   
   
   
 
