第 42 篇 k8s之日志管理:使用 EFK 或 Loki 采集日志

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 的日志才能找到某一个错误。

集中式日志系统的核心价值就是:

  1. 聚合:将所有 Pod、节点的日志汇聚到一个地方,一处查询全局日志。

  2. 持久化:日志独立于 Pod/容器的生命周期,Pod 重建后日志依然可查。

  3. 搜索与分析:通过标签(Pod 名、命名空间、容器名)快速过滤,通过关键词搜索定位错误。

  4. 可视化:结合 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 数据源

  1. 访问 Grafana(第 41 篇已部署,默认通过 kubectl port-forward -n monitoring svc/monitoring-grafana 3000:80 访问)。

  2. 左侧菜单 → ConnectionsData SourcesAdd data source → 搜索 Loki

  3. URL 填写 http://loki.logging:3100(因为 Loki 部署在 logging 命名空间,Grafana 在 monitoring 命名空间,需跨命名空间 DNS 解析)。

  4. 点击 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 同平台的最大优势------你可以在一个页面上同时看到监控指标和对应时间段的日志:

  1. Explore 中打开 Loki 查询,输入 {app="flask-counter"} |= "ERROR"

  2. 点击 Split 按钮,在右侧面板选择 Prometheus 数据源。

  3. 输入 rate(flask_http_request_total{status="404"}[5m]),查看 404 错误请求的速率趋势。

  4. 如果指标显示 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 思维 !

相关推荐
m0_7381207214 分钟前
渗透测试基础——基于Docker的Rsync服务靶场搭建与原理讲解
运维·服务器·网络·安全·web安全·docker·容器
小义_1 小时前
【Ansible】(三)基础配置与连接设置
云原生·ansible
松岩2 小时前
网络问题导致 Pod Pending
kubernetes·aiops
极客先躯5 小时前
高级java每日一道面试题-2026年02月09日-实战篇[Docker]-Docker 容器有哪些安全风险?如何缓解?
java·运维·网络·安全·docker·容器
yuanzhengme5 小时前
Ollama【部署 07】搭建本地智能体的简单说明(局域网离线部署Ollama+模型迁移+Docker部署AnythingLLM)
运维·docker·容器·大模型·ollama·本地智能体
运维老郭6 小时前
Kubernetes 二进制部署完全指南:从零搭建生产级HA集群
运维·云原生·kubernetes
成为你的宁宁6 小时前
【K8S黑盒监控实践:Probe配置、Prometheus验证与Grafana可视化】
kubernetes·grafana·prometheus
成为你的宁宁6 小时前
【Prometheus Operator监控K8S Nginx】
nginx·kubernetes·prometheus
宇明一不急7 小时前
k8s headless svc
云原生·容器·kubernetes
容器魔方7 小时前
Karmada v1.18 版本发布!新增混合云溢出式调度能力
人工智能·云原生·容器·华为云·云计算