Kubernetes pod pending 排查

Kubernetes 中的 Pod 的生命周期由几个不同的阶段组成:

  • 创建 pod 时,它从Pending阶段开始。
  • 一旦 pod 被调度并且容器已经启动,pod 就会进入Running阶段。

大多数 pod 只需要几秒钟就可以从 Pending 到 Running 并在该状态下度过大部分时间。

图片

至此,Pod 已被 Kubernetes 集群接受。但是一个或多个容器尚未准备好对外提供服务。这包括 Pod 等待调度所花费的时间以及通过网络下载容器镜像所花费的时间。

当 pod 无法从 Pending to Running 阶段前进时,生命周期将停止并保留 pod,直到阻止它前进的问题得到修复。

常见原因

调度问题:无法在任何节点上调度 Pod。

图片

  • 节点内存和CPU不足、达到它可以运行的最大 pod 数(减少 pod 定义中的资源请求大小,添加更多节点或增加每个节点的大小来增加集群的容量。)
  • 不可调度的节点(磁盘压力,节点挂了之类)
  • 污点和容忍度,限制可以分配给不同节点的 pod

镜像问题:下载容器镜像时出现问题。

图片

  • 名称,镜像标签,存储仓库,身份验证错误

依赖性问题:Pod 需要一个卷、Secret 或 ConfigMap 才能运行。

图片

图片

  • 在 pod 启动之前,kubelet将尝试检查与其他 Kubernetes 元素的所有依赖关系。如果无法满足这些依赖项之一,则 pod 将保持挂起状态,直到满足依赖项。

    1
    2
    3
    4
    5
    6
    Events:
      Type     Reason       Age                  From               Message
      ----     ------       ----                 ----               -------
      Normal   Scheduled    3m19s                default-scheduler  Successfully assigned mysql/mysql-0 to ip-172-20-38-115.eu-west-1.compute.internal
      Warning  FailedMount  76s                  kubelet            Unable to attach or mount volumes: unmounted volumes=[config], unattached volumes=[kube-api-access-gxjf8 data config]: timed out waiting for the condition
      Warning  FailedMount  71s (x9 over 3m19s)  kubelet            MountVolume.SetUp failed for volume "config" : configmap "mysql" not found
    

    该 Message 列将为您提供足够的信息,以便能够查明缺失的元素。常见的原因有:

    • 尚未创建 ConfigMap 或者 Secret,或提供的名称不正确。
    • 无法在节点中挂载卷,因为它尚未被另一个节点释放。这尤其发生在更新 statefulset 的过程中,挂载的卷必须与旧 pod 相同。

解决方式

  • 使用 kubectl describe 查看事件,定位原因。
  • 查看pod log