预配 EFS 永久性卷

本页面介绍如何使用 EFS CSI 驱动程序设置基于 EFS 的 PersistentVolume,以便在 GKE on AWS 中使用。Elastic File System (EFS) 是为集群提供网络文件系统的底层 AWS 机制。基于 EFS 的 PersistentVolume 是一种集群资源,它通过 EFS 接入点为您的工作负载提供存储空间,并确保即使没有连接到工作负载,存储空间也会持久保留。

GKE on AWS 支持静态和动态预配 PersistentVolume。动态预配使用的设置略有不同,但之后所需的管理工作量更少。

准备工作

如需执行本页面中的步骤,请先完成以下步骤:

静态预配概览

创建 Elastic File System (EFS) 并通过静态预配将其提供给集群中的工作负载分为四个步骤:

  • 创建 EFS 资源
  • 配置您的网络
  • 创建装载目标
  • 创建 PersistentVolume

最后一步是工作负载:通过发出 PersistentVolumeClaim 来请求永久性存储空间。

动态预配概览

创建 EFS 资源并通过动态预配来提供它也分为四个步骤:

  • 创建 EFS 资源
  • 配置您的网络
  • 创建装载目标
  • 创建 StorageClass

创建 StorageClass 是一次性操作。定义具有给定特征的存储类别后,工作负载可以发出 PersistentVolumeClaim 或请求永久性存储空间。具有这些特征的存储空间的所有 PersistentVolumeClaim 都可以请求相同的 StorageClass

常见步骤

无论您在集群中使用静态还是动态预配,都必须从此处列出的设置步骤开始,然后视情况继续执行静态或动态预配步骤。创建 EFS 并使其可访问后,工作负载必须执行最后几个步骤才能访问它。使用 EFS 存储空间中介绍了执行此操作的步骤。

创建 AWS EFS 资源

无论您是使用静态还是动态预配,都需要 EFS 资源。如果您的集群使用这两者,则可以为它们分别创建单独的 EFS 资源或使用相同的资源。如需详细了解如何创建 EFS 资源,请参阅创建 Amazon EFS 文件系统

您也可以重复使用现有的 EFS,在这种情况下,您可以跳过此部分并转到创建装载目标

  1. 获取运行集群的 AWS 区域。

    gcloud container aws clusters describe CLUSTER_NAME \
      --location=LOCATION \
      --format="value(awsRegion)"
    

    替换以下内容:

    • CLUSTER_NAME:AWS 集群的名称。
    • LOCATION:AWS 集群的 Google Cloud 位置
  2. 使用以下命令在同一 AWS 区域创建 EFS 资源系统。

    aws efs create-file-system \
      --region AWS_REGION \
      --performance-mode generalPurpose \
      --query 'FileSystemId' \
      --output text
    

    替换以下内容:

    • AWS_REGION:运行集群的 AWS 区域

输出内容包括文件系统的 ID。请保存此值。您之后会用到它。

创建装载目标

EFS 的 CSI 驱动程序通过 EFS 装载目标访问文件系统。装载目标是使用 AWS 安全群组来控制对底层 EFS 的访问权限的专用 IP 地址。

如果集群中的节点池在不同的子网上运行,您必须在每个节点池子网上创建单独的装载目标。

