ClickHouse Operator 的 ClickHouseKeeper 引用指南:通过 KeeperRef 在 CHI 中自动解析 Keeper 拓扑
2026/9/18 14:04:05 网站建设 项目流程

ClickHouse Operator 的 ClickHouseKeeper 引用指南:通过 KeeperRef 在 CHI 中自动解析 Keeper 拓扑

【免费下载链接】clickhouse-operatorAltinity Kubernetes Operator for ClickHouse creates, configures and manages ClickHouse® clusters running on Kubernetes项目地址: https://gitcode.com/GitHub_Trending/cl/clickhouse-operator

本指南讲解 Altinity ClickHouse Operator 中spec.configuration.zookeeper.keeper(KeeperRef)的完整用法:如何在ClickHouseInstallation(CHI)中通过名称引用ClickHouseKeeperInstallation(CHK)资源,由 Operator 在协调(reconcile)期间自动解析出 ZooKeeper 节点地址。读完本文,你将掌握 KeeperRef 的字段语义、replicasservice两种端点发现模式、TLS 自动检测、就绪等待与超时配置、CHK 变更自动触发 CHI 协调,以及基于真实源码的故障排查方法。

为什么需要 Keeper 引用(KeeperRef)

在 ClickHouse 复制拓扑中,副本间的元数据同步依赖 ZooKeeper 兼容服务。传统写法是在spec.configuration.zookeeper.nodes中逐个显式写出host:port

zookeeper: nodes: - host: zookeeper-0.zookeepers.zoo3ns.svc.cluster.local port: 2181 - host: zookeeper-1.zookeepers.zoo3ns.svc.cluster.local port: 2181 - host: zookeeper-2.zookeepers.zoo3ns.svc.cluster.local port: 2181

这种方式要求运维人员预先知道 ZooKeeper/Keeper 的完整地址清单,且当 Keeper 扩缩容时必须手工同步维护 CHI 清单,极易出错。

KeeperRef 的引入正是为了解决这个问题:不再显式指定端点,而是通过名称引用一个ClickHouseKeeperInstallation(CHK)资源,由 Operator 在协调周期中自动解析出实际的 Keeper 节点地址并写入 ClickHouse 配置。从源码看,KeeperRef类型定义于 pkg/apis/clickhouse.altinity.com/v1/type_keeper_ref.go,它挂在ZookeeperConfig上(pkg/apis/clickhouse.altinity.com/v1/type_zookeeper.go),与显式Nodes是同一层级的两条可选路径。

基本用法

最简单的引用方式如下(完整可运行示例见 docs/chi-examples/04-replication-zookeeper-07-keeper-ref.yaml):

apiVersion: "clickhouse.altinity.com/v1" kind: "ClickHouseInstallation" metadata: name: my-chi spec: configuration: zookeeper: keeper: name: my-keeper clusters: - name: default layout: shardsCount: 1 replicasCount: 2

当 CHI 提交后,Operator 会:

  1. 通过 CHK 名称与命名空间定位对应的ClickHouseKeeperInstallation资源;
  2. 发现该 CHK 暴露的所有 Keeper 副本服务(或 CR 级服务,取决于serviceType);
  3. 将解析出的节点地址按<zookeeper><node><host>...</host><port>...</port></node>结构渲染进 ClickHouse 配置,使 ClickHouse 获得正确的 ZooKeeper 节点列表。

这条解析链路在源码中对应 pkg/controller/chi/controller-keeper-resolver.go 中的resolveKeeperNodes:它按serviceType分派到resolveKeeperByReplicas(按副本发现)或resolveKeeperByService(按 CR 级服务发现),最终返回一个api.ZookeeperNodes列表。值得注意的实现细节是:当副本发现失败或返回 0 个节点时,replicas模式会自动回退到 CR 级服务,提升了解析的健壮性。

KeeperRef 字段详解

下表完整列出KeeperRef支持的字段(与 type_keeper_ref.go 中的结构定义一一对应):

字段类型默认值说明
namestring(必填)ClickHouseKeeperInstallation资源的名称
namespacestringCHI 所在命名空间CHK 资源所在命名空间,跨命名空间引用时需显式指定
serviceTypestringreplicas端点发现模式,见下文

在类型层面,KeeperRef提供了几个 nil 安全的访问器:HasName()判断引用是否有效、GetNamespace(defaultNamespace)在未指定时回落到 CHI 命名空间、GetServiceType()在未指定时默认返回replicas。这也解释了文档中"namespace 省略则默认同命名空间"、serviceType默认replicas的行为。

另外,ZookeeperConfig.IsEmpty()的语义值得注意:只有当nodes为空没有keeper引用时,该配置才被视为空。也就是说,只要填了keeper,即使不写任何nodes,也能正常驱动解析逻辑。

ServiceType:两种端点发现模式

