ClickHouse Operator TestFlows 测试套件全解析:从环境搭建到回归执行
2026/9/18 23:53:48 网站建设 项目流程

ClickHouse Operator TestFlows 测试套件全解析:从环境搭建到回归执行

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

tests/README.md 是 ClickHouse Operator 仓库中关于端到端测试套件的唯一权威说明,本文以其为骨架,结合 tests/regression.py、tests/e2e/、tests/image/、tests/docker-compose/ 等目录的源码与配置,全面还原该 TestFlows 测试体系的运行机制、环境要求、镜像构建、并行回归执行与测试用例定位方法,帮助你快速在本机或 CI 中跑通这套覆盖 ClickHouse 集群全生命周期场景的测试。

一、测试套件是什么:TestFlows 驱动的一整套 e2e 回归

ClickHouse Operator 的测试代码集中在仓库的 tests/ 目录下,其核心是 tests/README.md 描述的 TestFlows 测试框架(Python 实现的通用测试框架)。它不是单点单元测试,而是一套完整的端到端(e2e)回归体系:每个测试会真实地拉起 Kubernetes(内部使用 minikube)、安装 ClickHouse Operator、创建 ClickHouseInstallation(CHI)等自定义资源、等待集群就绪、执行 ClickHouse 查询验证,最后清理命名空间。

从 tests/regression.py 的入口可以看出整个回归套件的组成:

@TestSuite @XFails(xfails) @ArgumentParser(argparser) @Specifications(QA_SRS026_ClickHouse_Operator) def regression(self, native, keeper_type): """ClickHouse Operator test regression suite.""" def run_features(): features = [ "e2e.test_metrics_exporter", "e2e.test_metrics_alerts", "e2e.test_backup_alerts", "e2e.test_operator", "e2e.test_clickhouse", "e2e.test_examples", "e2e.test_keeper", ] for feature_name in features: Feature(run=load(feature_name, "test"))

即回归套件由 7 个 Feature 组成:test_metrics_exportertest_metrics_alertstest_backup_alertstest_operatortest_clickhousetest_examplestest_keeper,分别对应 tests/e2e/test_metrics_exporter.py、tests/e2e/test_operator.py 等测试模块。每个模块内又包含大量以test_开头的@TestScenario测试场景。

注意:README 明确说明,当前套件"目前只涉及 operator 自身的测试,不包括 operator 依赖的第三方工具的测试"——即测试对象是 Operator 本身,ZooKeeper、MinIO、Prometheus 等第三方组件只是作为被测环境的依赖被安装。

每个测试场景都通过@Requirements(...)注解关联到需求文档 tests/requirements/requirements.md 中的 QA-SRS026 需求项,形成"需求 → 测试"的可追溯关系。例如 tests/e2e/test_operator.py 中的第一个测试:

@TestScenario @Name("test_010001. 1 node") @Requirements(RQ_SRS_026_ClickHouseOperator_Create("1.0")) def test_010001(self): create_shell_namespace_clickhouse_template() chi = "test-001" kubectl.create_and_check( manifest="manifests/chi/test-001.yaml", check={ "object_counts": {"statefulset": 1, "pod": 1, "service": 2}, "configmaps": 1, "pdb": {"single": 1}, "do_not_delete": 1, }, ) ...

这个测试通过 tests/e2e/kubectl.py 封装调用 kubectl 创建 CHI 清单 tests/e2e/manifests/chi/test-001.yaml,并断言生成的 StatefulSet、Pod、Service、ConfigMap、PDB 数量,再通过 tests/e2e/clickhouse.py 向集群内 ClickHouse 发起 SQL 查询做行为验证。测试编号按功能域划分(010xxx 集群创建、011xxx 安全与 Secret、014xxx 复制、021xxx 卷扩容等),可在 tests/e2e/manifests/chi/ 下找到与编号一一对应的 YAML 清单。

二、环境要求:两种执行方式的前提条件

README 给出了两种执行方式,其依赖截然不同:

2.1 Docker 容器方式(默认,约 2 倍慢但免配置)

在 Docker 容器中执行是默认路径,测试跑在一个专门构建的 runner 容器里,容器内部自带 minikube + docker,因此宿主机几乎不需要任何 Kubernetes 环境配置,代价是性能约为本机执行的 1/2。需要:

  • dockerdocker-compose
  • python3

2.2 本机原生方式(--native,快但要求环境齐全)

在本机直接跑测试时,测试进程直接使用宿主机的 kubectl 与 Python 环境,需要:

  • kubectl(且已配置好可用的集群上下文)
  • python3
  • jq(用于解析 kubectl 输出与 CI 脚本)

2.3 公共依赖:Python 3.8+ 与 TestFlows

无论哪种方式,都需要Python 3.8 或更高版本,并安装 TestFlows 测试框架及配套依赖,即 tests/image/requirements.txt:

