Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅
中国的 Amazon Web Services 服务入门
(PDF)。
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 Identity and Access Management IAM OpenID Connect (OIDC) 提供商。要确定您是否已经拥有一个或是否要创建一个,请参阅 为集群创建 IAM OIDC 提供商。
-
您的设备或 Amazon CloudShell 上安装并配置了 2.11.3
版或更高版本,或 1.27.93
版或更高版本的 Amazon CLI。您可以使用 aws --version | cut -d / -f2 | cut -d ' ' -f1
检查您的当前版本。软件包管理器(如 yum
、apt-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.24
,则可以将 kubectl
的 1.23
、1.24
或 1.25
版本与之配合使用。要安装或升级 kubectl
,请参阅 安装或更新 kubectl。
Amazon Fargate 上运行的 pod 会自动挂载 Amazon EFS 文件系统,无需此页面上所述的手动驱动程序安装步骤。
创建 IAM policy和角色
创建 IAM policy 并将其分配给 IAM 角色。该策略将允许 Amazon EFS 驱动程序与您的文件系统交互。
将 Amazon EFS CSI 驱动程序部署到 Amazon EKS 集群
-
创建允许 CSI 驱动程序的服务账户代表您调用 Amazon API 的 IAM policy。
-
从 GitHub 下载 IAM policy 文档。您还可以查看策略文档。
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/docs/iam-policy-example.json
-
创建策略。您可以将 AmazonEKS_EFS_CSI_Driver_Policy
更改为其他名称,但如果更改,请确保在后续步骤中也做出相应更改。
aws iam create-policy \
--policy-name AmazonEKS_EFS_CSI_Driver_Policy
\
--policy-document file://iam-policy-example.json
-
创建 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
-
-
确定集群的 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
-
创建 IAM 角色,从而向 Kubernetes 服务账户授予 AssumeRoleWithWebIdentity
操作权限。
-
将以下内容复制到名为 trust-policy
.json
的文件中。请将 111122223333
替换为您的账户 ID。将 EXAMPLED539D4633E53DE1B71EXAMPLE
和 region-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"
}
}
}
]
}
-
创建角色。您可以将 AmazonEKS_EFS_CSI_DriverRole
更改为其他名称,但如果更改,请确保在后续步骤中也做出相应更改。
aws iam create-role \
--role-name AmazonEKS_EFS_CSI_DriverRole
\
--assume-role-policy-document file://"trust-policy
.json"
-
使用以下命令将 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
-
创建一个使用您创建的 IAM 角色的 ARN 进行注释的 Kubernetes 服务账户。
-
将以下内容保存到名为 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
-
在集群上创建 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 注册表中存储的镜像来安装驱动程序
-
下载清单。将 release-1.X
替换为适用于您所需的已发布版本的标签。建议使用最新发布的版本。有关已发布版本和标签的更多信息以及更改日志,请参阅 GitHub 上的 aws-efs-csi-driver
版本。
kubectl kustomize \
"github.com/kubernetes-sigs/aws-efs-csi-driver/deploy/kubernetes/overlays/stable/ecr/?ref=release-1.X
" > private-ecr-driver.yaml
如果您遇到无法通过添加 IAM 权限来解决的问题,请改为尝试“清单(公有注册表)”步骤。
-
sed -i.bak -e 's|us-west-2|region-code
|' private-ecr-driver.yaml
-
sed -i.bak -e 's|602401143452||' private-ecr-driver.yaml
-
编辑 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
---
-
运用该清单。
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 文件系统
-
检索您的集群所在的 VPC ID,并将其存储在变量中,以便在后续步骤中使用。将 my-cluster
替换为您的集群名称。
vpc_id=$(aws eks describe-cluster \
--name my-cluster
\
--query "cluster.resourcesVpcConfig.vpcId" \
--output text)
-
检索您的集群的 VPC 的 CIDR 范围,并将其存储在变量中,以便在后续步骤中使用。将 region-code
替换为集群所在的 Amazon Web Services 区域。
cidr_range=$(aws ec2 describe-vpcs \
--vpc-ids $vpc_id \
--query "Vpcs[].CidrBlock" \
--output text \
--region region-code
)
-
创建一个安全组,该安全组包含一条允许您的 Amazon EFS 挂载点的入站 NFS 流量的入站规则。
-
创建安全组。将 example values
替换为您自己的值。
security_group_id=$(aws ec2 create-security-group \
--group-name MyEfsSecurityGroup
\
--description "My EFS security group
" \
--vpc-id $vpc_id \
--output text)
-
创建一条入站规则,该入站规则允许来自您的集群 VPC 的 CIDR 的入站 NFS 流量。
aws ec2 authorize-security-group-ingress \
--group-id $security_group_id \
--protocol tcp \
--port 2049 \
--cidr $cidr_range
要进一步限制对文件系统的访问,您可以将 CIDR 用于子网,而不是 VPC。
-
为您的 Amazon EKS 集群创建 Amazon EFS 文件系统。
-
创建文件系统。将 region-code
替换为集群所在的 Amazon Web Services 区域。
file_system_id=$(aws efs create-file-system \
--region region-code
\
--performance-mode generalPurpose \
--query 'FileSystemId' \
--output text)
-
创建挂载目标。
-
确定您的集群节点的 IP 地址。
kubectl get nodes
输出示例如下。
NAME STATUS ROLES AGE VERSION
ip-192-168-56-0.region-code
.compute.internal Ready <none> 19m v1.XX.X-eks-49a6c0
-
确定 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-code
c | 192.168.128.0/19 | subnet-EXAMPLE6e421a0e97
|
| region-code
b | 192.168.96.0/19 | subnet-EXAMPLEd0503db0ec
|
| region-code
c | 192.168.32.0/19 | subnet-EXAMPLEe2ba886490
|
| region-code
b | 192.168.0.0/19 | subnet-EXAMPLE123c7c5182
|
| region-code
a | 192.168.160.0/19 | subnet-EXAMPLE0416ce588p
|
+------------------+--------------------+----------------------------+
-
为节点所在的子网添加挂载目标。从前两个步骤的输出来看,集群有一个 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
-
先决条件
您必须使用版本 1.2x
或更高版本的 Amazon EFS CSI 驱动程序。
部署使用控制器所创建的持久性卷的示例应用程序
此过程利用来自 Amazon EFS 容器存储接口 (CSI) 驱动程序 GitHub 存储库的动态预置示例。它通过 Amazon EFS 接入点和 pod 使用的持久性卷声明 (PVC, Persistent Volume Claim) 动态创建一个持久性卷。
-
为 EFS 创建存储类。有关所有参数和配置选项,请参阅 GitHub 上的 Amazon EFS CSI 驱动程序。
-
检索您的 Amazon EFS 文件系统 ID。您可以在 Amazon EFS 控制台中查找此信息,或者使用以下 Amazon CLI 命令。
aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text
输出示例如下。
fs-582a03f3
-
下载 Amazon EFS 的 StorageClass
清单。
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/storageclass.yaml
-
编辑文件。请找到以下行,然后将 fileSystemId
的值替换为文件系统 ID。
fileSystemId: fs-582a03f3
-
部署存储类。
kubectl apply -f storageclass.yaml
-
通过部署利用 PersistentVolumeClaim
的 Pod 来测试自动预置:
-
下载一个清单,该清单将部署一个 pod 和一个 PersistentVolumeClaim。
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/pod.yaml
-
使用示例应用程序和 pod 使用的 PersistentVolumeClaimm 来部署 pod。
kubectl apply -f pod.yaml
-
确定运行控制器的 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
-
几秒钟后,您可以观察到控制器开始接受更改(已编辑,旨在提高可读性)。将 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 之一运行上一个命令。
-
确认已创建状态为 Bound
至 PersistentVolumeClaim
的持久性卷:
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
-
查看有关所创建的 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
-
请查看示例应用程序 pod 的状态,直到 STATUS
变成 Running
。
kubectl get pods -o wide
输出示例如下。
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
efs-app 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
状态。
-
确认数据已写入到卷。
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
...
-
(可选)终止运行 pod 的 Amazon EKS 节点并等待重新安排运行 pod。或者,您也可以删除 pod 并重新部署它。再次完成上一步,确认输出包含先前的输出。
- Static
-
部署使用您创建的持久性卷的示例应用程序
此过程利用来自 Amazon EFS 容器存储接口 (CSI) 驱动程序 GitHub 存储库的多个容器组(pod)读写许多示例来使用静态预置的 Amazon EFS 持久性卷,并使用 ReadWriteMany
访问模式从多个 pods 访问它。
-
将 Amazon EFS 容器存储接口 (CSI) 驱动程序 GitHub 存储库克隆到您的本地系统。
git clone https://github.com/kubernetes-sigs/aws-efs-csi-driver.git
-
导航到 multiple_pods
示例目录。
cd aws-efs-csi-driver/examples/kubernetes/multiple_pods/
-
检索您的 Amazon EFS 文件系统 ID。您可以在 Amazon EFS 控制台中查找此信息,或者使用以下 Amazon CLI 命令。
aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text
输出示例如下。
fs-582a03f3
-
编辑 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 是弹性文件系统,因此 spec.capacity
会被 Amazon EFS CSI 驱动程序忽略。创建文件系统时,不使用持久性卷和持久性卷声明中的实际存储容量值。但是,由于存储容量是 Kubernetes 的必填字段,您必须指定一个有效值,例如此示例中的 5Gi
。此值不会限制 Amazon EFS 文件系统的大小。
-
从 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
-
列出默认命名空间中的持久性卷。查找具有 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
之前,请勿继续执行下一步。
-
从 specs
目录部署 app1
和 app2
示例应用程序。
kubectl apply -f specs/pod1.yaml
kubectl apply -f specs/pod2.yaml
-
查看默认命名空间中的 pods 并等待 app1
和 app2
pods 的 STATUS
变为 Running
状态。
kubectl get pods --watch
可能需要几分钟 pods 才能达到 Running
状态。
-
描述持久性卷。
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
列出。
-
验证 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
...
-
验证 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
...
-
完成试验时,请删除此示例应用程序的资源以进行清理。
kubectl delete -f specs/
您还可以手动删除您创建的文件系统和安全组。