4. Helm 部署日志平台:使用 Helm 部署 Elasticsearch、Fluentd、Kibana(EFK)到 Kubernetes 集群

本章将带领你使用 Helm 在 Kubernetes 集群中一键部署完整的 EFK 日志栈。EFK 是 Elasticsearch、Fluentd、Kibana 的缩写,是目前云原生环境下最主流的日志采集、存储与可视化方案。通过 Helm Chart 的标准化封装,我们可以将原本复杂的组件依赖、配置注入、资源声明统一管理,实现可重复、可版本化的日志平台交付。

4.1 EFK 架构与组件职责

在开始部署之前,需要明确 EFK 三个核心组件的分工与数据流向。下图展示了 EFK 在 Kubernetes 集群中的典型部署架构:

EFK 日志平台 Helm 部署架构 Fluentd DaemonSet 日志采集 & 解析 tail / filter / parser Elasticsearch StatefulSet 日志存储 & 索引 分片 / 副本 / 检索 Kibana Deployment 可视化 & 分析 Dashboard / Discover HTTP / 9200 REST API Kubernetes 集群基础设施 Helm Release ConfigMap / Secret PVC / StorageClass Service / Ingress Helm Chart 统一管理所有 Kubernetes 资源定义与依赖关系
架构要点:Fluentd 以 DaemonSet 模式运行在每个 Node 上,采集容器标准输出和日志文件;Elasticsearch 以 StatefulSet 部署保证数据持久化与有序扩缩容;Kibana 作为无状态前端 Deployment 对外提供 Web 界面。Helm Chart 将这三者的 Service、ConfigMap、PVC 等附属资源统一打包。

4.2 选择 Helm Chart 与版本约束

社区维护的 EFK Helm Chart 主要有两个来源:Elastic 官方 Helm Charts 和 Bitnami 仓库。生产环境推荐使用 Elastic 官方 Chart,版本兼容性更可靠。下表对比了核心组件的版本选型建议:

组件 推荐 Chart 名称 推荐版本 Kubernetes 最低版本 说明
Elasticsearch elastic/elasticsearch 8.5.x 1.21+ 支持安全认证、TLS 默认开启
Fluentd fluent/fluentd 0.5.x 1.19+ 需配置 Elasticsearch 输出插件
Kibana elastic/kibana 8.5.x 1.21+ 版本需与 ES 大版本一致
版本对齐警告:Elasticsearch 与 Kibana 的主版本号必须严格一致(例如 8.x 对 8.x),否则 Kibana 无法连接 ES。Fluentd 的 elasticsearch 插件版本也需要与 ES 版本兼容。建议在 values.yaml 中显式锁定 image tag。

4.3 部署 Elasticsearch

Elasticsearch 是 EFK 的存储核心,需要合理配置资源、存储和集群拓扑。以下是使用 Helm 部署 ES 的完整步骤。

4.3.1 添加 Helm 仓库并更新

# 添加 Elastic 官方 Helm 仓库
helm repo add elastic https://helm.elastic.co

# 添加 Fluentd 社区仓库
helm repo add fluent https://fluent.github.io/helm-charts

# 更新本地仓库索引
helm repo update

4.3.2 创建 Elasticsearch values 文件

创建一个 es-values.yaml 文件,覆盖默认配置以适应生产环境需求:

# es-values.yaml
clusterName: "efk-logging"
nodeGroup: "data"
replicas: 3

resources:
  requests:
    cpu: "1"
    memory: "2Gi"
  limits:
    cpu: "2"
    memory: "4Gi"

volumeClaimTemplate:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 50Gi
  storageClassName: "gp2"  # 根据集群存储类调整

esConfig:
  elasticsearch.yml: |
    xpack.security.enabled: true
    xpack.security.transport.ssl.enabled: true
    xpack.security.http.ssl.enabled: true

extraEnvs:
  - name: ELASTIC_PASSWORD
    valueFrom:
      secretKeyRef:
        name: elasticsearch-master-credentials
        key: password

4.3.3 执行 Helm 安装

# 创建命名空间
kubectl create namespace logging

# 部署 Elasticsearch
helm install elasticsearch elastic/elasticsearch \
  --namespace logging \
  --values es-values.yaml \
  --version 8.5.1
部署验证:使用 kubectl get pods -n logging -w 观察 Pod 启动状态。Elasticsearch StatefulSet 会按顺序启动,每个 Pod 就绪后才会启动下一个。全部就绪后,使用 kubectl exec -it elasticsearch-master-0 -n logging -- curl -u elastic:${PASSWORD} https://localhost:9200 测试集群健康状态。

4.4 部署 Fluentd

Fluentd 负责从每个节点采集容器日志,解析后发送到 Elasticsearch。我们需要配置日志源路径、解析规则和输出目标。

4.4.1 创建 Fluentd values 文件

# fluentd-values.yaml
image:
  repository: fluent/fluentd-kubernetes-daemonset
  tag: "v1.16-debian-elasticsearch8-1"

