4、日志采集策略:kubectl logs实时查看、--previous查看崩溃前日志、stern多Pod日志聚合
在 CrashLoop 故障排查中,日志是还原事故现场的第一手证据。Kubernetes 提供了多层次的日志采集手段,从单 Pod 实时流式输出到多 Pod 聚合检索,再到崩溃前日志的追溯。本章将系统讲解三种核心策略的适用场景、命令格式与实战技巧。
4.1 日志采集策略全景
下表对比了三种日志采集方式的核心差异,帮助你在不同故障阶段快速选择正确的工具。
| 策略 | 命令/工具 | 适用场景 | 关键参数 | 限制 |
|---|---|---|---|---|
| 实时查看 | kubectl logs -f |
跟踪当前 Pod 运行状态,观察启动日志 | -f 持续输出,--tail 控制行数 |
Pod 重启后日志丢失 |
| 崩溃前日志 | kubectl logs --previous |
查看 CrashLoop 中上一实例的退出日志 | --previous 追溯上一容器 |
仅保留最近一次崩溃的日志 |
| 多 Pod 聚合 | stern |
跨多个 Pod 或 Deployment 实时聚合日志 | 正则匹配 Pod 名,--tail 回溯行数 |
需额外安装,不支持 --previous |
4.2 实时查看:kubectl logs -f
当 Pod 处于 CrashLoopBackOff 状态时,使用 kubectl logs 可以观察容器启动瞬间的日志输出。这是最直接的诊断手段。
4.2.1 基础用法
# 查看指定 Pod 的日志(默认只显示当前容器实例)
kubectl logs <pod-name> -n <namespace>
# 持续跟踪日志输出(类似 tail -f)
kubectl logs -f <pod-name> -n <namespace>
# 只显示最后 50 行日志
kubectl logs --tail=50 <pod-name> -n <namespace>
4.2.2 多容器 Pod 指定容器
如果 Pod 包含多个容器(如 Sidecar 模式),必须使用 -c 参数指定容器名:
kubectl logs -f <pod-name> -c <container-name> -n <namespace>
--tail=100 获取最近日志,再配合 -f 观察下一次重启的启动过程。
4.3 崩溃前日志:kubectl logs --previous
CrashLoop 的核心特征是容器反复重启。每次重启后,当前实例的日志会被新进程覆盖。使用 --previous 参数可以查看上一崩溃实例的日志,这是还原崩溃原因的关键手段。
4.3.1 命令格式
# 查看上一崩溃实例的日志
kubectl logs --previous <pod-name> -n <namespace>
# 指定容器(多容器 Pod)
kubectl logs --previous <pod-name> -c <container-name> -n <namespace>
4.3.2 工作原理
Kubernetes 在容器重启时,会将上一容器的日志文件保留在节点文件系统中(通常位于 /var/log/pods/ 目录下)。--previous 参数会读取该历史日志文件,而不是当前运行中的日志流。
--previous 只能查看最近一次崩溃的日志。如果 Pod 已经重启多次,较早的崩溃日志会被覆盖。建议在发现 CrashLoop 后第一时间执行此命令。
4.3.3 典型输出示例
$ kubectl logs --previous my-app-7d4f8b6c9-x2k3j -n production
Error: failed to connect to database at 10.0.1.5:5432
dial tcp 10.0.1.5:5432: connect: connection refused
panic: unable to initialize database connection
goroutine 1 [running]:
main.initDB()
/app/main.go:45 +0x1a4
...
从上述日志可以快速定位到数据库连接失败是崩溃的直接原因。
4.4 多 Pod 日志聚合:stern
在生产环境中,一个 Deployment 通常运行多个 Pod 副本。CrashLoop 可能只影响部分副本,或者需要对比多个 Pod 的日志来定位问题。此时 stern 工具可以按正则表达式匹配 Pod 名称,实现多 Pod 日志的实时聚合输出。
4.4.1 安装 stern
# macOS
brew install stern
# Linux (下载二进制)
wget https://github.com/stern/stern/releases/download/v1.28.0/stern_1.28.0_linux_amd64.tar.gz
tar xzf stern_1.28.0_linux_amd64.tar.gz
sudo mv stern /usr/local/bin/
4.4.2 常用命令
# 匹配所有名称包含 "my-app" 的 Pod
stern my-app -n production
# 匹配多个命名空间
stern my-app --namespace production --namespace staging
# 回溯最近 200 行日志
stern my-app --tail 200 -n production
# 排除特定 Pod
stern my-app --exclude-pod my-app-7d4f8b6c9-x2k3j -n production
4.4.3 输出格式说明
stern 默认会在每行日志前添加 Pod 名称和容器名称,方便区分来源:
my-app-7d4f8b6c9-x2k3j container-0 2025-01-15T10:23:45Z Starting application...
my-app-7d4f8b6c9-y4l5m container-0 2025-01-15T10:23:46Z Connected to database
my-app-7d4f8b6c9-z6n7o container-0 2025-01-15T10:23:44Z Error: connection refused
stern --tail 100 获取所有相关 Pod 的最近日志,快速识别哪些副本处于异常状态;然后针对异常 Pod 使用 kubectl logs --previous 深入分析崩溃原因。
4.5 日志采集策略决策流程
以下 SVG 流程图展示了在 CrashLoop 故障排查中如何根据当前状态选择正确的日志采集策略。
4.6 日志采集策略对比总结
下表从更多维度对比三种策略,帮助你在不同场景下做出最优选择。
| 对比维度 | kubectl logs -f | kubectl logs --previous | stern |
|---|---|---|---|
| 安装依赖 | 无(kubectl 内置) | 无(kubectl 内置) | 需单独安装 |
| 多 Pod 支持 | 否(单 Pod) | 否(单 Pod) | 是(正则匹配) |
| 历史日志追溯 | 仅当前实例 | 上一崩溃实例 | 仅当前实例 |
| 实时流式输出 | 是(-f 参数) | 否(静态输出) | 是(默认持续输出) |
| 输出可读性 | 纯日志内容 | 纯日志内容 | 带 Pod/容器前缀 |
| 典型场景 | 跟踪单 Pod 启动过程 | CrashLoop 崩溃原因定位 | 多副本异常对比 |
4.7 实战案例:CrashLoop 日志采集三步法
以下是一个完整的 CrashLoop 日志采集流程,结合三种策略快速定位问题。
- 第一步:快速扫描
# 使用 stern 查看所有相关 Pod 的最近日志 stern my-app --tail 50 -n production发现
my-app-7d4f8b6c9-x2k3j和my-app-7d4f8b6c9-y4l5m两个 Pod 频繁报错。 - 第二步:追溯崩溃原因
# 查看崩溃前日志 kubectl logs --previous my-app-7d4f8b6c9-x2k3j -n production日志显示
Failed to connect to Redis at 10.0.1.10:6379,确认是 Redis 连接问题。 - 第三步:实时验证修复
# 修复 Redis 配置后,实时跟踪 Pod 启动 kubectl logs -f my-app-7d4f8b6c9-x2k3j -n production观察到
Connected to Redis successfully,Pod 进入 Running 状态。