使用 Helm Chart 在 Kubernetes 上部署 ELK 日志栈:elastic-stack 聚合 Chart 实战指南
使用 Helm Chart 在 Kubernetes 上部署 ELK 日志栈:elastic-stack 聚合 Chart 实战指南
本指南围绕 charts 仓库中 elastic-stack Helm Chart 展开,系统讲解如何通过一个聚合 Chart 在 Kubernetes 上一次性部署 Elasticsearch 集群、Kibana 与 Logstash(ELK),以及如何按需启用或替换 Fluentd、Filebeat、Elasticsearch Curator、Nginx LDAP 认证代理等周边组件。读完本文,你将掌握该 Chart 的安装、卸载、数据清理、组件开关与关键参数配置方法,并理解其底层基于 StatefulSet 的多角色集群设计与条件依赖机制。
一、Chart 定位与版本背景
elastic-stack 是一个典型的 Helm 聚合 Chart(umbrella chart),它本身不直接渲染业务工作负载,而是通过 requirements.yaml 声明依赖,把 elasticsearch、kibana、logstash 等多个子 Chart 组合为开箱即用的完整日志分析平台。原文档位于 incubator/elastic-stack/README.md,其 Chart.yaml 记录了版本 0.11.2、appVersion: 6.0,并明确标注 deprecated: true——该 Chart 已被提升并迁移至 stable/elastic-stack。
需要注意的是,该 Chart 对应 Elastic Stack 6.x 时代的设计;仓库整体已于 2020 年 11 月起归档不再更新,因此本指南中的命令、版本与镜像配置以当前仓库实际内容为准,适用于在旧版本 Kubernetes 环境中复现与学习,而非面向最新版 Elastic Stack 的生产选型。
二、前置条件
依据原文档与 stable 版本的 README,部署前需要满足:
- Kubernetes 1.8+(incubator 版本),stable 版本进一步要求 Kubernetes 1.10+;
- 底层基础设施支持 PV 动态供给(dynamic provisioning),因为数据节点依赖 PersistentVolumeClaim 保存索引数据;
- 已安装 Helm(本文命令基于 Helm 2 时代的
helm install --name语法)。
三、Chart 核心能力
Chart 默认安装 Elasticsearch 集群 + Kibana + Logstash,并可选的组件包括 Filebeat、Fluentd、Fluent Bit、Fluentd-elasticsearch、nginx-ldapauth-proxy、elasticsearch-curator 与 elasticsearch-exporter。其核心能力可归纳为三点:
- 基于 Kubernetes StatefulSet/Deployment 实现动态可伸缩的 Elasticsearch 集群;
- 多角色部署:将节点划分为 master(主节点)、client(协调/客户端节点)与 data(数据节点)三类角色;
- StatefulSet 支持无损缩容:缩减副本数时不会破坏集群整体可用性。
从 stable 版本 elasticsearch 子 Chart 的 values.yaml 可以看到角色划分在配置层的落地:client 角色默认 replicas: 2、serviceType: ClusterIP,data 与 master 角色同样各自管理副本数与资源,整体由子 Chart 分别渲染为 StatefulSet 与配套 Service。
四、安装 Chart
按原文档指引,安装 release 名为 my-release 的实例:
$ helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
$ helm install --name my-release incubator/elastic-stack
若使用已迁移到 stable 的版本,则执行:
$ helm install --name my-release stable/elastic-stack
安装完成后,Chart 的 NOTES.txt 会输出访问指引。默认情况下 Kibana 使用 ClusterIP 服务,可通过端口转发访问:
export POD_NAME=$(kubectl get pods --namespace <namespace> -l "app=kibana,release=my-release" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:5601 to use Kibana"
kubectl port-forward --namespace <namespace> $POD_NAME 5601:5601
如果 Kibana 服务类型改为 NodePort,则用如下命令获取对外地址:
export NODE_PORT=$(kubectl get --namespace <namespace> -o jsonpath="{.spec.ports[0].nodePort}" services <kibana-svc-name>)
export NODE_IP=$(kubectl get nodes --namespace <namespace> -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
需要特别警惕的是:若将 Kibana/Elasticsearch 服务直接暴露为 LoadBalancer,NOTES.txt 会给出明确警告——Elasticsearch 默认不对公网暴露的集群提供任何安全防护,最低限度的安全做法是改用 ClusterIP/NodePort,并在集群前置 Nginx 网关以锁死危险的 HTTP 端点与动词(详见 NOTES.txt 中 LoadBalancer 分支)。同时 LoadBalancer 类型下服务 IP 需要几分钟就绪,可通过 kubectl get svc -w 观察状态。
五、卸载与数据清理
卸载 Helm release 与常规操作一致:
$ helm delete my-release
但需要明确一个关键事实:删除 StatefulSet 并不会级联删除关联的 PVC。残留的 PVC 及其底层 PV 数据仍会占用存储资源,需手动按标签清理:
$ kubectl delete pvc -l release=my-release,component=data
该命令通过 component=data 标签精确定位数据节点的 PVC,避免误删。若你的 data 节点使用自定义标签,请相应调整 selector。这正是日志平台这类有状态工作负载在 Kubernetes 上的典型运维要点:应用删除与数据删除必须分开处理。
六、组件开关与条件依赖机制
elastic-stack 之所以能做到"按需组装",依赖 Helm 的条件依赖(condition)特性。查看 incubator/elastic-stack/requirements.yaml,每个可选子 Chart 都绑定了对应的 condition:
| 依赖 Chart | 版本约束 | 默认开关(condition) |
|---|---|---|
| elasticsearch | ^1.10.0 | 始终安装 |
| kibana | ^0.16.0 | 始终安装 |
| filebeat | ^1.0.0 | filebeat.enabled |
| logstash | ^1.1.0 | logstash.enabled |
| fluentd | ^1.0.0 | fluentd.enabled |
| fluent-bit | ^0.13.0 | fluent-bit.enabled |
| fluentd-elasticsearch | ^1.0.0 | fluentd-elasticsearch.enabled |
| nginx-ldapauth-proxy | ^0.1.0 | nginx-ldapauth-proxy.enabled |
| elasticsearch-curator | ^1.0.0 | elasticsearch-curator.enabled |
| elasticsearch-exporter | ^0.4.0 | elasticsearch-exporter.enabled |
条件依赖机制意味着:只需在 values 中把对应组件的 enabled 置为 true/false,Helm 就会在解析依赖时决定是否渲染该子 Chart。stable 版本的 values.yaml 展示了默认组合:elasticsearch、kibana、logstash 三个组件 enabled: true 默认启用,其余组件(filebeat、fluentd、fluent-bit、fluentd-elasticsearch、nginx-ldapauth-proxy、elasticsearch-curator、elasticsearch-exporter)默认关闭。因此"默认安装 Elasticsearch + Kibana + Logstash"的说法,正是这些默认值在依赖解析层的直接体现;如果你偏好 Fluentd 替代 Logstash,只需设置 logstash.enabled: false 与 fluentd.enabled: true。
stable 版本的依赖锁定关系记录在 requirements.lock,其中锁定了各子 Chart 的具体版本:elasticsearch 1.32.5、kibana 3.2.8、logstash 2.4.1、fluentd 2.5.1、fluent-bit 2.10.1、filebeat 3.1.1、nginx-ldapauth-proxy 0.1.4、elasticsearch-curator 2.2.1、elasticsearch-exporter 2.3.0,可据此确认各子 Chart 的可复现版本组合。
七、关键参数配置详解
聚合 Chart 的配置原则是:每个子 Chart 使用该 Chart 自身定义的配置项,统一收敛在 elastic-stack 的 values 层级下。以下结合 stable/elastic-stack/values.yaml 逐组件说明。
7.1 Kibana 连接 Elasticsearch
Kibana 默认通过环境变量注入 ES 地址,关键配置位于 values.yaml 第 9-10 行:
kibana:
enabled: true
env:
ELASTICSEARCH_HOSTS: http://{{ .Release.Name }}-elasticsearch-client:9200
ELASTICSEARCH_HOSTS 使用了模板插值,自动生成 <release名>-elasticsearch-client:9200 这样的服务地址,指向 ES 的 client(协调)角色 Service。这一约定与子 Chart 中 kibana 的 env 配置风格 一致——Kibana 的所有配置项都可经环境变量调整,规则是把配置键大写并把 . 替换为 _(例如 server.port → SERVER_PORT)。注意 6.6 版本以下的 Kibana 应改用 ELASTICSEARCH_URL。
7.2 Logstash 输出到 Elasticsearch
logstash:
enabled: true
# elasticsearch:
# host: elastic-stack-elasticsearch-client
默认启用的 Logstash 可直接通过子 Chart 的 elasticsearch.host 指向 client 服务;由于集群内部各组件通过 Kubernetes 服务发现互通,通常无需额外配置即可将日志写入 ES。
7.3 Filebeat 采集与输出
Filebeat 默认关闭,启用后可把采集到的日志输出到 Logstash 或直接写入 ES:
filebeat:
enabled: false
# config:
# output.file.enabled: false
# output.logstash:
# hosts: ["elastic-stack-logstash:5044"]
# indexTemplateLoad:
# - elastic-stack-elasticsearch-client:9200
配置要点:output.logstash.hosts 指向 Logstash 的 5044 端口服务;indexTemplateLoad 用于在启动时向 ES client 服务加载索引模板,保证索引映射与分片设置符合预期。
7.4 用 Nginx LDAP 代理保护 Kibana
当需要为 Kibana 增加认证时,可启用 nginx-ldapauth-proxy 并按其示例配置(values.yaml 第 35-61 行):
nginx-ldapauth-proxy:
enabled: false
proxy:
port: 5601
host: "elk-kibana.default.svc.cluster.local" # Kibana 服务内部主机名
authName: "ELK:Infrastructure:LDAP"
ldapHost: "ldap.example.com"
ldapDN: "dc=example,dc=com"
ldapFilter: "objectClass=organizationalPerson"
ldapBindDN: "cn=reader,dc=example,dc=com"
requires:
- name: "ELK-USER"
filter: "cn=elkuser,ou=groups,dc=example,dc=com"
ingress:
enabled: true
hosts:
- "elk.example.com"
annotations:
kubernetes.io/ingress.class: nginx
tls:
- hosts:
- elk.example.com
secretName: example-elk-tls
secrets:
ldapBindPassword: PASSWORD
这套配置把 LDAP 认证代理放在 Kibana(5601 端口)之前,配合 Ingress 与 TLS 证书实现对外安全访问,正好补足了 7.1 小节中 NOTES.txt 提到的"集群前置网关锁死访问"的安全建议。
7.5 Curator 与指标导出
- elasticsearch-curator(默认关闭):用于定期执行索引生命周期管理,如按时间清理过期索引,防止日志索引无限增长耗尽存储;
- elasticsearch-exporter(默认关闭):将 Elasticsearch 集群指标以 Prometheus 格式暴露,便于接入监控告警体系。
两者都通过各自子 Chart 的配置项(如调度周期、索引保留策略)进行定制。
八、资源命名与模板机制
聚合 Chart 自身的模板非常精简,仅包含 NOTES.txt 与 _helpers.tpl。其中 _helpers.tpl 定义了通用的资源命名规则,值得关注:
elastic-stack.name:默认取 Chart 名,可通过nameOverride覆盖;elastic-stack.fullname:优先使用fullnameOverride;否则若 release 名已包含 Chart 名则直接使用 release 名,否则拼接为<release>-<chart名>,并统一截断至 63 字符(DNS 命名规范上限)后去除尾部-;elastic-stack.chart:生成<chart名>-<版本>格式,用于资源标签。
这套命名约定决定了上文中 my-release-elasticsearch-client、<release>-kibana 等服务名的推导逻辑,也是你在编写外部集成(如其他工作负载访问 ES 服务)时需要遵循的寻址规则。
九、运维注意事项与限制
综合原文档、Chart 源码与仓库归档状态,梳理以下几点运维要点:
- 有状态数据必须显式清理:
helm delete只删除 Kubernetes 对象,PVC/PV 及其中的数据需要按component=data标签手动清理(见第五节); - 缩容安全:Chart 宣称 StatefulSet 支持无损缩容,但 ES 集群的稳定性仍依赖
discovery.zen.minimum_master_nodes等关键参数——子 Chart 默认将其设置为2(见 elasticsearch values.yaml 第 77 行),生产环境缩容前应核实 master 节点数与最小 master 节点配置的匹配关系,避免脑裂或数据丢失; - 安全边界:Elastic Stack 6.x 默认镜像不含 X-Pack 安全特性,公网暴露前必须前置认证网关(如本 Chart 集成的 nginx-ldapauth-proxy)或开启镜像自带的 xpack(见 elasticsearch values 中
cluster.xpackEnable配置); - 版本前提:stable 版要求 Kubernetes 1.10+,且仓库自 2020 年 11 月起归档,命令与镜像版本(如 Elasticsearch OSS 6.8.6)已固定,不再适配新版 Elastic Stack;
- 配置入口统一:所有子 Chart 参数都通过
elastic-stack的 values 层级下发,实际覆盖各子 Chart 的默认值,具体参数应查阅对应子 Chart 的文档(如 stable/elasticsearch、stable/kibana)。
十、小结
elastic-stack 是一个以"组合而非重复发明"为设计理念的 ELK 聚合 Chart:一条 helm install 命令即可拉起 Elasticsearch 多角色集群、Kibana 可视化与 Logstash 管道,并通过 Helm 条件依赖机制灵活替换采集/代理组件。本文从安装、访问、卸载到逐组件配置,完整覆盖了原文档的全部操作路径,并结合仓库内的 values、requirements 与 NOTES 模板,补充了依赖开关机制、命名规则、安全边界等源码级细节。对于希望理解 Helm 聚合 Chart 设计模式,或在旧版本 Kubernetes 上复现经典 ELK 部署的读者,本仓库的 stable/elastic-stack 是一份可直接对照阅读的完整参考实现。