在此示例中,对每个装载目标的访问受包含装载目标和节点池机器的单个安全群组保护。根据您的 VPC 配置和安全要求,您可能会选择将此配置拆分为两个或更多安全群组,例如,一个用于装载目标,另一个用于节点池工作器节点。

  1. 创建专用安全群组来控制对 EFS 的访问权限

    获取运行集群的 AWS VPC 的 ID。

    gcloud container aws clusters describe CLUSTER_NAME \
      --location=LOCATION \
      --format="value(networking.vpcId)"
    

    替换以下内容:

    • CLUSTER_NAME
    • LOCATION

    输出包含 VPC 的 ID。请保存此值。您之后会用到它。

  2. 创建安全群组以控制对 EFS 装载目标的访问权限。

    aws ec2 create-security-group \
      --group-name gke-efs-security-group \
      --description "EFS security group" \
      --vpc-id VPC_ID \
      --output text
    

    VPC_ID 替换为运行集群的 AWS VPC 的 ID。

    输出包含新安全群组的 ID。请保存此值。您之后会用到它。

  3. 默认情况下,AWS 会使用允许所有出站流量的默认规则创建安全群组。移除默认的出站规则。

    aws ec2 revoke-security-group-egress \
      --group-id SECURITY_GROUP_ID
      --ip-permissions '[{"IpProtocol":"-1","FromPort":-1,"ToPort":-1,"IpRanges":[{"CidrIp":"0.0.0.0/0"}]}]'
    

    SECURITY_GROUP_ID 替换为 AWS 安全群组的 ID。

  4. 授权 EFS(端口 2049)的入站和出站流量。

    aws ec2 authorize-security-group-ingress \
        --group-id SECURITY_GROUP_ID \
        --protocol tcp \
        --port 2049 \
        --source-group SECURITY_GROUP_ID
    
    aws ec2 authorize-security-group-egress \
        --group-id SECURITY_GROUP_ID \
        --protocol tcp \
        --port 2049 \
        --source-group SECURITY_GROUP_ID
    
  5. 在每个节点池子网上创建 EFS 装载目标。

    列出与所有节点池关联的子网。

    gcloud container aws node-pools list \
      --cluster=CLUSTER_NAME \
      --location=LOCATION \
      --format="value(subnetId)"
    

    替换以下内容:

    • CLUSTER_NAME
    • LOCATION

    输出为子网 ID 列表。请保存此值。您之后会用到它。

  6. 对于每个子网,创建一个应用安全群组的关联 EFS 装载目标。

    aws efs create-mount-target \
        --file-system-id EFS_ID \
        --subnet-id SUBNET_ID \
        --security-groups SECURITY_GROUP_ID
    

    替换以下内容:

    • EFS_ID:EFS 资源的 ID。
    • SUBNET_ID:节点池子网的 ID。
    • SECURITY_GROUP_ID
  7. 将 EFS 安全群组添加到所有集群节点池。

    获取所有节点池的列表。

    gcloud container aws node-pools list \
      --cluster=CLUSTER_NAME \
      --location=LOCATION
    

    替换以下内容:

    • CLUSTER_NAME
    • LOCATION

    输出包含集群的节点池的名称。请保存此值。您之后会用到它。

  8. 更新每个节点池以包含新的 EFS 安全群组。

    gcloud container aws node-pools update NODE_POOL_NAME \
      --cluster=CLUSTER_NAME \
      --location=LOCATION  \
      --security-group-ids=SECURITY_GROUP_IDS
    

    替换以下内容:

    • NODE_POOL_NAME:节点池的名称。
    • CLUSTER_NAME:您的集群的名称。
    • LOCATION
    • SECURITY_GROUP_IDS:工作器节点的安全群组 ID 的列表。

创建一个 PersistentVolume(静态)或 StorageClass(动态)

如果您使用的是静态预配,则下一步是创建 PersistentVolume。如果您使用的是动态预配,则 EFS 驱动程序会为您执行此操作;您可以为工作负载定义 StorageClass,以便在其 PersistentVolumeClaim 中指定。选择与您所选的配置方法匹配的标签页。

静态预配

