Amazon EFS CSI 驱动程序 - Amazon EKS
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

Amazon EFS CSI 驱动程序

Amazon EFS Container Storage Interface (CSI) 驱动程序提供了一个 CSI 接口,允许在Amazon上运行的 Kubernetes 集群管理 Amazon EFS 文件系统的生命周期。

本主题介绍了如何部署 Amazon EFS CSI 驱动程序到您的 Amazon EKS 集群,并验证它是否正常工作。

注意

Amazon EKS 集群 不支持 Amazon EFS CSI 驱动程序的 Alpha 功能。

有关可用参数的详细说明和演示驱动程序功能的完整示例,请参阅 GitHub 上的 Amazon EFS Container Storage Interface (CSI) 驱动程序项目。

注意事项

  • Amazon EFS CSI 驱动程序与基于 Windows 的容器映像不兼容。

  • 您不能将动态持久性卷预置与 Fargate 节点结合使用,但可以使用静态预置。

  • 动态预置需要 1.2 版或更高版本的驱动程序,这一点需要 1.17 版或更高版本的集群。您可以在任何受支持的 Amazon EKS 集群版本上使用 1.1 版本的驱动程序静态预置持久性卷。

  • 此驱动程序的 1.3.2 版或更高版本支持 Arm64 架构,包括基于 Amazon EC2 Graviton 的实例。

先决条件

  • 集群的现有 Amazon Identity and Access Management (IAM) OpenID Connect (OIDC) 提供程序。要确定您是否已经拥有一个或是否要创建一个,请参阅 为集群创建 IAM OIDC 提供商

  • 您的计算机或 Amazon CloudShell 上安装并配置了 2.4.9 版或更高版本,或 1.22.30 版或更高版本的 Amazon CLI。有关更多信息,请参阅 Amazon Command Line Interface 用户指南中的安装、更新和卸载 Amazon CLI 以及使用 aws configure 进行快速配置

  • 计算机或 Amazon CloudShell 上已安装 kubectl 命令行工具。其版本必须与您的集群版本相同,或者最多高出两个版本。要安装或升级 kubectl,请参阅 安装 kubectl

注意

Amazon Fargate 上运行的容器会自动挂载 Amazon EFS 文件系统,无需此页面上所述的手动驱动程序安装步骤。

创建 IAM 策略和角色

创建 IAM 策略并将其分配给 IAM 角色。该策略将允许 Amazon EFS 驱动程序与您的文件系统交互。

