跳至内容

为什么我的 Amazon EKS 容器组卡滞在 ContainerCreating 状态并显示 "Failed to create pod sandbox" 错误?

5 分钟阅读
0

我的 Amazon Elastic Kubernetes Service (Amazon EKS) 容器组卡滞在 ContainerCreating 状态并显示 "failed to create pod sandbox" 错误。

解决方法

先决条件

确定有问题的容器组。完成以下步骤:

  1. 运行以下命令列出集群中的容器组,识别处于 ContainerCreating 状态的容器组:

    kubectl get pods --all-namespaces -o wide
  2. 运行以下命令,检索处于 ContainerCreating 状态的每个容器组的相关详细信息:

    kubectl describe pod pod-name -n pod-namespace

    **注意:**请将 pod-name 替换为您的容器组名称,并将 pod-namespace 替换为您的容器组所在的命名空间。

  3. 查看 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"

要暂时解决此问题,请重新启动节点。

要对此问题进行故障排除,请完成以下步骤:

  1. 收集 ContainerdKubelet 的节点日志。
    对于 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
  2. 然后,运行下载的脚本:

    sudo bash eks-log-collector.sh
  3. 查看 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)"

  4. 识别僵尸进程,然后停止不必要的进程。
    对于 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"

出现此错误的原因可能有多种,主要分为三类:

资源限制:

  • 子网 IP 已耗尽
  • 已达到最大 ENI 连接限制

配置问题:

  • 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 容器映像,请完成以下步骤:

  1. 要检查您的 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
  2. 要拉取映像并获取 ECR 身份验证令牌,请运行以下命令:

    ECR_REGION=YOUR-REGION
    ECR_PASSWORD=$(aws ecr get-login-password --region $ECR_REGION)

    **注意:**请将 YOUR-REGION 替换为您的 AWS 区域。

  3. 从 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(发行版)中选择最新的映像版本。

  4. 将映像标记为 EKS 的本地主机。

    例如:

    sudo ctr -n k8s.io image tag 602401143452.dkr.ecr.aws.example.region.amazonaws.com/eks/pause:<ImageVersion> localhost/kubernetes/pause:latest
  5. 备份 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-nodenode-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 角色

2评论

在eks(v1.30)node 上部署deployment报错:Failed to create pod sandbox: rpc error: code = Unknown desc = failed to get sandbox image ".dkr.ecr.us-west-1.amazonaws.com/eks/pause:3.5": failed to pull image ".dkr.ecr.us-west-1.amazonaws.com/eks/pause:3.5": failed to pull and unpack image ".dkr.ecr.us-west-1.amazonaws.com/eks/pause:3.5": failed to resolve reference ".dkr.ecr.us-west-1.amazonaws.com/eks/pause:3.5": pull access denied, repository does not exist or may require authorization: authorization failed: no basic auth credentials


解决方案: 因为 containerd 无法获取 ECR 凭证来拉取沙箱容器映像。您可以 systemctl restart sandbox-image 来触发拉取,但仍然需要调查为什么image被删除。 比如可能的原因: 1.使用在每个节点上运行的自定义脚本来清理节点上未使用的图像并退出容器,这也将删除节点上的pause image。可以修改脚本,排除节点上的一些image。 2.使用类似 crictl rmi --prune命令手动删除了image,应避免类似操作,交由kubelet进行image回收。

kubelet 会每两分钟对未使用的镜像执行一次垃圾收集, 每分钟对未使用的容器执行一次垃圾收集。 你应该避免使用外部的垃圾收集工具,因为外部工具可能会破坏 kubelet 的行为,移除应该保留的容器。

AWS
支持工程师
已回复 2 年前

感谢您的评论。我们将会根据需要审核和更新知识中心文章。

AWS
审核人员
已回复 2 年前