configMaps:
  fluentd.conf: |
    <source>
      @type tail
      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>

    <filter kubernetes.**>
      @type kubernetes_metadata
      @id filter_kube_metadata
    </filter>

    <match kubernetes.**>
      @type elasticsearch
      host elasticsearch-master.logging.svc.cluster.local
      port 9200
      scheme https
      ssl_verify false
      user "#{ENV['ES_USER']}"
      password "#{ENV['ES_PASSWORD']}"
      logstash_format true
      logstash_prefix kubernetes-logs
      <buffer>
        @type file
        path /var/log/fluentd-buffers/kubernetes.system.buffer
        flush_mode interval
        retry_type exponential_backoff
        flush_interval 5s
      </buffer>
    </match>

env:
  - name: ES_USER
    value: "elastic"
  - name: ES_PASSWORD
    valueFrom:
      secretKeyRef:
        name: elasticsearch-master-credentials
        key: password

resources:
  requests:
    cpu: 500m
    memory: 512Mi
  limits:
    cpu: 1
    memory: 1Gi

4.4.2 部署 Fluentd

helm install fluentd fluent/fluentd \
  --namespace logging \
  --values fluentd-values.yaml \
  --version 0.5.2
日志采集路径说明:Fluentd 默认采集 /var/log/containers/*.log,这是 kubelet 将容器标准输出重定向到节点的默认路径。如果你的集群使用不同的容器运行时(如 containerd),路径可能为 /var/log/pods/*/*/*.log,需要在 source 配置中调整。

4.5 部署 Kibana

Kibana 提供日志查询和可视化的 Web 界面。部署时需要配置 Elasticsearch 连接信息。

4.5.1 创建 Kibana values 文件

# kibana-values.yaml
imageTag: "8.5.1"

resources:
  requests:
    cpu: "500m"
    memory: "1Gi"
  limits:
    cpu: "1"
    memory: "2Gi"

kibanaConfig:
  kibana.yml: |
    server.name: kibana
    server.host: "0.0.0.0"
    elasticsearch.hosts: ["https://elasticsearch-master.logging.svc.cluster.local:9200"]
    elasticsearch.username: elastic
    elasticsearch.password: ${ELASTIC_PASSWORD}
    elasticsearch.ssl.verificationMode: none

extraEnvs:
  - name: ELASTIC_PASSWORD
    valueFrom:
      secretKeyRef:
        name: elasticsearch-master-credentials
        key: password

service:
  type: ClusterIP
  port: 5601

ingress:
  enabled: true
  className: "nginx"
  hosts:
    - host: kibana.logging.example.com
      paths:
        - path: /
          pathType: Prefix

4.5.2 部署 Kibana

helm install kibana elastic/kibana \
  --namespace logging \
  --values kibana-values.yaml \
  --version 8.5.1

4.6 验证 EFK 整体连通性

部署完成后,需要从数据采集、存储到可视化的全链路验证。下表列出了关键验证点:

验证步骤 命令 / 操作 预期结果
检查所有 Pod 状态 kubectl get pods -n logging 所有 Pod 处于 Running 状态,READY 列为 1/1
验证 ES 集群健康 kubectl exec -it elasticsearch-master-0 -n logging -- curl -u elastic:${PASS} -k https://localhost:9200/_cluster/health 返回 status: "green" 或 "yellow"
检查 Fluentd 日志输出 kubectl logs -n logging -l app.kubernetes.io/name=fluentd --tail=20 无连接 ES 报错,显示成功发送日志的日志行
验证 ES 索引创建 curl -u elastic:${PASS} -k https://localhost:9200/_cat/indices 存在以 kubernetes-logs- 开头的索引
Kibana 访问 浏览器打开 https://kibana.logging.example.com Kibana 登录页面正常加载,使用 elastic 用户登录
创建索引模式 Kibana → Stack Management → Index Patterns → 创建 kubernetes-logs-* Discover 页面显示采集到的容器日志
根因定位前置准备:验证通过后,建议在 Kibana 中创建几个常用的 Dashboard(如 Pod 日志量趋势、错误日志分布、特定 Namespace 日志聚合),为后续根因定位章节的实战操作打好数据可视化基础。

4.7 常见部署问题与排错

Helm 部署 EFK 过程中可能遇到以下典型问题,提前了解有助于快速定位:

  • Elasticsearch Pod 启动失败(CrashLoopBackOff):检查 PVC 是否绑定成功,kubectl describe pvc -n logging 查看 Events;确认 StorageClass 是否存在且可用;检查节点资源是否满足 requests 配置。
  • Fluentd 无法连接 Elasticsearch:确认 ES Service 名称和端口正确;检查 Secret 中的密码是否与 ES 初始化密码一致;如果 ES 启用了 TLS,Fluentd 配置中需要设置 scheme https 和 ssl_verify false。
  • Kibana 页面 503 错误:Kibana 启动时需等待 ES 完全就绪;检查 Kibana 日志 kubectl logs -n logging deployment/kibana-kibana 查看具体连接错误;确认 elasticsearch.hosts 配置的 URL 协议和端口正确。
  • 日志索引未创建:Fluentd 的 logstash_prefix 配置决定了索引名称;检查 Fluentd 日志中是否有 400 或 403 响应码,可能是 ES 安全认证配置问题。
安全注意事项:Elasticsearch 8.x 默认启用了安全功能,首次启动时会自动生成 elastic 用户的密码。使用 kubectl get secret elasticsearch-master-credentials -n logging -o jsonpath="{.data.password}" | base64 -d 获取密码。生产环境中建议使用 Vault 或 External Secrets Operator 管理凭证,避免明文存储在 values 文件中。