如果您使用的是静态预配,则下一步是创建用于装载 EFS 共享的 PersistentVolume。

  1. 根据您是直接连接到 EFS 共享还是通过接入点连接,选择相应的标签页。

    直接连接

    将以下 YAML 清单复制到名为 efs-volume.yaml 的文件中。该清单引用您之前创建的 EFS 存储类别。

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: VOLUME_NAME
    spec:
      capacity:
        # Note: storage capacity is not used by the EFS CSI driver.
        # It is required by the PersistentVolume spec.
        storage: 5Gi
      volumeMode: Filesystem
      accessModes:
        - ReadWriteMany
      persistentVolumeReclaimPolicy: Retain
      storageClassName: "" # storageClassName is not required, see note in the following section.
      claimRef:
        name: CLAIM_NAME
        namespace: default
      csi:
        driver: efs.csi.aws.com
        volumeHandle: EFS_ID
    

    替换以下内容:

    • VOLUME_NAME 替换为永久性卷的名称。
    • CLAIM_NAME 替换为您要用于 PersistentVolumeClaim 的名称。
    • EFS_ID 替换为您的 EFS 资源 ID。例如 fs-12345678a

    接入点

    要创建基于接入点的卷,您需要手动预配。如需了解详情,请参阅使用 EFS 接入点

    将以下 YAML 清单复制到名为 efs-volume.yaml 的文件中。该清单引用您之前创建的 EFS 存储类别。

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: VOLUME_NAME
    spec:
      capacity:
        # Note: storage capacity is not used by the EFS CSI driver.
        # It is required by the PersistentVolume spec.
        storage: 5Gi
      volumeMode: Filesystem
      accessModes:
        - ReadWriteMany
      persistentVolumeReclaimPolicy: Retain
      # Set storageClassName to empty string for static provisioning. See [Use an EFS resource](/anthos/clusters/docs/multi-cloud/aws/how-to/use-efs)
      storageClassName: ""
      claimRef:
        name: CLAIM_NAME
        namespace: default
      csi:
        driver: efs.csi.aws.com
        volumeHandle: EFS_ID::ACCESS_POINT_ID
    

    替换以下内容:

    • VOLUME_NAME 替换为永久性卷的名称。
    • CLAIM_NAME 替换为您要用于 PersistentVolumeClaim 的名称。
    • EFS_ID 替换为您的 EFS 资源 ID。例如 fs-12345678a
    • ACCESS_POINT_ID 替换为您的接入点 ID。例如 fsap-1234567890abcde
  2. 将 YAML 应用到您的集群。

    kubectl apply -f efs-volume.yaml
    

    输出内容将确认 PersistentVolume 的创建。

    persistentvolume/VOLUME_NAME created
    
    

动态预配

本部分介绍如何创建引用您之前创建的 EFS 资源的 StorageClass。完成此操作后,开发者便可以按照使用 EFS 资源中所述的步骤访问 EFS 资源。

  1. 创建一个引用 EFS 资源 ID 的 StorageClass。

    将以下 yaml fragment 复制到名为 efs-storage-class.yaml 的新文件。如需详细了解如何调整此文件描述的 StorageClass 的特性,请参阅有关 EFS StorageClass 参数的文档。

    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: EFS_STORAGE_CLASS_NAME
    provisioner: efs.csi.aws.com
    mountOptions:
      - tls
    parameters:
      provisioningMode: efs-ap
      fileSystemId: EFS_ID
      directoryPerms: "700"
    
    

    您需要将其中的:

    • EFS_STORAGE_CLASS_NAME 替换为您为 StorageClass 选择的名称。
    • EFS_ID 替换为您的 EFS 资源 ID,例如 fs-12345678a。
  2. 将 YAML 应用到您的集群。

    kubectl apply -f efs-storage-class.yaml
    

    如果成功,此命令的输出将包含类似于以下内容的行:

    storageclass/EFS_STORAGE_CLASS_NAME created

清理

如需移除您在前面部分创建的资源,请运行以下命令:

  1. 使用 kubectl 从集群中移除 EFS 声明资源:

    kubectl delete -f efs-claim.yaml
    
  2. 如果使用静态预配,请使用 kubectl 从集群中移除关联资源:

    kubectl delete -f efs-volume.yaml
    
  3. 如果使用动态预配,请使用 kubectl 从集群中移除关联资源:

    kubectl delete -f efs-storage-class.yaml
    
  4. 找到您的装载目标 ID:

    aws efs describe-mount-targets \
    --file-system-id EFS_ID \
    --profile adminuser \
    --region AWS_REGION
    

    替换以下内容:

    • EFS_ID:EFS 资源的 ID
    • AWS_REGION:运行集群的 AWS 区域

    输出包含装载目标 ID。请保存此值。您之后会用到它。

  5. 删除 EFS 装载目标:

    aws efs delete-mount-target \
    --mount-target-id MOUNT_TARGET_ID \
    --profile adminuser \
    --region AWS_REGION
    

    替换以下内容:

    • MOUNT_TARGET_ID:您的 EFS 装载目标的 ID
    • AWS_REGION:装载目标的 AWS 区域
  6. 删除您创建的任何安全群组。

  7. 使用 delete-file-system CLI 命令删除文件系统。您可以使用 describe-file-systems CLI 命令获取文件系统列表。响应中包含文件系统 ID。

    aws efs delete-file-system \
      --file-system-id EFS_ID \
      --profile adminuser \
      --region AWS_REGION
    

    替换以下内容:

    • EFS_ID
    • AWS_REGION

后续步骤