将 Amazon EFS CSI 驱动程序部署到 Amazon EKS 集群

  1. 创建允许 CSI 驱动程序的服务账户代表您调用 Amazon API 的 IAM 策略。

    1. 从 GitHub 下载 IAM 策略文档。您还可以查看策略文档

      curl -o iam-policy-example.json https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/v1.3.2/docs/iam-policy-example.json
    2. 创建策略。您可以将 AmazonEKS_EFS_CSI_Driver_Policy 更改为其他名称,但如果更改,请确保在后续步骤中也做出相应更改。

      aws iam create-policy \ --policy-name AmazonEKS_EFS_CSI_Driver_Policy \ --policy-document file://iam-policy-example.json
  2. 创建 IAM 角色并向其附加此 IAM 策略。用 IAM 角色 ARN 对 Kubernetes 服务账户进行注释,用 Kubernetes 服务账户名称对 IAM 角色进行注释。您可以使用 eksctl 或 Amazon CLI 创建角色。

    eksctl

    运行下面的命令,创建 IAM 角色和 Kubernetes 服务账户。它还将策略附加到角色,用 IAM 角色 ARN 对 Kubernetes 服务账户添加注释,并将 Kubernetes 服务账户名称添加到 IAM 角色的信任策略中。请将 my-cluster 替换为集群名称,将 111122223333 替换为账户 ID,并将 region-code 替换为集群所在的 Amazon Web Services 区域。

    eksctl create iamserviceaccount \ --name efs-csi-controller-sa \ --namespace kube-system \ --cluster my-cluster \ --attach-policy-arn arn:aws:iam::111122223333:policy/AmazonEKS_EFS_CSI_Driver_Policy \ --approve \ --override-existing-serviceaccounts \ --region region-code
    Amazon CLI
    1. 确定集群的 OIDC 提供商 URL。将 my-cluster 替换为您的集群名称。如果命令的输出为 None,请查看先决条件

      aws eks describe-cluster --name my-cluster --query "cluster.identity.oidc.issuer" --output text

      输出

      https://oidc.eks.region-code.amazonaws.com.cn/id/oidc-id
    2. 创建 IAM 角色,向 Kubernetes 服务账户授予 AssumeRoleWithWebIdentity 操作权限。

      1. 将以下内容复制到名为 trust-policy.json 的文件中。将 111122223333 替换为您的账户 ID。将 oidc-idregion-code 替换为在上一步中返回的值。

        { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.region-code.amazonaws.com.cn/id/oidc-id" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.eks.region-code.amazonaws.com.cn/id/oidc-id:sub": "system:serviceaccount:kube-system:efs-csi-controller-sa" } } } ] }
      2. 创建角色。您可以将 AmazonEKS_EFS_CSI_DriverRole 更改为其他名称,但如果更改,请确保在后续步骤中也做出相应更改。

        aws iam create-role \ --role-name AmazonEKS_EFS_CSI_DriverRole \ --assume-role-policy-document file://"trust-policy.json"
    3. 向角色附加 IAM 策略。将 111122223333 替换为您的账户 ID。

      aws iam attach-role-policy \ --policy-arn arn:aws:iam::111122223333:policy/AmazonEKS_EFS_CSI_Driver_Policy \ --role-name AmazonEKS_EFS_CSI_DriverRole
    4. 创建一个使用您创建的 IAM 角色的 ARN 进行注释的 Kubernetes 服务账户。

      1. 将以下内容保存到名为 efs-service-account.yaml 的文件中。将 111122223333 替换为您的账户 ID。

        --- apiVersion: v1 kind: ServiceAccount metadata: name: efs-csi-controller-sa namespace: kube-system labels: app.kubernetes.io/name: aws-efs-csi-driver annotations: eks.amazonaws.com.cn/role-arn: arn:aws:iam::111122223333:role/AmazonEKS_EFS_CSI_DriverRole
      2. 运用该清单。

        kubectl apply -f efs-service-account.yaml

安装 Amazon EFS 驱动程序

使用 Helm 或清单安装 Amazon EFS CSI 驱动程序。

重要
  • 以下步骤将安装 1.3.2 版的驱动程序,该版本需要 1.17 版或更高版本的集群。如果要在 1.17 版之前的集群上安装驱动程序,则需要安装 1.1 版的驱动程序。有关更多信息,请参阅 GitHub 上的 Amazon EFS CSI 驱动程序

  • 预设情况下,使用 TLS 对传输中的数据进行加密。使用传输中加密,数据在通过网络传输到 Amazon EFS 服务期间进行加密。要禁用它并使用 NFSv4 挂载卷,请在您的持久性卷清单中将 volumeAttributes 字段 encryptInTransit 设置为 "false"。有关示例清单,请参阅 GitHub 上的传输中加密示例

Helm

此过程需要 Helm V3 或更高版本。要安装或升级 Helm,请参阅 将 Helm 与 Amazon EKS 结合使用

使用 Helm 安装驱动程序

  1. 添加 Helm 存储库。

    helm repo add aws-efs-csi-driver https://kubernetes-sigs.github.io/aws-efs-csi-driver/
  2. 更新存储库。

    helm repo update
  3. 使用 Helm Chart 安装驱动程序的版本。请将存储库地址替换为集群的容器镜像地址

    helm upgrade -i aws-efs-csi-driver aws-efs-csi-driver/aws-efs-csi-driver \ --namespace kube-system \ --set image.repository=123456789012.dkr.ecr.region-code.amazonaws.com.cn/eks/aws-efs-csi-driver \ --set controller.serviceAccount.create=false \ --set controller.serviceAccount.name=efs-csi-controller-sa
