
# 跨账号挂载对象存储
#### 应用场景
- 跨账号数据共享。例如，公司内部多团队需要共享数据，但不同团队使用不同的账号。
- 跨账户数据迁移和备份。例如，账号A即将停用，所有的数据需要迁移至账户B。
- 数据处理与分析。例如，账号B是外部数据处理商，需要访问账户A的原始数据进行大数据分析和机器学习等操作。
通过跨账户挂载对象存储，您可以实现数据共享，降低存储和传输成本，同时确保数据的安全性和一致性。这种方式使多个团队或组织能够安全、便捷地访问彼此的数据资源，避免重复存储和冗余传输，同时确保数据的最新性和合规性，从而提升整体的业务效率和安全性。
#### 操作流程
假设账号B在某种情况下需要访问和使用账号A的某个OBS桶，具体操作流程请参见[图1]和[表1]。
图1跨账号挂载对象存储   
![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000002047843721.png "点击放大")
 表1操作流程说明 
| 操作流程                                                                  | 说明                                          |
|:---|:---|
| [步骤一：创建OBS桶策略和桶ACL]    | 账户A对OBS配置桶策略和桶ACL，授予账号B相应的权限（如读写权限）。        |
| [步骤二：创建挂载OBS的工作负载]     | 基于账号A的OBS桶，账号B创建对应的PV和PVC，并将PVC挂载到需要的工作负载中。 |
| [步骤三：检查Pod对OBS桶的操作权限] | 基于桶策略，检查账号B创建的Pod实例是否具有相应权限。                |
| [步骤四：清理资源]             | 完成该示例的学习后，您可以清理相关资源以避免产生结算费用。               |
   
