资讯动态

ClickHouse Operator 更新 ClickHouse 版本实战:基于 PodTemplate 的分级滚动升级指南

发布时间:2026/9/18 4:38:50 来源:尧图企业网站定制
ClickHouse Operator 更新 ClickHouse 版本实战基于 PodTemplate 的分级滚动升级指南【免费下载链接】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 仓库中的官方升级演练文档 docs/chi_update_clickhouse_version.md完整演示如何对一个运行中的 ClickHouseInstallationCHI进行版本升级并重点讲解「先灰度更新单个实例、再更新整个集群」的两步式操作以及这套机制背后的 PodTemplate 模板引用与覆盖原理。读完本文你将掌握如何编写带多版本 podTemplates 的 CHI 清单、如何用kubectl apply触发升级、如何逐个验证 Pod 上实际运行的 ClickHouse 版本以及 Operator 在源码层面如何解析模板引用并驱动 StatefulSet 完成滚动更新。前置条件集群中已经安装并正常运行clickhouse-operator安装方式可参考 operator_installation_details.md 与 quick_start.md拥有目标命名空间的kubectl操作权限。本文所有操作都在dev命名空间中进行且假设clickhouse-operator已部署在dev命名空间内。一、确认初始状态只有 Operator 在运行在安装任何 ClickHouse 之前先检查集群当前状态kubectl -n dev get all,configmap此时只有clickhouse-operator自身在运行输出大致如下NAME READY STATUS RESTARTS AGE pod/clickhouse-operator-5cbc47484-v5cfg 1/1 Running 0 17s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/clickhouse-operator-metrics ClusterIP 10.102.229.22 none 8888/TCP 17s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/clickhouse-operator 1/1 1 1 17s NAME DESIRED CURRENT READY AGE replicaset.apps/clickhouse-operator-5cbc47484 1 1 1 17s这一步的价值在于在干净的初始环境下安装后续所有由 Operator 创建的 Pod、Service、ConfigMap 都归属于我们的 CHI 资源便于观察「版本更新」动作的完整副作用。二、安装初始版本的 ClickHouseInstallation使用仓库中提供的初始位置清单 08-clickhouse-version-update-01-initial-position.yaml 安装集群kubectl -n dev apply -f 08-clickhouse-version-update-01-initial-position.yaml该清单的核心内容如下完整文件见 docs/chi-examples/08-clickhouse-version-update-01-initial-position.yamlapiVersion: clickhouse.altinity.com/v1 kind: ClickHouseInstallation metadata: name: version-update spec: configuration: clusters: - name: update templates: podTemplate: clickhouse:24.8 # 集群级默认 Pod 模板 layout: shards: - replicas: - tcpPort: 9000 # 3 个副本3 个独立 Pod - tcpPort: 9000 - tcpPort: 9000 templates: podTemplates: - name: clickhouse:24.8 # 模板名可被上层引用 spec: containers: - name: clickhouse-pod image: clickhouse/clickhouse-server:24.8说明官方文档正文以23.3.0 → 23.8.0为例叙述升级流程而当前仓库中这三个演练清单使用的镜像版本分别为24.8、24.3、23.8。本文以仓库内实际清单文件为准展开讲解原理与操作步骤完全一致。这个清单展示了版本更新的两个核心构造模板定义spec.templates.podTemplates下声明一个名为clickhouse:24.8的 PodTemplate其spec.containers[].image指定了 ClickHouse 服务器镜像模板引用spec.configuration.clusters[].templates.podTemplate引用该模板名。由于它位于 cluster 层级会作为该集群内所有实例Host的默认模板生效。模板引用在源码中的定义模板引用字段定义在 pkg/apis/clickhouse.altinity.com/v1/type_templates_list.go 的TemplatesList结构中它同时支持 Host 级与集群级引用type TemplatesList struct { HostTemplate string json:hostTemplate,omitempty yaml:hostTemplate,omitempty PodTemplate string json:podTemplate,omitempty yaml:podTemplate,omitempty DataVolumeClaimTemplate string json:dataVolumeClaimTemplate,omitempty yaml:dataVolumeClaimTemplate,omitempty LogVolumeClaimTemplate string json:logVolumeClaimTemplate,omitempty yaml:logVolumeClaimTemplate,omitempty ServiceTemplate string json:serviceTemplate,omitempty yaml:serviceTemplate,omitempty // ... 其他模板引用 }而 PodTemplate 本体定义在 pkg/apis/clickhouse.altinity.com/v1/type_templates.go其Spec直接复用 Kubernetes 原生的core.PodSpectype PodTemplate struct { Name string json:name yaml:name GenerateName string json:generateName,omitempty yaml:generateName,omitempty Zone PodTemplateZone json:zone,omitempty yaml:zone,omitempty PodDistribution []PodDistribution json:podDistribution,omitempty yaml:podDistribution,omitempty ObjectMeta meta.ObjectMeta json:metadata,omitempty yaml:metadata,omitempty Spec core.PodSpec json:spec,omitempty yaml:spec,omitempty }正因为 PodTemplate 的Spec是标准 PodSpecimage字段的修改会直接反映到最终生成的 StatefulSet Pod 模板上——这是「改模板即改版本」的根本原因。验证初始安装结果再次查看命名空间内的资源kubectl -n dev get all,configmap可以看到 ClickHouse 集群已创建3 个 Pod 全部处于Running状态NAME READY STATUS RESTARTS AGE pod/chi-06791a-28a0-0-0-0 1/1 Running 0 9s pod/chi-06791a-28a0-0-1-0 1/1 Running 0 9s pod/chi-06791a-28a0-0-2-0 1/1 Running 0 9s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/chi-06791a-28a0-0-0 ClusterIP None none 8123/TCP,9000/TCP,9009/TCP 9s service/chi-06791a-28a0-0-1 ClusterIP None none 8123/TCP,9000/TCP,9009/TCP 9s service/chi-06791a-28a0-0-2 ClusterIP None none 8123/TCP,9000/TCP,9009/TCP 9s service/clickhouse-version-update LoadBalancer 10.111.214.30 pending 8123:32444/TCP,9000:30048/TCP,9009:31089/TCP 9s NAME READY AGE statefulset.apps/chi-06791a-28a0-0-0 1/1 9s statefulset.apps/chi-06791a-28a0-0-1 1/1 9s statefulset.apps/chi-06791a-28a0-0-2 1/1 9s NAME DATA AGE configmap/chi-06791a-common-configd 2 9s configmap/chi-06791a-common-usersd 0 9s configmap/chi-06791a-deploy-confd-28a0-0-0 1 9s configmap/chi-06791a-deploy-confd-28a0-0-1 1 9s configmap/chi-06791a-deploy-confd-28a0-0-2 1 9s从输出可以提炼出 Operator 资源模型的关键事实命名规律Pod、StatefulSet、ConfigMap 均以chi-chi-hash-cluster-hash-...命名chi-06791a与28a0分别是对 CHI 名和集群名哈希后的结果一实例一 StatefulSet3 个副本各自对应一个独立 StatefulSetchi-06791a-28a0-0-0/1/2而不是一个多副本 StatefulSet。这意味着 Operator 可以在 Host 粒度上精确控制每个实例的更新服务类型每个实例有独立的 Headless Service同时存在一个名为clickhouse-version-update的 LoadBalancer 型外部服务暴露8123/9000/9009端口HTTP、原生 TCP、集群间通信端口。逐个验证 Pod 内实际运行的版本按初始清单所有 Pod 都应运行清单中指定的镜像版本。进入每个 Pod 执行 ClickHouse 客户端确认kubectl -n dev exec -it chi-06791a-28a0-0-0-0 -- clickhouse-clientClickHouse client version 23.3.0. Connecting to localhost:9000. Connected to ClickHouse server version 23.3.0 revision 54413.kubectl -n dev exec -it chi-06791a-28a0-0-1-0 -- clickhouse-clientClickHouse client version 23.3.0. Connecting to localhost:9000. Connected to ClickHouse server version 23.3.0 revision 54413.kubectl -n dev exec -it chi-06791a-28a0-0-2-0 -- clickhouse-clientClickHouse client version 23.3.0. Connecting to localhost:9000. Connected to ClickHouse server version 23.3.0 revision 54413.三个 Pod 运行版本一致revision 54413是服务端程序修订号可据此判断服务端版本细节。初始状态确认无误接下来按两个步骤执行升级先更新一个ClickHouse 实例一个 Pod再更新其余所有实例其余所有 Pod。三、第一步只更新一个实例灰度/金丝雀更新在生产场景中直接整集群升级风险较高。官方演练的第一步是只更新最后一个实例观察其运行情况后再推进。做法是在**单个副本replica / Host**上显式指定与集群默认不同的 PodTemplate。应用清单 08-clickhouse-version-update-02-apply-update-one.yamlkubectl -n dev apply -f 08-clickhouse-version-update-02-apply-update-one.yaml该清单与初始版本的关键差异如下完整文件见 docs/chi-examples/08-clickhouse-version-update-02-apply-update-one.yamlspec: configuration: clusters: - name: update templates: podTemplate: clickhouse:24.3 # 集群默认模板改为 24.3 layout: shards: - replicas: - tcpPort: 9000 # 实例 0使用集群默认 24.3 - tcpPort: 9000 # 实例 1使用集群默认 24.3 - tcpPort: 9000 templates: podTemplate: clickhouse:24.8 # 实例 2Host 级覆盖为 24.8 templates: podTemplates: - name: clickhouse:24.3 # 新增 24.3 模板 spec: containers: - name: clickhouse-pod image: clickhouse/clickhouse-server:24.3 - name: clickhouse:24.8 # 保留 24.8 模板 spec: containers: - name: clickhouse-pod image: clickhouse/clickhouse-server:24.8关键点是Host 级模板覆盖在第三个副本replica的templates.podTemplate下显式写了clickhouse:24.8而前两个副本没有写因此它们继承集群级默认的clickhouse:24.3。三个实例因此可以各自运行不同的 ClickHouse 版本。模板覆盖机制的源码印证从 pkg/apis/clickhouse.altinity.com/v1/type_templates_list.go 可以看到TemplatesList提供了HasPodTemplate()/GetPodTemplate()等方法并且mergeFromFillEmptyValues上游如集群级模板引用会在下游如 Host 级为空时填充进来mergeFromOverwriteByNonEmptyValues下游非空值可以覆盖上游值。也就是说模板引用的解析遵循「集群级 → 分片级 → Host 级」的自上而下继承、下级非空即覆盖的规则Host 级显式指定的podTemplate优先级最高。这正是「第三个实例单独升级、其余实例保持默认」能够成立的原因。验证只有一个实例被更新升级动作由 Operator 的 reconcile 循环触发入口见 pkg/controller/chi/worker-reconciler-chi.go其中对每个 Host 调用ReconcileStatefulSet。等待收敛后逐一检查三个 Pod 的版本kubectl -n dev exec -it chi-06791a-28a0-0-0-0 -- clickhouse-clientClickHouse client version 23.3.0. Connecting to localhost:9000. Connected to ClickHouse server version 23.3.0 revision 54413.第二个 Podkubectl -n dev exec -it chi-06791a-28a0-0-1-0 -- clickhouse-clientClickHouse client version 23.3.0. Connecting to localhost:9000. Connected to ClickHouse server version 23.3.0 revision 54413.最关键的第三个 Podkubectl -n dev exec -it chi-06791a-28a0-0-2-0 -- clickhouse-clientClickHouse client version 23.8.0. Connecting to localhost:9000 as user default. Connected to ClickHouse server version 23.8.0 revision 54415.前两个 Pod 仍是旧版本而第三个 Pod 已经运行了显式指定的新版本注意revision 54415高于旧版的54413且连接信息多出as user default。同一集群内多版本并存的能力得到验证——这为灰度发布、逐实例推进升级提供了操作基础。四、第二步更新整个集群单个实例验证通过后将集群整体切换到新版本。应用清单 08-clickhouse-version-update-03-apply-update-all.yamlkubectl -n dev apply -f 08-clickhouse-version-update-03-apply-update-all.yaml该清单将集群级默认模板指向clickhouse:23.8且所有副本都不再携带 Host 级覆盖完整文件见 docs/chi-examples/08-clickhouse-version-update-03-apply-update-all.yamlspec: configuration: clusters: - name: update templates: podTemplate: clickhouse:23.8 # 集群默认模板 layout: shards: - replicas: - tcpPort: 9000 - tcpPort: 9000 - tcpPort: 9000 templates: podTemplates: - name: clickhouse:24.8 # 模板定义仍保留在清单中 spec: containers: - name: clickhouse-pod image: clickhouse/clickhouse-server:24.8注意这里有意保留了一个「未被引用」的clickhouse:24.8模板定义多余模板不会报错Operator 只会按引用关系生效。实践中建议及时清理无用模板保持清单整洁。验证所有 Pod 均为新版本kubectl -n dev exec -it chi-06791a-28a0-0-0-0 -- clickhouse-clientClickHouse client version 23.8.0. Connecting to localhost:9000 as user default. Connected to ClickHouse server version 23.8.0 revision 54415.kubectl -n dev exec -it chi-06791a-28a0-0-1-0 -- clickhouse-clientClickHouse client version 23.8.0. Connecting to localhost:9000 as user default. Connected to ClickHouse server version 23.8.0 revision 54415.kubectl -n dev exec -it chi-06791a-28a0-0-2-0 -- clickhouse-clientClickHouse client version 23.8.0. Connecting to localhost:9000 as user default. Connected to ClickHouse server version 23.8.0 revision 54415.三个 Pod 全部升级到新版本整个集群版本更新完成。五、原理纵深Operator 如何驱动版本更新理解了「改 YAML → 版本变化」的用法后再看 Operator 源码中的实现链路能帮你更好地预测行为与排查问题。1. 模板规范化NormalizerCHI 清单在被应用后会先经过规范化处理。在 pkg/model/chi/normalizer/normalizer.go 的normalizePodTemplate中每个 podTemplates 条目会被规范化并引入模板索引Index后续根据templates.podTemplate引用名即可快速查找到对应的 Pod 模板// normalizePodTemplate normalizes .spec.templates.podTemplates func (n *Normalizer) normalizePodTemplate(template *chi.PodTemplate) { ... templates.NormalizePodTemplate(n.macro, n.labeler, replicasCount, template) // Introduce PodTemplate into Index ... }从代码结构看Operator 会把清单解析为「模板库 引用关系」两个层面Host 在生成时通过GetPodTemplate()取出最终生效的 PodSpec见 pkg/model/chi/normalizer/normalizer-host.go 以及 pkg/model/chi/namer/name.go 中通过 PodTemplate 解析 Pod 命名模式等逻辑。2. StatefulSet 调和与滚动更新版本更新的落地依赖ReconcileStatefulSet该函数在 pkg/controller/chi/kube/statesfulset.go 中实现并由 pkg/controller/chi/worker-reconciler-chi.go 对每个 Host 逐一调用。因为 CHI 的每个副本对应一个独立的 StatefulSet所以修改某个 Host 的模板引用 → 只重建/更新对应的 StatefulSetPod 其余部分不受影响模板中image变化会反映到 StatefulSet 的 Pod 模板 → 触发 Kubernetes 原生的滚动更新策略RollingUpdate因此“灰度一个实例”与“整集群升级”本质上是同一套机制在不同引用粒度上的应用。3. 版本更新的运维要点更新路径规划官方提供了从初始位置到升级的完整示例序列08-*系列配合 docs/chi-examples/07-rolling-update-stateless-01-initial-position.yaml 与 docs/chi-examples/09-rolling-update-emptydir-01-initial-position.yaml 等滚动更新示例可以覆盖有状态持久卷与无状态emptyDir两种场景验证手段clickhouse-client输出的 server version 与 revision 是判断升级是否生效的最直接依据也可以结合kubectl get statefulset观察 Pod 模板 hash 变化与滚动状态故障回退由于 Operator 采用声明式调和只要把清单中的模板引用回退到旧版本镜像并重新kubectl apply即可触发反向滚动恢复到旧版本多版本并存期间灰度窗口内新旧版本实例同时对外服务建议先在测试集群完整演练参考 tests/ 目录下的 e2e 用例确认跨版本兼容后再在生产集群执行。六、小结通过三步操作——安装初始版本、Host 级覆盖升级单个实例、集群级默认模板升级全部实例——本指南完整演示了 ClickHouse Operator 的版本更新能力。核心要点总结如下要点说明版本来源版本由spec.templates.podTemplates[].spec.containers[].image定义引用层级集群级templates.podTemplate为默认Host 级templates.podTemplate可覆盖详见 type_templates_list.go触发方式修改清单后kubectl applyOperator 自动调和对应 StatefulSet更新粒度每个副本一个 StatefulSet可单实例灰度也可整集群更新验证方法kubectl exec ... -- clickhouse-client查看 server version 与 revision这套「模板引用 声明式调和 StatefulSet 滚动更新」的机制让 ClickHouse 版本升级从手工逐节点操作变成了可控、可回退、可灰度的声明式流程。更多更新场景如添加副本、引入复制可继续阅读 chi_update_add_replication.md 与 docs/chi-examples 目录下的0*系列示例。【免费下载链接】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 小时内与您沟通定制方案

免费获取报价