4. 标准输出日志采集:kubectl logs 实战技巧
说实话,在云原生环境里排查故障,kubectl logs 是我用得最频繁的命令之一。没有之一。你想想看,Pod 里跑着应用,出了问题第一反应是什么?肯定是看日志啊。但很多人只会用最基础的 kubectl logs <pod>,遇到复杂场景就抓瞎了。今天我把这些年积累的实战经验掰开揉碎讲给你听。
4.1 基础用法:kubectl logs 到底怎么用
先看最基础的。一个 Pod 只有一个容器时,直接敲:
kubectl logs my-pod
这会打印出 Pod 里所有标准输出日志。注意,是 标准输出(stdout)和标准错误(stderr)。容器里写日志,只要写到这两个流里,kubectl 就能抓到。
我个人习惯在开发环境直接看全部日志,但生产环境千万别这么干。为什么?因为一个运行了几天的 Pod,日志量可能上 GB,终端直接卡死。我曾经在客户现场,看到有人对着一个跑了 72 小时的 Pod 执行 kubectl logs,结果终端直接无响应,场面一度非常尴尬。
kubectl logs。建议始终加上 --tail 或 --since 参数限制日志量。
4.2 只看尾巴:kubectl logs --tail 的妙用
排查问题时,我们通常只关心最近发生的日志。这时候 --tail 就派上用场了:
# 只看最后 100 行
kubectl logs my-pod --tail=100
# 只看最后 10 行
kubectl logs my-pod --tail=10
嗯,这里有个小细节。如果你不指定 --tail,默认行为是显示所有日志。但如果你指定了 --tail=0,那就什么都不显示。这个参数我经常用来配合 -f 使用,后面会讲。
我在项目中遇到过一种情况:Pod 一直在重启,CrashLoopBackOff 状态。这时候用 kubectl logs my-pod --tail=50 看最后 50 行,往往就能找到 OOM 或者配置错误的线索。比看完整日志高效太多了。
4.3 实时追踪:kubectl logs -f 的实战技巧
-f 参数,说白了就是 tail -f 的 Kubernetes 版。它会持续输出日志,直到你按 Ctrl+C 退出。
# 实时查看日志
kubectl logs my-pod -f
# 只看最后 20 行,然后实时追踪
kubectl logs my-pod --tail=20 -f
第二个命令是我最常用的组合。为什么?因为只看最后 20 行,能快速定位到当前上下文,然后实时追踪后续日志。你想想看,如果直接 -f,终端里可能刷出几万行历史日志,真正有用的信息早就被冲走了。
kubectl logs -f 实时看日志,另一个执行操作(比如发请求、改配置)。这样能实时看到操作产生的日志反馈,排查效率翻倍。
我曾经排查过一个诡异的问题:应用每隔 5 分钟报一次错,但重启后就正常了。我开了 kubectl logs -f 等了 5 分钟,果然看到错误日志。原来是一个连接池泄漏的问题。如果没有 -f,这种间歇性问题根本抓不到。
4.4 多容器 Pod 的日志查看技巧
这是很多人容易踩坑的地方。一个 Pod 里有多个容器,直接 kubectl logs my-pod 会报错:
Error from server (BadRequest): a container name must be specified for pod my-pod, choose one of: [container-a, container-b]
这时候需要用 -c 参数指定容器名:
# 查看指定容器的日志
kubectl logs my-pod -c container-a
# 实时查看指定容器的日志
kubectl logs my-pod -c container-b -f
# 只看最后 50 行
kubectl logs my-pod -c container-a --tail=50
那如果我想同时看多个容器的日志呢?嗯,kubectl 本身不支持。但有个小技巧:用 --all-containers=true 参数:
# 查看所有容器的日志(Kubernetes 1.14+ 支持)
kubectl logs my-pod --all-containers=true
不过说实话,这个命令会把所有容器的日志混在一起输出,没有区分标识。我个人不太推荐。更好的做法是开多个终端,或者用 stern、kubetail 这类工具。
-c 指定容器名。这是最基础也最容易忽略的坑。
4.5 实战场景:Init 容器的日志查看
Init 容器也值得单独说一下。Init 容器在 Pod 启动时运行,完成后就退出了。查看它的日志,需要指定 Init 容器的名字:
# 查看 Init 容器日志
kubectl logs my-pod -c init-container-name
我记得有一次,一个 Pod 一直处于 Init:CrashLoopBackOff 状态。我用了 kubectl logs my-pod -c init-myservice --tail=20,发现是 Init 容器里一个配置文件路径写错了。如果没有这个技巧,你根本不知道 Init 容器里发生了什么。
4.6 常用参数速查表
| 参数 | 作用 | 使用场景 |
|---|---|---|
--tail=N |
显示最后 N 行日志 | 只看最近日志,避免刷屏 |
-f |
实时追踪日志输出 | 调试、监控实时行为 |
-c <name> |
指定容器名 | 多容器 Pod 查看日志 |
--since=1h |
显示最近 1 小时的日志 | 按时间范围过滤 |
--all-containers=true |
显示所有容器日志 | 快速查看,但日志会混在一起 |
4.7 避坑指南
最后,分享几个我踩过的坑:
- Pod 被删除了怎么办? 如果 Pod 已经被删除,
kubectl logs会报错找不到 Pod。这时候需要用kubectl logs --previous查看上一个实例的日志,或者用kubectl describe pod看事件。 - 日志太多终端卡死? 我建议始终加
--tail=100或--since=5m。别问我怎么知道的,问就是经历过。 - 多容器日志混在一起? 用
-c分别查看,或者用stern工具(支持按 Pod 和容器名过滤,还能加颜色区分)。 - Init 容器日志看不到? 记得 Init 容器名和普通容器名是分开的,用
kubectl logs pod -c <init-container-name>查看。
嗯,以上就是 kubectl logs 的实战技巧。说白了,这些命令都不复杂,但用好了能大幅提升排查效率。你想想看,别人还在翻几千行日志的时候,你已经用 --tail 和 -f 定位到问题了。这就是老手和新手的区别。