使用带 AWS Fargate 的 Amazon EFS on Amazon EKS,运行带持久数据存储的有状态工作负载 - AWS 规范指引

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用带 AWS Fargate 的 Amazon EFS on Amazon EKS,运行带持久数据存储的有状态工作负载

Ricardo Morais、Rodrigo Bersa 和 Lucio Pereira,Amazon Web Services

Summary

此模式为使用 AWS Fargate 预调配计算资源来启用 Amazon Elastic File System(Amazon EFS)作为在 Amazon Elastic Kubernetes Service(Amazon EKS)上运行的容器的存储设备的提供了指导。

此模式中描述的设置遵循安全最佳实践,默认提供静态安全性和传输安全性。若要加密您的 Amazon EFS 文件系统,请使用 AWS Key Management Service (AWS KMS) 密钥,但您也可以指定密钥别名来调度 KMS 密钥创建过程。

您可以按照此模式中的步骤为 proof-of-concept (PoC) 应用程序创建命名空间和 Fargate 配置文件,安装用于将 Kubernetes 集群与 Amazon EFS 集成的亚马逊 EFS 容器存储接口 (CSI) 驱动程序,配置存储类并部署 PoC 应用程序。这些步骤会生成 Amazon EFS 文件系统,该文件系统在多个 Kubernetes 工作负载之间共享,在 Fargate 上运行。此模式附带自动执行这些步骤的脚本。

如果您希望在容器化应用程序中实现数据持久化,并且希望避免在扩展操作期间丢失数据,可以使用此模式。例如:

  • DevOps 工具 — 常见的场景是开发持续集成和持续交付(CI/CD) strategy. In this case, you can use Amazon EFS as a shared file system to store configurations among different instances of the CI/CD tool or to store a cache (for example, an Apache Maven repository) for pipeline stages among different instances of the CI/CD工具。

  • Web 服务器 – 常见的场景为使用 Apache 作为 HTTP web 服务器。您可以将 Amazon EFS 用作共享文件系统,以存储在 Web 服务器的不同实例之间共享的静态文件。在此示例场景中,直接修改文件系统,而不是将静态文件融入 Docker 映像中。

先决条件和限制

先决条件

  • 一个有效的 Amazon Web Services account

  • 运行 Kubernetes 版本 1.17 或更高版本的现有 Amazon EKS 集群(已测试至版本 1.27)

  • 现有 Amazon EFS 文件系统,用于绑定 Kubernetes StorageClass 并动态配置文件系统

  • 集群管理权限

  • 配置为指向所需 Amazon EKS 集群的上下文

限制

  • 配合使用 Amazon EKS 与 Fargate 时需要考虑某些限制。例如,不支持使用某些 Kubernetes 结构,例如 DaemonSets 和特权容器。有关 Fargate 限制的更多信息,请参阅 Amazon EKS 文档中的 AWS Fargate 注意事项

  • 此模式代码支持运行 Linux 或 macOS 的工作站。

产品版本

  • AWS 命令行界面(AWS CLI)版本 2 或更高版本

  • Amazon EFS CSI 驱动程序版本 1.0 或更高版本(已测试至版本 2.4.8)

  • eksctl 0.24.0 版本或更高版本(已测试至版本 0.158.0)

  • jq 版本 1.6 或更高版本

  • kubectl 版本 1.17 或更高版本(已测试至版本 1.27)

  • Kubernetes 版本 1.17 或更高版本(已测试至版本 1.27)

架构

使用 Amazon EFS 运行带持久化数据存储的有状态工作负载的架构图

目标架构由以下基础设施组成:

  • 虚拟私有云(VPC)

  • 两个可用区

  • 具有可访问互联网的 NAT 网关的公有子网

  • 具有 Amazon EKS 集群和 Amazon EFS 挂载目标(也称为挂载点)的私有子网

  • VPC 级别的 Amazon EFS

