K8s 运维系列 | 第 13 天:日志体系——Loki 与 EFK 日志采集分析

在 Kubernetes 集群中,Pod 随时可能被调度、重启或销毁,容器产生的日志如果只保存在本地文件里,会随着容器的生命周期一起消失。当线上出现故障时,运维人员往往需要在成百上千个 Pod 之间来回切换、逐个 kubectl logs,效率极低。因此,一套集中化的日志采集与分析体系,是生产级 K8s 集群不可或缺的基础设施。本文将围绕两大主流方案展开:以 Loki 为代表的轻量级日志系统,以及以 Elasticsearch 为核心的 EFK 经典方案,帮助读者建立起完整的日志治理思路。

K8s 运维 第13天

一、为什么容器日志必须集中管理

传统虚拟机时代,应用日志通常写入固定目录,配合 filebeat 或 logrotate 就能完成采集与轮转。但 Kubernetes 引入了动态编排的特性,带来了三个新的挑战:

  1. 日志随 Pod 漂移:Pod 被调度到不同节点,本地日志不再固定。
  2. 短生命周期:Job、CronJob 任务执行完即退出,日志若不及时采集就会丢失。
  3. 规模爆炸:微服务化后实例数量激增,逐个登录节点查看日志不现实。

因此,业界普遍采用「采集器 + 存储 + 查询界面」的三层架构,把分散在各节点 /var/log/containers 下的日志统一汇聚,实现检索、告警与可视化。

二、核心概念:日志管线的三层结构

一套完整的日志系统通常由三部分组成:

  • 采集层(Collector):运行在每个节点上,以 DaemonSet 形式部署,负责读取容器日志并转发,代表组件有 Promtail、Fluentd、Filebeat、Fluent Bit。
  • 存储层(Storage):负责持久化与索引日志,例如 Loki、Elasticsearch。
  • 展示层(Dashboard):提供查询与可视化界面,如 Grafana、Kibana。

Kubernetes 官方推荐的日志采集方式,是让采集器以 DaemonSet 挂载宿主机的日志目录,按容器元数据(命名空间、Pod、容器名)打标签后统一上报。

三、Loki:为 K8s 而生的轻量级日志方案

Loki 是 Grafana 实验室开源的项目,最大特点是只索引元数据(labels),不对日志全文建立索引,而是把日志压缩后按时间分块存储。这种设计让它相比 Elasticsearch 更省资源,尤其适合中小规模集群与成本敏感的场景。

3.1 Loki 的核心组件

  • Promtail:日志采集器,运行在每个节点,负责发现目标、解析标签并把日志推送到 Loki。
  • Loki:日志存储与查询引擎,接收日志流并提供 LogQL 查询接口。
  • Grafana:统一的可视化面板,通过 Data Source 连接 Loki 进行查询。

3.2 部署 Promtail 的 DaemonSet

下面是一份精简的 Promtail DaemonSet 配置,关键是把宿主机的日志目录以只读方式挂载进容器:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: promtail
  namespace: logging
spec:
  selector:
    matchLabels:
      app: promtail
  template:
    metadata:
      labels:
        app: promtail
    spec:
      containers:
      - name: promtail
        image: grafana/promtail:2.9.0
        args:
          - -config.file=/etc/promtail/promtail.yaml
        volumeMounts:
        - name: varlog
          mountPath: /var/log
          readOnly: true
        - name: containers
          mountPath: /var/lib/docker/containers
          readOnly: true
        - name: config
          mountPath: /etc/promtail
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: containers
        hostPath:
          path: /var/lib/docker/containers
      - name: config
        configMap:
          name: promtail-config

3.3 使用 LogQL 查询日志

Loki 使用 LogQL 查询语言,语法与 PromQL 类似。常用查询示例:

# 查询命名空间 default 下所有日志(最近 1 小时)
{namespace="default"} |= ""

# 过滤包含 error 关键字的日志
{namespace="default"} |= "error"