Manifest (private registry)

如果您想下载带清单的镜像,我们建议首先尝试以下步骤,以从私有 Amazon ECR 注册表中提取受保护的镜像。

使用私有 Amazon ECR 注册表中存储的镜像来安装驱动程序

  1. 下载清单。

    kubectl kustomize \ "github.com/kubernetes-sigs/aws-efs-csi-driver/deploy/kubernetes/overlays/stable/ecr?ref=release-1.3" > private-ecr-driver.yaml
    注意

    如果您遇到无法通过添加 IAM 权限来解决的问题,请改为尝试“清单(公有注册表)”步骤。

  2. 编辑该文件并删除用于创建 Kubernetes 服务账户的以下行。由于服务账户是在上一步骤中创建的,因此无需执行此操作。

    apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/name: aws-efs-csi-driver name: efs-csi-controller-sa namespace: kube-system ---
  3. 查找以下行。请将以下地址替换为容器镜像地址。做出更改后,保存修改后的清单。

    image: 123456789012.dkr.ecr.region-code.amazonaws.com.cn/eks/aws-efs-csi-driver:v1.3.2
  4. 运用该清单。

    kubectl apply -f private-ecr-driver.yaml
Manifest (public registry)

在某些情况下,您可能无法添加从私有 Amazon ECR 注册表中提取所需的 IAM 权限。这种情况的一个例子是,如果不允许 IAM 用户或角色使用他人的账户进行身份验证。如果是这样,则可以使用公有 Amazon ECR 注册表。

使用公有 Amazon ECR 注册表中存储的镜像来安装驱动程序

  1. 下载清单。

    kubectl kustomize \ "github.com/kubernetes-sigs/aws-efs-csi-driver/deploy/kubernetes/overlays/stable/?ref=release-1.3" > public-ecr-driver.yaml
  2. 编辑该文件并删除用于创建 Kubernetes 服务账户的以下行。由于上一步已经创建了服务账户,因此无需执行此操作。

    apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/name: aws-efs-csi-driver name: efs-csi-controller-sa namespace: kube-system ---
  3. 运用该清单。

    kubectl apply -f public-ecr-driver.yaml

创建 Amazon EFS 文件系统

Amazon EFS CSI 驱动程序支持 Amazon EFS 接入点,这些接入点是 Amazon EFS 文件系统中特定于应用程序的入口点,便于更轻松地在多个 Pod 之间共享文件系统。接入点可以为通过接入点发出的所有文件系统请求强制执行用户身份,并为每个 Pod 强制执行根目录。有关更多信息,请参阅 GitHub 上的 Amazon EFS 接入点

重要

您必须在同一个终端中完成以下步骤,因为这些步骤中设置并使用了变量。

