部署后报错Unhealthy Liveness probe failed / Unhealthy Readiness probe failed: dial tcp
- 一、部署后报错Unhealthy Liveness probe failed / Unhealthy Readiness probe failed: dial tcp
- 二、确认容器是否正常监听了对应端口(在容器里 netstat -tunlp 或查看日志) 这个怎么看?
- 三、curl localhost:PORT这个之后还是拒绝
- 四、Kubernetes 的 Service 暴露端口与容器实际监听端口不一致,或者探活配置的端口和真实端口不同,也会出现“connection refused”。 这个应该怎么配置?
- 五、是先在容器内部或应用日志中确认“我到底监听了哪个端口? 这个具体怎么看?
- 六、部分应用会在启动时打印类似“Listening on port XXXX”或“Server started at http://0.0.0.0:XXXX”之类的日志。可以通过 kubectl logs <pod-name> 这个我模糊查询怎么找?
一、部署后报错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
这通常说明:
-
容器没有在指定端口监听
- 例如当前探活配置里写的是
:50901
,但是容器实际监听的端口不是这个,或者没有正常启动导致服务端口没打开。
- 例如当前探活配置里写的是
-
应用尚未启动完毕
- 如果应用预启动过程耗时较长,而 Liveness/Readiness 的
initialDelaySeconds
、timeoutSeconds
配置过短,服务还没来得及起来,就会被探活判断为失败。
- 如果应用预启动过程耗时较长,而 Liveness/Readiness 的
-
探活配置不一致
- Liveness 和 Readiness probe 中的
port
、path
与容器暴露的端口或健康接口不一致,导致拒绝连接。
- Liveness 和 Readiness probe 中的
-
网络通信问题
- 如果该 Pod 所在节点实际无法通过 TCP 连接到这个容器的端口,也会显示 “connection refused”。
可先确认以下几点来排查:
- 确认容器是否正常监听了对应端口(在容器里
netstat -tunlp
或查看日志)。 - 探活配置中的端口/路径是否与应用实际一致,并适当增大
initialDelaySeconds
以给应用足够的启动时间。 - Pod 中的服务日志是否正常,是否报错或退出。
- 若在云服务平台上,还需查看是否有额外 安全组或网络策略 阻断了探活请求。
只要将容器暴露的端口与探活 probe 的设置对上,并保证应用如期启动,一般就能通过探活检查。
二、确认容器是否正常监听了对应端口(在容器里 netstat -tunlp 或查看日志) 这个怎么看?
要确认容器里有没有在指定端口监听,常用的做法是进入容器执行网络命令,或查看应用日志。大致步骤如下:
-
使用
kubectl exec
进入容器
假设你的 Pod 名为my-pod
,容器里有netstat
可以用时,可以执行:kubectl exec -it my-pod -- /bin/sh
进入容器后,就能在容器里的终端执行命令了。
-
查看监听端口
- 如果容器镜像包含
net-tools
,就可以用:
或netstat -tunlp
来查看当前监听的 TCP/UDP 端口以及对应的进程。ss -tunlp
- 如果报
command not found
,说明镜像里没有安装相关工具,需要先安装(对于部分精简镜像可能不支持安装)。如果无法安装,可以尝试换个方式,比如curl localhost:PORT
测试连通性,或在应用日志里查看启动端口信息。
- 如果容器镜像包含
-
查看应用日志
- 可以用:
或对多容器 Pod,需要指定容器名:kubectl logs my-pod
kubectl logs my-pod -c my-container
- 日志里一般会有应用启动时打印的“Listening on port …”或类似提示,可以确认它实际监听的端口。
- 可以用:
通过上面方法,能判断容器是否真的监听了Liveness/Readiness探活所配置的端口,并进一步排查端口配置不一致或应用尚未启动完成等问题。
三、curl localhost:PORT这个之后还是拒绝
如果在容器里执行 curl localhost:<PORT>
依然提示 “Connection refused”,通常意味着容器里没有任何进程在该端口上监听,或者监听尚未就绪。可能的原因如下:
-
应用并未在该端口启动
- 例如你在 Deployment/Pod 中将探活端口设置为 50901,但实际上应用只监听了 8080 或别的端口。
- 可以通过查看应用日志以及镜像启动参数来核实应用真正的监听端口。
-
应用还没完全启动
- 如果应用启动比较慢,还没来得及打开监听端口就被探活检查了,或你在容器里执行
curl
时它尚未就绪,就会导致连接被拒绝。 - 可以先查看容器日志,通过延长
initialDelaySeconds
、timeoutSeconds
等方式,确保探活不会太快判定失败。
- 如果应用启动比较慢,还没来得及打开监听端口就被探活检查了,或你在容器里执行
-
容器环境缺少网络工具
- 有些镜像非常精简,
curl
或netstat
都可能没有装。如果装了却依旧拒绝连接,那就说明端口确实没监听,或监听在别的接口(比如只在127.0.0.1
某个子端口上)。
- 有些镜像非常精简,
-
配置不一致
- Kubernetes 的 Service 暴露端口与容器实际监听端口不一致,或者探活配置的端口和真实端口不同,也会出现“connection refused”。
排查思路:
- 通过
kubectl logs <pod-name>
查看应用日志,确认其真正的监听端口以及启动状态。 - 在容器内执行
netstat -tunlp
或ss -tunlp
(若可用)确认监听端口。 - 确保探活配置(port/path)与应用暴露端口一致,必要时调整
initialDelaySeconds
让应用先顺利启动再进行探活。
四、Kubernetes 的 Service 暴露端口与容器实际监听端口不一致,或者探活配置的端口和真实端口不同,也会出现“connection refused”。 这个应该怎么配置?
在 Kubernetes 中,Service 只是将“集群对外或对内的端口”映射到“容器实际监听的端口”上,所以需要确保:
-
Deployment/Pod 容器端口配置:
在 Deployment(或 Pod)的spec.template.spec.containers[].ports
中,指定容器真正监听的端口,比如:containers: - name: my-app image: my-image ports: - name: http containerPort: 8080
-
Service 暴露端口配置:
在 Service 的spec.ports
中,“port
” 是 Service 端口(集群内访问时用),“targetPort
” 是 Pod 内容器的端口,如:ports: - name: http port: 80 # Service监听的端口 targetPort: 8080 # 容器实际监听的端口
-
探活检查(Probes)端口匹配:
- 如果探活写在容器配置里(Deployment 中的
livenessProbe
/readinessProbe
),httpGet.port
通常要填 容器端口(如 8080),或者使用 “命名端口”(如name: http
)。 - 如果误填了 Service 暴露端口(比如 80)而 Service 又没 correctly 转发, 或者把真实监听端口写错,就会出现 “connection refused”。
- 如果探活写在容器配置里(Deployment 中的
小结:
- 容器内部监听端口要与 Deployment
containerPort
、探活port
对应; - Service 之所以可以用
port=80
、targetPort=8080
,是因为 Kubernetes 会将请求转发到容器 8080,但探活要根据容器实际监听端口来配置(除非在探活里专门指定要访问 Service IP:Service Port,这种场景并不常见)。
只要三者(容器监听端口、ServicetargetPort
、探活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
其中要注意两点:
- 容器进程要在
8080
(示例)端口上监听,否则用tcpSocket: port: 8080
时就会“connection refused”。 - 如果你的 Service 暴露端口和容器实际监听端口不同,那也没关系。
tcpSocket
里的port
需要对应 容器监听端口(而非 Service 的port
),只要容器确实在该端口上开启了 TCP 监听即可。
五、是先在容器内部或应用日志中确认“我到底监听了哪个端口? 这个具体怎么看?
你可以通过以下两种方式确认容器实际监听的端口:
-
查看应用日志
- 部分应用会在启动时打印类似“Listening on port XXXX”或“Server started at http://0.0.0.0:XXXX”之类的日志。
- 你可以通过
kubectl logs <pod-name>
(如果 Pod 只有一个容器就不用加-c <container-name>
)查看输出。
-
进入容器查看网络端口(netstat/ss)
- 使用
kubectl exec -it <pod-name> -- /bin/sh
或kubectl exec -it <pod-name> -- bash
进入容器终端; - 在容器里执行
netstat -tunlp
或ss -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 行日志,再在其中搜索,可以让搜索更快、更方便。