【问题解决】Kubernetes健康检测probe errored: rpc error: code = DeadlineExceeded desc = context deadline exceed

本文记录了一次在基于Kubernetes的OpenShift平台上遇到的健康检测探针错误,导致服务卡住的问题。问题源于Kubernetes的LivenessProbe在某些情况下未能正确处理错误,使得故障节点未被剔除。解决方案包括改用httpGet或tcpSocket检测方式,或者升级Kubernetes至v1.15.12以上版本。此外,文中还介绍了健康检测的基础知识,包括存活探针、就绪探针和启动探针,并提供了httpGet方式的示例配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说说为啥写本文

春节假前,生产环境(基于Kubernetes的PaaS平台OpenShift)出现使用健康检测探针报错,但应用Pod并未下线的情况,导致服务卡住(某一节点死锁,Service总是负载均衡到此节点)。

查了OpenShift官方文档对此并无提及,在 Kubernetes 官方仓库的 Issue列表 中有所收获,在这里简单记录下。(Kubernetes v1.15.12以上版本已解决)

简单说来,这可能是 Kubernetes 历史遗留的一个 Bug,不过值得肯定的是:问题根源在于Kubernetes对于健康检测方式不同,对于运行时的报错处理也不同,直接导致了健康检测的报错。

底层出错不应该影响上层,上层本应防住的为啥不防住呢?你说是吧。

健康检测基础知识

健康检测,顾名思义是对应用节点进行检测,判断该节点是否健康可提供服务。

在Kubernetes 提供了三种健康检测的探针(Probes):

  • Liveness Probe 存活探针,检测Pod状态是否正常,如不正常则删除Pod,由Deployment自动创建新Pod
  • Readiness Probe 就绪探针,检测Pod容器内应用服务是否可用,如不可用,从Service列表中移出,不再有流量进入
  • Startup Probe 启动探针,Kubernetes 1.18开始出现的新探针,适用于应用启动慢的服务使用,防止在服务正常启动前被Liveness Probe判定为不健康状态删除Pod,与减少Readiness Probes频繁失败的问题

这三种探针都有相同的三种检测方式,只不过它们对检测结果的处理不同。三者均包含:

  • exec 容器执行命令方式
  • httpGet HTTP GET请求方式
  • tcpSocket 创建套接字方式

这里就不继续展开了,参见文末官方文档地址吧。

问题描述

生产环境中,使用了相对灵活的 exec 容器执行命令: curl http://localhost:8188/actuator/health/readiness,作为就绪探针(Readiness Probe),每10秒检测一下服务状态,在某个节点负载请求时,发生节点死锁,命令执行超时无响应,超过超时时间探针报错,但此节点未从Service列表中移出,导致集群其它节点没有流量进入,服务处于不可用状态。

报错信息为 Readiness probe errored: rpc error: code = DeadlineExceeded desc = context deadline exceeded

为什么会发生此问题?

参考了这个issue中某位热心网友提供的源码注释

exec 容器内执行命令的探针遇到错误时并未变更Pod的状态,导致仍在负载均衡的列表中;其他探针中将检测过程中遇到的所有错误,都算作检测失败,变更Pod状态。

解决思路

问题本身出现在容器运行时上,但是问题反映在Kubernetes健康检测时,所以最简单的解决办法是 使用其他检测方式,如 httpGettcpSocket

除此之外,升级Kubernetes 版本至 v1.15.12以上也可以解决问题,当然,要去根的话,需要升级 Containerd 版本了,一般对应 Docker 版本变化即可(Docker 绑定了 Containerd 管理容器)。

看来docker v19.03.6没问题 😆

  • Kubernetes v1.20以后移除Docker运行时这事和本文关系不大,因为错误出在底层Containerd上
  • 我这边公司用的OpenShift对应的Kubernetes版本太低,Docker也不能升(平台运维团队是甲方……),所以只能改了httpGet方式检测,另外因为OpenShift限制了界面上的端口号,又改了Deployment的yaml才搞定……

使用 httpGet 方式示例

重点关注 spec.containers 下的 livenessProbe 处定义,如更换其它探针类型,只换下名称即可。

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/liveness
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 3
      periodSeconds: 3

以上使用 httpGet方式,请求 http://localhost:8080/healthz,启动时间延迟3秒,容器启动3秒后,开始每隔3秒一次检测。

总结

使用第三方服务还是需要深入了解下它的机制、有没有什么坑等情况,以免出现碰到问题不知如何解决的被动局面。

路茫茫其修远兮,吾将上下而求所。

参考

  • https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
  • https://github.com/kubernetes/kubernetes/issues/82987
