Kubernetes Handbook 应用日志收集实战:基于 Filebeat Sidecar 与自有 ELK 集群的轻量级日志采集方案
2026/9/23 12:27:38 网站建设 项目流程
  • 教程
  • 云原生
  • 容器编排

【免费下载链接】kubernetes-handbook

Kubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南

项目地址:https://gitcode.com/gh_mirrors/ku/kubernetes-handbook
点击查看免费下载

在 Kubernetes 集群中收集应用日志,官方 EFK 方案并非唯一选择。本篇技术指南以 practice/app-log-collection.md 为核心,讲解如何在每个 Pod 中以 Sidecar 方式运行轻量级日志采集组件 Filebeat,将应用日志送入团队自有的 ELK(Elasticsearch + Logstash + Kibana)集群。读完本文,你将掌握 Kubernetes 日志收集的三种架构模式及其取舍、Filebeat Sidecar 方案的完整 YAML 编写方法(ConfigMap 与环境变量两种配置方式),以及如何在 Kibana 中验证日志索引与字段。

背景:为什么放弃 Logstash,改用 Filebeat

在 Kubernetes 环境中设计日志收集方案时,Logstash 往往是第一选择——它是 ELK stack 中的重要成员,功能强大且生态成熟。但 Logstash 基于 JDK 运行,资源开销十分可观。团队在测试中发现:在没有产生任何日志的情况下,单纯启动 Logstash 就大约消耗 500M 内存

如果每个 Pod 中都启动一个日志收集组件,这个资源开销显然难以接受。经过测试对比,团队改用Filebeat替代 Logstash:单独启动一个 Filebeat 容器大约只消耗12M 内存,相较 Logstash 相当轻量级,非常适合以 Sidecar 模式与业务容器同 Pod 部署。

方案选型:官方 EFK 的局限与三种收集架构对比

Kubernetes 官方提供了 EFK(Elasticsearch + Fluentd + Kibana)日志收集解决方案,但该方案并不适合所有业务场景,存在以下局限性:

  • 所有日志必须是 stdout 前台输出,而真实业务场景中无法保证所有日志都在前台输出;
  • 只能有一个日志输出文件,而真实业务场景中往往有多个日志输出文件;
  • Fluentd 并不是常用的日志收集工具,团队更习惯用 Logstash,现改用 Filebeat 替代;
  • 团队已有自己的 ELK 集群且有专人维护,没有必要再在 Kubernetes 上重复搭建日志收集服务。

基于以上原因,最终决定复用自有的 ELK 集群。Kubernetes 集群中的日志收集解决方案主要有三种,对比如下:

编号方案优点缺点
1每个 app 的镜像中都集成日志收集组件部署方便,kubernetes 的 yaml 文件无须特别配置,可以为每个 app 自定义日志收集配置强耦合,不方便应用和日志收集组件升级和维护,且会导致镜像过大
2单独创建一个日志收集组件,跟 app 的容器一起运行在同一个 Pod 中低耦合,扩展性强,方便维护和升级需要对 kubernetes 的 yaml 文件进行单独配置,略显繁琐
3将所有的 Pod 的日志都挂载到宿主机上,每台主机上单独起一个日志收集 Pod完全解耦,性能最高,管理起来最方便需要统一日志收集规则、目录和输出方式

综合优缺点,团队选择方案二:Filebeat 作为 Sidecar 容器与业务容器共享同一个 Pod。该方案在扩展性、个性化、部署和后期维护方面都能做到均衡。

该方案的基本思路是:业务应用将日志写入 Pod 内的共享卷(如 emptyDir),Filebeat 容器挂载同一卷并监听其中的日志文件,再通过output.elasticsearch将日志发送到自有 ELK 集群。Filebeat 镜像由团队自行构建,可直接使用公开源码构建镜像。

实战:以 Filebeat 为 Sidecar 的日志收集测试

完整 YAML:Deployment + Service + ConfigMap

创建应用 YAML 文件filebeat-test.yaml,完整内容如下(该文件可以在 manifests/test/filebeat-test.yaml 找到):

