- 教程
- 云原生
- 容器编排
【免费下载链接】kubernetes-handbook
Kubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南
在 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 内同时运行
filebeat和app两个容器,通过共享的app-logs(emptyDir: {})卷实现日志传递: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.hostname和beat.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 原生基础设施的构建指南
相关推荐
Aptos 集群日志收集实战:基于 Helm 与 Vector DaemonSet 的 Kubernetes 日志管道搭建指南
Aptos 集群日志收集实战:基于 Helm 与 Vector DaemonSet 的 Kubernetes 日志管道搭建指南 导读 本文面向在 Kuberne
区块链Web3Collabnix Kubelabs 项目:Filebeat 作为 Sidecar 容器的日志收集方案
Collabnix Kubelabs 项目:Filebeat 作为 Sidecar 容器的日志收集方案 引言:Kubernetes 日志收集的挑战与机遇 在现代
示例工程教程文档如何快速使用linefit_ground_segmentation:从零开始的激光雷达地面分割完整教程
如何快速使用linefit_ground_segmentation:从零开始的激光雷达地面分割完整教程 linefit_ground_segmentation是
自动驾驶计算机视觉
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考