serviceType控制 Keeper 端点如何被发现(两种模式的常量定义见 type_keeper_ref.go):

  • replicas(默认):发现每个 Keeper 副本对应的 per-host 服务,为每个 Keeper 副本生成一个 ZooKeeper 节点。ClickHouse 能感知完整的 Keeper 拓扑,故障转移时具备全局视野,生产环境推荐使用。源码实现上,resolveKeeperByReplicas通过 CHK labeler 的LabelCRNameLabelServiceValueHost标签选择器列出所有 host 服务,按名称排序后逐一生成节点(见 controller-keeper-resolver.go)。
  • service:将 CHK CR 级 headless 服务作为一个单一 ZooKeeper 节点条目。配置更简单,但 ClickHouse 看不到各个 Keeper 副本,拓扑感知能力较弱。源码实现resolveKeeperByService直接通过 CHK 命名器构造 CR 级服务名并查询该 Service 的端口信息(见 controller-keeper-resolver.go)。

与其他 ZooKeeper 设置的组合

keeper引用与zookeeper下的其他字段完全正交,可以同时使用。解析出的节点会与显式声明的nodes共存,最终统一渲染进 ClickHouse 的<zookeeper>配置:

zookeeper: keeper: name: my-keeper session_timeout_ms: 30000 operation_timeout_ms: 10000 root: "/clickhouse/my-cluster" identity: "user:password"

各字段的 ClickHouse 侧语义(依据 type_zookeeper.go 的注释):

  • session_timeout_ms:ZooKeeper 会话超时(毫秒),渲染为<session_timeout_ms>
  • operation_timeout_ms:单次 ZooKeeper 操作超时(毫秒),渲染为<operation_timeout_ms>
  • root:ClickHouse 所有 znode 的可选根路径前缀,渲染为<root>
  • identity:ZooKeeper digest 认证凭据,格式user:password,渲染为<identity>
  • use_compression:Keeper 协议客户端-服务端通信压缩开关,渲染为<use_compression>

从合并逻辑看,ZookeeperConfig.MergeFrom(type_zookeeper.go)采用"节点去重追加、Keeper 引用仅在接收方为空时采纳、标量字段非零覆盖"的策略,模板与 CHI 合并时行为可预期。

集群级覆盖(Cluster-Level Override)

同一个 CHI 下可以部署多个集群,每个集群可以拥有自己的 Keeper 引用,从而覆盖顶层配置。覆盖规则很明确:只要某个集群带有自己的zookeeper配置(无论是自己的keeper引用还是自己的nodes),顶层配置对该集群就被整体忽略

spec: configuration: zookeeper: keeper: name: default-keeper clusters: - name: cluster-a # 使用 default-keeper(继承自顶层配置) layout: shardsCount: 2 replicasCount: 2 - name: cluster-b # 使用自己专属的 keeper zookeeper: keeper: name: dedicated-keeper namespace: keeper-namespace layout: shardsCount: 1 replicasCount: 3

真实的全字段示例(docs/chi-examples/99-clickhouseinstallation-max.yaml)中同样包含一个集群级覆盖:shards-only集群声明了自己的zookeeper.keepercluster-specific-keeperserviceType: service),与顶层配置并存互不干扰。

TLS 自动检测

Operator 会自动探测 Keeper 是否启用了 TLS,探测依据是服务端口定义。相关常量与检测函数位于 pkg/apis/clickhouse.altinity.com/v1/type_host.go:

  • 端口2181或端口名为zk→ 不安全连接;
  • 端口2281或端口名为zk-secure→ 安全连接(会在 ClickHouse 配置中设置<secure>1</secure>)。

检测函数ExtractZKPortInfo的优先级是:优先返回安全端口(若同时暴露了多个端口,只要存在zk-secure/2281就以安全模式解析),否则回落到非安全端口,最后兜底为默认的2181。因此,只要 Keeper 暴露了安全端口,解析出的 ZooKeeper 节点会自动带上secure: true,无需任何手工配置。完整的常量映射为:

  • zk/2181:Keeper 默认 ZooKeeper 客户端端口(不安全)
  • zk-secure/2281:Keeper 安全(TLS)ZooKeeper 客户端端口
  • raft/9444:Keeper 内部 Raft 端口(不用于客户端连接)

Keeper 就绪等待(Readiness)

在解析端点之前,Operator 会等待被引用的 CHK 的 Pod 进入Running阶段。这主要处理 CHK 与 CHI同时创建的场景——此时 Keeper Pod 可能尚未启动,直接解析会失败。

等待超时通过 Operator 配置ClickHouseOperatorConfiguration控制:

spec: reconcile: coordination: keeper: readyTimeout: 120 # 秒(默认:120)

