在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]
  1. Fluent Bit (轻量级日志收集器 - 推荐)

    • 部署方式: DaemonSet(每个节点运行一个 Pod)
    • 作用:
      • 读取节点上所有容器的 stdout/stderr 日志(默认路径 /var/log/containers/*.log
      • 采集节点系统日志(如 /var/log/syslog
      • 通过 Tail Input Plugin 跟踪日志文件变化
      • 解析、过滤、丰富日志(如添加 Kubernetes 元数据:Pod 名称、Namespace、标签等)
      • 将处理后的日志 高效转发 到 Elasticsearch 或 Fluentd 聚合层
  2. Elasticsearch (分布式搜索与存储引擎)

    • 部署方式: StatefulSet(有状态应用,需持久化存储)
    • 作用:
      • 接收并索引来自 Fluent Bit/Fluentd 的日志数据
      • 提供分布式、高可用的日志存储
      • 支持 PB 级数据检索与分析
  3. 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

高级优化与生产实践

  1. 日志缓冲与可靠性

    • 问题: ES 故障时日志丢失风险
    • 方案: 引入 Kafka 作为缓冲队列
      graph LR A[Fluent Bit] --> B[Kafka] B --> C[Fluentd] C --> D[Elasticsearch]
    • Fluent Bit 配置输出到 Kafka,由 Fluentd 消费后写入 ES。
  2. 日志过滤与裁剪

    • 使用 Fluent Bit 过滤器:
      [FILTER]
          Name    grep
          Match   *
          Exclude log /healthcheck|ping/
      
    • 丢弃无关日志(如健康检查),减少 ES 负载。
  3. 多租户与索引策略

    • 按命名空间分离索引:
      [OUTPUT]
          Name          es
          Match         *
          Index         fluent-bit-${kubernetes['namespace_name']}
      
    • 便于按团队管理日志和设置权限。
  4. 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": {}}
            }
          }
        }
      }
      
    • 自动滚动删除旧索引,控制存储成本。
  5. 安全性增强

    • TLS 加密: Fluent Bit 到 ES 的 HTTPS 通信。
    • RBAC: Kibana 中按角色限制日志访问权限。
    • 网络策略: 限制 Fluent Bit 仅可访问 ES 的 9200 端口。
  6. 性能调优参数

    [SERVICE]
        Flush           5         # 刷新间隔(秒)
        HTTP_Server     On        # 开启监控端点
        storage.path    /var/log/flb-storage/  # 磁盘缓冲
        storage.sync    normal
        storage.checksum off
        storage.backlog.mem_limit 50M
    

验证与使用

  1. 检查日志采集:

    kubectl logs -n logging fluent-bit-xxxxx
    # 查看 Fluent Bit 是否正常发送日志到 ES
    
  2. 访问 Kibana:

    • 通过 kubectl port-forward svc/kibana -n logging 5601:5601 临时访问
    • 或配置 Ingress 暴露服务
    • 在 Kibana 中创建 Index Pattern(如 fluent-bit-*
  3. 查询示例:

    // 查找 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 提供高可靠、可扩展的日志管理能力,满足从开发测试到大规模生产环境的需求。

posted @ 2025-08-15 13:36  天道酬勤zjh  阅读(21)  评论(0)    收藏  举报