IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章,助你少走弯路。
在第 41 篇中,我们用 Prometheus + Grafana 搭建了监控体系。监控告诉我们"集群出问题了"------某个 Pod 的 CPU 飙升、某个 Deployment 的请求延迟突然变高。但接下来你一定会问:为什么? 是代码逻辑错误、数据库连接池耗尽、还是外部 API 超时?
答案藏在日志里。
在 Docker 时代,docker logs 查看单个容器的日志就够了。在第 6 篇中,我们甚至配置了日志轮转策略来防止日志文件撑爆磁盘。但在 Kubernetes 集群中,几十个 Pod 分散在多台节点上,Pod 随时可能被删除重建(滚动更新、节点故障、资源驱逐),容器内的日志会随之消失。你不可能 SSH 到每台节点上 tail -f 日志文件------你需要一个集中式日志系统。
今天这篇,我们从容器日志的短暂性讲起,对比 EFK 和 Loki 两种主流的日志方案,最终用 Loki 为贯穿案例的 Flask 应用构建一个轻量、高效的日志聚合系统。
一、为什么需要集中式日志?
Kubernetes 中,容器的 stdout/stderr 输出由容器运行时(containerd/docker)捕获,写入节点上的临时文件。这些日志的生命周期与 Pod 绑定------Pod 被删除后,kubelet 会清理这些日志文件。即使你为 Pod 挂载了持久化卷来保存日志,当应用有 10 个副本时,你需要查看 10 个 Pod 的日志才能找到某一个错误。
集中式日志系统的核心价值就是:
-
聚合:将所有 Pod、节点的日志汇聚到一个地方,一处查询全局日志。
-
持久化:日志独立于 Pod/容器的生命周期,Pod 重建后日志依然可查。
-
搜索与分析:通过标签(Pod 名、命名空间、容器名)快速过滤,通过关键词搜索定位错误。
-
可视化:结合 Grafana 在同一平台查看监控指标和日志,形成完整的可观测性闭环。
二、方案选型:EFK vs Loki
Kubernetes 生态中最主流的两种日志方案是 EFK(Elasticsearch + Fluentd + Kibana)和 Loki + Promtail。
2.1 EFK 栈
EFK 是日志领域的经典组合,三个组件分工明确:
-
Elasticsearch:分布式搜索引擎,用于存储和索引日志。它会对日志内容做全文分词索引,使搜索速度极快,但代价是资源消耗极高------CPU、内存、磁盘 IO 都很大。
-
Fluentd:日志采集器,以 DaemonSet 形式部署在每个节点上,收集容器日志并发送到 Elasticsearch。它支持丰富的插件生态和强大的日志处理(解析、过滤、转换)能力。
-
Kibana:数据可视化界面,提供丰富的仪表板、图表和查询功能。
EFK 的典型场景是大规模、对全文搜索要求高的生产环境,比如需要每秒处理数万条日志,或日志分析团队需要对日志内容做复杂的聚合查询。
2.2 Loki + Promtail
Loki 是 Grafana Labs 推出的轻量级日志聚合系统,设计理念与 Prometheus 一脉相承:
-
Loki:类似 Prometheus,但不索引日志内容,只索引元数据标签(Pod 名、命名空间、容器名)。这使得它的资源消耗远低于 Elasticsearch,运维复杂度也大大降低。
-
Promtail:日志采集代理,以 DaemonSet 形式部署在每个节点上,收集日志并推送给 Loki。它自动为日志附加 Kubernetes 元数据标签(Pod 名、命名空间、标签等)。
-
Grafana:与监控使用同一套 Grafana,无需额外维护可视化工具。你可以把监控仪表板和日志查询面板放在同一页面上,排查问题时在指标和日志间无缝切换。
Loki 的典型场景是资源敏感、追求轻量和简洁的中小规模集群,或者已经使用了 Prometheus + Grafana 技术栈的团队。
2.3 选型决策
对于我们的贯穿案例来说,Loki 是更合适的选择------轻量、与 Prometheus + Grafana 技术栈天然集成,且 Minikube 单节点环境资源有限。
三、Loki 的架构与核心概念
Loki 的架构与 Prometheus 高度相似,如果你理解了第 41 篇的 Prometheus,Loki 的概念几乎可以 1:1 映射:
Loki 的查询语言 LogQL 由两部分组成:
-
日志流选择器 :
{app="flask-counter", namespace="default"}选择特定的日志流 -
日志管道 :
|= "ERROR"包含关键词、!= "DEBUG"排除关键词、| json解析 JSON 格式日志
四、部署 Loki + Promtail
我们将使用 Helm Chart 来部署 Loki Stack(包含 Loki 和 Promtail)。
4.1 添加 Grafana 仓库并安装
bash
# 添加 Grafana 官方 Helm 仓库
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
# 安装 Loki Stack(包含 Loki 和 Promtail)
helm upgrade --install loki grafana/loki-stack \
--namespace logging --create-namespace \
--set loki.auth_enabled=false \
--set promtail.config.snippets.extraScrapeConfigs='[
{
"job_name": "flask-logs",
"kubernetes_sd_configs": [{"role": "pod"}],
"relabel_configs": [
{
"source_labels": ["__meta_kubernetes_pod_label_app"],
"action": "keep",
"regex": "flask-counter"
}
]
}
]'
参数说明:
-
loki.auth_enabled=false:开发环境关闭认证,简化配置 -
promtail.config.snippets.extraScrapeConfigs:额外的日志采集配置,只采集带有app=flask-counter标签的 Pod 日志,减少噪音数据
4.2 验证部署
bash
kubectl get pods -n logging
输出:
bash
NAME READY STATUS RESTARTS AGE
loki-0 1/1 Running 0 30s
promtail-xxxxx 1/1 Running 0 30s
-
loki-0:Loki 实例,负责接收和存储日志(Minikube 单节点使用 StatefulSet 以便持久化)
-
promtail-xxxxx:Promtail DaemonSet,每个节点上运行一个,自动采集所有容器的日志
五、在 Grafana 中查询日志
5.1 添加 Loki 数据源
-
访问 Grafana(第 41 篇已部署,默认通过
kubectl port-forward -n monitoring svc/monitoring-grafana 3000:80访问)。 -
左侧菜单 → Connections → Data Sources → Add data source → 搜索 Loki。
-
URL 填写
http://loki.logging:3100(因为 Loki 部署在logging命名空间,Grafana 在monitoring命名空间,需跨命名空间 DNS 解析)。 -
点击 Save & Test,应显示绿色成功提示。
5.2 查询 Flask 应用日志
在 Grafana 左侧菜单点击 Explore,选择 Loki 数据源,输入查询:
bash
{app="flask-counter", namespace="default"}
点击 Run query,你会看到 Flask 应用的实时日志流。每条日志都标注了时间戳和来源 Pod 名称。
过滤包含错误关键词的日志:
bash
{app="flask-counter"} |= "ERROR"
排除健康检查请求的日志(减少噪音):
bash
{app="flask-counter"} != "/health"
使用正则表达式匹配:
bash
{app="flask-counter"} |~ "(?i)error|exception|fail"
5.3 查看 Redis 日志
bash
{app="redis", namespace="default"}
现在,你可以从 Redis 日志中看到连接请求、数据持久化(RDB/AOF)状态、内存使用报告等信息。
六、实战:模拟错误并排查
现在我们把日志系统真正用起来------模拟一个生产故障并追踪定位。
6.1 制造错误
bash
# 进入 Flask 容器,手动触发一个错误
kubectl exec deploy/flask-deployment -- curl -X POST http://localhost:5000/nonexistent
应用代码中没有 /nonexistent 端点,Flask 会返回 404 错误,并在日志中记录这个错误请求。
6.2 在 Loki 中定位错误
回到 Grafana Explore,使用 LogQL 查询:
bash
{app="flask-counter"} |= "404"
你会看到类似如下的日志行:
bash
2025-05-27 10:15:30 10.244.1.25 - - [27/May/2025:10:15:30 +0000] "POST /nonexistent HTTP/1.1" 404 -
同时可以查询同一时间段内该 Pod 的所有请求日志,分析在错误发生前后是否有异常:
bash
{app="flask-counter", pod="flask-deployment-xxxxxxxx-xxxxx"}
6.3 结合监控指标与日志(可观测性闭环)
这是 Loki 与 Grafana 同平台的最大优势------你可以在一个页面上同时看到监控指标和对应时间段的日志:
-
在 Explore 中打开 Loki 查询,输入
{app="flask-counter"} |= "ERROR"。 -
点击 Split 按钮,在右侧面板选择 Prometheus 数据源。
-
输入
rate(flask_http_request_total{status="404"}[5m]),查看 404 错误请求的速率趋势。 -
如果指标显示 10:15 左右 404 速率突然升高,日志面板中同时段会显示对应的错误日志详情------指标告诉你"发生了什么",日志告诉你"为什么会发生"。
七、日志轮转与保留策略
Loki 默认使用本地存储(Minikube 环境)。生产环境建议使用对象存储(S3、GCS)来持久化日志,并配置保留策略。
在 values.yaml 中配置:
bash
loki:
persistence:
enabled: true
size: 10Gi
config:
table_manager:
retention_deletes_enabled: true
retention_period: 168h # 保留 7 天
这比 Docker Compose 时代手动配置 max-size: 10m, max-file: 3 的日志轮转更加集中化和可管理------你不再需要逐个容器配置日志轮转,而是在日志聚合层统一控制保留策略。
八、对比 Docker Compose 的日志管理
从 Docker Compose 到 K8s + Loki,日志管理从"本地、分散、手动"演进到"集中、聚合、可检索"。在第 6 篇学到的 docker logs -f --tail 50 和日志轮转配置,在 Loki 中变成了 {app="xxx"} |= "ERROR" 和统一的 retention_period。
九、命令速查表
十、本篇总结
-
集中式日志的必要性 :Pod 日志是短暂的,必须聚合到外部系统才能持久化和检索。
kubectl logs只是临时调试工具,不是日志管理的最终方案。 -
EFK vs Loki:EFK 功能强大但资源消耗高,适合大规模全文搜索场景;Loki 轻量、与 Grafana 原生集成,适合已采用 Prometheus 技术栈的团队。
-
Loki 实战:部署了 Loki + Promtail,在 Grafana 中添加 Loki 数据源,通过 LogQL 查询 Flask 和 Redis 日志。指标和日志在同一平台展示,从"发现问题"到"定位原因"只需一次界面切换。
-
日志与监控的闭环:Prometheus 告诉你"Pod 在频繁重启",Loki 告诉你"因为数据库连接超时"。两者结合,才能真正做到快速排错。
下一篇------第 43 篇:集群网络策略:NetworkPolicy 入门,我们将学习如何通过 NetworkPolicy 实现 Pod 间的网络隔离,为微服务集群加上一道关键的网络安全防线。
想了解更多还可以去各个平台搜索「IT策士」,一起升级 IT 思维 !