如何对 Amazon EKS 中 EBS 卷挂载的问题进行排查?
上次更新日期:2022 年 8 月 22 日
我在 Amazon Elastic Kubernetes Service(Amazon EKS)集群中挂载 Amazon Elastic Block Store(Amazon EBS)卷时,在我的容器组(pod)中收到以下错误:“Timeout expired waiting for volumes to attach or mount for pod(超时已到期,等待为容器组(pod)连接或挂载卷)”
解决方法
在开始执行以下问题排查步骤之前,请确认您具备以下条件:
- 您的“ebs-csi-controller-sa”服务账户 IAM 角色所需的 AWS Identity and Access Management (IAM) 权限。
- 有效的 PersistentVolumeClaim (PVC) 与一组容器(pod)存在于相同的命名空间中。
- 使用树内配置程序“kubernetes.io/aws-ebs”或 Amazon EBS Container Storage Interface (CSI) 驱动程序配置程序“ebs.csi.aws.com”的有效 EBS 存储类定义。
验证 Amazon EBS CSI 驱动程序控制器和节点 pod 是否正在运行
Amazon EBS CSI 驱动程序包括作为部署运行的控制器 pod 和作为守护进程组运行的节点 pod。运行以下命令来验证这些 pod 是否在您的集群中运行:
kubectl get all -l app.kubernetes.io/name=aws-ebs-csi-driver -n kube-system
注意:Windows Worker 节点或 EKS Fargate 不支持 Amazon EBS CSI 驱动程序。
验证 PVC 在绑定到 EBS 持久卷时是否遇到问题
要验证 PVC 是否遇到问题,请运行以下命令查看事件。在以下示例命令中,将 pvc-name 和 namespace 替换为适合您环境的正确值。
kubectl describe pvc <pvc-name> -n <namespace>
如果您使用的是动态卷调配,请查看返回的事件以确定卷调配是成功还是失败。您还可以看到 PVC 绑定到的相应持久卷名称,如以下示例所示:
Name: ebs-claim
Namespace: default
StorageClass: ebs-sc
Status: Bound
Volume: pvc-5cbd76de-6f15-41e4-9948-2bba2574e205
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
volume.beta.kubernetes.io/storage-provisioner: ebs.csi.aws.com
volume.kubernetes.io/selected-node: ip-10-0-2-57.ec2.internal
. . . . .
. . . . .
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
. . . . .
Normal Provisioning 5m22s ebs.csi.aws.com_ebs-csi-controller-57d4cbb9cc-dr9cd_8f0373e8-4e58-4dd0-b83c-da6f9ad5d5ce External provisioner is provisioning volume for claim "default/ebs-claim"
Normal ProvisioningSucceeded 5m18s ebs.csi.aws.com_ebs-csi-controller-57d4cbb9cc-dr9cd_8f0373e8-4e58-4dd0-b83c-da6f9ad5d5ce Successfully provisioned volume pvc-5cbd76de-6f15-41e4-9948-2bba2574e205
如果调配失败,请在事件中找到错误消息。
查看Amazon EBS CSI 控制器 pod 的日志
检查控制器 pod 日志以了解挂载失败的原因。如果卷在创建过程中出现故障,请参阅 ebs-plugin 和 csi-provisioner 日志。运行以下命令以检索 ebs-plugin 容器日志:
kubectl logs deployment/ebs-csi-controller -n kube-system -c ebs-plugin
kubectl logs daemonset/ebs-csi-node -n kube-system -c ebs-plugin
运行以下命令以检索 csi-provisioner 容器日志:
kubectl logs deployment/ebs-csi-controller -n kube-system -c csi-provisioner
如果 EBS 卷无法连接到 pod,请查看 csi-attacher 日志以了解原因。运行以下命令以检索 csi-attacher 容器日志:
kubectl logs deployment/ebs-csi-controller -n kube-system -c csi-attacher
验证 Amazon EBS CSI 驱动程序控制器服务账户是否带有正确的 IAM 角色注释,以及 IAM 角色是否具有所需的权限
PVC 事件或 ebs-csi-controller 日志中未经授权的错误是由以下原因引起的:
- IAM 角色中缺少权限。
- 与服务账户关联的 IAM 角色不正确。
1. 运行以下命令以确定 ebs-csi-controller pod 使用的服务账户是否具有正确的注释:
kubectl describe sa ebs-csi-controller-sa -n kube-system
验证是否存在以下注释:
eks.amazonaws.com/role-arn = arn:aws:iam::111122223333:role/AmazonEKS_EBS_CSI_DriverRole
2. 验证集群的 IAM OIDC 提供程序是否已创建,以及 IAM 角色是否具有执行 EBS API 调用所需的权限。此外,请验证 IAM 角色的信任策略是否信任服务账户 ebs-csi-controller-sa。
3. 查看您账户的 AWS CloudTrail 日志,以验证是否正在进行 CreateVolume、AttachVolume 和 DetachVolume 调用。同时查看 CloudTrail 日志以确定是哪个主体进行了调用。此信息可帮助您确定服务账户 IAM 角色是在由控制器使用还是由 Worker 节点 IAM 角色使用。
验证持久卷的节点关联性
创建的每个持久卷都具有节点关联性,以限制将持久卷附加到单个可用区内的节点。这是因为 EBS 卷只能连接到在创建它们的同一可用区上运行的 pod 或节点。如果调度到一个可用区节点上的 pod 尝试在另一个可用区中使用 EBS 持久卷,您会收到类似以下内容的错误:
FailedScheduling: 1 node(s) had volume node affinity conflict
为避免出现这种情况,请使用 StatefulSets 而不是 Deployment,以便为与 pod 位于同一可用区内的 StatefulSets 的每个 pod 创建一个唯一的 EBS 卷。
您可以通过运行以下命令来验证持久卷的节点关联性。在以下示例命令中,将 persistent-volume-name 替换为您的卷名称。
kubectl describe pv <persistent-volume-name>
注意:请记住,您不能将 EBS 卷挂载到运行在两个不同 Worker 节点上的两个不同的 pod。EBS 卷可以附加到在一个节点上运行的 pod,但不能同时附加到另一个节点。如果您尝试将 EBS 卷附加到不同 Worker 节点上的两个不同 pod,则 pod 会发生故障,并且您会收到类似以下内容的错误:
Warning FailedAttachVolume 2m38s attachdetach-controller Multi-Attach error for volume "pvc-1cccsdfdc8-fsdf6-43d6-a1a9-ea837hf7h57fa" Volume is already exclusively attached to one node and can't be attached to another
确保您的 EBS 控制器 pod 可以连接到 EC2 API
如果您在 EBS-CSI-Controller 日志中看到指示连接超时的错误,则说明 EBS CSI 控制器可能未连接到 EC2 API。如果控制器 pod 存在与 EC2 API 的连接问题,则在创建 PVC 时,您会看到类似以下内容的错误:
Warning ProvisioningFailed persistentvolumeclaim/storage-volume-1 failed to provision volume with StorageClass "ebs-sc": rpc error: code = DeadlineExceeded desc = context deadline exceeded
要更正此错误,请验证 EBS 控制器容器组(pod)的子网是否可以连接到 EC2 API。如果您使用 HTTP/HTTPS 代理运行私有集群,请验证您的 EBS CSI 控制器容器组(pod)是否配置为使用 HTTP/HTTPS 代理。EBS CSI 驱动程序的 Helm 安装支持设置 HTTP/HTTPS 代理。