第 11/15 天
引言
Elasticsearch(简称 ES)是当今最流行的分布式搜索与分析引擎,基于 Apache Lucene 构建,提供近实时的全文检索、结构化搜索、聚合分析能力。无论是日志聚合(ELK/EFK Stack)、应用搜索、安全分析,还是可观测性平台,Elasticsearch 都是底层数据存储与查询的核心。
在 Kubernetes 上部署 Elasticsearch 的难点在于:它对存储 I/O 和内存稳定性要求较高,节点发现依赖稳定的网络标识,且需要奇数节点保证 Master 选举正常。当我们将 ES 集群跑在 K8s 上、并通过 Ceph RBD 提供持久化存储时,便能获得数据可靠、Pod 可迁移、运维标准化的分布式搜索底座。
本篇是「Ceph+K8s 中间件实战」系列第 11 天,将完整讲解 Elasticsearch 集群在 K8s 上的架构设计、Bitnami Helm Chart 部署流程、Ceph RBD 持久化配置,以及登录验证与日常巡检命令。

设计架构
组件拓扑
Elasticsearch 集群在 K8s 上的部署架构涉及以下核心组件:
| 组件 | 说明 | 数量 |
|---|---|---|
| Master 节点 | 负责集群元数据管理、索引创建/删除、分片分配决策 | 3(奇数,专用 Master) |
| Data 节点 | 存储实际索引数据,执行 CRUD 与搜索/聚合查询 | 3(可按数据量横向扩展) |
| Coordinating 节点 | 接收客户端请求,做查询路由与结果归并(可选) | 1-2(高负载场景启用) |
| Headless Service | 为 StatefulSet 提供稳定 Pod DNS(es-master-0.es-headless) |
1 |
| ClusterIP Service | 客户端访问入口(9200 REST / 9300 Transport) | 1 |
| PVC(Ceph RBD) | 每个 Data 与 Master Pod 独立持久卷,存储索引数据与集群状态 | 6 |
| ConfigMap | 存放 elasticsearch.yml 配置、JVM 堆参数 |
1 |
数据流向
Elasticsearch 采用 分片(Shard)+ 副本(Replica) 机制实现数据分布与高可用,数据流向如下:
- 文档写入:客户端向任意 Coordinating 节点发送索引请求(POST /index/_doc)。
- 路由分片:Coordinating 节点根据
routing值(默认文档_id哈希)计算目标主分片。 - 主分片写入:主分片(Primary Shard)所在 Data 节点执行 Lucene 写入流程:先写 Translog(事务日志),再写入内存 Buffer。
- 同步副本:主分片将请求并行转发至所有副本分片(Replica Shard),等待副本 ACK。
- 刷新提交:内存 Buffer 每秒 refresh 生成新 Segment(可被搜索),Translog 定期 flush 落盘生成新 Lucene 段。
- 响应客户端:所有副本确认后,Coordinating 节点向客户端返回成功。
高可用机制
- Master 选举:3 个专用 Master 节点通过 Zen Discovery(ES 7.x+)互相探测,超过半数(quorum=2)达成共识后选出 Master。避免脑裂。
- 分片副本:每个主分片配置 1 个或多个副本,分布在不同 Data 节点上。单节点宕机,副本自动提升为主分片,数据不丢。
- Pod 重调度:K8s StatefulSet 保证 Pod 有序启停,Ceph RBD PVC 在 Pod 重建后重新挂载,数据持久化。
- 跨可用区部署:通过
topologySpreadConstraints或nodeSelector将 Pod 分散到不同节点/可用区,提升容灾能力。
存储规划
- Master 节点:仅存集群状态(cluster state),体积小,分配 10Gi Ceph RBD 即可。
- Data 节点:存储实际索引数据,按业务数据量规划。生产建议 100Gi 起步,使用 Ceph RBD 提供 Block 级别随机读写性能。
- Ceph RBD 优势:块设备语义契合 Lucene 随机写 Translog 与 Segment 合并;多副本由 Ceph 集群保障,K8s 层 PVC 仅做 ReadWriteOnce 挂载。
部署实战
本篇使用 Bitnami 维护的 elasticsearch Helm Chart(bitnami/elasticsearch),它原生支持 Master/Data/Coordinating 角色分离、PVC 持久化、安全认证等企业级特性,是社区最稳定的 ES Chart 之一。
第一步:添加 Bitnami Helm 仓库
# 添加 Bitnami 官方 Chart 仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
# 验证 elasticsearch chart 可用
helm search repo bitnami/elasticsearch
# 预期输出:
# NAME CHART VERSION APP VERSION DESCRIPTION
# bitnami/elasticsearch 21.6.0 8.15.0 Elasticsearch is a distributed search …
第二步:创建命名空间
kubectl create namespace middleware
kubectl config set-context –current –namespace=middleware
第三步:编写 values.yaml 自定义配置
核心配置重点:storageClass 指向第 2 天创建的 ceph-rbd-sc,Master 与 Data 角色分离,副本数取奇数,资源限制适配节点规格。
# es-values.yaml —— Ceph RBD 持久化的 Elasticsearch 集群配置
global:
elasticsearch:
nameOverride: "es"
# 集群全局参数
clusterName: "es-cluster"
extraEnvVars:
– name: ELASTICSEARCH_SKIP_SET_KERNEL_PARAMETERS
value: "true" # K8s 环境跳过宿主机内核参数设置
# 安全配置(生产务必开启)
security:
enabled: true
elasticPassword: "Elastic@2026"
tls:
autoGenerated: true
restEncryption: true
# Master 专用节点(3 个,奇数防脑裂)
master:
replicaCount: 3
heapSize: "512m"
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "1"
memory: "2Gi"
persistence:
enabled: true
storageClass: "ceph-rbd-sc" # 第 2 天创建的 Ceph RBD StorageClass
accessModes:
– ReadWriteOnce
size: "10Gi"
# Data 节点(存储索引数据,3 副本可扩展)
data:
replicaCount: 3
heapSize: "2g"
resources:
requests:
cpu: "1"
memory: "4Gi"
limits:
cpu: "2"
memory: "6Gi"
persistence:
enabled: true
storageClass: "ceph-rbd-sc" # 关键:指向 Ceph RBD
accessModes:
– ReadWriteOnce
size: "100Gi"
# Coordinating 节点(查询归并,按需启用)
coordinating:
replicaCount: 1
heapSize: "512m"
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "1"
memory: "2Gi"
# Service 暴露
service:
type: ClusterIP
ports:
restAPI: 9200
transport: 9300
第四步:执行 helm install 部署
# 使用自定义 values 部署 Elasticsearch 集群
helm install es-cluster bitnami/elasticsearch
-f es-values.yaml
–namespace middleware
–version 21.6.0
# 预期输出:
# NAME: es-cluster
# LAST DEPLOYED: Sat Oct 3 00:30:00 2026
# NAMESPACE: middleware
# STATUS: deployed
# REVISION: 1
# NOTES: … Elasticsearch can be accessed within the cluster …
第五步:验证 Pod / Service / PVC 状态
# 查看 Pod 启动情况(StatefulSet 有序拉起)
kubectl get pods -n middleware -l app.kubernetes.io/instance=es-cluster -w
# 预期:
# NAME READY STATUS RESTARTS AGE
# es-cluster-master-0 1/1 Running 0 5m
# es-cluster-master-1 1/1 Running 0 4m
# es-cluster-master-2 1/1 Running 0 3m
# es-cluster-data-0 1/1 Running 0 5m
# es-cluster-data-1 1/1 Running 0 4m
# es-cluster-data-2 1/1 Running 0 3m
# es-cluster-coordinating-0 1/1 Running 0 5m
# 查看 PVC 是否已绑定 Ceph RBD 卷
kubectl get pvc -n middleware -l app.kubernetes.io/instance=es-cluster
# 预期:6 个 PVC 全部 Bound
# NAME STATUS VOLUME CAPACITY STORAGECLASS
# data-es-cluster-master-0 Bound pvc-ceph-xxxx-aaaa 10Gi ceph-rbd-sc
# data-es-cluster-master-1 Bound pvc-ceph-xxxx-bbbb 10Gi ceph-rbd-sc
# …
# 查看 Service
kubectl get svc -n middleware -l app.kubernetes.io/instance=es-cluster
# es-cluster-master ClusterIP 10.96.50.10 <none> 9200/TCP,9300/TCP
# es-cluster-master-headless ClusterIP None <none> 9200/TCP,9300/TCP
第六步:集群健康状态验证(JSON 输出)
# 获取 elastic 用户密码(生产建议用 Secret 注入)
export ELASTIC_PASSWORD="Elastic@2026"
# 端口转发到本地验证
kubectl port-forward svc/es-cluster-master 9200:9200 -n middleware &
# 查看集群健康状态
curl -u elastic:$ELASTIC_PASSWORD -sk https://localhost:9200/_cluster/health?pretty
# 预期 JSON 输出:
# {
# "cluster_name" : "es-cluster",
# "status" : "green",
# "timed_out" : false,
# "number_of_nodes" : 7,
# "number_of_data_nodes" : 3,
# "active_primary_shards" : 0,
# "active_shards" : 0,
# "relocating_shards" : 0,
# "initializing_shards" : 0,
# "unassigned_shards" : 0
# }
登录验证
部署完成后,通过以下命令验证集群功能是否正常。
集群节点列表
# 查看集群所有节点角色
curl -u elastic:$ELASTIC_PASSWORD -sk https://localhost:9200/_cat/nodes?v
# 预期:
# IP heap.percent ram.percent cpu load_1m …
# 10.244.1.5 45 65 12 0.15 … dim – es-cluster-data-0
# 10.244.2.7 50 70 10 0.20 … dim – es-cluster-data-1
# 10.244.3.6 42 62 8 0.10 … dim – es-cluster-data-2
# 10.244.1.3 20 40 3 0.05 … m – es-cluster-master-0
# …
节点角色说明:m=master、d=data、i=ingest、-=未选举为 Master 的候选。
创建索引与写入测试
# 创建一个 3 主分片 1 副本的测试索引
curl -u elastic:$ELASTIC_PASSWORD -sk -X PUT https://localhost:9200/test-index?pretty
-H 'Content-Type: application/json'
-d '{
"settings": { "number_of_shards": 3, "number_of_replicas": 1 }
}'
# 写入一条测试文档
curl -u elastic:$ELASTIC_PASSWORD -sk -X POST https://localhost:9200/test-index/_doc/1?pretty
-H 'Content-Type: application/json'
-d '{ "title": "Ceph+K8s 中间件实战", "day": 11, "topic": "Elasticsearch" }'
# 执行全文检索
curl -u elastic:$ELASTIC_PASSWORD -sk "https://localhost:9200/test-index/_search?q=Ceph&pretty"
集群健康检查
# 综合健康信息
curl -u elastic:$ELASTIC_PASSWORD -sk https://localhost:9200/_cluster/health?pretty
# 查看分片分布
curl -u elastic:$ELASTIC_PASSWORD -sk https://localhost:9200/_cat/shards?v
# 查看索引列表
curl -u elastic:$ELASTIC_PASSWORD -sk https://localhost:9200/_cat/indices?v
日常巡检
健康检查
# 集群状态(green=健康 / yellow=副本缺失 / red=主分片缺失)
curl -u elastic:$ELASTIC_PASSWORD -sk https://localhost:9200/_cluster/health | jq '.status'
# 节点磁盘水位
curl -u elastic:$ELASTIC_PASSWORD -sk https://localhost:9200/_cat/allocation?v
# shard disk.indices disk.used disk.avail disk.total disk.percent node
# 12 5.2gb 6.1gb 93.9gb 100gb 6 es-cluster-data-0
# 未分配分片排查
curl -u elastic:$ELASTIC_PASSWORD -sk https://localhost:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason | grep UNASSIGNED
日志查看
# 查看 Master 节点日志(关注选举、集群状态变更)
kubectl logs -n middleware es-cluster-master-0 –tail=100
# 查看 Data 节点日志(关注 GC、慢查询、磁盘告警)
kubectl logs -n middleware es-cluster-data-0 –tail=200 | grep -E "GC|slowlog|disk"
# 实时跟踪某个 Data 节点日志
kubectl logs -n middleware es-cluster-data-1 -f
性能监控
# 节点级热点统计(CPU、堆、磁盘 IO)
curl -u elastic:$ELASTIC_PASSWORD -sk https://localhost:9200/_nodes/stats?pretty | jq '.nodes | to_entries[] | {node: .value.name, cpu: .value.process.cpu.percent, heap: .value.jvm.mem.heap_used_percent}'
# 索引级写入/查询延迟
curl -u elastic:$ELASTIC_PASSWORD -sk https://localhost:9200/_stats/indexing,search?pretty | jq '.indices | to_entries[] | {index: .key, indexing_time: .value.total.indexing.index_time_in_millis, search_time: .value.total.search.query_time_in_millis}'
# 慢查询日志阈值(已开启时查看)
curl -u elastic:$ELASTIC_PASSWORD -sk https://localhost:9200/test-index/_settings | jq '."test-index".index.search.slowlog'
容量巡检
# 查看集群存储总量与使用量
curl -u elastic:$ELASTIC_PASSWORD -sk https://localhost:9200/_cat/allocation?v
# Ceph RBD PVC 容量确认
kubectl get pvc -n middleware -l app.kubernetes.io/instance=es-cluster -o custom-columns=NAME:.metadata.name,SIZE:.spec.resources.requests.storage,STATUS:.status.phase
# Ceph 侧 RBD 镜像实际占用
kubectl exec -n rook-ceph deploy/rook-ceph-tools — ceph df | grep -A5 "POOLS"
常见问题
Q1:Pod 启动报错 max virtual memory areas vm.max_map_count [65530] is too low?
A:Elasticsearch 要求宿主机 vm.max_map_count >= 262144。K8s 中有两种解决方式:① 在所有 K8s 节点执行 sysctl -w vm.max_map_count=262144 并写入 /etc/sysctl.conf;② 使用 initContainer 以特权模式设置内核参数(已在 values 中用 ELASTICSEARCH_SKIP_SET_KERNEL_PARAMETERS 跳过宿主机设置,实际部署建议用 DaemonSet 预设)。
Q2:PVC 一直 Pending,Ceph RBD 没有绑定?
A:检查三点:① ceph-rbd-sc StorageClass 是否存在(kubectl get sc ceph-rbd-sc);② Ceph-CSI Driver Pod 是否正常(kubectl get pods -n ceph-csi-rbd);③ Ceph 集群池(如 replicapool)是否有足够空间。可通过 kubectl describe pvc <name> 查看 Provisioner 失败事件。
Q3:集群状态长期 yellow,如何修复?
A:yellow 表示有副本分片未分配。常见原因:Data 节点数不足(副本需分布到不同节点)、磁盘水位超 85% 触发水位保护、节点重启后分片恢复中。可通过 curl _cluster/allocation/explain 查看未分配原因,临时降低副本数 number_of_replicas: 0 或扩容 Data 节点解决。
总结
本篇完整实战了在 K8s 上通过 Bitnami Helm Chart 部署 Elasticsearch 集群的全流程:Master/Data/Coordinating 角色分离的架构设计、基于 Ceph RBD 的 PVC 持久化配置、安全认证与 TLS 启用,以及从 Pod/PVC 状态验证到索引写入检索的完整登录验证。Elasticsearch 作为 ELK 生态核心,其稳定运行依赖存储性能与内存规划——Ceph RBD 提供的块存储语义恰好契合 Lucene 的随机写与 Segment 合并场景。
关键要点回顾:
– 角色分离:Master 奇数节点防脑裂,Data 按数据量横向扩展,Coordinating 承接查询归并压力。
– 存储选型:Ceph RBD 的 ReadWriteOnce 卷与 ES Data 节点一对一绑定,Pod 重建后数据不丢。
– 安全基线:生产环境务必开启 security.enabled + TLS,elastic 密码通过 K8s Secret 注入而非明文。
– 巡检闭环:_cluster/health 状态、_cat/allocation 磁盘水位、慢查询日志,三件套覆盖日常运维。
下期预告
明天(第 12 天)将带来 K8s 部署 Kafka 集群(Ceph RBD + 消息队列架构 + 运维)。Kafka 作为高吞吐分布式消息系统,其底层正依赖 Zookeeper(第 10 天已部署)进行元数据管理。我们将讲解 Partition/Replica 数据流、Controller 选举机制,并通过 Bitnami Kafka Chart 完成 Ceph RBD 持久化部署,敬请期待。
系列目录
- 第 1 天:Ceph 分布式存储回顾与 K8s 存储体系概述 ✅ 已发布
- 第 2 天:K8s 接入 Ceph RBD 块存储(CSI Driver + StorageClass 配置实战) ✅ 已发布
- 第 3 天:K8s 接入 CephFS 共享文件存储(多读场景与性能调优) ✅ 已发布
- 第 4 天:K8s 部署 MySQL 高可用集群(Ceph RBD 持久化 + 架构设计 + 登录巡检) ✅ 已发布
- 第 5 天:K8s 部署 Redis Cluster 集群(Ceph RBD + 架构设计 + 巡检命令) ✅ 已发布
- 第 6 天:K8s 部署 Redis Sentinel 哨兵模式(高可用架构 + 登录验证) ✅ 已发布
- 第 7 天:K8s 部署 MinIO 对象存储集群(分布式架构 + 运维巡检) ✅ 已发布
- 第 8 天:K8s 部署 MongoDB 副本集集群(Ceph RBD + 架构设计 + 登录) ✅ 已发布
- 第 9 天:K8s 部署 Nacos 注册配置中心(集群架构 + 登录巡检) ✅ 已发布
- 第 10 天:K8s 部署 Zookeeper 集群(分布式协调架构 + 运维命令) ✅ 已发布
- 第 11 天:K8s 部署 Elasticsearch 集群(Ceph RBD + 架构设计 + 巡检) 📍 本文
- 第 12 天:K8s 部署 Kafka 集群(Ceph RBD + 消息队列架构 + 运维) 📅 即将发布
- 第 13 天:K8s 部署 GitLab 代码托管平台(Ceph RBD 持久化 + 架构 + 巡检) 📅 即将发布
- 第 14 天:K8s 部署 ClickHouse 列式数据库集群(Ceph RBD + 架构设计) 📅 即将发布
- 第 15 天:K8s 中间件统一监控与运维巡检总结(Prometheus + Grafana 全景) 📅 即将发布

















暂无评论内容