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

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

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

亚马逊 Web Services 的 Ricardo Morais、Rodrigo Bersa 和 Lucio Pereira

摘要

此模式为使用 AWS Fargate 配置计算资源来启用亚马逊弹性文件系统 (Amazon EFS) 作为在亚马逊弹性 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 网络服务器。您可以将 Amazon EFS 用作共享文件系统,以存储在 Web 服务器的不同实例之间共享的静态文件。在此示例场景中,直接修改文件系统,而不是将静态文件融入 Docker 映像中。

先决条件和限制

先决条件

  • 一个有效的 Amazon Web Services account

  • 具有 Kubernetes 版本 1.17 或更高版本的现有亚马逊 EKS 集群(已测试至 1.27 版本)

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

  • 集群管理权限

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

限制

  • 配合使用 Amazon EKS 与 Fargate 时需要考虑某些限制。例如,不支持使用某些 Kubernetes 结构,例如 DaemonSets 和特权容器。有关 Fargate 限制的更多信息,请参阅亚马逊 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 分布在可用区中

    • 在集群级别绑定到永久卷 (PV) 的一个永久卷声明 (PVC)

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

工具

Amazon Web Services

其他工具

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

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

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

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

代码

此模式的代码在使用 AWS Fargate 存储库的 Amazon EFS GitHub 持久性配置中提供。这些脚本按照 epic 的顺序整epic01epic06,按照 Epics 部分中此模式的顺序排列。

最佳实践

目标架构包括以下服务和组件,它遵循了 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 Pods,用于验证内容是否可以由应用程序的不同实例共享、使用和编写。

操作说明

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 写入的文件。

输入以下命令以验证工作负载 2 是否可以读取工作负载 1 写入的/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