该行为在 pkg/controller/chi/worker-keeper-resolver.go 的waitKeeperReady中实现:它读取chop.Config().Reconcile.Coordination.Keeper.ReadyTimeout(单位秒),轮询 CHK 的所有 Pod,任一 Pod 未处于Running阶段就继续等待。

如果等待超时,CHI 协调将以ErrKeeperNotReady错误失败,并在 CHI 资源上发出 Kubernetes Event。该错误哨兵值定义于 controller-keeper-resolver.go,同类错误还包括ErrKeeperRefResolve(引用解析失败,如服务未找到)与ErrKeeperRefNoNodes(解析成功但得到 0 个节点)。

CHK 变更自动触发 CHI 协调(Auto-Reconcile)

Keeper 集群扩缩容后,ClickHouse 侧需要感知新的节点列表。Operator 提供了可选的 CHK 资源监听机制:

# ClickHouseOperatorConfiguration spec: reconcile: coordination: keeper: readyTimeout: 120 onKeeperResourceUpdate: reconcile # "none"(默认)或 "reconcile"

onKeeperResourceUpdate: reconcile时:

  • Operator 在监听命名空间内 watch 所有 CHK 资源(pkg/controller/chi/controller-chk-watcher.go 中的StartCHKWatcher通过动态 informer 实现,resync 周期 60 秒);
  • 仅当 CHK转换到Completed状态时才触发依赖 CHI 的重新协调(onCHKUpdate只对"从非 Completed 变为 Completed"的转换响应,InProgress阶段不会触发,见 controller-chk-watcher.go);
  • 触发前会做一次端点差分shouldReconcileOnKeeperUpdate将当前 CHK 状态解析出的节点集合与 CHI 上次完成协调(NormalizedCRCompleted)消费的节点集合做集合相等比较(controller-chk-watcher.go)。只有当解析出的 ZooKeeper 端点列表确实发生变化时才入队协调——像磁盘扩容这类不影响端点列表的 CHK 变更会被跳过,并发出KeeperUpdateNoEndpointChange事件说明跳过原因。

这一差分机制保证了 ClickHouse 能及时跟上 Keeper 拓扑变化(如 Keeper 扩缩容),同时避免无意义的空转协调。

故障排查(Troubleshooting)

查看解析出的端点

解析后的 Keeper 节点会出现在 CHI 的归一化状态中:

kubectl get chi my-chi -o json | jq '.status.normalizedCompleted.spec.configuration.zookeeper.nodes'

查看 Kubernetes Events

Keeper 引用解析失败会发出 Kubernetes Events:

kubectl get events --field-selector involvedObject.name=my-chi,reason=ReconcileFailed

结合前文,还可以用reason=KeeperUpdateNoEndpointChange查看"CHK 完成但端点未变化、协调被跳过"的事件。

常见问题速查表

症状原因解决方法
CHI 卡在 InProgressCHK Pod 未运行检查 CHK 状态:kubectl get chk
CHI 协调超时失败readyTimeout过短在 Operator 配置中增大readyTimeout
ClickHouse 无法连接 Keeperkeeper 引用中的 namespace 错误校验namespace字段,或省略以使用同命名空间
只解析出 1 个 ZK 节点使用了serviceType: service切换为serviceType: replicas(默认)
Keeper 扩缩后 CHI 未更新Watcher 未启用在 Operator 配置中设置onKeeperResourceUpdate: reconcile

另外,源码层面还有两个可辅助诊断的错误语义:ErrKeeperRefNoNodes提示解析成功但 CHK 当前没有任何可用的 host 服务(例如 CHK 尚未生成服务或副本数为 0);而replicas模式在副本发现失败时自动回退到 CR 级服务,若最终仍失败才会返回ErrKeeperRefResolve

完整配置示例

  • Basic keeper reference:最简引用 +session_timeout_ms/operation_timeout_ms组合;
  • All fields example:同时演示顶层keeper引用(注释形式)与集群级zookeeper.keeper覆盖(shards-only集群)、以及显式nodes对照写法;
  • Operator config with coordination:完整ClickHouseOperatorConfiguration,其中reconcile.coordination.keeper一节同时给出了readyTimeout: 120onKeeperResourceUpdate: none(默认值)的完整上下文,可在此基础上按需修改。

总结

KeeperRef 将"ClickHouse ↔ ZooKeeper/Keeper 拓扑"的耦合点从手工维护的host:port清单,收敛为对 CHK 资源的声明式引用。配合replicas模式的完整拓扑感知、基于服务端口的 TLS 自动检测、CHK 就绪等待与readyTimeout超时保护,以及onKeeperResourceUpdate: reconcile下的端点差分触发协调,Operator 能够在不改动 CHI 的情况下自动跟随 Keeper 集群的演进,这是生产环境搭建复制集群(如 docs/chi-examples/04-replication-zookeeper-07-keeper-ref.yaml 演示的 1 分片 2 副本场景)时推荐的首选方式。

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询