如何使用 Amazon EBS 多重挂载将同一个卷挂载到 Amazon EKS 中的多个工作负载?

3 分钟阅读
0

我想使用 Amazon Elastic Block Store (Amazon EBS) 多重挂载来处理 Amazon Elastic Kubernetes Service (Amazon EKS) 中跨多个集群的多个工作负载。

简短描述

当您使用 Amazon EBS 存储在 Amazon EKS 中创建永久工作负载时,默认卷类型为 gp2。Amazon EBS 多重挂载允许您将单个预调配 IOPS SSD(io1 或 io2)卷挂载到同一可用区中的多个实例。

通用 SSD 卷(如 gp2 和 gp3)不支持 Amazon EBS 多重挂载。Amazon EBS CSI 驱动程序不支持将卷多重挂载至同一集群中不同节点上运行的工作负载上。

要将同一 Amazon EBS 永久存储多重挂载至不同集群中的多个工作负载,请使用预调配 IOPS SSD 卷。请确保容器组(pod)在集群中位于相同可用区(AZ)的 Worker 节点上运行。

**注意:**如果工作负载位于相同或不同集群的多个可用区中,则请使用 Amazon Elastic File System (Amazon EFS)。有关更多信息,请参阅 GitHub 网站的 Create an Amazon EFS file system for Amazon EKS 文章。

解决方法

在开始之前,请确保在所需的 Amazon EKS 集群中安装 Amazon EBS CSI 驱动程序。
**注意:**可以将启用多重挂载的卷挂载至最多 16 个 Linux 实例,这些实例创建于 Nitro 系统且位于同一可用区内。

要使用 Amazon EBS 多重挂载将同一个卷挂载到多个集群中的多个工作负载,请完成以下步骤。

预调配 Amazon EBS 卷

要预调配 Amazon EBS 卷,请执行以下操作:

  1. 静态预调配卷:
    aws ec2 create-volume --volume-type io2 --multi-attach-enabled --size 10 --iops 2000 --region <example-region> --availability-zone <example-az> --tag-specifications 'ResourceType=volume,Tags=[{Key=purpose,Value=prod},{Key=Name,Value=multi-attach-eks}]'
    **注意:**将 **<example-region>**替换为您所需的 AWS 区域。将 **<example-az>**替换为所需的可用区。
  2. 如果您的现有工作负载具有 gp2 或 gp3 卷,请先创建该卷的快照。然后,根据该快照创建 io2 卷。 
    注意:创建 io1 卷后,无法为其开启 Amazon EBS 多重挂载。如果 io2 卷未挂载到实例,则可以在创建 io2 卷后为其启用 Amazon EBS 多重挂载。对于 Amazon EKS 中的 io2 动态存储预置,请指定立即模式以预置卷,避免使用容器组(pod)创建存储类别。在创建容器组(pod)之前,请务必开启 Amazon EBS 多重挂载。

检索卷 ID

检索工作负载预置卷的 ID:

aws ec2 describe-volumes --filters "Name=tag:Name,Values=multi-attach-eks*" --query "Volumes[*].{ID:VolumeId}" --region <example-region>  

**注意:**将 example-region 替换为所需的 AWS 区域。

