Ceph+K8s 中间件实战 | 第 11 天:K8s 部署 Elasticsearch 集群(Ceph RBD + 架构设计 + 巡检)

第 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 持久化配置,以及登录验证与日常巡检命令。

K8s Logo

设计架构

组件拓扑

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) 机制实现数据分布与高可用,数据流向如下:

  1. 文档写入:客户端向任意 Coordinating 节点发送索引请求(POST /index/_doc)。
  2. 路由分片:Coordinating 节点根据 routing 值(默认文档 _id 哈希)计算目标主分片。
  3. 主分片写入:主分片(Primary Shard)所在 Data 节点执行 Lucene 写入流程:先写 Translog(事务日志),再写入内存 Buffer。
  4. 同步副本:主分片将请求并行转发至所有副本分片(Replica Shard),等待副本 ACK。
  5. 刷新提交:内存 Buffer 每秒 refresh 生成新 Segment(可被搜索),Translog 定期 flush 落盘生成新 Lucene 段。
  6. 响应客户端:所有副本确认后,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. 第 1 天:Ceph 分布式存储回顾与 K8s 存储体系概述 ✅ 已发布
  2. 第 2 天:K8s 接入 Ceph RBD 块存储(CSI Driver + StorageClass 配置实战) ✅ 已发布
  3. 第 3 天:K8s 接入 CephFS 共享文件存储(多读场景与性能调优) ✅ 已发布
  4. 第 4 天:K8s 部署 MySQL 高可用集群(Ceph RBD 持久化 + 架构设计 + 登录巡检) ✅ 已发布
  5. 第 5 天:K8s 部署 Redis Cluster 集群(Ceph RBD + 架构设计 + 巡检命令) ✅ 已发布
  6. 第 6 天:K8s 部署 Redis Sentinel 哨兵模式(高可用架构 + 登录验证) ✅ 已发布
  7. 第 7 天:K8s 部署 MinIO 对象存储集群(分布式架构 + 运维巡检) ✅ 已发布
  8. 第 8 天:K8s 部署 MongoDB 副本集集群(Ceph RBD + 架构设计 + 登录) ✅ 已发布
  9. 第 9 天:K8s 部署 Nacos 注册配置中心(集群架构 + 登录巡检) ✅ 已发布
  10. 第 10 天:K8s 部署 Zookeeper 集群(分布式协调架构 + 运维命令) ✅ 已发布
  11. 第 11 天:K8s 部署 Elasticsearch 集群(Ceph RBD + 架构设计 + 巡检) 📍 本文
  12. 第 12 天:K8s 部署 Kafka 集群(Ceph RBD + 消息队列架构 + 运维) 📅 即将发布
  13. 第 13 天:K8s 部署 GitLab 代码托管平台(Ceph RBD 持久化 + 架构 + 巡检) 📅 即将发布
  14. 第 14 天:K8s 部署 ClickHouse 列式数据库集群(Ceph RBD + 架构设计) 📅 即将发布
  15. 第 15 天:K8s 中间件统一监控与运维巡检总结(Prometheus + Grafana 全景) 📅 即将发布
微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像 - 恒星
欢迎您留下宝贵的见解!
提交
头像 - 恒星

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容