在K8S中,如何使用EFK实现日志的统一管理?
在 Kubernetes 中使用 EFK 栈(Elasticsearch + Fluentd/Fluent Bit + Kibana) 实现日志统一管理,是业界标准的集中式日志解决方案。它通过高效收集、存储、分析和可视化容器日志,满足企业级需求。以下是详细实现步骤和关键配置:
核心架构与组件作用
graph LR
A[Kubernetes Pods] -->|stdout/stderr| B((Node))
B -->|Log Files| C[Fluent Bit DaemonSet]
C -->|聚合/过滤日志| D[Kafka/缓冲队列 可选]
D --> E[Fluentd Aggregator 可选]
C --> F[Elasticsearch]
E --> F
F --> G[Kibana]
G --> H[DevOps/SRE]
-
Fluent Bit (轻量级日志收集器 - 推荐)
- 部署方式:
DaemonSet
(每个节点运行一个 Pod) - 作用:
- 读取节点上所有容器的
stdout/stderr
日志(默认路径/var/log/containers/*.log
) - 采集节点系统日志(如
/var/log/syslog
) - 通过 Tail Input Plugin 跟踪日志文件变化
- 解析、过滤、丰富日志(如添加 Kubernetes 元数据:Pod 名称、Namespace、标签等)
- 将处理后的日志 高效转发 到 Elasticsearch 或 Fluentd 聚合层
- 读取节点上所有容器的
- 部署方式:
-
Elasticsearch (分布式搜索与存储引擎)
- 部署方式:
StatefulSet
(有状态应用,需持久化存储) - 作用:
- 接收并索引来自 Fluent Bit/Fluentd 的日志数据
- 提供分布式、高可用的日志存储
- 支持 PB 级数据检索与分析
- 部署方式:
-
Kibana (日志分析与可视化平台)
- 部署方式:
Deployment
- 作用:
- 通过 Web UI 查询、分析 Elasticsearch 中的日志
- 创建仪表盘(如错误日志统计、请求延迟分析)
- 设置告警规则(如 ERROR 日志突增)
- 部署方式:
详细部署步骤
步骤 1: 部署 Elasticsearch
# elasticsearch-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: elasticsearch
namespace: logging # 建议使用独立命名空间
spec:
serviceName: elasticsearch
replicas: 3 # 至少3节点保证高可用
selector:
matchLabels:
app: elasticsearch
template:
metadata:
labels:
app: elasticsearch
spec:
containers:
- name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:8.9.0
env:
- name: node.name
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: cluster.name
value: k8s-logs
- name: discovery.seed_hosts
value: "elasticsearch-0.elasticsearch,elasticsearch-1.elasticsearch,elasticsearch-2.elasticsearch"
- name: ES_JAVA_OPTS
value: "-Xms2g -Xmx2g" # 根据节点内存调整
- name: ELASTIC_PASSWORD # 设置密码(生产环境必须)
value: "your-strong-password"
ports:
- containerPort: 9200
name: http
- containerPort: 9300
name: transport
volumeMounts:
- name: data
mountPath: /usr/share/elasticsearch/data
volumes:
- name: data
persistentVolumeClaim:
claimName: es-data # 需要提前创建 PVC
---
# Service(Headless 用于节点发现)
apiVersion: v1
kind: Service
metadata:
name: elasticsearch
namespace: logging
spec:
clusterIP: None # Headless Service
ports:
- port: 9200
name: http
- port: 9300
name: transport
selector:
app: elasticsearch
步骤 2: 部署 Fluent Bit (DaemonSet)
# fluent-bit-config.yaml (ConfigMap)
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
namespace: logging
data:
fluent-bit.conf: |
[SERVICE]
Flush 5
Log_Level info
Daemon off
Parsers_File parsers.conf
[INPUT]
Name tail
Path /var/log/containers/*.log
Parser docker
Tag kube.*
Refresh_Interval 5
Mem_Buf_Limit 50MB # 内存缓冲区限制
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Kube_Tag_Prefix kube.var.log.containers.
Merge_Log On
Keep_Log Off
[OUTPUT]
Name es
Match *
Host elasticsearch.logging.svc # ES 服务地址
Port 9200
Logstash_Format On
Logstash_Prefix fluent-bit
HTTP_User elastic # ES 用户名
HTTP_Passwd your-strong-password
tls On
tls.verify Off # 测试环境可关闭验证,生产需配置 CA
---
# fluent-bit-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluent-bit
namespace: logging
spec:
selector:
matchLabels:
app: fluent-bit
template:
metadata:
labels:
app: fluent-bit
spec:
serviceAccountName: fluent-bit # 需创建有权限的 SA
containers:
- name: fluent-bit
image: fluent/fluent-bit:2.1.8
volumeMounts:
- name: config
mountPath: /fluent-bit/etc/
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: config
configMap:
name: fluent-bit-config
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
关键配置说明:
- Kubernetes Filter: 自动添加 Pod 元数据(名称、命名空间、标签等)。
- Logstash Format: 自动按日生成索引(如
fluent-bit-2023.10.01
)。- RBAC: 需创建 ServiceAccount 并绑定
get/list/watch
Pod 和 Namespace 的权限。
步骤 3: 部署 Kibana
# kibana-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kibana
namespace: logging
spec:
replicas: 1
selector:
matchLabels:
app: kibana
template:
metadata:
labels:
app: kibana
spec:
containers:
- name: kibana
image: docker.elastic.co/kibana/kibana:8.9.0
env:
- name: ELASTICSEARCH_HOSTS
value: "http://elasticsearch:9200"
- name: ELASTICSEARCH_USERNAME
value: "elastic"
- name: ELASTICSEARCH_PASSWORD
value: "your-strong-password"
ports:
- containerPort: 5601
---
# kibana-service.yaml
apiVersion: v1
kind: Service
metadata:
name: kibana
namespace: logging
spec:
type: NodePort # 或 LoadBalancer/Ingress 暴露
ports:
- port: 5601
targetPort: 5601
selector:
app: kibana
高级优化与生产实践
-
日志缓冲与可靠性
- 问题: ES 故障时日志丢失风险
- 方案: 引入 Kafka 作为缓冲队列graph LR A[Fluent Bit] --> B[Kafka] B --> C[Fluentd] C --> D[Elasticsearch]
- Fluent Bit 配置输出到 Kafka,由 Fluentd 消费后写入 ES。
-
日志过滤与裁剪
- 使用 Fluent Bit 过滤器:
[FILTER] Name grep Match * Exclude log /healthcheck|ping/
- 丢弃无关日志(如健康检查),减少 ES 负载。
- 使用 Fluent Bit 过滤器:
-
多租户与索引策略
- 按命名空间分离索引:
[OUTPUT] Name es Match * Index fluent-bit-${kubernetes['namespace_name']}
- 便于按团队管理日志和设置权限。
- 按命名空间分离索引:
-
Elasticsearch 优化
- 冷热架构:
- 热节点(SSD):存放近期日志(高性能)
- 温节点(HDD):存放历史日志(低成本)
- 索引生命周期管理 (ILM):
PUT _ilm/policy/logs-policy { "policy": { "phases": { "hot": { "min_age": "0ms", "actions": {"rollover": {"max_size": "50gb"}} }, "delete": { "min_age": "30d", "actions": {"delete": {}} } } } }
- 自动滚动删除旧索引,控制存储成本。
- 冷热架构:
-
安全性增强
- TLS 加密: Fluent Bit 到 ES 的 HTTPS 通信。
- RBAC: Kibana 中按角色限制日志访问权限。
- 网络策略: 限制 Fluent Bit 仅可访问 ES 的 9200 端口。
-
性能调优参数
[SERVICE] Flush 5 # 刷新间隔(秒) HTTP_Server On # 开启监控端点 storage.path /var/log/flb-storage/ # 磁盘缓冲 storage.sync normal storage.checksum off storage.backlog.mem_limit 50M
验证与使用
-
检查日志采集:
kubectl logs -n logging fluent-bit-xxxxx # 查看 Fluent Bit 是否正常发送日志到 ES
-
访问 Kibana:
- 通过
kubectl port-forward svc/kibana -n logging 5601:5601
临时访问 - 或配置 Ingress 暴露服务
- 在 Kibana 中创建 Index Pattern(如
fluent-bit-*
)
- 通过
-
查询示例:
// 查找 nginx 命名空间的 ERROR 日志 { "query": { "bool": { "must": [ {"match": {"kubernetes.namespace_name": "nginx"}}, {"match": {"log": "ERROR"}} ] } } }
常见问题排查
- 日志未采集: 检查 Fluent Bit 的
Path
配置是否匹配容器日志路径(如 Docker/Containerd 差异)。 - ES 连接失败: 检查网络策略、ES 认证信息和证书。
- 元数据缺失: 确认 Fluent Bit 的 Kubernetes Filter 配置正确且 RBAC 权限足够。
- 性能瓶颈: 监控 Fluent Bit 内存/CPU 使用率,调整
Mem_Buf_Limit
和 Flush 间隔。
通过以上步骤,EFK 栈可为 Kubernetes 提供高可靠、可扩展的日志管理能力,满足从开发测试到大规模生产环境的需求。