为您的 Amazon EKS 集群创建 Amazon EFS 文件系统

  1. 检索您的集群所在的 VPC ID,并将其存储在变量中,以便在后续步骤中使用。将 my-cluster 替换为您的集群名称。

    vpc_id=$(aws eks describe-cluster \ --name my-cluster \ --query "cluster.resourcesVpcConfig.vpcId" \ --output text)
  2. 检索您的集群的 VPC 的 CIDR 范围,并将其存储在变量中,以便在后续步骤中使用。

    cidr_range=$(aws ec2 describe-vpcs \ --vpc-ids $vpc_id \ --query "Vpcs[].CidrBlock" \ --output text)
  3. 创建一个安全组,该安全组包含一条允许您的 Amazon EFS 挂载点的入站 NFS 流量的入站规则。

    1. 创建安全组。将 example values 替换为您自己的值。

      security_group_id=$(aws ec2 create-security-group \ --group-name MyEfsSecurityGroup \ --description "My EFS security group" \ --vpc-id $vpc_id \ --output text)
    2. 创建一条入站规则,该入站规则允许来自您的集群 VPC 的 CIDR 的入站 NFS 流量。

      aws ec2 authorize-security-group-ingress \ --group-id $security_group_id \ --protocol tcp \ --port 2049 \ --cidr $cidr_range
      重要

      要进一步限制对文件系统的访问,您可以将 CIDR 用于子网,而不是 VPC。

  4. 为您的 Amazon EKS 集群创建 Amazon EFS 文件系统。

    1. 创建文件系统。将 region-code 替换为集群所在的 Amazon Web Services 区域。

      file_system_id=$(aws efs create-file-system \ --region region-code \ --performance-mode generalPurpose \ --query 'FileSystemId' \ --output text)
    2. 创建挂载目标。

      1. 确定您的集群节点的 IP 地址。

        kubectl get nodes

        输出

        NAME STATUS ROLES AGE VERSION ip-192-168-56-0.region-code.compute.internal Ready <none> 19m v1.19.6-eks-49a6c0
      2. 确定 VPC 中子网的 ID 以及子网所在的可用区。

        aws ec2 describe-subnets \ --filters "Name=vpc-id,Values=$vpc_id" \ --query 'Subnets[*].{SubnetId: SubnetId,AvailabilityZone: AvailabilityZone,CidrBlock: CidrBlock}' \ --output table

        输出

        | DescribeSubnets | +------------------+--------------------+----------------------------+ | AvailabilityZone | CidrBlock | SubnetId | +------------------+--------------------+----------------------------+ | region-codec | 192.168.128.0/19 | subnet-EXAMPLE6e421a0e97 | | region-codeb | 192.168.96.0/19 | subnet-EXAMPLEd0503db0ec | | region-codec | 192.168.32.0/19 | subnet-EXAMPLEe2ba886490 | | region-codeb | 192.168.0.0/19 | subnet-EXAMPLE123c7c5182 | | region-codea | 192.168.160.0/19 | subnet-EXAMPLE0416ce588p | +------------------+--------------------+----------------------------+
      3. 为节点所在的子网添加挂载目标。从前两个步骤的输出来看,集群有一个 IP 地址为 192.168.56.0 的节点。该 IP 地址位于 ID 为 subnet-EXAMPLEe2ba886490 的子网的 CidrBlock 内。因此,以下命令会为节点所在的子网创建一个挂载目标。如果集群中有更多节点,那么您应该为每个 AZ 中有节点的子网运行一次命令,将 subnet-EXAMPLEe2ba886490 替换为相应的子网 ID。

        aws efs create-mount-target \ --file-system-id $file_system_id \ --subnet-id subnet-EXAMPLEe2ba886490 \ --security-groups $security_group_id

部署示例应用程序

您可以部署动态创建持久性卷的示例应用程序,也可以手动创建持久性卷。您可以用其他应用程序替换本节中给出的示例。

Dynamic
重要

不能将动态预置与 Fargate 节点一起使用。

先决条件

您必须使用 1.2x 版或更高版本的 Amazon EFS CSI 驱动程序,该驱动程序需要 1.17 或更高版本的集群。要更新集群,请参阅 更新集群

部署使用控制器所创建的持久性卷的示例应用程序

