我的 Amazon Elastic Kubernetes Service (Amazon EKS) 容器组卡滞在 ContainerCreating 状态并显示 "failed to create pod sandbox" 错误。
解决方法
先决条件
确定有问题的容器组。完成以下步骤:
-
运行以下命令列出集群中的容器组,识别处于 ContainerCreating 状态的容器组:
kubectl get pods --all-namespaces -o wide
-
运行以下命令,检索处于 ContainerCreating 状态的每个容器组的相关详细信息:
kubectl describe pod pod-name -n pod-namespace
**注意:**请将 pod-name 替换为您的容器组名称,并将 pod-namespace 替换为您的容器组所在的命名空间。
-
查看 Events(事件)中的输出以识别相关容器组,然后使用以下部分对您的问题进行故障排除。
"Resource temporarily unavailable" 错误
如果您为 PID 或文件定义的内核设置超过操作系统 (OS) 的最大限制,那么您会收到类似于以下内容的错误消息:
"kubelet, ip-192-168-0-1.us-east-1.compute.internal Failed to create Pod sandbox: rpc error: code = Unknown desc = failed to start sandbox container for Pod "example_pod": Error response from daemon: failed to start shim: fork/exec /usr/bin/containerd-shim: resource temporarily unavailable: unknown"
要暂时解决此问题,请重新启动节点。
要对此问题进行故障排除,请完成以下步骤:
-
收集 Containerd 和 Kubelet 的节点日志。
对于 Windows,连接到您的实例。打开 PowerShell 命令提示符,然后使用 Windows EKS 日志收集器脚本来收集 Worker 节点日志。有关详细信息,请参阅 GitHub 网站上的 EKS Logs Collector (Windows)(EKS 日志收集器 (Windows))。运行以下命令:
Invoke-WebRequest -OutFile eks-log-collector.ps1 https://raw.githubusercontent.com/awslabs/amazon-eks-ami/main/log-collector-script/windows/eks-log-collector.ps1
.\eks-log-collector.ps1
对于 Linux,连接到您的实例。然后,使用 Linux EKS 日志收集器脚本来收集 Worker 节点日志。有关详细信息,请参阅 GitHub 网站上的 EKS Logs Collector (Linux)(EKS 日志收集器 (Linux))。运行以下命令,下载日志收集器脚本:
curl -O https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/log-collector-script/linux/eks-log-collector.sh
-
然后,运行下载的脚本:
sudo bash eks-log-collector.sh
-
查看 Kubelet 日志中是否有以下错误响应:
"kubelet[5267]: runtime: failed to create new OS thread (have 2 already; errno=11)""kubelet[5267]: runtime: may need to increase max user processes (ulimit -u)"
-
识别僵尸进程,然后停止不必要的进程。
对于 Windows,打开任务管理器,然后选择 Details(详细信息)选项卡。检查状态显示为 Not responding(无响应)的进程,以便识别僵尸进程。
对于 Linux,运行以下 ps 命令,检查列出的处于 Z 状态的僵尸进程:
ps aux | egrep "Z|defunct"
有关详细信息,请参阅 Linux Journal 网站上的 How to kill Zombie processes on Linux(如何在 Linux 上终止僵尸进程)。
"Network plugin cni failed to set up pod network" 错误
如果容器网络接口 (CNI) 无法为您新创建的容器组分配 IP 地址,您可能会收到以下错误消息:
"Network plugin cni failed to set up pod network: add cmd: failed to assign an IP address to container"
出现此错误的原因可能有多种,主要分为三类:
资源限制:
配置问题:
- Worker 节点上缺少 IAM CNI 策略
- VPC CNI (aws-node) 容器组未处于 Running(正在运行)状态
- VPC CNI、kube-proxy 或 CoreDNS 的版本已过时
- 安全组或访问控制列表配置不正确
架构特定挑战:
- VPC CNI 配置与您的使用案例不一致
- 缺少 OpenID Connect (OIDC) 配置
- 使用的是自行管理的插件,而非 EKS 托管的插件
有关详细的故障排除步骤,请参阅我如何解决 Amazon EKS 的 kubelet 或 CNI 插件问题?
最佳做法是执行以下操作:
**注意:**如果您对 CNI 配置进行了任何更改,则必须重新启动受影响的节点才能使更改生效。
"Error while dialing" 错误
如果 aws-node 容器组无法与 IPAM 通信(因为 aws-node 容器组无法在该节点上运行),您会收到类似于以下内容的错误:
"Error while dialing dial tcp 127.0.0.1:50051: connect: connection refused"
此错误会在以下情况中出现:
VPC CNI 处于“待处理”状态
存活和就绪探测失败可能由于安全规则配置或应用程序错误而导致。资源耗尽也可能会导致延迟。通常,如果在 POD_SECURITY_GROUP_ENFORCING_MODE 设为严格模式的情况下将 DISABLE_TCP_EARLY_DEMUX 设置为 false,则可能会出现失败。
如果您使用容器组的安全组以及存活或就绪探测,请在严格模式下将 DISABLE_TCP_EARLY_DEMUX 设置为 true。这使得 kubelet 能够使用 TCP 连接到分支网络接口上的容器组。
CNI 托管插件问题
当在 AWS 管理控制台中被添加为托管插件时,aws-node 会导致探测失败。发生此情况是因为托管插件会覆盖服务账户。
要解决此问题,请执行以下操作之一:
- 从 AWS 管理控制台中移除托管插件。然后,使用提供所需的 AmazonEKS_CNI_Policy IAM 策略的正确 IAM 角色重新创建此插件。
- 编辑现有的 aws-node 服务账户,将其与具备所需 CNI 权限的正确 IAM 角色相关联。
- 如果您在集群上使用容器组身份,请创建必要的容器组身份关联,将 aws-node 服务账户与 VPC CNI 要使用的 IAM 角色绑定。
其他建议:
"Failed to setup network for sandbox" 错误
如果您在 VPC-CNI (aws-node) 容器组中使用“启用前缀委托”,您可能会收到以下错误消息:
"Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox"
要获取有关此问题的更多详细信息,请查看 Worker 节点中 /var/log/aws-routed-eni/ipamd.log 处的 IP 地址管理进程守护程序 (IPAMD) 日志。
即使您的子网拥有可用 IP 地址,但如果该子网内没有任何连续的 /28 IP 块可用,也会出现此错误。当现有辅助 IP 地址的分段分布在子网中时,将会出现此错误。该错误会出现在 Kubernetes 的 Amazon VPC CNI 插件日志中,或受影响 Worker 节点的 CloudTrail 事件中。您可能会收到以下错误消息:
"InsufficientCidrBlocks: The specified subnet does not have enough free cidr blocks to satisfy the request"
要解决此错误,请完成以下选项之一:
创建一个新子网,然后在其中启动容器组。
-or-
使用 Amazon EC2 子网的 CIDR 预留功能在子网内预留空间,以便用于前缀分配。
如果要从 IP 地址分配转换为 IP 前缀分配,请创建新的节点组。然后,您可以增加可用 IP 地址的数量,而不是滚动替换现有节点。
如果您在同时分配了 IP 地址和前缀的节点上运行容器组,则可能会导致播发的 IP 地址容量出现不一致。这种情况可能会影响节点上未来的工作负载。要解决此问题,请按照为带前缀的 Amazon EKS 节点分配更多 IP 地址中的步骤进行操作。
"Container image authentication" 错误
如果容器运行时没有拉取映像的必要权限,那么您可能会收到一条类似于以下内容的错误消息:
"pull access denied, repository does not exist or may require authorization: authorization failed: no basic auth credentials"
要解决此错误,请检查以下内容:
- 查看附加到 EKS Worker 节点的 IAM 角色。如果缺少 IAM 策略 AmazonEC2ContainerRegistryReadOnly,则附加该策略。
- 如果您从跨账户的 ECR 存储库拉取映像,请参阅如何允许辅助账户在我的 Amazon ECR 映像存储库中推送或拉取映像?确保存储库级别的策略已设置适当的权限。
- 如果您使用 ECR VPC 端点来拉取映像。然后,确保 VPC 端点安全组允许来自 EKS 节点安全组的端口 443 上的入站 HTTPS 流量。有关更多信息,请参阅 Amazon ECR 接口 VPC 端点 (AWS PrivateLink)。
- 对于 containerd,pause 图像拉取仅在引导期间执行。之后,映像必须保留在实例上。请勿使用自定义清理脚本或手动删除命令(如 crictl rmi —prune)来移除 pause 映像。让 kubelet 处理垃圾收集 (gc),它每 1-2 分钟自动运行一次。当您移除 containerd pause 容器映像时,新的容器组 (pod) 将无法启动。当前容器组 (pod) 在节点上运行时没有任何问题,但 kubelet 日志会显示 "Failed to create pod sandbox" 错误。
如果您从 EKS Worker 节点中删除了 pause 容器映像,请完成以下步骤:
-
要检查您的 EKS Worker 节点是否有 pause 映像,请运行以下命令:
ctr -n k8s.io images ls | grep -o "602401143452.dkr.ecr.YOUR-REGION.amazonaws.com/eks/pause:3.10"
**注意:**请将 YOUR-REGION 替换为您的 AWS 区域。
如果 EKS Worker 节点有 pause 映像,则输出将如下所示:
602401143452.dkr.ecr.aws.example.region.amazonaws.com/eks/pause:3.10
602401143452.dkr.ecr.aws.example.region.amazonaws.com/eks/pause:3.10
要检查您的 EKS Worker 节点是否已删除,请运行以下命令:
ctr -n k8s.io images ls | grep -o "localhost/kubernetes/pause:latest"
如果映像已删除,输出将如下所示:
ctr -n k8s.io images list |grep -i pause
-
要拉取映像并获取 ECR 身份验证令牌,请运行以下命令:
ECR_REGION=YOUR-REGION
ECR_PASSWORD=$(aws ecr get-login-password --region $ECR_REGION)
**注意:**请将 YOUR-REGION 替换为您的 AWS 区域。
-
从 ECR 拉取 pause 映像。确保您的 pause 映像版本正确无误。如果您不确定映像版本,请登录到任意 Worker 节点并选择映像版本。
例如:
sudo ctr -n k8s.io image pull --user "AWS:$ECR_PASSWORD" 602401143452.dkr.ecr.aws.example.region.amazonaws.com/eks/pause:<ImageVersion>
**注意:**您可以从 GitHub 网站上的 Releases(发行版)中选择最新的映像版本。
-
将映像标记为 EKS 的本地主机。
例如:
sudo ctr -n k8s.io image tag 602401143452.dkr.ecr.aws.example.region.amazonaws.com/eks/pause:<ImageVersion> localhost/kubernetes/pause:latest
-
备份 pause 映像后,新的容器组 (pod) 即可启动和运行,不会出现任何问题。
"Container image authentication" 错误
如果容器运行时没有拉取映像的必要权限,那么您可能会收到一条类似于以下内容的错误消息:
"pull access denied, repository does not exist or may require authorization: authorization failed: no basic auth credentials"
要解决此错误,请检查以下内容:
- 查看附加到 EKS Worker 节点的 IAM 角色。如果缺少 IAM 策略 AmazonEC2ContainerRegistryReadOnly,请附加该策略。
- 如果您从跨账户的 ECR 存储库拉取映像,请参阅如何允许辅助账户在我的 Amazon ECR 映像存储库中推送或拉取映像?确保存储库级别的策略已设置适当的权限。
- 如果您使用 ECR VPC 端点来拉取映像,请确保 VPC 端点安全组允许来自 EKS 节点安全组的端口 443 上的入站 HTTPS 流量。有关更多信息,请参阅 Amazon ECR 接口 VPC 端点 (AWS PrivateLink)。
- 对于 containerd,pause 图像拉取仅在引导期间执行。之后,映像必须保留在实例上。请勿使用自定义清理脚本或手动删除命令(如 crictl rmi —prune)来移除 pause 映像。让 kubelet 处理垃圾收集 (gc),它每 1-2 分钟自动运行一次。当您移除 containerd pause 容器映像时,新的容器组 (pod) 将无法启动。当前容器组 (pod) 在节点上运行时没有任何问题,但 kubelet 日志会显示 "Failed to create pod sandbox" 错误。
Windows 节点上的 "Pod does not have label" 错误
如果容器组未在 Windows 节点上配置计划的 nodeSelector,您可能会收到类似于以下的错误消息:
"Failed to parse Kubernetes args: pod does not have label vpc.amazonaws.com/PrivateIPv4Address" or "Pod does not have label vpc.amazonaws.com/PrivateIPv4Address"
要解决此问题,请确保在 PodSpec 中为 nodeSelector 参数包含以下标签:
nodeSelector:
kubernetes.io/os: windows
kubernetes.io/arch: amd64
确认在 amazon-vpc-cni 中将 enable-windows-ipam 参数设置为 true。
如果您没有 amazon-vpc-cni configmap,请使用以下模板并上传到您的集群:
apiVersion: v1
kind: ConfigMap
metadata:
name: amazon-vpc-cni
namespace: kube-system
data:
enable-windows-ipam: "true"
重新启动 aws-node 和 node-windows 容器组。
有关如何在 Amazon EKS 集群上部署 Windows 节点的详细信息,请参阅在 EKS 集群上部署 Windows 节点。
安全组错误
如果您遇到安全组问题,则会收到与以下内容类似的错误:
"Plugin type="aws-cni" name="aws-cni" failed (add): add cmd: failed to assign an IP address to container
Vpc-resource-controller failed to allocate branch ENI to pod: creating network interface, NoCredentialProviders: no valid providers in chain.Deprecated."
此错误响应可能表明 health.kubernetes 控制面板存在问题。要解决此问题,请联系 AWS Support。
相关信息
如何解决 Amazon EKS 的 kubelet 或 CNI 插件问题?
如何对 Amazon EKS 中的 OIDC 提供商和 IRSA 问题进行故障排除?
如何排查 Amazon EKS 中的 IRSA 错误?
配置 Amazon VPC CNI 插件以使用 IRSA
服务账户的 IAM 角色