使用前面的卷 ID 在现有集群中预置永久工作负载

  1. 创建下列清单并命名为 workloadA.yml

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: <example-pv-claim-name-a>
    spec:
      storageClassName: ""
      volumeName: <example-pv-name-a>
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 5Gi
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: <example-pod-a>
    spec:
      containers:
      - name: <example-pod-container-name>
        image: centos
        command: ["/bin/sh"]
        args: ["-c", "while true; do echo $(date -u) on pod A >> /data/out.txt; sleep 15; done"]
        volumeMounts:
        - name: <example-volume-mount-name>
          mountPath: /data
      volumes:
      - name: <example-volume-mount-name>
        persistentVolumeClaim:
          claimName: <example-pv-claim-name-a>
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: <example-pv-name-a>
    spec:
      accessModes:
      - ReadWriteOnce
      capacity:
        storage: 5Gi
      csi:
        driver: ebs.csi.aws.com
        fsType: ext4
        volumeHandle: <example-preceding-volume-id>
      nodeAffinity:
        required:
          nodeSelectorTerms:
            - matchExpressions:
                - key: topology.ebs.csi.aws.com/zone
                  operator: In
                  values:
                    - <example-az>

    **注意:**将以下命令中的所有 example 字符串替换为所需的值。确保将 storageClassName 参数值设置为空的 "" 字符串。

  2. 将 kubectl 上下文切换到集群 A,然后部署工作负载:

    kubectl config use-context <example-clusterA-context>  
    kubectl apply -f workloadA.yml

使用前面的卷 ID 在另一个集群中创建另一个工作负载

  1. 创建并部署以下清单并命名为 workloadB.yml

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: <example-pv-claim-name-b>
    spec:
      storageClassName: ""
      volumeName: <example-pv-name-b>
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 5Gi
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: <example-pod-b>
    spec:
      containers:
      - name: <example-pod-container-name>
        image: centos
        command: ["/bin/sh"]
        args: ["-c", "tail -f /data/out.txt"]
        volumeMounts:
        - name: <example-volume-mount-name>
          mountPath: /data
      volumes:
      - name: <example-volume-mount-name>
        persistentVolumeClaim:
          claimName: <example-pv-claim-name-b>
    
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: <example-pv-name-b>
    spec:
      accessModes:
      - ReadWriteOnce
      capacity:
        storage: 5Gi
      csi:
        driver: ebs.csi.aws.com
        fsType: ext4
        volumeHandle: <example-preceding-volume-id>
      nodeAffinity:
        required:
          nodeSelectorTerms:
            - matchExpressions:
                - key: topology.ebs.csi.aws.com/zone
                  operator: In
                  values:
                    - example-az

    **注意:**确保将所有 example 字符串替换为所需的值。确保将 storageClassName 参数值设置为空的 "" 字符串。

  2. 将 kubectl 上下文切换到集群 B,然后部署工作负载:

    kubectl config use-context <example-clusterB-context>
    kubectl apply -f workloadB.ym

    注意: 请将 example-clusterB-context 替换为您的上下文。

检查容器组(pod)是否正在运行且内容是否相同

  1. 在不同的集群上进行身份验证并运行以下命令:

    kubectl get pods

    集群 A 的输出示例:

    NAME                          READY   STATUS    RESTARTS   AGE
    example-pod-a                 1/1     Running   0          18m  

    集群 B 的输出示例:

    NAME                          READY   STATUS    RESTARTS   AGE
    example-pod-b                 1/1     Running   0          3m13s
  2. 对于 example-pod-a,请运行以下命令来查看写入存储空间的内容:

    kubectl exec -it <example-pod-a> -- cat /data/out.txt

    输出示例:

    Fri Sep 22 12:39:04 UTC 2024 on example-pod-a  
    Fri Sep 22 12:39:19 UTC 2024 on example-pod-a  
    Fri Sep 22 12:39:34 UTC 2024 on example-pod-a
  3. 对于 example-pod-b,请运行以下命令来读取与 example-pod-a 写入相同的存储空间中的内容:

    kubectl logs -f <example-pod-b>

    输出示例:

    Fri Sep 22 12:39:04 UTC 2024 on example-pod-b  
    Fri Sep 22 12:39:19 UTC 2024 on example-pod-b  
    Fri Sep 22 12:39:34 UTC 2024 on example-pod-b

**注意:**无法从多台服务器同时访问 XFS 和 EXT4 等标准文件系统。有关更多信息,请参阅注意事项和限制

相关信息

What is Amazon Elastic File System?

AWS 官方
AWS 官方已更新 7 个月前