以下是 Amazon EKS 集群的环境基础设施:

  • 在命名空间层级适配 Kubernetes 构造的 AWS Fargate 配置文件

  • 包含以下组件的 Kubernetes 命名空间:

    • 跨可用区分布的两个应用程序容器组(pod)

    • 在集群层级与持久卷绑定的持久卷声明(PVC)

  • 绑定到命名空间中的 PVC 且指向集群外部私有子网中的 Amazon EFS 挂载目标的集群范围 PV

工具

AWS 服务

其他工具

  • Docker 是一组平台即服务(PaaS)产品,它们利用操作系统级的虚拟化技术在容器中提供软件。

  • eksctl 是一款命令行实用程序,用于在 Amazon EKS 上创建和管理 Kubernetes 集群。

  • kubectl:针对 Kubernetes 集群运行命令的命令行界面。

  • jq 是一个用于解析 JSON 的命令行工具。

代码

此模式的代码在使用 AWS Fargate 存储库的 Amazon EFS GitHub 持久性配置中提供。这些脚本按操作说明整理,存放于 epic01epic06 文件夹中,与此模式的操作说明部分中的顺序相对应。

最佳实践

目标架构包括以下服务和组件,并遵循 AWS Well-Architected Framework 最佳实践:

  • Amazon EFS 提供了一个简单、可扩展、完全托管的弹性 NFS 文件系统。这用作在容器组(pod)(分布在所选 Amazon EKS 集群的私有子网中)中运行的 PoC 应用程序的所有复制的共享文件系统。

  • 每个私有子网的 Amazon EFS 挂载目标。其为集群的虚拟私有云(VPC)中的每个可用区域提供冗余。

  • 运行 Kubernetes 工作负载的 Amazon EKS。您必须预置 Amazon EKS 集群,然后才能使用此模式,如先决条件部分所述。

  • 为存储在 Amazon EFS 文件系统中的内容提供静态加密的 AWS KMS。

  • Fargate 管理容器的计算资源,因此您可以专注于业务需求而不是基础设施负担。Fargate 配置文件是为所有私有子网创建的。其为集群的虚拟私有云(VPC)中的每个可用区域提供冗余。

  • 用于验证内容是否可以由应用程序的不同实例共享、使用和编写的 Kubernetes 容器组(pod)。

操作说明

Task说明所需技能

创建一个 Amazon EKS 集群。

注意

如果您已部署集群,请跳至下一操作说明。在现有 AWS 账户中创建 Amazon EKS 集群。在GitHub 目录中,使用其中一种模式使用 Terraform 或 eksctl 部署 Amazon EKS 集群。有关更多信息,请参阅 Amazon EKS 文档中的创建 Amazon EKS 集群。在 Terraform 模式中,还提供了以下操作的示例:将 Fargate 配置文件关联到 Amazon EKS 集群、创建 Amazon EFS 文件系统,以及在 Amazon EKS 集群中部署 Amazon EFS CSI 驱动程序。

AWS 管理员、Terraform 或 eksctl 管理员、Kubernetes 管理员

导出环境变量。

运行 env.sh 脚本。该脚本会提供后续步骤所需的信息。

source ./scripts/env.sh Inform the AWS Account ID: <13-digit-account-id> Inform your AWS Region: <aws-Region-code> Inform your Amazon EKS Cluster Name: <amazon-eks-cluster-name> Inform the Amazon EFS Creation Token: <self-genereated-uuid>

如果尚未注明,则可通过以下 CLI 命令获取上述所需的全部信息。

# ACCOUNT ID aws sts get-caller-identity --query "Account" --output text
# REGION CODE aws configure get region
# CLUSTER EKS NAME aws eks list-clusters --query "clusters" --output text
# GENERATE EFS TOKEN uuidgen
AWS 系统管理员
Task说明所需技能

为应用程序工作负载创建 Kubernetes 命名空间和 Fargate 配置文件。

创建命名空间以接收与 Amazon EFS 交互的应用程序工作负载。运行 create-k8s-ns-and-linked-fargate-profile.sh 脚本。您可以选择使用自定义的命名空间名称或默认提供的命名空间 poc-efs-eks-fargate

使用自定义的应用程序命名空间名称:

