【云原生技术】部署后报错Unhealthy Liveness probe failed / Unhealthy Readiness probe failed: dial tcp

一、部署后报错Unhealthy Liveness probe failed / Unhealthy Readiness probe failed: dial tcp

从事件信息来看,错误提示是:

Unhealthy Liveness probe failed / Unhealthy Readiness probe failed: dial tcp 10.158.8.219:50901: connect connection refused

这通常说明:

  1. 容器没有在指定端口监听

    • 例如当前探活配置里写的是 :50901,但是容器实际监听的端口不是这个,或者没有正常启动导致服务端口没打开。
  2. 应用尚未启动完毕

    • 如果应用预启动过程耗时较长,而 Liveness/Readiness 的 initialDelaySecondstimeoutSeconds 配置过短,服务还没来得及起来,就会被探活判断为失败。
  3. 探活配置不一致

    • Liveness 和 Readiness probe 中的 portpath 与容器暴露的端口或健康接口不一致,导致拒绝连接。
  4. 网络通信问题

    • 如果该 Pod 所在节点实际无法通过 TCP 连接到这个容器的端口,也会显示 “connection refused”。

可先确认以下几点来排查:

  • 确认容器是否正常监听了对应端口(在容器里 netstat -tunlp 或查看日志)。
  • 探活配置中的端口/路径是否与应用实际一致,并适当增大 initialDelaySeconds 以给应用足够的启动时间。
  • Pod 中的服务日志是否正常,是否报错或退出。
  • 若在云服务平台上,还需查看是否有额外 安全组或网络策略 阻断了探活请求。

只要将容器暴露的端口与探活 probe 的设置对上,并保证应用如期启动,一般就能通过探活检查。

二、确认容器是否正常监听了对应端口(在容器里 netstat -tunlp 或查看日志) 这个怎么看?

要确认容器里有没有在指定端口监听,常用的做法是进入容器执行网络命令,或查看应用日志。大致步骤如下:

  1. 使用 kubectl exec 进入容器
    假设你的 Pod 名为 my-pod,容器里有 netstat 可以用时,可以执行:

    kubectl exec -it my-pod -- /bin/sh
    

    进入容器后,就能在容器里的终端执行命令了。

  2. 查看监听端口

    • 如果容器镜像包含 net-tools,就可以用:
      netstat -tunlp
      
      ss -tunlp
      
      来查看当前监听的 TCP/UDP 端口以及对应的进程。
    • 如果报 command not found,说明镜像里没有安装相关工具,需要先安装(对于部分精简镜像可能不支持安装)。如果无法安装,可以尝试换个方式,比如 curl localhost:PORT 测试连通性,或在应用日志里查看启动端口信息。
  3. 查看应用日志

    • 可以用:
      kubectl logs my-pod 
      
      或对多容器 Pod,需要指定容器名:
      kubectl logs my-pod -c my-container
      
    • 日志里一般会有应用启动时打印的“Listening on port …”或类似提示,可以确认它实际监听的端口。

通过上面方法,能判断容器是否真的监听了Liveness/Readiness探活所配置的端口,并进一步排查端口配置不一致或应用尚未启动完成等问题。

三、curl localhost:PORT这个之后还是拒绝

如果在容器里执行 curl localhost:<PORT> 依然提示 “Connection refused”,通常意味着容器里没有任何进程在该端口上监听,或者监听尚未就绪。可能的原因如下:

  1. 应用并未在该端口启动

    • 例如你在 Deployment/Pod 中将探活端口设置为 50901,但实际上应用只监听了 8080 或别的端口。
    • 可以通过查看应用日志以及镜像启动参数来核实应用真正的监听端口。
  2. 应用还没完全启动

    • 如果应用启动比较慢,还没来得及打开监听端口就被探活检查了,或你在容器里执行 curl 时它尚未就绪,就会导致连接被拒绝。
    • 可以先查看容器日志,通过延长 initialDelaySecondstimeoutSeconds 等方式,确保探活不会太快判定失败。
  3. 容器环境缺少网络工具

    • 有些镜像非常精简,curlnetstat 都可能没有装。如果装了却依旧拒绝连接,那就说明端口确实没监听,或监听在别的接口(比如只在 127.0.0.1 某个子端口上)。
  4. 配置不一致

    • Kubernetes 的 Service 暴露端口与容器实际监听端口不一致,或者探活配置的端口和真实端口不同,也会出现“connection refused”。

排查思路:

  1. 通过 kubectl logs <pod-name> 查看应用日志,确认其真正的监听端口以及启动状态。
  2. 在容器内执行 netstat -tunlpss -tunlp(若可用)确认监听端口。
  3. 确保探活配置(port/path)与应用暴露端口一致,必要时调整 initialDelaySeconds 让应用先顺利启动再进行探活。