testflows==2.2.8 requests PyYAML setuptools

安装命令为:

pip3 install -r ./tests/image/requirements.txt

从源码看,TestFlows 被用于测试的组织与执行控制:@TestSuite定义套件、@TestScenario定义场景、@XFails声明已知失败用例(见 tests/regression.py,例如test_010021存储测试在 GitHub 上不稳定、Keeper 扩缩容 flaky 等)、Feature(run=load(...))动态加载子模块。这些机制共同支撑了"按路径过滤执行"的核心用法。

三、构建测试镜像:本地构建 vs 直接拉取

运行 Docker 方式测试时,runner 镜像默认从 GitLab registry 拉取:

registry.gitlab.com/altinity-public/container-images/clickhouse-operator-test-runner:latest

README 同时给出了本地构建并推送该镜像的步骤:

docker login registry.gitlab.com bash -xe ./tests/image/build_docker.sh docker push registry.gitlab.com/altinity-public/container-images/clickhouse-operator-test-runner:latest

⚠️镜像体积提醒:README 明确提示,无论构建还是拉取,都需要约5 GB 的下载数据。这是因为 tests/image/Dockerfile 会装入 docker-ce、minikube 1.27.1、kubectl、k9s、yq、jq 等全套工具,而 tests/image/build_docker.sh 还会预拉并docker save一长串镜像(clickhouse-server 23.8/23.3/latest、ZooKeeper、operator/metrics-exporter 新旧版本、MinIO、Prometheus 全家桶、clickhouse-backup、busybox 等)缓存进镜像,使得测试运行时无需再从公网拉取。

其中build_docker.sh支持大量可通过环境变量覆盖的版本参数,例如:

OPERATOR_VERSION=${OPERATOR_VERSION:=0.23.0} OPERATOR_VERSION_OLD=${OPERATOR_VERSION_OLD:=0.22.2} CLICKHOUSE_IMAGE=${CLICKHOUSE_IMAGE:="clickhouse/clickhouse-server:23.8"} K8S_VERSION=${K8S_VERSION:=1.28.5} ZOOKEEPER_IMAGE=${ZOOKEEPER_IMAGE:="zookeeper:3.8.4"} CLICKHOUSE_OPERATOR_TESTS_IMAGE=${CLICKHOUSE_OPERATOR_TESTS_IMAGE:="registry.gitlab.com/altinity-public/container-images/clickhouse-operator-test-runner:latest"}

这些环境变量与 tests/e2e/settings.py 中的默认值互相呼应——settings.py里同样支持通过OPERATOR_VERSIONCLICKHOUSE_TEMPLATETEST_NAMESPACEKEEPER_TYPE等环境变量覆盖测试上下文,实现"同一套测试代码跑多版本矩阵"。

四、执行完整回归:一条命令跑通 operator 测试

4.1 Docker 方式执行(默认)

README 给出的标准执行命令是:

pip3 install -U -r ./tests/image/requirements.txt docker pull registry.gitlab.com/altinity-public/container-images/clickhouse-operator-test-runner:latest COMPOSE_HTTP_TIMEOUT=1800 python3 ./tests/regression.py --only "/regression/e2e.test_operator/*"

要点解读:

  • 先升级安装测试依赖,再拉取 runner 镜像(或使用本地已构建镜像)。
  • COMPOSE_HTTP_TIMEOUT=1800将 docker-compose 的 HTTP 超时放宽到 1800 秒。这是因为 tests/docker-compose/docker-compose.yml 定义的runner服务是privileged: true的,其入口 tests/image/dockerd-start.sh 会在容器内启动一个嵌套的 docker daemon 用于跑 minikube,健康检查会等到kubectl get pods --namespace kube-system中出现 clickhouse-operator 的 Running Pod 才判定就绪(start_period: 600s,即最多等待 10 分钟);all_services_ready这个 dummy 服务用来在依赖全部 healthy 后才真正开始跑测试。首次启动嵌套 docker 并拉起集群耗时较长,因此必须调大 HTTP 超时。
  • --only "/regression/e2e.test_operator/*"是 TestFlows 的路径过滤参数:/regression对应 tests/regression.py 中的regression套件,e2e.test_operator对应 tests/e2e/test_operator.py 模块,*表示该模块下所有场景。按 README 的说法,当前套件"只包含 operator 测试,不包含 operator 所用第三方工具的测试",因此用这条命令即可覆盖当前完整回归内容。

4.2 原生方式执行

在本机直接执行只需追加--native参数:

COMPOSE_HTTP_TIMEOUT=1800 python3 ./tests/regression.py --native --only "/regression/e2e.test_operator/*"