export $APP_NAMESPACE=<CUSTOM_NAME> ./scripts/epic01/create-k8s-ns-and-linked-fargate-profile.sh \ -c "$CLUSTER_NAME" -n "$APP_NAMESPACE"

不使用自定义的应用程序命名空间名称:

./scripts/epic01/create-k8s-ns-and-linked-fargate-profile.sh \ -c "$CLUSTER_NAME"

其中,$CLUSTER_NAME 是 Amazon EKS 集群的名称。-n <NAMESPACE> 参数是可选的;如果未指定该参数,系统将提供默认生成的命名空间名称。

拥有授予权限的 Kubernetes 用户
Task说明所需技能

生成唯一令牌。

Amazon EFS 需要一个创建令牌,以确保幂等操作(使用相同的创建令牌调用该操作没有效果)。若要满足此要求,您必须通过可用技术生成唯一令牌。例如,您可以生成通用唯一标识符(UUID),以用作创建令牌。

AWS 系统管理员

创建 Amazon EFS 文件系统。

创建用于接收应用程序工作负载读取和写入数据文件的文件系统。您可以创建加密或非加密文件系统。(根据最佳实践标准,此模式的代码将创建加密系统,以默认启用静态加密。) 您可以使用唯一对称的 AWS KMS 密钥对文件系统进行加密。如果未指定自定义密钥,则使用 AWS 托管式密钥。

为 Amazon EFS 生成唯一令牌后,使用 create-efs.sh 脚本创建加密或非加密 Amazon EFS 文件系统。

使用静态加密,无 KMS 密钥:

./scripts/epic02/create-efs.sh \ -c "$CLUSTER_NAME" \ -t "$EFS_CREATION_TOKEN"

其中,$CLUSTER_NAME 是 Amazon EKS 集群的名称,$EFS_CREATION_TOKEN 是文件系统的唯一创建令牌。

使用静态加密,有 KMS 密钥:

./scripts/epic02/create-efs.sh \ -c "$CLUSTER_NAME" \ -t "$EFS_CREATION_TOKEN" \ -k "$KMS_KEY_ALIAS"

其中,$CLUSTER_NAME 是 Amazon EKS 集群的名称,$EFS_CREATION_TOKEN 是文件系统的唯一创建令牌,$KMS_KEY_ALIAS 是 KMS 密钥的别名。

不使用加密:

./scripts/epic02/create-efs.sh -d \ -c "$CLUSTER_NAME" \ -t "$EFS_CREATION_TOKEN"

其中,$CLUSTER_NAME 是 Amazon EKS 集群的名称,$EFS_CREATION_TOKEN 是文件系统的唯一创建令牌,–d 禁用静态加密。

AWS 系统管理员

创建安全组。

创建允许 Amazon EKS 集群访问 Amazon EFS 文件系统的安全组。

AWS 系统管理员

更新安全组的入站规则

更新安全组的入站规则,以允许对传入流量进行以下设置:

  • TCP 协议 – 端口 2049

  • – 包含 Kubernetes 集群的 VPC 中的私有子网的 CIDR 数据块范围

AWS 系统管理员

为每个私有子网添加挂载目标。

对于 Kubernetes 集群的每个私有子网,请为文件系统和安全组创建挂载目标。

AWS 系统管理员
Task说明所需技能

部署 Amazon EFS CSI 驱动程序。

将 Amazon EFS CSI 驱动程序部署至集群。驱动程序会根据应用程序创建的持久卷声明预调配存储。运行 create-k8s-efs-csi-sc.sh 脚本,以将 Amazon EFS CSI 驱动程序和存储类别部署到集群中。

./scripts/epic03/create-k8s-efs-csi-sc.sh

此脚本使用 kubectl 实用程序,因此请确保上下文已配置且指向所需的 Amazon EKS 集群。

拥有授予权限的 Kubernetes 用户

部署存储类。

将 Amazon EFS 配置器 (efs.csi.aws.com) 的存储类部署至集群中。

拥有授予权限的 Kubernetes 用户
Task说明所需技能

部署持久卷。