#### 前提条件
- 涉及账户在同一区域内。
- 已创建一个安装CCE容器存储（Everest）的集群，其中要求Everest版本≥1.1.11，集群版本≥1.15。若没有可用集群 ，请参照[购买Standard/Turbo集群](https://support.huaweicloud.com/usermanual-cce/cce_10_0028.html)创建。
- 集群所在VPC下，已创建绑定弹性公网IP的ECS虚拟机，且该ECS通过kubectl连接集群。若没有连接集群，请参照[通过kubectl连接集群](https://support.huaweicloud.com/usermanual-cce/cce_10_0107.html)。
 
 #### 步骤一：创建OBS桶策略和桶ACL
账户A对OBS配置桶策略和桶ACL，授予账号B相应的权限（如读写权限）。
1. 登录OBS管理控制台，左侧导航栏选择"桶列表"。
2. 在"桶列表"中，单击待操作桶，进入"对象"页面。
3. 在左侧导航栏，单击"权限控制 \> 桶策略"，单击"创建"，进入"创建桶策略"页面。
4. 配置相关参数。本示例仅解释必要参数，其余保留默认值。关于配置参数的详细说明请参见[桶策略](https://support.huaweicloud.com/perms-cfg-obs/obs_40_0004.html)。
   
   表2桶策略参数配置 
   | 参数    | 参数说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | 示例                                                                 |
   |:---|:---|:---|
   | 策略名称  | 自定义名称。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | example01                                                          |
   | 效力    | 用于指定策略的行为。 - 允许：表示允许策略中定义的操作。  - 拒绝：表示拒绝策略中定义的操作。                                                                                                                                                                                                                                                                    | 允许                                                                 |
   | 被授权用户 | 用于指定被授权账户（可多选）。对于不同类型的授权账户，OBS控制台在授权操作中预置了不同的模板配置，具体请参见[使用模板创建桶策略](https://support.huaweicloud.com/usermanual-obs/obs_03_0142.html)。 - 所有账户：任何账户不通过身份认证即可执行当前桶策略，数据可能存在安全风险。  - 当前账户：授权当前账户下的特定IAM账户。  - 其他账户：授权其他账户下的特定IAM账户。   | 其他账户 XXX（账户ID）/XXX（IAM ID） |
   | 授权资源  | 用于指定授权的资源范围。 - 整个桶（包括桶内对象）：允许被授权账户对整个桶和桶内的所有对象进行操作。  - 当前桶：仅允许被授权账户对整个桶进行操作。  - 指定对象：仅允许被授权账户对桶内特定对象进行操作。                                                                                                                           | 整个桶（包括桶内对象）                                                        |
   | 授权操作  | 用于指定授权的具体操作。 - 模板配置：OBS控制台预置的权限配置模板。当选择"桶读写"时，高级设置默认"排除以上授权操作"。  - 自定义配置：自定义选择授权的具体操作。                                                                                                                                                                                                                                          | 模板配置 \> 桶读写                                                        |
      
   图2创建桶策略   
   ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000002046909973.png "点击放大")
   
   
5. 在左侧导航栏，单击"权限控制 \> 桶ACL"，单击"用户权限 \> 增加"，输入授权用户的账号ID，"桶访问权限"勾选"读取权限"和"写入权限"，"对象权限"勾选"对象读权限"，"ACL访问权限"勾选"读取权限"和"写入权限"，单击"确定"。
 
 #### 步骤二：创建挂载OBS的工作负载
基于账号A的OBS，账号B创建对应的PV和PVC，并将PVC挂载到需要的工作负载中。
1. 创建名为paas-obs-endpoint的ConfigMap，配置OBS所在区域和Endpoint。
   
   ```
   vim config.yaml
   ```
   具体内容如下，参数说明请参见[表3]：
   ```
   apiVersion: v1
   kind: ConfigMap
   metadata:
     name: paas-obs-endpoint   # 名称必须为paas-obs-endpoint
     namespace: kube-system    # 必须在kube-system命名空间下
   data:
     obs-endpoint: |
       {"<region_name>": "<endpoint_address>"}
   ```
   利用config.yaml创建ConfigMap。
   ```
   kubectl create -f config.yaml
   ```
    表3ConfigMap参数说明 
   | ConfigMap          | 说明                                                                                                                                                                                         | 示例                                                                                                                           |
   |:---|:---|:---|
   | metadata.name      | ConfigMap名称，固定为paas-obs-endpoint，不可修改。                                                                                                                                                     | paas-obs-endpoint                                                                                                            |
   | metadata.namespace | 命名空间，固定为系统命名空间kube-system，不可修改。                                                                                                                                                            | kube-system                                                                                                                  |
   | data.obs-endpoint  | 区域名称和Endpoint以键值对形式对应，\<region_name\>和\<endpoint_address\>需替换为具体值，多个取值间使用逗号隔开。 Region对应的值请参见[地区和终端节点](https://developer.huaweicloud.com/endpoint)。 | {"cn-south-4": "https://obs.cn-south-4.myhuaweicloud.com:443", "cn-north-4": "https://obs.cn-north-4.myhuaweicloud.com:443"} |
      
   
   
2. 创建名为test-user的Secret，名称可自定义，用于在CSI挂载卷时提供访问凭证。
   
   1. 获取访问密钥。返回控制台，鼠标指向界面右上角的登录用户名，在下拉列表中单击"我的凭证"。 在左侧导航栏单击"访问密钥"，单击"新增访问密钥"，进入"新增访问密钥"页面。
      单击"确定"，下载访问密钥。
      
   
   2. 对访问密钥进行base64编码（假设上文获取到的AK为"xxx"，SK为"yyy"），并记录编码后的AK和SK。
      ```
      echo -n xxx|base64
      echo -n yyy|base64
      ```
      
   
   3. 新建一个secret的YAML文件，如test_user.yaml。
      ```
      vim test_user.yaml
      ```
      文件内容如下，参数说明请参见[表4]：
      ```
      apiVersion: v1
      data:
        access.key: QUxPQUlJU******
        secret.key: aVMwZkduQ******
      kind: Secret
      metadata:
        name: test-user
        namespace: default
      type: cfe/secure-opaque
      ```
      利用test_user.yaml创建Secret。
      ```
      kubectl create -f test_user.yaml
      ```
       表4Secret参数说明 
      | 参数         | 说明                                                                                         | 示例                    |
      |:---|:---|:---|
      | access.key | base64编码后的AK。                                                                              | QUxPQUlJU\*\*\*\*\*\* |
      | secret.key | base64编码后的SK。                                                                              | aVMwZkduQ\*\*\*\*\*\* |
      | type       | 密钥类型，固定为cfe/secure-opaque，不可修改。 使用该类型，用户输入的数据会自动加密。 | cfe/secure-opaque     |
         
      
   
   
   
   
3. 创建名为testing_abc的PV，并挂载名为test_user的Secret。 
   ```
   vim testing_abc.yaml
   ```
   文件内容如下，参数说明请参见[表5]：
   ```
   kind: PersistentVolume
   apiVersion: v1
   metadata:
     name: testing-abc
     annotations:
       pv.kubernetes.io/bound-by-controller: 'yes'
       pv.kubernetes.io/provisioned-by: everest-csi-provisioner
   spec:
     capacity:
       storage: 1Gi
     mountOptions:
     - default_acl=bucket-owner-full-control      #新增的OBS挂载参数
     csi:
       driver: obs.csi.everest.io
       volumeHandle: obs-cce-test                 # 待挂载的OBS桶的名称
       fsType: s3fs                               # obsfs表示并行文件系统；s3fs表示对象桶
       volumeAttributes:
         everest.io/obs-volume-type: STANDARD     # 桶类型，使用对象桶时支持标准（STANDARD）和低频（WARM）两种桶。
         everest.io/region: <region_name>         # OBS桶所在区域，需替换为具体取值
         storage.kubernetes.io/csiProvisionerIdentity: everest-csi-provisioner
       nodePublishSecretRef:                      # 挂载OBS桶使用的AK/SK
         name: test-user
         namespace: default
     accessModes:
       - ReadWriteMany
     persistentVolumeReclaimPolicy: Retain        # PV回收策略
     storageClassName: csi-obs                    # csi-obs是自动创建的OBS存储类，可以根据情况，自定义创建
     volumeMode: Filesystem
   ```
   利用testing_abc.yaml创建PV。
   ```
   kubectl create -f testing_abc.yaml
   ```
    表5PV参数说明 
   | 参数                            | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | 示例                                                                                                                                                                               |
   |:---|:---|:---|
   | mountOptions.default_acl      | 指定桶及对象的访问控制策略。本示例中，账户A是桶的所有者，账号A和账号B都可能是上传者。 - private：只有桶的所有者可以完全访问桶或对象。  - public-read：桶的所有者对桶或对象有完全控制权，其他用户可以读取数据，但不能修改、删除或上传数据。  - public-read-write：桶的所有者对桶或对象有完全控制权，其他用户可以对数据进行读写操作。  - bucket-owner-read：上传者对自己上传的对象具有完全的控制权限，而桶的所有者对对象有读取权限，**常用于跨账户共享的场景**。  - bucket-owner-full-control：上传者拥有对自己上传对象的写入权限，默认情况下可能没有读取权限。桶的所有者对对象具有完全控制权限，**常用于跨账户共享的场景**。   | bucket-owner-full-control 说明： 由于账户A设置的桶策略中授予账号B整个桶的读写权限，所以账号B对整个桶（包括自己上传的对象和账户A上传的对象）具有写入和读取权限。 |
   | csi.nodePublishSecretRef      | 指定需要挂载的密钥。 - name：Secret的名字。  - namespace：Secret的命名空间。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | test-user default                                                                                                                       |
   | csi.volumeHandle              | 指定需要挂载的OBS桶名称。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | obs-cce-test（账户A授权的OBS名称）                                                                                                                                                        |
   | csi.fsType                    | 指定文件类型。 - obsfs：创建obs并行文件系统。  - s3fs：创建obs对象桶。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | s3fs 须知： PV和PVC指定的文件类型需一致，否则PVC无法绑定对应的PV。                                                     |
   | accessModes                   | 指定存储卷的访问模式，OBS仅支持ReadWriteMany。 - ReadWriteOnce：存储卷可以被一个节点以读写方式挂载。  - ReadWriteMany：存储卷可以被多个节点以读写方式挂载。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | ReadWriteMany                                                                                                                                                                    |
   | persistentVolumeReclaimPolicy | 指定PV的回收策略。 - Delete：当PVC被删除时，PV对象与底层存储资源均会被删除。YAML文件中若添加annotations"everest.io/reclaim-policy: retain-volume-only"，则底层存储资源会保留。    - Retain：当PVC对象被删除时，PV对象与底层存储资源均不会被删除，需要手动删除回收。PVC删除后PV资源状态为"已释放（Released）"，且不能直接再次被PVC绑定使用。                                                                                                                                                                                                                                                                                                                                              | Retain 说明： 多个PV使用同一个对象存储时建议使用Retain，避免级联删除底层卷。                                               |
      
   
   
4. 创建名为pvc-test-abc的PVC，并绑定新建的PV，即testing_abc。 
   ```
   vim pvc_test_abc.yaml
   ```
   文件内容如下：
   ```
   apiVersion: v1
   kind: PersistentVolumeClaim
   metadata:
     name: pvc-test-abc
     namespace: default
     annotations:
       csi.storage.k8s.io/node-publish-secret-name: test-user      # 挂载Secret
       csi.storage.k8s.io/node-publish-secret-namespace: default   # Secret的命名空间
       everest.io/obs-volume-type: STANDARD       # 桶类型，使用对象桶时支持标准（STANDARD）和低频（WARM）两种桶。
       csi.storage.k8s.io/fstype: s3fs            # 文件类型，obsfs表示并行文件系统；s3fs表示对象桶
       volume.beta.kubernetes.io/storage-provisioner: everest-csi-provisioner
   spec:
     accessModes:
     - ReadWriteMany             # 对象存储必须为ReadWriteMany
     resources:
       requests:
         storage: 1Gi            # PVC申请容量大小，此处仅为校验需要（不能为空和0），设置的大小不起作用，此处设定为固定值1Gi
     storageClassName: csi-obs   # csi-obs是自动创建的OBS存储类，可以根据情况，自定义创建
     volumeName: testing-abc     # PV的名称
   ```
   利用pvc_test_abc.yaml创建PVC。
   ```
   kubectl create -f pvc_test_abc.yaml
   ```
   
   
5. 创建工作负载，并挂载PVC，以Nginx无状态工作负载为例。 
   ```
   vim obs_deployment_example.yaml
   ```
   文件内容如下：
   ```
   apiVersion: apps/v1 
   kind: Deployment 
   metadata: 
     name: obs-deployment-example                  # 工作负载名称，可自定义
     namespace: default 
   spec: 
     replicas: 1 
     selector: 
       matchLabels: 
         app: obs-deployment-example              # 标签，可自定义
     template: 
       metadata: 
         labels: 
           app: obs-deployment-example 
       spec: 
         containers: 
         - image: nginx
           name: container-0 
           volumeMounts: 
           - mountPath: /tmp                       # PVC挂载路径，可以根据需求自定义
             name: pvc-obs-example 
         restartPolicy: Always
         imagePullSecrets:
           - name: default-secret
         volumes: 
         - name: pvc-obs-example  
           persistentVolumeClaim: 
             claimName: pvc-test-abc               # PVC名称
   ```
   利用obs_deployment_example.yaml创建工作负载obs-deployment-example。
   ```
   kubectl create -f obs_deployment_example.yaml
   ```
   检查工作负载是否创建成功。
   ```
   kubectl get pod
   ```
   回显结果如下，若状态为Running，则说明工作负载创建成功。
   ```
   NAME                                      READY   STATUS              RESTARTS        AGE
   obs-deployment-example-6b4dfd7b57-frfxv   1/1     Running             0               22h
   ```
   
   
 
 #### 步骤三：检查Pod对OBS桶的操作权限
基于桶策略，检查账号B创建的Pod实例是否具有相应权限。
1. 检查Pod能否对账号A创建的OBS桶对象进行读写操作，假设OBS桶中已存在test.txt文件（账号A创建）。 
   利用以下命令进入创建的工作负载，Ctrl+d可退出当前负载。
   ```
   kubectl -n default exec -it obs-deployment-example-6b4dfd7b57-frfxv -c container-0 -- bash
   ```
   利用以下命令查看该Pod实例对test.txt的操作权限，"/tmp"为PVC挂载路径。
   ```
   ls -l /tmp/test.txt
   ```
   回显内容如下，说明该Pod实例对test.txt具有读写权限，这与账户A设置的桶策略相关。
   ```
   -rwxrwxrwx 1 root root 4 Sep  5 09:09 /tmp/test.txt
   ```
   
   
2. 检查Pod能否对自己创建的OBS桶对象进行读写操作。 
   在/tmp路径下创建一个新文件test01.txt，并写入"test\\n"。
   ```
   echo -e "test\n" > /tmp/test01.txt
   ```
   利用以下命令查看test01.txt内容，从而验证Pod能否写入和读取自己创建的新对象。此外，账号A也可以在OBS桶中查看新对象。
   ```
   cat /tmp/test01.txt
   ```
   回显内容如下，说明Pod对自己创建的对象具有读写权限。
   ```
   test
   ```
   
   
 
 #### 步骤四：清理资源
完成该示例的学习后，您可以清理相关资源以避免产生结算费用。如果您打算学习其他示例，请等到完成这些示例后再进行清理。
1. 利用以下命令删除工作负载。 
   ```
   kubectl delete -f obs_deployment_example.yaml
   ```
   回显结果如下：
   ```
   deployment.apps "obs-deployment-example" deleted
   ```
   
   
2. 利用以下命令删除PVC。 
   ```
   kubectl delete -f pvc_test_abc.yaml
   ```
   回显结果如下：
   ```
   persistentvolumeclaim "pvc-test-abc" deleted
   ```
   
   
3. 利用以下命令删除PV。 
   ```
   kubectl delete -f testing_abc.yaml
   ```
   回显结果如下：
   ```
   persistentvolume "testing-abc" deleted
   ```
   
   
4. 利用以下命令删除Secret。 
   ```
   kubectl delete -f test_user.yaml
   ```
   回显结果如下：
   ```
   secret "test-user" deleted
   ```
   
   
5. 利用以下命令删除ConfigMap。 
   ```
   kubectl delete -f config.yaml
   ```
   回显结果如下：
   ```
   configmap "paas-obs-endpoint" deleted
   ```
   
   
 
#### 常见问题
若工作负载出现创建不成功的情况，可以根据Pod实例事件中的报错进行排查，具体请参考[表6]。如果以下思路均不能解决您的问题，请[提交工单](https://console.huaweicloud.com/ticket/?locale=zh-cn#/ticketindex/business?productTypeId=2a129f7ed0b543c6b92d73e2c26aa590&subTypeId=-1&type=2)联系华为云客服为您解答。
 表6工作负载创建不成功的排查思路 
| 报错                                                                                                                                                                                                                                                                                                    | 原因分析                          | 排查思路                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
|:---|:---|:---|
| 0/4 nodes are available: pod has unbound immediate PersistentVolumeClaims. preemption: 0/4 nodes are available: 4 Preemption is not helpful for scheduling.                                                                                                                                           | PVC未与PV绑定。                    | 1. 根据以下命令检查PVC的状态： ``` kubectl get pvc ``` 若PVC状态为Pending，则证实PVC未与PV绑定。   2. 查看PVC详细信息，以确定绑定不成功的具体原因。 ``` kubectl describe pvc <pvc_name> ```   3. 常见问题如下，可以通过修改YAML文件解决。 - PVC未绑定正确的PV。  - PVC与PV的参数未对应，如fsType（需要一致）、StorageClass（需要一致，并保证挂载的StorageClass为对象存储类型）、accessModes（都需要设置为ReadWriteMany，因为OBS只支持该访问模式）以及storage（PVC请求的storage必须小于或等于PV提供的storage）等。     |
| MountVolume.SetUp failed for volume *"obs-cce-example"*: rpc error: code = Unknown desc = failed to get secret(paas.longaksk), err: get secret(paas.longaksk) failed: get secret paas.longaksk from namespace kube-system failed: secrets "paas.longaksk" not found                                   | 挂载存储卷时无法找到所需的Secret。          | 1. 检查挂载的Secret是否存在。 ``` kubectl get secret ``` 若存在，则说明Secret被错误配置。若不存在，请参见[创建Secret]。   2. 检查Secret的配置参数，常见问题如下： - access.key和secret.key未设置为base64编码后的AK和SK。  - type未设置为cfe/secure-opaque。                                                                                                                                                                                                                  |
| MountVolume.SetUp failed for volume *"pv-obs-example"*: rpc error: code = Internal desc = \[8032c354-4e1b-41b0-81ce-9d4b3f8c49c9\] get obsUrl failed before mount bucket obs-cce-example, get configMap paas-obs-endpoint from namespace kube-system failed: configmaps "paas-obs-endpoint" not found | 存储OBS访问端点的ConfigMap不存在或配置不正确。 | 1. 检查ConfigMap是否存在。 ``` kubectl get configmap -n kube-system ``` 若存在，则说明ConfigMap被错误配置。若不存在，请参见[创建ConfigMap]。   2. 检查ConfigMap的配置参数，常见问题如下： - name未设置为paas-obs-endpoint。  - namespace未设置为系统命名空间kube system。  - 区域名称未设置为OBS所在区域。                                                                                                   |
   