<think>嗯,用户遇到了Kubernetes中Pod状态为CreateContainerError问题,具体在命名空间sskk下。使用kubectl describe查看后,发现就绪探针报错:rpc error: code = Unknown desc = container not running。我需要帮他们分析可能的原因和解决方案。 首先,状态是CreateContainerError,这说明容器创建阶段出问题了。可能的原因包括镜像拉取失败、容器启动命令错误、资源限制、或者权限问题。而就绪探针的报错显示容器未运行,这可能是因为容器启动后立即崩溃,导致探针无法执行。 接下来要考虑具体的排查步骤。用户可能需要检查Pod的事件日志,看看是否有更详细的错误信息。比如,镜像拉取失败的话,kubectl describe会显示ImagePullBackOff或者ErrImagePull。如果容器启动命令有误,查看容器日志会显示具体的应用错误。资源不足的话,比如内存或CPU限制过紧,可能导致容器被OOMKilled。另外,挂载卷的问题,比如不存在的PersistentVolumeClaim,也可能导致容器无法启动。 就绪探针的配置也需要检查,如果探针设置得太早(比如initialDelay太短),容器还没完全启动就开始探测,可能会误报。或者探针的类型(HTTPGet、TCPSocket、Exec)是否正确,参数是否合理。 解决方案方面,可以分步骤来。首先,检查Pod的事件和容器日志,获取更多错误信息。然后,确认镜像是否正确存在,拉取权限是否足够。接着,检查容器的资源限制是否合理,是否有足够的资源分配。再检查挂载的存储卷是否存在且配置正确。最后,调整就绪探针的配置,比如延长initialDelaySeconds,确保容器有足够时间启动。 如果用户不太清楚如何执行这些命令,可能需要指导他们具体的kubectl命令,比如kubectl get events -n sskk --sort-by=.metadata.creationTimestamp,或者kubectl logs -n sskk <pod-name> -c <container-name>。同时,提醒他们在修改配置后重新部署Pod,观察状态是否改善。 可能还需要考虑其他因素,比如节点资源是否充足,节点是否处于Ready状态,或者是否有网络策略阻止了镜像拉取。不过根据当前的错误信息,重点还是在容器启动失败的原因上。需要一步步引导用户排查,从最可能的因素开始,逐步排除。</think>针对Pod状态为`CreateContainerError`且就绪探针报错`container not running`的问题,以下是逐步排查和解决方案: --- ### **1. 核心问题定位** - **关键现象**:`Readiness probe`失败的直接原因是容器未运行,但根本问题在于**容器启动阶段已失败**,导致就绪探针无法检测到运行中的容器。 --- ### **2. 常见原因分析** #### **(1) 容器启动失败** - **镜像问题** - 镜像名称错误(如拼写错误、版本不存在) - 镜像拉取失败(私有仓库权限未配置或凭证错误) - 镜像本身存在缺陷(如启动命令异常退出) - **资源限制** - 内存不足(OOMKilled)或CPU配额过小 - 未配置`resources.limits`导致资源耗尽 - **存储挂载问题** - 引用了不存在的`PersistentVolumeClaim`(PVC) - 挂载路径权限错误(如只读文件系统) - **命令或参数错误** - `command`或`args`配置错误导致容器立即退出 #### **(2) 探针配置不合理** - `initialDelaySeconds`过短,容器尚未启动完成即触发探针 - 探针类型(HTTP/Exec/TCP)或参数(端口、路径)配置错误 --- ### **3. 排查步骤** #### **步骤1:查看Pod详细事件** ```bash kubectl -n sskk describe pod <pod-name> ``` - 重点关注`Events`部分,寻找`Failed`或`Warning`日志(如镜像拉取失败、资源不足等)。 #### **步骤2:检查容器日志** ```bash kubectl -n sskk logs <pod-name> -c <container-name> --previous ``` - 若容器已崩溃,需添加`--previous`查看上次运行日志。 #### **步骤3:验证镜像信息** - 确认镜像地址和标签正确: ```bash kubectl -n sskkk get pod <pod-name> -o jsonpath='{.spec.containers[*].image}' ``` - 手动拉取镜像测试: ```bash docker pull <image-name:tag> ``` #### **步骤4:检查资源限制** - 查看Pod的`resources.limits`配置是否合理: ```bash kubectl -n sskk get pod <pod-name> -o json | jq '.spec.containers[].resources' ``` - 检查节点资源使用情况: ```bash kubectl top nodes ``` #### **步骤5:验证存储配置** - 确认PVC是否存在且已绑定: ```bash kubectl -n sskk get pvc ``` - 检查挂载路径权限: ```yaml # 示例配置 volumeMounts: - name: data mountPath: /data readOnly: false # 确保非只读 ``` #### **步骤6:调整探针配置** ```yaml readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 30 # 延长等待时间 periodSeconds: 5 ``` --- ### **4. 解决方案示例** #### **场景1:镜像拉取失败** ```bash # 配置镜像拉取密钥 kubectl -n sskk create secret docker-registry my-registry-key \ --docker-server=<registry-url> \ --docker-username=<user> \ --docker-password=<password> # 在Pod中引用密钥 spec: imagePullSecrets: - name: my-registry-key ``` #### **场景2:启动命令异常** ```yaml spec: containers: - name: app image: nginx:latest command: ["nginx", "-g", "daemon off;"] # 强制前台运行 ``` --- ### **5. 后续监控** - 部署后持续观察Pod状态: ```bash kubectl -n sskk get pod -w ``` - 使用`k9s`等工具实时监控容器日志。 --- 通过以上步骤,可系统性定位并解决容器启动失败的问题。如果问题仍存在,请提供`kubectl describe`和`kubectl logs`的完整输出,以便进一步分析。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东北小狐狸-Hellxz

请作者喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值