部署持久卷,并将其链接至创建的存储类和 Amazon EFS 文件系统的 ID。应用程序使用持久卷读取和写入内容。您可以在存储字段中为持久卷指定任何大小。Kubernetes 需要此字段,但由于 Amazon EFS 是弹性文件系统,因此其不会强制实施任何文件系统容量。您可以部署加密或不加密的持久卷。(根据最佳实践标准,Amazon EFS CSI 驱动程序默认启用加密。) 运行 deploy-poc-app.sh 脚本,以部署持久卷、持久卷声明和两个工作负载。

使用传输中加密:

./scripts/epic04/deploy-poc-app.sh \ -t "$EFS_CREATION_TOKEN"

其中,$EFS_CREATION_TOKEN 是文件系统的唯一创建令牌。

不使用传输中加密:

./scripts/epic04/deploy-poc-app.sh -d \ -t "$EFS_CREATION_TOKEN"

其中,$EFS_CREATION_TOKEN 是文件系统的唯一创建令牌,–d 禁用传输中加密。

拥有授予权限的 Kubernetes 用户

部署应用程序请求的持久卷声明。

部署应用程序请求的持久卷声明,并将其链接到存储类别。使用与之前创建的持久卷相同的访问模式。您可以在存储字段中为持久卷声明指定任何大小。Kubernetes 需要此字段,但由于 Amazon EFS 是弹性文件系统,因此其不会强制实施任何文件系统容量。

拥有授予权限的 Kubernetes 用户

部署工作负载 1。

部署可代表应用程序工作负载 1 的容器组(pod)。此工作负载会将内容写入文件 /data/out1.txt

拥有授予权限的 Kubernetes 用户

部署工作负载 2。

部署可代表应用程序工作负载 2 的容器组(pod)。此工作负载会将内容写入文件 /data/out2.txt

拥有授予权限的 Kubernetes 用户
Task说明所需技能

检查 PersistentVolume 的状态。

输入以下命令以检查 PersistentVolume 的状态。

kubectl get pv

有关示例输出,请参阅其他信息部分。

拥有授予权限的 Kubernetes 用户

检查 PersistentVolumeClaim 的状态。

输入以下命令以检查 PersistentVolumeClaim 的状态。

kubectl -n poc-efs-eks-fargate get pvc

有关示例输出,请参阅其他信息部分。

拥有授予权限的 Kubernetes 用户

验证工作负载 1 是否可写入文件系统。

输入以下命令以验证工作负载 1 是否正在向 /data/out1.txt 写入数据。

kubectl exec -ti poc-app1 -n poc-efs-eks-fargate -- tail -f /data/out1.txt

结果类似于以下内容:

... Thu Sep 3 15:25:07 UTC 2023 - PoC APP 1 Thu Sep 3 15:25:12 UTC 2023 - PoC APP 1 Thu Sep 3 15:25:17 UTC 2023 - PoC APP 1 ...
拥有授予权限的 Kubernetes 用户

验证工作负载 2 是否可写入文件系统。

输入以下命令以验证工作负载 2 是否正在向 /data/out2.txt 写入数据。

kubectl -n $APP_NAMESPACE exec -ti poc-app2 -- tail -f /data/out2.txt

结果类似于以下内容:

... Thu Sep 3 15:26:48 UTC 2023 - PoC APP 2 Thu Sep 3 15:26:53 UTC 2023 - PoC APP 2 Thu Sep 3 15:26:58 UTC 2023 - PoC APP 2 ...
拥有授予权限的 Kubernetes 用户

验证工作负载 1 是否可以读取由工作负载 2 写入的文件。

输入以下命令,以验证工作负载 1 是否能够读取由工作负载 2 写入的 /data/out2.txt 文件。

kubectl exec -ti poc-app1 -n poc-efs-eks-fargate -- tail -n 3 /data/out2.txt

结果类似于以下内容:

... Thu Sep 3 15:26:48 UTC 2023 - PoC APP 2 Thu Sep 3 15:26:53 UTC 2023 - PoC APP 2 Thu Sep 3 15:26:58 UTC 2023 - PoC APP 2 ...
拥有授予权限的 Kubernetes 用户

