资讯动态

在 Kubernetes 上为 ClickHouse Operator 部署 ZooKeeper:从快速启动到高级配置实战指南

发布时间:2026/9/18 8:24:02 来源:尧图企业网站定制
在 Kubernetes 上为 ClickHouse Operator 部署 ZooKeeper从快速启动到高级配置实战指南【免费下载链接】clickhouse-operatorAltinity Kubernetes Operator for ClickHouse creates, configures and manages ClickHouse® clusters running on Kubernetes项目地址: https://gitcode.com/GitHub_Trending/cl/clickhouse-operator本文是 clickhouse-operator 仓库中 ZooKeeper 环境搭建的完整实战指南覆盖从一键快速启动Quick Start到逐项精细配置Advanced Setup两条部署路径并深入讲解 Service、Headless Service、PodDisruptionBudget、StorageClass、StatefulSet 等关键资源的配置要点与 ZooKeeper 集群的验证方法。读完本文你将能够在 Kubernetes 上独立完成单节点或三节点 ZooKeeper 集群的部署、存储方案选型与运行状态检查为 ClickHouse 复制表等高可用特性提供可靠的协调服务底座。一、为什么 ClickHouse 集群需要 ZooKeeperClickHouse 的复制表Replicated Table依赖 ZooKeeper 来协调副本间的元数据、日志序号与 leader 选举。在 docs/replication_setup.md 与docs/chi-examples/目录下的04-replication-zookeeper-*.yaml系列示例中均可以看到 ZooKeeper 作为复制协调服务被显式引用。因此在生产环境为 ClickHouse Operator 部署一套高可用的 ZooKeeper 是前置条件之一。本文档对应的部署脚本与清单全部位于 deploy/zookeeper/zookeeper-manually 目录采用手工manually方式部署。仓库同时提供 zookeeper-with-zookeeper-operator 的 Operator 方式部署目录可自行对比选用。本文描述的 ZooKeeper 安装会创建/配置以下 Kubernetes 资源资源作用Service为客户端访问 ZooKeeper 提供统一入口Headless Service为每个 ZooKeeper 节点提供独立 DNS 名称PodDisruptionBudget中断预算限制任意时刻可离线的 ZooKeeper Pod 数量StorageClass可选指定 ZooKeeper 数据存储使用的存储类StatefulSet管理并伸缩 ZooKeeper Pod 集合ZooKeeper 安装分为两种方式Quick start快速启动直接运行不做过多询问适合测试。Advanced setup高级设置精细配置存储类、副本数等内部细节适合生产。二、快速启动Quick Start快速启动提供两种存储风格持久化卷Persistent Volume适合 AWS 等云环境文件位于 deploy/zookeeper/zookeeper-manually/quick-start-persistent-volume。本地 emptyDir 存储适合单机本地运行但没有真正的持久化能力Pod 重建即数据丢失文件位于 deploy/zookeeper/zookeeper-manually/quick-start-volume-emptyDir。每种风格都提供两种集群规模1 节点 ZooKeeper 集群zookeeper-1-前缀文件不提供故障切换failover能力。3 节点 ZooKeeper 集群zookeeper-3-前缀文件提供故障切换能力生产推荐。选型建议需要在 AWS 或任何其他云厂商测试推荐使用 quick-start-persistent-volume 的持久化存储。本地测试可以使用 quick-start-volume-emptyDir 的emptyDir。2.1 脚本方式安装以 AWS 上 1 节点 ZooKeeper 集群为例使用 quick-start-persistent-volume 目录下的脚本。仓库同时提供创建和删除两个脚本创建zookeeper-1-node-create.sh删除zookeeper-1-node-delete.sh从脚本实现可以看到命名空间的可定制机制默认zoo1ns# zookeeper-1-node-create.sh ZK_NAMESPACE${ZK_NAMESPACE:-zoo1ns} kubectl create namespace ${ZK_NAMESPACE} kubectl --namespace${ZK_NAMESPACE} apply -f ${CUR_DIR}/zookeeper-1-node.yaml即默认会创建名为zoo1ns的命名空间并应用zookeeper-1-node.yaml。若需自定义命名空间可在执行前设置环境变量ZK_NAMESPACEmyzkns ./zookeeper-1-node-create.sh删除脚本则直接删除整个命名空间# zookeeper-1-node-delete.sh kubectl delete namespace ${ZK_NAMESPACE}3 节点集群对应使用 zookeeper-3-nodes-create.sh 与 zookeeper-3-nodes-delete.shemptyDir风格目录下也有对应脚本。2.2 手动方式安装如果希望手动部署 ZooKeeper按以下步骤执行。创建命名空间kubectl create namespace zoo1ns部署 ZooKeeperkubectl apply -f zookeeper-1-node.yaml -n zoo1ns其中zookeeper-1-node.yaml位于 deploy/zookeeper/zookeeper-manually/quick-start-persistent-volume/zookeeper-1-node.yaml。该清单文件是一个多文档 YAML一次性包含了 Service、Headless Service、PodDisruptionBudget 与 StatefulSet 四类资源这也是快速启动一条命令全部搞定的体现。现在 ZooKeeper 应该已经启动运行可以前往本文验证 ZooKeeper 集群一节查看如何确认集群状态。IMPORTANT快速启动的 ZooKeeper 安装主要面向测试目的。如需精细化调优的 ZooKeeper 部署请参考下一节高级设置。三、高级设置Advanced Setup高级设置的清单文件位于 deploy/zookeeper/zookeeper-manually/advanced 目录所有资源被拆分到不同的独立文件中便于单独修改和按需配置。高级设置同样提供两种存储选项持久化卷Persistent VolumeemptyDir 卷Volume每种选项都提供创建与删除脚本持久化卷zookeeper-persistent-volume-create.sh 与 zookeeper-persistent-volume-delete.shemptyDir 卷zookeeper-volume-emptyDir-create.sh 与 zookeeper-volume-emptyDir-delete.sh从创建脚本可以清楚看到资源的应用顺序以持久化卷为例# zookeeper-persistent-volume-create.sh ZK_NAMESPACE${ZK_NAMESPACE:-zoons} YAML_FILES_LIST\ 01-service-client-access.yaml \ 02-headless-service.yaml \ 03-pod-disruption-budget.yaml \ 04-storageclass-zookeeper.yaml \ 05-stateful-set-persistent-volume.yaml\ source ${CUR_DIR}/zookeeper-create-universal.sh即默认命名空间为zoons按编号顺序依次应用 5 个清单文件通用逻辑封装在 zookeeper-create-universal.sh 中。以下为逐步手动执行的详细说明。3.1 创建命名空间kubectl create namespace zoons后续所有资源都会创建在该命名空间内。3.2 Zookeeper Service客户端访问服务kubectl apply -f 01-service-client-access.yaml -n zoons预期输出service/zookeeper created该 Service 为客户端访问所有 ZooKeeper 节点提供统一的 DNS 名称形如zookeeper.zoons。清单位于 01-service-client-access.yaml核心配置如下apiVersion: v1 kind: Service metadata: # DNS would be like zookeeper.zoons name: zookeeper labels: app: zookeeper spec: ports: - port: 2181 name: client - port: 7000 name: prometheus selector: app: zookeeper what: node其中 2181 是 ZooKeeper 客户端端口7000 是 Prometheus 指标端口selector 与 StatefulSet 的 Pod 标签app: zookeeper, what: node相对应。3.3 Zookeeper Headless Service无头服务kubectl apply -f 02-headless-service.yaml -n zoons预期输出service/zookeeper-nodes created无头服务Headless ServiceclusterIP: None为每个 ZooKeeper 节点提供独立的 DNS 名称是 StatefulSet 稳定网络标识的基础。清单位于 02-headless-service.yamlapiVersion: v1 kind: Service metadata: # DNS would be like zookeeper-0.zookeepers.etc name: zookeepers labels: app: zookeeper spec: ports: - port: 2888 name: server - port: 3888 name: leader-election clusterIP: None selector: app: zookeeper what: node其中 2888 是 ZooKeeper 节点间数据同步端口3888 是 leader 选举端口均用于节点间通信而非客户端访问。3.4 PodDisruptionBudget中断预算kubectl apply -f 03-pod-disruption-budget.yaml -n zoons预期输出poddisruptionbudget.policy/zookeeper-pod-distribution-budget created中断预算向 k8s 声明任意时刻最多允许多少个 ZooKeeper 节点离线用于在节点维护等自愿中断场景下保护 ZooKeeper 的法定人数quorum。清单位于 03-pod-disruption-budget.yamlapiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: zookeeper-pod-distribution-budget spec: selector: matchLabels: app: zookeeper maxUnavailable: 13.5 StorageClass存储类这部分并非直接照抄即可可能需要与 k8s 实例管理员沟通确认。首先需要决定 ZooKeeper 使用哪种存储Persistent Volume持久化卷走05-stateful-set-persistent-volume.yaml。emptyDir 卷走05-stateful-set-volume-emptyDir.yaml。简单来说StorageClass 用于将 Persistent Volume 绑定在一起——这些 PV 要么由 k8s 管理员手工创建要么由 Provisioner动态供应自动创建。无论哪种方式PV 都是由 k8s 在外部提供给待部署应用的。因此应用必须在自己的持久化卷声明Persistent Volume Claim中向 k8s 请求一个具体的StorageClass 名称该名称需要向 k8s 管理员索取并填写在 StatefulSet 配置的.spec.volumeClaimTemplates.storageClassName参数中。对应清单文件为emptyDir 版05-stateful-set-volume-emptyDir.yaml持久化卷版05-stateful-set-persistent-volume.yaml仓库的 04-storageclass-zookeeper.yaml 提供了一个默认全部注释掉的 StorageClass 模板用于在集群没有默认存储类时启用#apiVersion: storage.k8s.io/v1 #kind: StorageClass #metadata: # name: storageclass-zookeeper #provisioner: kubernetes.io/no-provisioner ## Choose desired volumeBindingMode ##volumeBindingMode: WaitForFirstConsumer #volumeBindingMode: Immediate注意其 provisioner 为kubernetes.io/no-provisioner即该模板面向管理员预先准备 PV的静态供应场景如需动态供应应替换为集群实际的 provisioner并选择合适的volumeBindingModeWaitForFirstConsumer或Immediate。3.6 StatefulSet有状态应用集根据存储偏好编辑对应清单05-stateful-set-volume-emptyDir.yaml05-stateful-set-persistent-volume.yaml选择 emptyDir 存储时确保.spec.template.spec.containers.volumes生效形如volumes: - name: datadir-volume emptyDir: medium: #accepted values: empty str (means nodes default medium) or Memory sizeLimit: 1Gi同时确保.spec.volumeClaimTemplates处于注释状态。选择 Persistent Volume 存储时确保.spec.template.spec.containers.volumes处于注释状态并取消.spec.volumeClaimTemplates的注释volumeClaimTemplates: - metadata: name: datadir-volume spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi ## storageClassName has to be coordinated with k8s admin and has to be created as a kind: StorageClass resource storageClassName: storageclass-zookeeper并确保storageClassName本例为storageclass-zookeeper已按存储类一节正确填写。关于storageClassName字段还有两个值得注意的语义清单文件注释中已明确不指定storageClassName表示使用默认存储类指定为空字符串表示不使用动态供应do not use dynamic provisioning。StatefulSet 内部结构速览持久化卷版与 emptyDir 版两份 StatefulSet 清单05-stateful-set-persistent-volume.yaml除存储部分外主体一致关键设计如下可帮助理解其工作原理apiVersion: apps/v1 kind: StatefulSet metadata: # nodes would be named as zookeeper-0, zookeeper-1, zookeeper-2 name: zookeeper spec: selector: matchLabels: app: zookeeper serviceName: zookeepers replicas: 3 updateStrategy: type: RollingUpdate podManagementPolicy: ParallelserviceName: zookeepers绑定到前面创建的无头服务Pod 因此获得zookeeper-0.zookeepers.zoons这类稳定 DNSreplicas: 3对应三节点 ZooKeeper 集群podManagementPolicy: Parallel允许并行创建/更新所有 Pod区别于快速启动版使用的OrderedReady快速启动 zookeeper-1-node.yaml 中为OrderedReady即按顺序逐个就绪。容器启动命令会动态生成 ZooKeeper 配置/conf/zoo.cfg包括clientPort2181、tickTime2000、initLimit300、syncLimit10、maxClientCnxns2000、maxSessionTimeout60000000、autopurge.snapRetainCount10、autopurge.purgeInterval1、4lw.commands.whitelist*等参数并通过解析 Pod 名称序号zookeeper-0→ myid1写入myid文件、追加server.Nhost:port:port配置最终以zkServer.sh start-foreground前台方式启动。同时启用 Prometheus 指标7000 端口并通过 Pod 注解prometheus.io/scrape: true、prometheus.io/port: 7000暴露抓取端点。此外还配置了探针readiness 与 liveness 均通过向127.0.0.1:2181发送ruok并检查返回imok来实现用于判断 ZooKeeper 是否存活并就绪安全上下文runAsUser: 1000与fsGroup: 1000以非特权用户运行反亲和podAntiAffinity基于kubernetes.io/hostname强制要求不同 ZooKeeper Pod 调度到不同节点避免单点故障数据目录volumeMounts将datadir-volume挂载到/var/lib/zookeeper。应用 StatefulSet清单准备就绪后用kubectl应用kubectl apply -f 05-stateful-set.yaml -n zoons预期输出statefulset.apps/zookeeper-node created注实际清单文件名为05-stateful-set-persistent-volume.yaml或05-stateful-set-volume-emptyDir.yaml按所选存储方案替换上面命令中的文件名即可。现在可以查看部署在 k8s 中的 ZooKeeper 集群了。四、验证 ZooKeeper 集群Explore ZooKeeper Cluster4.1 DNS 名称以高级设置的三节点集群为例在zoons命名空间内预期有 3 个 Pod名称分别为zookeeper-0 zookeeper-1 zookeeper-2这些 Pod 拥有如下短 DNS 名称zookeeper-0.zookeepers.zoons zookeeper-1.zookeepers.zoons zookeeper-2.zookeepers.zoons其中zookeepers是 ZooKeeper 无头服务Headless Service的名称zoons是 ZooKeeper 命名空间的名称。完整 DNS 名称FQDN为zookeeper-0.zookeepers.zoons.svc.cluster.local zookeeper-1.zookeepers.zoons.svc.cluster.local zookeeper-2.zookeepers.zoons.svc.cluster.local这些稳定的网络标识正是 ZooKeeper 集群节点间互相发现、以及 ClickHouse 复制表协调时所依赖的地址基础。若 ClickHouse 需要接入该 ZooKeeper可在 CHI 的spec.configuration.clusters中通过zookeeper配置段引用这些地址参见 04-replication-zookeeper-01-minimal.yaml 等复制示例。4.2 资源检查查看 Podkubectl get pod -n zoons预期输出类似NAME READY STATUS RESTARTS AGE zookeeper-0 1/1 Running 0 9m2s zookeeper-1 1/1 Running 0 9m2s zookeeper-2 1/1 Running 0 9m2s查看 Servicekubectl get service -n zoons预期输出类似NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE zookeeper ClusterIP 10.108.36.44 none 2181/TCP 168m zookeepers ClusterIP None none 2888/TCP,3888/TCP 31m可以看到zookeeper客户端访问入口暴露 2181 端口zookeepers无头服务为ClusterIP: None并暴露 2888/3888 节点间通信端口。查看 StatefulSetkubectl get statefulset -n zoons预期输出类似NAME READY AGE zookeepers 3/3 10m如果一切正常说明 ZooKeeper 集群已经成功运行。五、与 ClickHouse Operator 的集成与进一步参考本文对应的全部手工部署清单与脚本位于 deploy/zookeeper/zookeeper-manually其中 advanced 目录还提供了zookeeper-watch.sh等辅助脚本供观察部署过程。若希望以 Operator 方式管理 ZooKeeper可参考 zookeeper-with-zookeeper-operator 目录下的安装脚本与 CR 示例1 节点/3 节点含自定义探针版本。将 ZooKeeper 与 ClickHouse 复制表结合使用的完整流程请阅读 docs/replication_setup.md 及 docs/chi-examples/ 中04-replication-zookeeper-*.yaml系列示例。监控方面ZooKeeper 已通过 7000 端口暴露 Prometheus 指标仓库的 deploy/prometheus/prometheus-alert-rules-zookeeper.yaml 提供了现成的告警规则示例Grafana 仪表盘模板见 grafana-dashboard/Zookeeper_dashboard.json。若计划从 ZooKeeper 迁移到 ClickHouse Keeper可参考 docs/keeper_migration_from_23_to_24.md 与 docs/keeper_reference.md。总结在 clickhouse-operator 项目中ZooKeeper 的部署路径清晰可循测试场景走 快速启动一条命令即可拉起 1 节点或 3 节点集群生产场景走 高级设置按 Service → Headless Service → PDB → StorageClass → StatefulSet 的顺序逐项精细配置并显式声明存储方案。部署完成后通过 Pod/Service/StatefulSet 的kubectl get输出以及ruok/mntr等四字命令即可确认集群健康状态随后即可将 ZooKeeper 地址接入 ClickHouse 复制集群构建完整的高可用数据链路。【免费下载链接】clickhouse-operatorAltinity Kubernetes Operator for ClickHouse creates, configures and manages ClickHouse® clusters running on Kubernetes项目地址: https://gitcode.com/GitHub_Trending/cl/clickhouse-operator创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价