四、Kubernetes 的 Service 暴露端口与容器实际监听端口不一致,或者探活配置的端口和真实端口不同,也会出现“connection refused”。 这个应该怎么配置?

在 Kubernetes 中,Service 只是将“集群对外或对内的端口”映射到“容器实际监听的端口”上,所以需要确保:

  1. Deployment/Pod 容器端口配置
    在 Deployment(或 Pod)的 spec.template.spec.containers[].ports 中,指定容器真正监听的端口,比如:

    containers:
      - name: my-app
        image: my-image
        ports:
          - name: http
            containerPort: 8080
    
  2. Service 暴露端口配置
    在 Service 的 spec.ports 中,“port” 是 Service 端口(集群内访问时用),“targetPort” 是 Pod 内容器的端口,如:

    ports:
      - name: http
        port: 80          # Service监听的端口
        targetPort: 8080  # 容器实际监听的端口
    
  3. 探活检查(Probes)端口匹配

    • 如果探活写在容器配置里(Deployment 中的 livenessProbe / readinessProbe),httpGet.port 通常要填 容器端口(如 8080),或者使用 “命名端口”(如 name: http)。
    • 如果误填了 Service 暴露端口(比如 80)而 Service 又没 correctly 转发, 或者把真实监听端口写错,就会出现 “connection refused”。

小结

  • 容器内部监听端口要与 Deployment containerPort、探活 port 对应;
  • Service 之所以可以用 port=80targetPort=8080,是因为 Kubernetes 会将请求转发到容器 8080,但探活要根据容器实际监听端口来配置(除非在探活里专门指定要访问 Service IP:Service Port,这种场景并不常见)。
    只要三者(容器监听端口、Service targetPort、探活 port)互相对应一致,就不会再出现 “connection refused” 的问题。
    如果你的 Liveness/Readiness Probe 是通过 tcpSocket 来做探活,那么需要保证容器里确实监听了对应的 TCP 端口。例如:
containers:
  - name: my-app
    image: my-image
    ports:
      - containerPort: 8080
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      timeoutSeconds: 1
      periodSeconds: 10
      failureThreshold: 3
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      timeoutSeconds: 1
      periodSeconds: 10
      failureThreshold: 3

其中要注意两点:

  1. 容器进程要在 8080(示例)端口上监听,否则用 tcpSocket: port: 8080 时就会“connection refused”。
  2. 如果你的 Service 暴露端口和容器实际监听端口不同,那也没关系。tcpSocket 里的 port 需要对应 容器监听端口(而非 Service 的 port),只要容器确实在该端口上开启了 TCP 监听即可。

五、是先在容器内部或应用日志中确认“我到底监听了哪个端口? 这个具体怎么看?

你可以通过以下两种方式确认容器实际监听的端口:

  1. 查看应用日志

    • 部分应用会在启动时打印类似“Listening on port XXXX”或“Server started at http://0.0.0.0:XXXX”之类的日志。
    • 你可以通过 kubectl logs <pod-name>(如果 Pod 只有一个容器就不用加 -c <container-name>)查看输出。
  2. 进入容器查看网络端口(netstat/ss)

    • 使用 kubectl exec -it <pod-name> -- /bin/shkubectl exec -it <pod-name> -- bash 进入容器终端;
    • 在容器里执行 netstat -tunlpss -tunlp 命令(如果镜像里装有这些工具),查看当前监听的端口。
    • 输出通常会以 “0.0.0.0:<端口>” 或 “:::<端口>” 的形式显示,表示该进程正在监听该端口;若未显示该端口,则说明应用并未监听它。

通过这两种方式,就能准确知道容器里应用真正绑定和监听的端口。然后再对照你的探活配置,确认探活 port 与实际监听端口是否一致。

六、部分应用会在启动时打印类似“Listening on port XXXX”或“Server started at http://0.0.0.0:XXXX”之类的日志。可以通过 kubectl logs 这个我模糊查询怎么找?

如果想对 Pod 日志进行部分文字匹配或模糊搜索,最简单的方法是把日志通过管道传给 grep,例如:

kubectl logs <pod-name> | grep -i "listening on"
  • -i 表示大小写不敏感。
  • "listening on" 可以替换成你想搜索的关键字。也可以只搜 part of it,比如 "listen""port" 等等。

如果你的 Pod 有多个容器,则需要加上容器名参数:

kubectl logs <pod-name> -c <container-name> | grep -i "listening on"

当然,如果日志量很大,为防止一次性输出刷屏,可以加一些参数进行限制,比如:

kubectl logs <pod-name> --tail=500 | grep -i "listening on"

这样只会拉取最近 500 行日志,再在其中搜索,可以让搜索更快、更方便。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿寻寻

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值