1. 简介
在 Kubernetes 的所有组件中,kubelet 是运行在每个节点上的核心代理,负责管理由 Kubernetes 编排的容器。由于其关键作用,我们需要访问和理解 kubelet 日志来调试、监控并确保 Kubernetes 生态系统的健康状态。
然而,定位 Kubernetes 日志可能会让人感到困惑,尤其是在不同的部署环境和配置中。本文将系统讲解在不同 Kubernetes 部署方式下,如何查找和分析 kubelet 日志。
无论你是正在排查节点问题的 DevOps 工程师,还是想了解 Pod 行为的系统管理员,掌握 kubelet 日志的获取方法是深入了解 Kubernetes 集群运行机制的第一步。我们开始吧!
2. kubelet 的作用
kubelet 是 Kubernetes 节点上的核心代理组件,负责与控制平面通信,并管理节点上的容器生命周期。它确保根据 Kubernetes 清单中定义的期望状态,启动、运行并监控由 PodSpec 描述的容器。
此外,kubelet 还负责执行控制平面下发的指令,管理容器生命周期,处理卷挂载、网络配置、资源分配等操作。
由于其核心地位,kubelet 会生成大量日志,记录节点状态、Pod 状态、容器执行情况等信息。这些日志对于诊断容器启动失败、资源配置问题、网络连接异常等问题至关重要。
例如,当某个安全策略阻止了容器启动,或者资源限制导致容器被终止时,kubelet 日志往往能提供关键线索。
3. 不同环境中访问 kubelet 日志的方法
kubelet 日志的位置和访问方式会根据 Kubernetes 的部署方式有所不同。从云厂商托管服务到本地开发环境,每种设置可能存储日志的位置不同,或需要特定命令访问。
以下是一些常见部署方式及其对应的日志获取方法。
3.1. 使用 systemd
大多数现代 Linux 发行版(如 CentOS、Fedora 和 Ubuntu 15.04 及以上版本)都使用 systemd 作为初始化系统。如果 Kubernetes 节点运行在使用 systemd 的操作系统上,那么 kubelet 通常作为一个 systemd 服务运行。
要查看 kubelet 日志,可以使用 journalctl
命令查询 systemd 日志:
$ journalctl -u kubelet
Mar 13 12:00:45 my-k8s-node kubelet[9876]: I0313 12:00:45.789101 9876 server.go:155] Successfully started kubelet
Mar 13 12:01:10 my-k8s-node kubelet[9876]: W0313 12:01:10.456789 9876 container_manager_linux.go:912] Running with swap on is not supported, please disable swap
该日志显示 kubelet 成功启动,并提示当前启用了 Swap(Kubernetes 不支持)。
你也可以使用 journalctl
的其他参数来过滤、分页或实时查看日志。
3.2. 查看 /var/log/syslog
在一些未使用 systemd 的 Linux 系统中,kubelet 日志可能输出到 /var/log/syslog 文件中。这个文件通常用于聚合系统日志。
由于内容较多,建议使用 grep
过滤:
$ grep kubelet /var/log/syslog
Mar 13 14:20:30 my-k8s-node kubelet: I0313 14:20:30.123456 reconciliation.go:104] "Reconciler sync states" pod="my-namespace/my-pod"
Mar 13 14:21:00 my-k8s-node kubelet: E0313 14:21:00.654321 eviction_manager.go:255] "Eviction manager: failed to get get summary stats" err="failed to get node info: node \"my-k8s-node\" not found"
该日志显示了 Pod 状态同步正常,随后出现了驱逐管理器因找不到节点而失败的错误。
3.3. Docker-MultiNode 环境
如果你使用 Docker-MultiNode 部署 Kubernetes(较少使用),kubelet 是运行在 Docker 容器中的。
要访问日志,首先找到运行 kubelet 的容器 ID:
$ docker ps | grep kubelet
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
abcdef123456 kubelet:latest "/usr/local/bin/kube…" 3 minutes ago Up 3 minutes k8s_kubelet
然后使用 docker logs
查看日志:
$ docker logs abcdef123456
I0313 16:34:20.789101 1 kuberuntime_manager.go:207] "Container runtime status check" runtimeStatus=ok
E0313 16:35:25.654321 1 pod_workers.go:190] "Error syncing pod, skipping" err="failed to \"StartContainer\" for \"my-container\" with CrashLoopBackOff: \"back-off 5m0s restarting failed container=my-container pod=my-pod(my-namespace)\""
该日志显示了容器运行时状态正常,但某个容器因反复崩溃而进入 CrashLoopBackOff 状态。
3.4. 使用 Upstart
Ubuntu 15.04 之前的版本使用 Upstart 作为初始化系统。在这些系统中,kubelet 日志通常位于 /var/log/upstart/ 目录下。
查看日志:
$ less /var/log/upstart/kubelet.log
I0313 10:34:20.123456 1 server.go:408] "Starting to listen" address="0.0.0.0" port=10250
E0313 10:34:25.654321 1 kubelet.go:2187] "Node has no valid hostname and/or IP address" err="node IP not set"
日志显示 kubelet 启动成功,但提示节点缺少 IP 配置。
4. 在 Kubernetes in Docker(kind)中访问日志
如果你在本地使用 kind(Kubernetes in Docker)搭建集群,kubelet 日志可以通过进入 Docker 容器查看。
4.1. 列出运行中的容器
首先列出所有运行中的容器,找到 kind 节点容器:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
...
4a1b2c3d4e5f kindest/node:v1.20.2 "/usr/local/bin/entr…" 10 minutes ago Up 10 minutes 127.0.0.1:32768->6443/tcp kind-control-plane
...
然后进入容器:
$ docker container exec -it kind-control-plane bash
4.2. 查看 /var/log/containers/ 和 /var/log/pods/
在容器内,kubelet 日志通常位于以下两个目录中:
- **/var/log/containers/**:每个容器日志的符号链接。
- **/var/log/pods/**:按 Pod 组织的日志目录,每个 Pod 有其 UUID 命名的目录,包含其容器日志。
示例查看某个容器日志:
$ tail -n 100 /var/log/containers/myapp-container_<pod-uuid>.log
2024-03-13T12:34:56.789Z INFO myapp-container "Starting application..."
2024-03-13T12:35:01.234Z INFO myapp-container "Application configuration loaded"
2024-03-13T12:35:05.678Z WARN myapp-container "Deprecated API usage detected"
2024-03-13T12:35:10.123Z ERROR myapp-container "Failed to connect to database"
持续查看日志:
$ tail -f /var/log/pods/<pod-uuid>/myapp-container/0.log
2024-03-13T12:36:20.345Z INFO myapp-container "Listening on port 8080"
2024-03-13T12:40:15.678Z INFO myapp-container "Received new connection"
2024-03-13T12:41:10.123Z INFO myapp-container "Connection closed"
5. 日志中常见问题识别
kubelet 日志是排查集群问题的宝贵资源。以下是一些常见问题及对应的日志特征。
5.1. 容器启动失败
日志中可能出现类似以下内容:
"Failed to start container" 或 "Error response from daemon"
这类日志通常来自容器运行时,提示配置错误、资源不足或镜像拉取失败。
5.2. 资源分配问题
资源限制过低可能导致容器被 OOMKilled(Out Of Memory Killed)或 CPU 资源不足。
日志中可能包含:
"Out Of Memory Killed" 或 "CPU limit exceeded"
这类日志有助于优化资源请求和限制设置。
5.3. 网络连接问题
网络插件异常、DNS 解析失败或连接超时等错误会在日志中体现:
"NetworkPlugin not ready" 或 "Failed to setup network for pod"
这类日志提示网络配置或插件问题。
6. 自动化日志监控
虽然手动查看 kubelet 日志对排查特定问题很有帮助,但自动化监控能让我们更主动地发现和响应问题。
6.1. 使用监控工具
可以使用 Prometheus + Grafana 搭配 Loki(日志聚合系统)进行日志监控。
- Prometheus 收集指标
- Loki 收集日志
- Grafana 可视化并设置告警
也可以使用 EFK(Elasticsearch + Fluentd + Kibana)进行日志聚合和复杂查询。
6.2. 脚本与自动化
可以编写脚本定期检查 kubelet 日志,识别错误并发送报告。例如,以下是一个 Bash 脚本示例:
#!/bin/bash
recipient_email="admin@example.com"
subject="Daily Kubelet Log Report"
report_file=$(mktemp)
echo "Kubelet Log Report for $(date)" >> "$report_file"
echo "----------------------------------------" >> "$report_file"
function count_logs {
log_level=$1
message_tag=$2
count=$(journalctl -u kubelet --since "yesterday" | grep -ic "$log_level")
echo "$message_tag: $count" >> "$report_file"
}
count_logs "error" "Critical Errors"
count_logs "warn" "Warnings"
count_logs "info" "Informational Messages"
image_pull_errors=$(journalctl -u kubelet --since "yesterday" | grep -ic "Failed to pull image")
echo "Image Pull Errors: $image_pull_errors" >> "$report_file"
mail -s "$subject" "$recipient_email" < "$report_file"
rm "$report_file"
赋予执行权限并添加到 crontab:
$ chmod +x check_all_logs.sh
$ crontab -e
0 1 * * * /path/to/check_all_logs.sh
7. 总结
本文系统讲解了在不同 Kubernetes 部署方式下访问 kubelet 日志的方法。kubelet 日志是管理 Kubernetes 集群不可或缺的资源,能帮助我们诊断问题、优化配置、保障集群稳定运行。
有效的日志管理不仅在于查看日志本身,更在于通过工具和实践实现自动化监控与响应。无论是手动分析还是自动化脚本,掌握 kubelet 日志的获取和分析方法,将有助于你构建一个更健康、高效的 Kubernetes 环境。