# 统计每分钟 error 日志的数量
sum by (pod) (rate({namespace="default"} |= "error" [1m]))

四、EFK:成熟稳定的经典方案

EFK 即 Elasticsearch + Fluentd + Kibana 的组合,是传统日志体系在容器时代的延续。它的优势在于 Elasticsearch 强大的全文检索能力,适合日志量巨大、对检索性能要求高的场景,代价则是更高的资源开销与运维复杂度。

4.1 各组件职责

  • Fluentd / Fluent Bit:日志采集与转发,支持丰富的输入、过滤、输出插件。
  • Elasticsearch:分布式搜索引擎,负责日志的索引与存储。
  • Kibana:可视化前端,提供检索、仪表盘与告警。

4.2 Fluentd 采集配置示例

<source>
  @type tail
  path /var/log/containers/*.log
  pos_file /var/log/fluentd-containers.log.pos
  tag kubernetes.*
  <parse>
    @type json
  </parse>
</source>

<filter kubernetes.**>
  @type kubernetes_metadata
</filter>

<match kubernetes.**>
  @type elasticsearch
  host elasticsearch
  port 9200
  logstash_format true
  logstash_prefix k8s
</match>

4.3 在 Kibana 中检索

日志进入 Elasticsearch 后,可以在 Kibana 的 Discover 页面用 KQL 或 Lucene 语法检索,例如:

{
  "query": {
    "bool": {
      "must": [
        { "match": { "kubernetes.namespace_name": "default" } },
        { "match": { "message": "error" } }
      ]
    }
  }
}

五、实战步骤:为集群接入日志采集

下面以 Loki 方案为例,梳理一条完整的接入路径:

  1. 部署 Grafana 与 Loki:通过 Helm 一键安装官方 chart。
  2. 部署 Promtail DaemonSet:确保每个节点都有采集器运行。
  3. 验证采集:在 Grafana 中新增 Loki Data Source,输入 LogQL 查询,确认能检索到日志。
  4. 配置告警:针对 error 日志设置 Grafana Alert,接入邮件或 Webhook。

使用 Helm 快速安装 Loki 全家桶的命令如下:

# 添加 Grafana 官方仓库并安装 Loki Stack
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
helm install loki grafana/loki-stack 
  --set grafana.enabled=true 
  --set promtail.enabled=true 
  --namespace logging --create-namespace

六、常见问题与排查

6.1 日志采集不到

首先检查 Promtail / Fluentd 是否在每个节点都正常运行:

kubectl get pods -n logging -o wide
kubectl logs -n logging -l app=promtail --tail=50

常见原因是 DaemonSet 的 hostPath 挂载路径与实际容器运行时不一致。使用 containerd 时,日志路径在 /var/log/pods,而 Docker 则在 /var/lib/docker/containers,需要按实际情况调整。

6.2 Elasticsearch 磁盘打满

EFK 方案最容易遇到磁盘告警。建议通过 ILM(Index Lifecycle Management)策略自动清理过期索引,并提前规划存储容量。

6.3 日志量过大导致成本激增

可以通过 Promtail 的 pipeline 阶段在源头丢弃无关日志,或在 Loki 中为不同的日志流设置不同的保留期(retention),避免无意义地长期保存调试日志。

七、总结

日志体系是 Kubernetes 可观测性建设的基石。Loki 以其轻量、低成本的特性,成为中小集群与云原生场景的热门选择;而 EFK 凭借强大的全文检索能力,依然是超大规模、强检索需求场景的可靠方案。二者并非互斥,许多团队会根据日志等级与用途,将两类系统组合使用。掌握日志管线的基本原理,理解「采集、存储、查询」三层的职责边界,是每一位 K8s 运维工程师的必修课。

下期预告:第 14 天我们将进入监控告警的世界,介绍如何用 Prometheus 与 Grafana 对集群指标进行采集、存储与可视化,敬请期待。

微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容