此过程利用来自 Amazon EFS Container Storage Interface (CSI) 驱动程序 GitHub 存储库的动态预置示例。它通过 Amazon EFS 接入点和 Pod(一组容器)使用的持久性卷声明 (PVC) 动态创建一个持久性卷。

  1. 为 EFS 创建存储类。有关所有参数和配置选项,请参阅 GitHub 上的 Amazon EFS CSI 驱动程序

    1. 检索您的 Amazon EFS 文件系统 ID。您可以在 Amazon EFS 控制台中查找此信息,或者使用以下 Amazon CLI 命令。

      aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text

      输出:

      fs-582a03f3
    2. 下载 Amazon EFS 的 StorageClass 清单。

      curl -o storageclass.yaml https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/storageclass.yaml
    3. 编辑文件。找到以下行,然后将 fileSystemId 的值替换为文件系统 ID。

      fileSystemId: fs-582a03f3
    4. 部署存储类。

      kubectl apply -f storageclass.yaml
  2. 通过部署利用 PersistentVolumeClaim 的 Pod 来测试自动预置:

    1. 下载一个清单,该清单将部署一个 Pod 和一个 PersistentVolumeClaim。

      curl -o pod.yaml https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/pod.yaml
    2. 使用示例应用程序和 Pod 使用的 PersistentVolumeClaim 来部署 Pod。

      kubectl apply -f pod.yaml
  3. 确定运行控制器的 Pod 的名称。

    kubectl get pods -n kube-system | grep efs-csi-controller

    输出

    efs-csi-controller-74ccf9f566-q5989 3/3 Running 0 40m efs-csi-controller-74ccf9f566-wswg9 3/3 Running 0 40m
  4. 几秒钟后,您可以观察到控制器开始接受更改(已编辑,旨在提高可读性)。将 74ccf9f566-q5989 替换成来自上一个命令输出中的一个 Pod 的值。

    kubectl logs efs-csi-controller-74ccf9f566-q5989 \ -n kube-system \ -c csi-provisioner \ --tail 10

    输出

    ... 1 controller.go:737] successfully created PV pvc-5983ffec-96cf-40c1-9cd6-e5686ca84eca for PVC efs-claim and csi volume name fs-95bcec92::fsap-02a88145b865d3a87

    如果未看到上一个输出,请使用其他控制器 Pod 之一运行上一个命令。

  5. 确认已创建状态为 BoundPersistentVolumeClaim 的持久性卷:

    kubectl get pv

    输出

    NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-5983ffec-96cf-40c1-9cd6-e5686ca84eca 20Gi RWX Delete Bound default/efs-claim efs-sc 7m57s
  6. 查看有关所创建的 PersistentVolumeClaim 的详细信息。

    kubectl get pvc

    输出

    NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE efs-claim Bound pvc-5983ffec-96cf-40c1-9cd6-e5686ca84eca 20Gi RWX efs-sc 9m7s
  7. 查看示例应用程序容器的状态,直到 STATUS 变成 Running

    kubectl get pods -o wide

    输出

    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES efs-example 1/1 Running 0 10m 192.168.78.156 ip-192-168-73-191.region-code.compute.internal <none> <none>
    注意

    如果容器没有列出 IP 地址,请确保为节点所在的子网添加了挂载目标(如 创建 Amazon EFS 文件系统 末尾所述)。否则该容器不会退出 ContainerCreating 状态。列出 IP 地址后,容器可能需要几分钟才能达到 Running 状态。

  8. 确认数据已写入到卷。

    kubectl exec efs-app -- bash -c "cat data/out"

    输出

    ... Tue Mar 23 14:29:16 UTC 2021 Tue Mar 23 14:29:21 UTC 2021 Tue Mar 23 14:29:26 UTC 2021 Tue Mar 23 14:29:31 UTC 2021 ...
  9. (可选)终止运行 Pod 的 Amazon EKS 节点并等待重新安排运行 Pod。或者,您也可以删除 Pod 并重新部署它。再次完成上一步,确认输出包含先前的输出。

Static

部署使用您创建的持久性卷的示例应用程序

