背景
在 Kubernetes 集群环境中,Pod 日志分散存储在各个节点上,传统方式需要登录到对应节点查看,效率低下且难以进行全局搜索和分析。本文介绍一种基于 Fluentd + Elasticsearch 的日志集中采集方案,实现日志的统一存储、检索和可视化展示。
方案架构
1
| Pod(stdout/stderr) → kubelet → 节点日志文件 → Fluentd DaemonSet → Elasticsearch → Kibana/Grafana
|
核心组件说明
- Fluentd DaemonSet:部署在每个节点上,以 DaemonSet 方式运行,负责采集节点级日志
- Elasticsearch:集中存储日志,提供全文检索能力
- Kibana/Grafana:可视化展示和查询界面
部署步骤
1. 部署 Elasticsearch 集群
推荐使用 operator 模式管理,以下为基础部署示例:
1 2 3 4 5 6 7 8 9 10 11 12
| apiVersion: elasticsearch.k8s.elastic.co/v1 kind: Elasticsearch metadata: name: es-cluster namespace: logging spec: version: 8.11.0 nodeSets: - name: default count: 3 config: node.store.allow_mmap: false
|
2. 部署 Fluentd DaemonSet
创建 fluentd 配置 ConfigMap:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| apiVersion: v1 kind: ConfigMap metadata: name: fluentd-config namespace: logging data: fluent.conf: | <source> @type tail @id input_container path /var/log/containers/*.log pos_file /var/log/fluentd-containers.log.pos tag kubernetes.* read_from_head true <parse> @type json time_format %Y-%m-%dT%H:%M:%S.%NZ </parse> </source> <source> @type tail @id input_docker path /var/log/docker.log pos_file /var/log/fluentd-docker.log.pos tag docker <parse> @type regexp expression /^(?<time>.{19})(?<stream>stdout|stderr)(?<log>.*)$/ time_format %Y-%m-%dT%H:%M:%S.%NZ </parse> </source> <filter kubernetes.**> @type kubernetes_metadata @id kubernetes_metadata </filter> <match **> @type elasticsearch @id output_elasticsearch host elasticsearch.logging.svc port 9200 logstash_format true logstash_prefix kubernetes flush_interval 10s </match>
|
3. 部署 Fluentd DaemonSet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd namespace: logging spec: selector: matchLabels: app: fluentd template: metadata: labels: app: fluentd spec: serviceAccountName: fluentd tolerations: - operator: Exists containers: - name: fluentd image: fluent/fluentd:v1.16-1 env: - name: FLUENTD_CONF value: fluent.conf resources: limits: memory: 512Mi cpu: 500m requests: memory: 256Mi cpu: 100m volumeMounts: - name: varlog mountPath: /var/log - name: varlogcontainers mountPath: /var/log/containers readOnly: true - name: fluentd-config mountPath: /etc/fluent/config.d volumes: - name: varlog hostPath: path: /var/log - name: varlogcontainers hostPath: path: /var/log/containers - name: fluentd-config configMap: name: fluentd-config
|
4. 创建 ServiceAccount 并授权
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| apiVersion: v1 kind: ServiceAccount metadata: name: fluentd namespace: logging --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: fluentd rules: - apiGroups: [""] resources: - pods - nodes verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: fluentd roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: fluentd subjects: - kind: ServiceAccount name: fluentd namespace: logging
|
验证与调试
检查 Fluentd 运行状态
1 2
| kubectl get pods -n logging -l app=fluentd kubectl logs -n logging -l app=fluentd --tail=100
|
检查 Elasticsearch 数据
1 2 3 4 5
| curl -s "http://elasticsearch.logging.svc:9200/_cat/indices?v"
curl -s "http://elasticsearch.logging.svc:9200/_cat/count/kubernetes-$(date +%Y.%m.%d)?v"
|
常见问题排查
日志未采集到:检查节点路径 /var/log/containers/ 是否存在,确认 Fluentd Pod 已调度到目标节点。
数据写入 Elasticsearch 失败:验证 Elasticsearch 服务可达性,检查 Fluentd 日志中的错误信息,可能是 ES 磁盘空间不足或认证问题。
字段解析异常:检查 JSON 格式是否标准,部分应用输出到 stdout 的格式可能不统一。
优化建议
- 日志级别控制:应用层合理设置日志级别,避免大量 DEBUG 日志占用存储
- 滚动策略:配置 Elasticsearch ILM 策略,默认 30 天后自动删除旧索引
- 资源限制:根据集群规模调整 Fluentd 的 CPU 和内存限制,防止资源抢占
- 敏感信息过滤:在 Fluentd 配置中添加脱敏 filter,过滤敏感字段
总结
通过 Fluentd DaemonSet 方案,可以实现 Kubernetes 集群日志的自动采集和集中存储。配合 Elasticsearch 和 Kibana,能够高效进行日志检索和可视化分析,显著提升故障排查和问题定位效率。建议在生产环境部署前,根据实际日志量评估 Elasticsearch 集群规模。