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 容器存储接口 (CSI) 驱动程序项目。

注意事项

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

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

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

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

  • 版本 1.4.1 或更高版本的此驱动程序支持使用 FIPS 装载文件系统。有关如何启用 FIPS 的更多信息,请参阅 GitHub 上的 README.md for Amazon EFS CSI 驱动程序

  • 注意 Amazon EFS 的资源配额。例如,可以为每个 Amazon EFS 文件系统创建 120 个接入点的配额。有关更多信息,请参阅https://docs.amazonaws.cn/efs/latest/ug/limits.html#limits-efs-resources-per-account-per-region

先决条件

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

  • 您的设备或 Amazon CloudShell 上安装并配置了 2.8.0 版或更高版本,或 1.25.87 版或更高版本的 Amazon CLI。您可以使用 aws --version | cut -d / -f2 | cut -d ' ' -f1 检查您的当前版本。软件包管理器(如 yumapt-get 或适用于 macOS 的 Homebrew)通常比 Amazon CLI 的最新版本落后几个版本。要安装最新版本,请参阅《Amazon Command Line Interface 用户指南》中的安装、更新和卸载 Amazon CLI使用 aws configure 进行快速配置。Amazon CloudShell 中安装的 Amazon CLI 版本也可能比最新版本落后几个版本。要对其进行更新,请参阅《Amazon CloudShell 用户指南》中的将 Amazon CLI 安装到您的主目录

  • 您的设备或 Amazon CloudShell 上安装了 kubectl 命令行工具。该版本可以与集群的 Kubernetes 版本相同,或者最多早于或晚于该版本一个次要版本。例如,如果您的集群版本为 1.22,则可以将 kubectl 版本 1.211.221.23 用于它。要安装或升级 kubectl,请参阅 安装或更新 kubectl

注意

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

创建 IAM policy和角色

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

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

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

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

      curl -o iam-policy-example.json https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/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 policy。用 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 \ --cluster my-cluster \ --namespace kube-system \ --name efs-csi-controller-sa \ --attach-policy-arn arn:aws:iam::111122223333:policy/AmazonEKS_EFS_CSI_Driver_Policy \ --approve \ --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/EXAMPLED539D4633E53DE1B71EXAMPLE
    2. 创建 IAM 角色,从而向 Kubernetes 服务账户授予 AssumeRoleWithWebIdentity 操作权限。

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

        { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.region-code.amazonaws.com.cn/id/EXAMPLED539D4633E53DE1B71EXAMPLE" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.eks.region-code.amazonaws.com.cn/id/EXAMPLED539D4633E53DE1B71EXAMPLE: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 policy 附加到该角色。请将 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: labels: app.kubernetes.io/name: aws-efs-csi-driver name: efs-csi-controller-sa namespace: kube-system annotations: eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/AmazonEKS_EFS_CSI_DriverRole
      2. 在集群上创建 Kubernetes 服务账户。使用您创建的名为 AmazonEKS_EFS_CSI_DriverRole 的 IAM 角色注释名为 efs-csi-controller-sa 的 Kubernetes 服务账户。

        kubectl apply -f efs-service-account.yaml

安装 Amazon EFS 驱动程序

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

重要

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

Manifest (private registry)

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

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

  1. 下载清单。将 v1.4.0 替换为适用于您所需的已发布版本的标签。有关已发布版本和标签,请参阅 GitHub 上的 aws-efs-csi-driver 版本

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

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

  2. sed -i.bak -e 's|us-west-2|region-code|' private-ecr-driver.yaml
  3. sed -i.bak -e 's|602401143452||' private-ecr-driver.yaml
  4. 编辑 private-ecr-driver.yaml 文件并删除用于创建 Kubernetes 服务账户的以下行。由于服务账户是在上一步骤中创建的,因此无需执行此操作。

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

    kubectl apply -f private-ecr-driver.yaml

创建 Amazon EFS 文件系统

Amazon EFS CSI 驱动程序支持 Amazon EFS 接入点,这些接入点是 Amazon EFS 文件系统中特定于应用程序的入口点,便于更轻松地在多个 pods 之间共享文件系统。接入点可以为通过接入点发出的所有文件系统请求强制执行用户身份,并为每个 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 驱动程序。

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

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

  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 使用的 PersistentVolumeClaimm 来部署 pod。

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

    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 替换为来自上一个命令输出中的一个 pods 的值。

    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

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

  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. 请查看示例应用程序 pod 的状态,直到 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>
    注意

    如果 pod 没有列出 IP 地址,请确保为节点所在的子网添加了挂载目标(如 创建 Amazon EFS 文件系统 末尾所述)。否则该 pod 不会退出 ContainerCreating 状态。列出 IP 地址后,pod 可能需要几分钟才能达到 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 容器存储接口 (CSI) 驱动程序 GitHub 存储库的多个容器组(pod)读写许多示例来使用静态预置的 Amazon EFS 持久性卷,并使用 ReadWriteMany 访问模式从多个 pods 访问它。

  1. Amazon EFS 容器存储接口 (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. 查看默认命名空间中的 pods 并等待 app1app2 pods 的 STATUS 变为 Running 状态。

    kubectl get pods --watch
    注意

    可能需要几分钟 pods 才能达到 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/

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