该参数由 tests/helpers/argparser.py 定义:--nativestore_true,帮助信息写着"run tests without docker-compose, require only working kubectl + python"。settings.py中会根据该标志决定 kubectl 命令形态——原生模式下直接调用宿主机kubectl,Docker 模式下则通过docker-compose -f .../docker-compose.yml exec -T runner kubectl在容器内执行。

4.3 并行与串行控制

README 指出:

Tests running in parallel by default, to run it consistently, add--parallel offparameter.

测试默认并行执行,如需稳定串行执行,添加--parallel off

COMPOSE_HTTP_TIMEOUT=1800 python3 ./tests/regression.py --parallel off --only "/regression/e2e.test_operator/*"

TestFlows 的--parallel参数控制测试场景的并发调度:并行模式能显著缩短整体耗时(尤其在 Docker runner 场景下),但多个场景同时操作同一集群/命名空间时可能互相干扰;--parallel off保证场景严格串行,适合调试单个失败或用例之间共享集群状态的场景。

此外,tests/e2e/run_tests_operator.sh 展示了在 CI 中编排回归的完整形态:先安装 pip 依赖、导出测试环境变量,然后调用regression.py,并支持RETRY_COUNT/RETRY_DELAY环境变量注入--retry "/regression/e2e.test_operator/test_0:,${RETRY_COUNT},,${RETRY_DELAY:-30}"参数实现失败自动重试,以及-o short--trim-results on--debug等输出控制选项。同类脚本还有 tests/e2e/run_tests_keeper.sh、tests/e2e/run_tests_metrics.sh、tests/e2e/run_tests_parallel.sh 等,分别面向 Keeper、Metrics 和并行编排场景。

五、只跑单个测试:按编号过滤与用例定位

5.1 按测试编号过滤

README 给出只执行单个测试的方法:

COMPOSE_HTTP_TIMEOUT=1800 python3 ./tests/regression.py --only "/regression/e2e.test_operator/test_009*"

其中009可替换为任意测试编号前缀,*通配该前缀下的所有场景。例如:

  • --only "/regression/e2e.test_operator/test_009*":只跑 operator 升级相关测试(对应 tests/e2e/manifests/chi/test-009-operator-upgrade-1.yaml、test-009-operator-upgrade-2.yaml);
  • --only "/regression/e2e.test_operator/test_021*":只跑卷扩容(rescale volume)测试;
  • 若要跑其他 Feature,把路径中间段换掉即可,如"/regression/e2e.test_keeper/*""/regression/e2e.test_metrics_alerts/*"

5.2 编号与名称的对应关系从哪来

README 明确说明:

Tests --- numbers and names correspondence may be found intests/regression.pyandtests/test_*.pysource code files.

注意此处 README 书写的tests/test_*.py实际对应仓库中的 tests/e2e/test_*.py 目录。每个测试场景的@Name注解即展示编号与名称,例如 tests/e2e/test_operator.py 的@Name("test_010001. 1 node")@Name("test_010002. useTemplates for pod, volume templates, and distribution")等。查询方式:

grep -n "@Name(\"test_009" tests/e2e/test_operator.py

同时,tests/e2e/manifests/chi/ 下与编号对应的 YAML 文件(如test-009-operator-upgrade-1.yamltest-009-operator-upgrade-2.yaml)展示了该测试实际应用的 CHI 资源定义,是理解用例意图的第一手资料;tests/requirements/requirements.md(QA-SRS026 需求规格)则提供了每个测试所验证需求的官方语义。

六、测试运行背后的实现机制

为了让读者对这套测试有更深理解,这里结合仓库源码补充几个关键机制(均可在仓库中直接验证):

6.1 测试上下文与环境变量

tests/e2e/settings.py 集中定义了测试运行时的可调参数,且几乎都支持环境变量覆盖,常用项包括:

环境变量默认值说明
TEST_NAMESPACEtest测试命名空间
OPERATOR_NAMESPACETEST_NAMESPACEOperator 安装的命名空间
OPERATOR_VERSION读取仓库根目录release文件被测 Operator 版本
OPERATOR_INSTALLyes是否自动安装 Operator
OPERATOR_DOCKER_REPOaltinity/clickhouse-operatorOperator 镜像仓库
METRICS_EXPORTER_DOCKER_REPOaltinity/metrics-exportermetrics-exporter 镜像仓库
CLICKHOUSE_OPERATOR_INSTALL_MANIFEST../../deploy/operator/clickhouse-operator-install-template.yaml安装清单路径
CLICKHOUSE_TEMPLATEmanifests/chit/tpl-clickhouse-stable.yaml被测 ClickHouse 版本模板
KEEPER_TYPEzookeeperzookeeperclickhouse_keeper,选择元数据存储
KUBECTL_MODEapplykubectl 应用方式(apply/replace
NO_CLEANUP未设置设为1/true/yes时测试结束不清理命名空间(调试用)
STEP未设置设为任意值时开启逐步执行模式

其中KEEPER_TYPE对应 tests/helpers/argparser.py 中的--keeper-type参数(可选zookeeperclickhouse-keeper,默认zookeeper),用于在同一套测试下分别验证以 ZooKeeper 或 ClickHouse Keeper 作为复制协调存储的两种部署形态;CLICKHOUSE_TEMPLATE指向 tests/e2e/manifests/chit/ 下的版本模板(如tpl-clickhouse-stable.yamltpl-clickhouse-23.8.yaml等),实现"同一测试逻辑、多 ClickHouse 版本矩阵"的回归。

6.2 Docker runner 的嵌套集群结构

tests/docker-compose/docker-compose.yml 揭示了 Docker 方式的结构:runner服务以privileged: true+network_mode: "host"运行,挂载仓库根目录../../到容器内/home/master/clickhouse-operator/,容器内启动 dockerd(入口脚本 tests/image/dockerd-start.sh),minikube 在该嵌套 docker 中创建 Kubernetes 集群,测试进程再通过docker-compose exec进入 runner 执行 kubectl。健康检查kubectl get pods --namespace kube-system | grep clickhouse-operator | grep Running确保整个链路就绪后才启动测试。

6.3 测试断言与清理模式

以 tests/e2e/test_operator.py 为例,每个场景遵循统一模式:create_shell_namespace_clickhouse_template()创建命名空间与初始资源 →kubectl.create_and_check(...)应用 CHI 清单并断言对象数量/模板应用结果/Pod 镜像/卷等 → 通过clickhouse.query(...)在 Pod 内执行 SQL 做行为验证(如第 106-113 行验证不同副本的default_replica_name各不相同)→kubectl.delete_chi(chi)删除 CHI →delete_test_namespace()清理命名空间。这种"创建-断言-查询-清理"模式贯穿全部 e2e 测试。

七、常见问题与调优建议

7.1 首次运行非常慢 / 卡在拉取镜像

首次运行 Docker 方式需要拉取约 5 GB 的 runner 镜像并构建嵌套集群,耗时可达数十分钟。建议:

  • 先执行docker pull单独拉取镜像,确认网络通畅;
  • 设置COMPOSE_HTTP_TIMEOUT=1800(或更大值)避免 docker-compose 因健康检查等待超时;
  • 若网络受限,可在有网环境先执行 tests/image/build_docker.sh 构建并推送镜像,目标机器直接 pull。

7.2 并行测试互相干扰

默认并行执行时,多个场景共享同一集群,若出现偶发失败,可改用--parallel off串行执行以定位问题;反之若 CI 中串行耗时过长,可参照 tests/e2e/run_tests_parallel.sh 做并行编排,并配合RETRY_COUNT/RETRY_DELAY对已知 flaky 用例设置重试。

7.3 已知失败用例(xfails)

tests/regression.py 中通过xfails字典声明了一批当前已知失败或已知 flaky 的测试,例如:

xfails = { "/regression/e2e.test_operator/test_010021*": [(Fail, "Storage test is flaky on github")], "/regression/e2e.test_operator/test_020005*": [(Fail, "Keeper scale-up/scale-down is flaky")], "/regression/e2e.test_clickhouse/test_ch_001*": [(Fail, "Insert Quorum test need to refactoring")], ... }

这些用例会被 TestFlows 的@XFails注解标记为"允许失败",跑回归时不会因它们而整体报红。调试时应先查看该列表,避免在已知 flaky 用例上浪费时间;同时也可在本地把对应条目注释掉后单独重跑,验证是否已修复。

7.4 调试单个场景

  • 使用--only "/regression/e2e.test_operator/test_<编号>*"缩小范围;
  • 设置NO_CLEANUP=1让测试结束后保留命名空间与资源,便于人工检查kubectl get chi -n test -o yaml或查看 Pod 日志;
  • 设置STEP=1进入逐步执行模式,配合 tests/e2e/steps.py 中的步骤化操作逐步观察;
  • 使用KUBECTL_MODE=replace可切换 kubectl 的应用方式(apply/replace),复现某些场景下两种方式的差异。

八、小结

tests/README.md 虽短,却精确勾勒出 ClickHouse Operator e2e 测试的完整操作路径:TestFlows 框架 + Python 3.8+ 依赖 → Docker runner(默认)或原生(--native)两种执行环境 → build_docker.sh 构建约 5 GB 的测试镜像 → regression.py 按 Feature 加载 7 大测试模块 → --only 路径过滤精准选测 → --parallel 控制并行度 → xfails 管理已知失败。配合本文补充的 tests/regression.py、tests/e2e/settings.py、tests/e2e/test_operator.py、tests/image/build_docker.sh、tests/docker-compose/docker-compose.yml 等源码依据,你可以快速在本机或 CI 中复现这套覆盖 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),仅供参考

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

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

立即咨询