此过程利用来自 Amazon EFS Container Storage Interface (CSI) 驱动程序 GitHub 存储库的多个 Pod 读写许多示例来使用静态预置的 Amazon EFS 持久性卷,并使用 ReadWriteMany 访问模式从多个 Pod 访问它。

  1. Amazon EFS Container Storage Interface (CSI) 驱动程序 GitHub 存储库克隆到您的本地系统。

    git clone https://github.com/kubernetes-sigs/aws-efs-csi-driver.git
  2. 导航到 multiple_pods 示例目录。

    cd aws-efs-csi-driver/examples/kubernetes/multiple_pods/
  3. 检索您的 Amazon EFS 文件系统 ID。您可以在 Amazon EFS 控制台中查找此信息,或者使用以下 Amazon CLI 命令。

    aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text

    输出:

    fs-582a03f3
  4. 编辑 specs/pv.yaml 文件并将 volumeHandle 值替换为您的 Amazon EFS 文件系统 ID。

    apiVersion: v1 kind: PersistentVolume metadata: name: efs-pv spec: capacity: storage: 5Gi volumeMode: Filesystem accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain storageClassName: efs-sc csi: driver: efs.csi.aws.com volumeHandle: fs-582a03f3
    注意

    Amazon EFS 是弹性文件系统,不会强制实施任何文件系统容量限制。创建文件系统时,不使用持久性卷和持久性卷声明中的实际存储容量值。但是,由于存储容量是 Kubernetes 的必填字段,您必须指定一个有效值,例如此示例中的 5Gi。此值不会限制 Amazon EFS 文件系统的大小。

  5. specs 目录部署 efs-sc 存储类、efs-claim 持久性卷声明以及 efs-pv 持久性卷。

    kubectl apply -f specs/pv.yaml kubectl apply -f specs/claim.yaml kubectl apply -f specs/storageclass.yaml
  6. 列出默认命名空间中的持久性卷。查找具有 default/efs-claim 声明的持久性卷。

    kubectl get pv -w

    输出:

    NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE efs-pv 5Gi RWX Retain Bound default/efs-claim efs-sc 2m50s

    STATUS 变为 Bound 之前,请勿继续执行下一步。

  7. specs 目录部署 app1app2 示例应用程序。

    kubectl apply -f specs/pod1.yaml kubectl apply -f specs/pod2.yaml
  8. 查看默认命名空间中的 Pod 并等待 app1app2 Pod 的 STATUS 变为 Running 状态。

    kubectl get pods --watch
    注意

    可能需要几分钟 Pod 才能达到 Running 状态。

  9. 描述持久性卷。

    kubectl describe pv efs-pv

    输出:

    Name: efs-pv Labels: none Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"PersistentVolume","metadata":{"annotations":{},"name":"efs-pv"},"spec":{"accessModes":["ReadWriteMany"],"capaci... pv.kubernetes.io/bound-by-controller: yes Finalizers: [kubernetes.io/pv-protection] StorageClass: efs-sc Status: Bound Claim: default/efs-claim Reclaim Policy: Retain Access Modes: RWX VolumeMode: Filesystem Capacity: 5Gi Node Affinity: none Message: Source: Type: CSI (a Container Storage Interface (CSI) volume source) Driver: efs.csi.aws.com VolumeHandle: fs-582a03f3 ReadOnly: false VolumeAttributes: none Events: none

    Amazon EFS 文件系统 ID 将作为 VolumeHandle 列出。

  10. 验证 app1 Pod 是否成功将数据写入卷。

    kubectl exec -ti app1 -- tail /data/out1.txt

    输出:

    ... Mon Mar 22 18:18:22 UTC 2021 Mon Mar 22 18:18:27 UTC 2021 Mon Mar 22 18:18:32 UTC 2021 Mon Mar 22 18:18:37 UTC 2021 ...
  11. 验证 app2 Pod 在卷中显示的数据与 app1 写入卷的数据相同。

    kubectl exec -ti app2 -- tail /data/out1.txt

    输出:

    ... Mon Mar 22 18:18:22 UTC 2021 Mon Mar 22 18:18:27 UTC 2021 Mon Mar 22 18:18:32 UTC 2021 Mon Mar 22 18:18:37 UTC 2021 ...
  12. 完成试验时,请删除此示例应用程序的资源以进行清理。

    kubectl delete -f specs/

    您还可以手动删除您创建的文件系统和安全组。