前言
通过上篇的学习,我们清楚了k8s中新手容易混淆的几个概念:
- 比如说k8s和docker的关系,通俗的讲就是docker负责造车,k8s负责让车队有序行驶;
- 又比如说Node和Pod的关系,Node相当于宿舍楼, Pod是宿舍楼中的某一间房子;
- 又比如说Ingress和Service的区别,Ingress的作用对象是Service,Service的作用对象是Pod, Service的用途是暴露服务,Ingress的用途是路由和反向代理;
- 再比如说Pod, Deployment,Service, Ingress之间的关系,Deployment创建并管理多个副本的 Pod,Service通过标签选择器连接这些 Pod,提供统一访问入口,Ingress定义基于域名和路径的访问规则,将外部请求路由到 Service,外部用户通过浏览器访问
http://example.com/app→ 被 Ingress Controller 接收 → 匹配到路径/app→ 转发到对应的 Service → Service 将流量负载均衡转发给 Deployment 管理的 Pod。
现在我们继续学习K8s常见的日志查看与排查故障操作。
五 日志查看与排查故障
在 Kubernetes 中进行日志查看和故障排查是日常运维中最重要的技能之一。排查故障的常规思路是: 问题表现 ==> 查找 Pod ==> 查看状态/事件 ==> 查看日志 ==> 查看服务连接 ==> 查看资源使用 ==> 进一步排查。下面将系统性地介绍如何查看日志和定位故障的常用方法。
| 场景 | 命令 |
|---|---|
| 查看 Pod 状态 | kubectl get pods |
| 查看详细信息 | kubectl describe pod <pod> |
| 查看当前日志 | kubectl logs <pod> |
| 查看历史日志 | kubectl logs --previous |
| 查看服务连接情况 | kubectl describe svc / ingress |
| 查看资源使用 | kubectl top pod / node |
5.1 Pod 状态和事件排查
查看 Pod 状态
kubectl get pods -n namespace
输出示例:
NAME READY STATUS RESTARTS AGE
namespace 0/1 CrashLoopBackOff 5 10m
说明 Pod 启动失败,反复崩溃。
查看详细信息(事件)
kubectl describe pod my-app-123 -n namespace
重点关注Events 部分,通常可以看到:
- 拉镜像失败
- 探针检查失败
- 资源不足
- 无法连接 Service、Volum
5.1.1 拉镜像失败(ImagePullBackOff / ErrImagePull)
错误关键词:
Warning Failed Failed to pull image "xxx"
Warning BackOff Back-off pulling image "xxx"
示例输出:
Warning Failed 12s (x4 over 1m) kubelet Failed to pull image "my-registry/myapp:latest": image not found
Warning BackOff 2s (x5 over 30s) kubelet Back-off pulling image "my-registry/myapp:latest"
常见原因:
- 镜像不存在或拼写错误
- 镜像仓库私有,需要认证
- 网络不通
5.1.2 探针检查失败(Liveness/Readiness probe failed)
探针(Probe) 是 Kubernetes 检查容器健康状态的机制。主要分为:
| 类型 | 用途 |
|---|---|
livenessProbe | 容器是否“活着”,失败会重启容器 |
readinessProbe | 容器是否“准备好提供服务”,失败会从 Service 中移除 |
错误关键词:
Warning Unhealthy Liveness probe failed
Warning Unhealthy Readiness probe failed
示例输出:
Warning Unhealthy Liveness probe failed: Get "http://10.244.0.12:8080/healthz": dial tcp 10.244.0.12:8080: connect: connection refused
常见原因:
- 应用没启动完成
- 探针配置错误(如端口/路径/超时时间)
- 容器本身服务崩溃
5.1.3 资源不足(Insufficient CPU / Memory)
错误关键词:
FailedScheduling 0/3 nodes are available: 3 Insufficient memory.
示例输出:
Warning FailedScheduling 2m default-scheduler 0/3 nodes are available: 3 Insufficient cpu.
常见原因:
- 请求的
resources.requests超出 Node 可用资源 - 集群资源本身不足
5.1.4 无法连接 Service / Volume
错误关键词(Service):
Connect: connection refused
错误关键词(Volume):
Unable to attach or mount volumes
示例输出(Service):
Error: Get "http://my-service.default.svc.cluster.local:8080/health": dial tcp: lookup my-service.default.svc.cluster.local: no such host
示例输出(Volume):
Warning FailedMount Unable to attach or mount volumes: unmounted volumes=[data], unattached volumes=[data default-token-xyz]
常见原因:
- Service 名错误或未创建
- Pod 所在 namespace 不一致
- PVC 没绑定或 StorageClass 有误
5.2 查看容器日志
先说说多容器 + 多副本的概念,一个 Pod 可以有多个容器,一个 Deployment 可以有多个副本 Pod。
5.2.1 Pod 中的多个容器
一个 Pod 通常有一个主容器(主业务逻辑),但也可以包含多个容器,例如:
- 一个主容器运行应用
- 一个 sidecar 容器负责日志收集、代理、配置同步等
这种设计允许它们共享网络和存储卷,但你在查看日志时必须指定 -c <container-name>。
例如:
kubectl logs my-app-123 -c app-container # 主容器日志
kubectl logs my-app-123 -c sidecar # 辅助容器日志
5.2.2 Deployment 中的多个副本
如果你有如下 Deployment:
spec:
replicas: 3
Kubernetes 会启动 3 个副本的 Pod,Pod 名字会自动加随机后缀,例如:
my-app-1234my-app-5678my-app-90ab
你可以使用以下命令查看这些副本的名字:
kubectl get pods -l app=my-app
然后用日志命令逐个查看:
kubectl logs my-app-1234 -c <container-name>
kubectl logs my-app-5678 -c <container-name>
5.1.3 查看历史容器日志(如 CrashLoop)
查看历史容器命令:
kubectl logs my-app-123 -c <container-name> --previous
如果你的应用名为 my-app,且其 Pod 名称为 my-app-123,容器名称为 main-container,那么具体命令可能是这样的:
kubectl logs my-app-123 -c main-container --previous
输出示例:
2025-05-03T09:05:23.456Z INFO application - Application started successfully.
2025-05-03T09:07:12.345Z ERROR application - Uncaught exception: NullPointerException ...
5.3 排查 CrashLoopBackOff 问题
CrashLoopBackOff 是 Kubernetes 中 Pod 无法正常启动并持续崩溃的一种状态,表示容器启动后立即崩溃,并且 Kubernetes 尝试重启它,但总是失败。当日志显示:
Back-off restarting failed container
说明发生了CrashLoopBackOff错误。常见的原因和解决方法是:
| 原因 | 解决建议 |
|---|---|
| 应用本身错误 | 检查日志,确认是否由于代码异常退出,或者缺少必要参数 |
| 配置错误 | 检查 ConfigMap、Secret、环境变量是否配置完整 |
| 依赖未准备好 | 应用依赖服务未启动或连接失败(如数据库、Redis) |
| 探针失败 | Liveness 或 Readiness Probe 配置过于严格导致频繁重启 |
| 资源限制过低 | memory 或 cpu 限制太小,导致容器 OOM(Exit Code 137) |
| 挂载卷失败 | PVC 未绑定、权限不足、路径错误等 |
| 镜像问题 | 镜像缺少入口点、依赖库、权限等问题 |
可按照如下步骤排查这个问题:
5.3.1 查看 Pod 状态与事件
使用以下命令查看 Pod 当前的状态和事件信息:
kubectl describe pod <pod-name> -n <namespace>
重点查看以下内容:
-
Last State是否有Exit Code(比如 1、137、139 等) -
Events区域是否提示:Back-off restarting failed containerLiveness probe failedFailedMount(可能是 volume 问题)ImagePullBackOff(可能是镜像拉取失败)
5.3.2 查看容器日志
查看容器崩溃前的日志:
kubectl logs <pod-name> -n <namespace> --previous
说明:
--previous表示查看上一次运行(已崩溃)的容器日志- 通常能看到崩溃前的错误输出,比如缺配置、环境变量错误、依赖未连接等
5.3.3 分析 Exit Code(退出码)
在 describe pod 中或 kubectl get pod 后添加 -o wide,查看容器退出码:
| 退出码 | 含义 |
|---|---|
| 1 | 通用错误,程序异常退出 |
| 137 | 被 SIGKILL 杀死,常因内存不足 |
| 139 | 段错误(Segmentation fault) |
| 255 | 通常表示严重错误或非法退出 |
5.3.4 检查YAML 配置
查看完整 YAML 配置,排查环境变量、探针设置、镜像配置、挂载路径等是否有误。
kubectl get pod <pod-name> -n <namespace> -o yaml
检查对应 Deployment 或 StatefulSet 的配置
kubectl describe deploy <deploy-name> -n <namespace>
kubectl get deploy <deploy-name> -n <namespace> -o yaml
5.3.5 检查 Node 和资源情况
判断是否是资源瓶颈导致 OOM。查看所有 Node 的资源使用情况
kubectl top 命令依赖于 Metrics Server 插件。检查是否安装:
kubectl get deployment metrics-server -n kube-system
如果没有安装,可以使用官方提供的方式快速部署:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/compon
kubectl top node
输出示例
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
node-1 350m 18% 1.2Gi 30%
node-2 100m 5% 800Mi 20%
查看某个命名空间下 Pod 的资源使用情况 或者 查看所有命名空间下的 Pod 使用情况
kubectl top pod -n <namespace>
kubectl top pod --all-namespaces
示例输出:
NAMESPACE NAME CPU(cores) MEMORY(bytes)
default my-app-7b74d6d969-abcde 25m 100Mi
5.4 排查 Service/Ingress 无法访问问题
Kubernetes 中遇到 Service 或 Ingress 无法访问的问题时,可以按照从下到上的层级逐步排查,涵盖网络、Service 类型、端口、路由、DNS 解析、Ingress Controller 状态等关键点。
5.4.1 检查 Service 配置
kubectl get svc -n <namespace>
kubectl describe svc <service-name> -n <namespace>
- 类型是否为
ClusterIP,NodePort,LoadBalancer Port和TargetPort是否匹配Selector是否能正确匹配 Pod 标签
常见错误:Pod 标签与 Service selector 不匹配,导致没有后端 Pod 被转发。验证后端 Pod 是否被选中:
kubectl get pod -l <service-selector> -n <namespace>
5.4.2 检查 Pod 和应用是否监听对应端口
进入 Pod 内测试端口是否监听:
kubectl exec -it <pod-name> -- netstat -tulnp
或直接在 Pod 中使用 curl 测试自身服务:
kubectl exec -it <pod-name> -- curl localhost:<port>
5.4.3 检查 Service 到 Pod 的连通性(Cluster 内部)
可以用 BusyBox 测试:
kubectl run tmp-shell --rm -i --tty --image=busybox -- /bin/sh
在里面测试:
nslookup <service-name>.<namespace>.svc.cluster.local
wget <service-name>:<port> -O -
5.4.4 检查 Ingress 配置
kubectl get ingress -n <namespace>
kubectl describe ingress <ingress-name> -n <namespace>
确认是否包含:
- 正确的
host配置 - 正确的
path与后端serviceName/servicePort - 是否设置了 TLS(如果启用 HTTPS)
5.4.5 检查 Ingress Controller 是否部署、正常运行
kubectl get pod -n ingress-nginx
kubectl logs -n ingress-nginx <ingress-controller-pod>
常见控制器:
ingress-nginxtraefikistio-ingressgateway
确保:
- 它监听了外部端口(默认 80 / 443)
- 有对应的
LoadBalancerIP 或NodePort暴露
5.4.6 外部网络访问测试
- 确认域名是否正确解析到 Ingress Controller 的地址
- 使用
curl -v http://your-domain/path查看响应 - 如果使用了 HTTPS,确认 TLS 证书是否配置成功
5.5 如何查看容器所在 Node 和调度状态?
要查看容器所在的 Node 以及它的调度状态,可以使用以下几个命令:
5.5.1 查看 Pod 所在 Node
kubectl get pod <pod-name> -n <namespace> -o wide
输出中会包含类似这样的字段:
NAME READY STATUS RESTARTS AGE IP NODE ...
my-app 1/1 Running 0 2m 10.244.1.10 node-worker-1 ...
NODE 列显示了 Pod 被调度到哪个 Node 上。
5.5.2 查看调度状态(Pending / 被 taint 拒绝等)
kubectl describe pod <pod-name> -n <namespace>
关注以下部分:
- 调度结果
Node: node-worker-1/<IP>
- 调度失败原因(如果 Pod 状态是
Pending)
会在 Events 中显示:
Warning FailedScheduling ... 0/3 nodes are available: 1 Insufficient cpu, 2 node(s) had taint ...
常见调度失败原因包括:
- CPU / 内存资源不足
- 节点被 taint 拒绝调度
- 节点不满足
nodeSelector、affinity等限制条件
5.5.3 排查调度失败的 Pod
找出所有 Pending 状态的 Pod:
kubectl get pod -A --field-selector=status.phase=Pending
逐个 describe 进行分析,查看是否是资源不足、节点限制、调度策略问题等。
5.5.4 查看 Node 资源与状态
kubectl get node -o wide
kubectl describe node <node-name>
kubectl top node
可用于分析:
- 当前节点是否可用
- 是否有 taint 导致 Pod 被拒调度
- 是否资源不足(通过
top)
在5.3.5章节讲过,不再赘述。
5.6 收集所有日志信息(进阶)
对于大型集群,建议使用日志收集系统:
- EFK(Elasticsearch + Fluentd + Kibana)
- Loki + Promtail + Grafana
- Datadog / Splunk / NewRelic 等商用方案
这些工具能收集全集群日志,统一存储、搜索和分析。
六 资源限制与健康检查
在 Kubernetes 中,为了保证服务稳定运行并避免资源争抢,资源限制(Resource Limits) 和 健康检查(Liveness / Readiness Probes) 是非常关键的配置。
6.1资源限制(Resource Requests & Limits)
6.1.1 定义方法(Pod/Container 中配置)
resources:
requests:
cpu: "100m"
memory: "200Mi"
limits:
cpu: "500m"
memory: "512Mi"
- requests:调度时预留的资源。如果不设置,可能无法合理调度。
- limits:运行时最大允许使用的资源。如果超出会被限速(CPU)或杀死(内存)。
6.1.2 示例(在容器中配置)
spec:
containers:
- name: my-app
image: my-image:latest
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
6.1.3 配置建议
| 场景 | 建议 |
|---|---|
| Web 服务 | requests 和 limits 设为相等,避免过度调度 |
| 批处理任务 | requests 小一点,limits 大一些,充分利用资源 |
| 高可用系统 | 配置合理的 limits,防止单 Pod 占满整个 Node |
6.2 健康检查(Liveness & Readiness)
Liveness Probe(活跃性检查)
- 判断容器是否 存活。
- 失败则会被 重启。
Readiness Probe(就绪检查)
- 判断容器是否 对流量就绪。
- 失败则 从 Service 负载中移除,但不会重启。
6.2.1 配置方式
有3种配置方式:
| 方式 | 说明 |
|---|---|
| httpGet | 访问某个 HTTP 路径,返回 2xx/3xx 表示健康 |
| tcpSocket | 尝试连接端口 |
| exec | 容器内执行命令返回 0 表示健康 |
6.2.2 示例配置(HTTP 方式)
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
6.2.3 实践建议
| 建议 | 说明 |
|---|---|
使用 /healthz 和 /ready 路径 | 应用应提供健康检查接口 |
设置合理的 initialDelaySeconds | 避免容器启动过慢被误判 |
| 在容器异常退出或无响应时重启 | 用 Liveness Probe 保证稳定性 |
| 应用初始化未完成时不接收流量 | 用 Readiness Probe 延迟加入服务流量 |
6.3 综合示例
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- name: myapp-container
image: myapp:latest
ports:
- containerPort: 8080
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
七 最佳实践与总结
最佳实践:
- 所有配置都应使用 Git 管理版本
- 使用 Helm 管理应用部署
- 启用资源限制和探针,提升稳定性
- 使用 Namespace、RBAC 进行隔离
- 定期监控集群指标与日志
到此,我们已经掌握了k8s核心概念和常用操作命令,也学会了如何排查故障,可以把本文当作实操手册,遇到问题,按照checklist逐一进行检查,会让你使用k8s的时候少走很多弯路。如果试了本文的方法还找不到解决方案,通过对本文的学习,现在你已经对k8s的核心基础概念有了一定的了解,你向大模型发问相较小白会更精准,会更快速的获得解决方案,这就是本文的价值以及你学习的收益。好了,我们下期见。