apiVersion: extensions/v1beta1 kind: Deployment metadata: name: filebeat-test namespace: default spec: replicas: 3 template: metadata: labels: k8s-app: filebeat-test spec: containers: - image: harbor-001.jimmysong.io/library/filebeat:5.4.0 name: filebeat volumeMounts: - name: app-logs mountPath: /log - name: filebeat-config mountPath: /etc/filebeat/ - image: harbor-001.jimmysong.io/library/analytics-docker-test:Build_8 name : app ports: - containerPort: 80 volumeMounts: - name: app-logs mountPath: /usr/local/TalkingData/logs volumes: - name: app-logs emptyDir: {} - name: filebeat-config configMap: name: filebeat-config --- apiVersion: v1 kind: Service metadata: name: filebeat-test labels: app: filebeat-test spec: ports: - port: 80 protocol: TCP name: http selector: run: filebeat-test --- apiVersion: v1 kind: ConfigMap metadata: name: filebeat-config data: filebeat.yml: | filebeat.prospectors: - input_type: log paths: - "/log/*" - "/log/usermange/common/*" output.elasticsearch: hosts: ["172.23.5.255:9200"] username: "elastic" password: "changeme" index: "filebeat-docker-test"

配置说明

核心要点

  • Pod 内同时运行filebeatapp两个容器,通过共享的app-logsemptyDir: {})卷实现日志传递:app 将日志写入/usr/local/TalkingData/logs,Filebeat 在/log目录下读取;
  • Filebeat 的配置文件通过filebeat-config这个 ConfigMap 挂载到/etc/filebeat/目录下,因此不需要再定义环境变量
  • filebeat.yml中使用filebeat.prospectors定义日志探测规则,input_type: log表示读取日志文件,paths支持配置多个日志路径(如/log/*/log/usermange/common/*);
  • output.elasticsearch指定输出目标:hosts为自有 ELK 集群中 Elasticsearch 的地址(172.23.5.255:9200),可配置username/password认证,index用于指定写入的索引名(此处为filebeat-docker-test);
  • Service 的 selector 使用run: filebeat-test,与 Deployment 中 pod template 的 labelk8s-app: filebeat-test并不一致,实际测试以kubectl命令创建的 Deployment 为准,请以你部署时实际的 selector 配置为准。

备选方案:通过环境变量配置 Filebeat

如果不使用 ConfigMap,也可以通过传统方式传递环境变量来配置 Filebeat。例如对 Filebeat 容器进行如下配置:

containers: - image: harbor-001.jimmysong.io/library/filebeat:5.4.0 name: filebeat volumeMounts: - name: app-logs mountPath: /log env: - name: PATHS value: "/log/*" - name: ES_SERVER value: 172.23.5.255:9200 - name: INDEX value: logstash-docker - name: INPUT_TYPE value: log

这种方式的局限在于:PATHS只能传递单个目录。如果想传递多个目录,需要修改 Filebeat 镜像的docker-entrypoint.sh脚本,对该环境变量进行解析,从而扩展 filebeat.yml 文件中的 PATHS 列表。因此推荐优先使用ConfigMap方式,使 Filebeat 的配置更加灵活。

注意事项

  • 将 app 的/usr/local/TalkingData/logs目录挂载到 Filebeat 的/log目录下;
  • 该文件可以在 manifests/test/filebeat-test.yaml 找到;
  • 文中使用了私有镜像仓库(harbor-001.jimmysong.io),测试时请换成自己的应用镜像与 Filebeat 镜像;
  • Filebeat 环境变量的取值可参考自建镜像的入口脚本约定,确保环境变量名与镜像内的解析逻辑一致。

部署与验证

创建应用

部署 Deployment:

kubectl create -f filebeat-test.yaml

验证 Elasticsearch 索引

查看http://172.23.5.255:9200/_cat/indices,可以看到如下类似的索引:

green open filebeat-docker-test 7xPEwEbUQRirk8oDX36gAA 5 1 2151 0 1.6mb 841.8kb

其中filebeat-docker-test即为 YAML 文件中 ConfigMap 里配置的index值。

在 Kibana 中查看日志

访问 Kibana 的 Web 页面,查看filebeat-2017.05.17索引,可以看到 Filebeat 已成功收集到 app 日志:

点开每个日志条目,可以看到以下详细字段:

  • _index值即我们在 YAML 文件的 ConfigMap 中配置的 index 值;
  • beat.hostnamebeat.name即 Pod 的名称;
  • source表示 Filebeat 容器中的日志目录。

实用技巧:让 index 与 Service 名称对应

可以通过人为地使index=service name,这样就可以方便地收集和查看每个 Service 的日志,实现按业务维度对日志进行隔离和检索。

仓库源码佐证:Manifest 与 EFK 方案的对比

仓库中的测试 Manifest

本仓库在 manifests/test/filebeat-test.yaml 中保留了完整的测试文件(共 64 行,包含 Deployment、Service、ConfigMap 三个资源对象)。与文中示例相比,仓库版本将index配置为filebeat-test,Service 的 selector 为k8s-app: filebeat-test,其他结构与示例一致。此外,在 develop/client-go-sample.md 中还可以看到该filebeat-testDeployment 的实际滚动更新演练:当镜像从analytics-docker-test:Build_9回退到Build_8时,ReplicaSet 经历了一次缩容/扩容过程,验证了"应用镜像 + Filebeat Sidecar"组合在发布流程中的可操作性。

与官方 EFK 方案的对比:fluentd-es-ds.yaml

官方 EFK 方案使用 DaemonSet 在每个 Node 上运行一个 Fluentd 收集宿主机日志,见 manifests/EFK/fluentd-es-ds.yaml:

spec: serviceAccountName: efk containers: - name: fluentd-es image: harbor-001.jimmysong.io/library/fluentd-elasticsearch:1.22 resources: limits: memory: 200Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers

从该 Manifest 可以看出两种方案的差异:

  • 部署形态:EFK 方案每个 Node 只运行一个 Fluentd(DaemonSet),依赖hostPath挂载宿主机/var/log/var/lib/docker/containers,只能采集 stdout 前台输出且统一路径的日志;而 Filebeat Sidecar 方案与业务容器同生命周期,天然支持多日志文件、多目录(paths列表)与自定义采集规则;
  • 资源占用:EFK 方案中单个 Fluentd Pod 的 requests 内存即为 200Mi,而 Filebeat 单独启动仅约 12M 内存,按 Pod 数量部署时的资源开销优势明显;
  • 配置灵活度:Filebeat 通过 ConfigMap 注入filebeat.yml,采集路径、输出地址、索引名称均可按应用个性化配置,适合业务日志形态多样的场景。

完整的 EFK 插件安装过程(含 Elasticsearch/Kibana 部署、Node 打标签beta.kubernetes.io/fluentd-ds-ready=true、RBAC 配置与 Kibana 访问方式)参见 practice/efk-addon-installation.md。

延伸:Pod 销毁时日志丢失问题的规避思路

Filebeat Sidecar 方案存在一个边界场景:当 Pod 被销毁时,如果 Filebeat 尚未收集完 Pod 内的日志,会产生数据丢失。本仓库的 practice/data-persistence-problem.md 针对该问题给出了解决思路:将应用日志持久化挂载到宿主机,再由宿主机上的日志收集组件(Logstash 或 Filebeat)采集,从而保证数据不丢失。这说明在实际生产环境中,可以组合使用两种方案:

  • 对实时性要求高、日志量小的应用,采用本文的 Filebeat Sidecar 方案(方案二);
  • 对日志需要持久化、不能容忍丢失的应用,采用宿主机挂载 + 独立收集 Pod 的方案(方案三)。

总结

本文从资源开销对比出发,梳理了 Kubernetes 日志收集的三种架构模式,并给出了基于"自有 ELK + Filebeat Sidecar"方案的完整落地过程:通过共享卷(emptyDir)打通业务容器与 Filebeat 的日志通道,通过 ConfigMap 灵活配置采集路径与 Elasticsearch 输出,并通过index = service name的命名约定实现按 Service 维度的日志检索。结合仓库中的 manifests/test/filebeat-test.yaml 与 manifests/EFK/fluentd-es-ds.yaml 对比,可以清晰理解 Sidecar 模式与官方 EFK DaemonSet 模式各自的适用场景,为生产环境日志收集方案选型提供直接参考。

  • 教程
  • 云原生
  • 容器编排

【免费下载链接】kubernetes-handbook

Kubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南

项目地址:https://gitcode.com/gh_mirrors/ku/kubernetes-handbook
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询