验证工作负载 2 是否可以读取由工作负载 1 写入的文件。

输入以下命令,以验证工作负载 1 是否能够读取由工作负载 2 写入的 /data/out1.txt 文件。

kubectl -n $APP_NAMESPACE exec -ti poc-app2 -- tail -n 3 /data/out1.txt

结果类似于以下内容:

... Thu Sep 3 15:29:22 UTC 2023 - PoC APP 1 Thu Sep 3 15:29:27 UTC 2023 - PoC APP 1 Thu Sep 3 15:29:32 UTC 2023 - PoC APP 1 ...
拥有授予权限的 Kubernetes 用户

验证移除应用程序组件后文件是否保留。

接下来,使用脚本移除应用程序组件(持久卷、持久卷声明和容器组(pod)),并验证文件 /data/out1.txt/data/out2.txt 是否仍保留在文件系统中。使用以下命令运行 validate-efs-content.sh 脚本。

./scripts/epic05/validate-efs-content.sh \ -t "$EFS_CREATION_TOKEN"

其中,$EFS_CREATION_TOKEN 是文件系统的唯一创建令牌。

结果类似于以下内容:

pod/poc-app-validation created Waiting for pod get Running state... Waiting for pod get Running state... Waiting for pod get Running state... Results from execution of 'find /data' on validation process pod: /data /data/out2.txt /data/out1.txt
拥有授予权限的 Kubernetes 用户、系统管理员
Task说明所需技能

监控应用程序日志。

作为第二天操作的一部分,请将应用程序日志发送到 Amazon CloudWatch 进行监控。

AWS 系统管理员、拥有授予权限的 Kubernetes 用户

使用 Container Insights 监控 Amazon EKS 和 Kubernetes 容器。

作为第二天操作的一部分,使用亚马逊容器洞察监控亚马逊 EKS 和 Kubernetes 系统。 CloudWatch 此工具从不同级别和维度的容器化应用程序收集、聚合以及汇总指标。有关更多信息,请参阅相关资源部分。

AWS 系统管理员、拥有授予权限的 Kubernetes 用户

使用监控 Amazon EFS CloudWatch。

作为第二天操作的一部分,使用 Amazon 监控文件系统 CloudWatch,Amazon 会收集来自 Amazon EFS 的原始数据并将其处理为可读的近乎实时的指标。有关更多信息,请参阅相关资源部分。

AWS 系统管理员
Task说明所需技能

清理所有已创建的模式资源。

完成本模式后,清理所有资源,以避免产生 AWS 费用。使用 PoC 应用程序后,请运行 clean-up-resources.sh 脚本,以删除所有资源。完成下列选项之一。

使用静态加密,有 KMS 密钥:

./scripts/epic06/clean-up-resources.sh \ -c "$CLUSTER_NAME" \ -t "$EFS_CREATION_TOKEN" \ -k "$KMS_KEY_ALIAS"

其中,$CLUSTER_NAME 是 Amazon EKS 集群的名称,$EFS_CREATION_TOKEN 是文件系统的创建令牌,$KMS_KEY_ALIAS 是 KMS 密钥的别名。

不使用静态加密:

./scripts/epic06/clean-up-resources.sh \ -c "$CLUSTER_NAME" \ -t "$EFS_CREATION_TOKEN"

其中,$CLUSTER_NAME 是 Amazon EKS 集群的名称,$EFS_CREATION_TOKEN 是文件系统的创建令牌。

拥有授予权限的 Kubernetes 用户、系统管理员

相关资源

参考

GitHub 教程和示例

必要工具

附加信息

以下是 kubectl get pv 命令的示例输出。

NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE poc-app-pv 1Mi RWX Retain Bound poc-efs-eks-fargate/poc-app-pvc efs-sc 3m56s

以下是 kubectl -n poc-efs-eks-fargate get pvc 命令的示例输出。

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE poc-app-pvc Bound poc-app-pv 1Mi RWX efs-sc 4m34s