news 2026/9/24 14:59:14

Prometheus Operator 端到端(E2E)测试完全指南:从本地集群搭建到自动化测试执行

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Prometheus Operator 端到端(E2E)测试完全指南:从本地集群搭建到自动化测试执行
  • 云原生
  • 可观测性

【免费下载链接】prometheus-operator

Prometheus Operator creates/configures/manages Prometheus clusters atop Kubernetes

项目地址:https://gitcode.com/gh_mirrors/pr/prometheus-operator
点击查看免费下载

Prometheus Operator 的端到端(E2E)测试是一套以 Go test 形式编写、在真实 Kubernetes 集群上运行的自动化测试,用于验证 Operator 在真实用户场景下的完整行为。本指南将围绕 test/e2e/README.md 的核心说明,结合仓库中的测试框架源码与 Makefile 构建目标,系统讲解 E2E 测试的前置条件、构建与运行方式、测试套件的组织与筛选、镜像准备以及失败诊断方法,帮助你从零开始在本机复现并调试这套与 CI 完全一致的测试体系。

E2E 测试是什么

端到端(End-to-end,E2E)测试是面向真实用户场景的自动化测试。与单元测试在隔离环境下验证单个函数不同,E2E 测试会启动一个真实的 Kubernetes 集群,在其中部署 Prometheus Operator、CRD、Prometheus/Alertmanager/ThanosRuler 等资源,并验证从"用户提交 CR 资源"到"Operator 完成协调并产生预期效果"的完整链路。

在 Prometheus Operator 仓库中,E2E 测试与单元测试、长时测试共同构成完整的测试矩阵,这一点在 TESTING.md 中有明确说明:

  • 单元测试:在隔离环境下测试特定代码片段,反馈循环最快;
  • 长时测试(long tests):包含耗时更长的单元测试用例;
  • E2E 测试:在真实 Kubernetes 集群中验证 Operator 的整体行为,也是 Pull Request 流水线中运行的那套测试。

从 Makefile 可以看到,三者可通过make test一键串联执行:

.PHONY: test test: test-unit test-long test-e2e ## Run all tests (unit, long, and e2e).

运行 E2E 测试的前置条件

根据 test/e2e/README.md,运行 E2E 测试需要满足三个前置条件:

  1. 一个正在运行的 Kubernetes 集群,以及对应的 kubeconfig,测试时需要把 kubeconfig 作为参数传入;
  2. kubeconfig 文件就绪,测试框架需要通过它连接集群的 API Server;
  3. Prometheus Operator 镜像就绪,用于在集群内拉起 Operator 的 Deployment。

E2E 测试本身是标准的 Go test 程序,因此 Go 测试的所有技术手段(例如选择运行哪些用例、控制超时时长)都同样适用。最简单的运行方式是直接调用go test

$ go test -v ./test/e2e/ --kubeconfig "$HOME/.kube/config" --operator-image=quay.io/prometheus-operator/prometheus-operator

其中:

  • --kubeconfig:指定 kubeconfig 文件的路径;
  • --operator-image:指定要部署到集群中的 Operator 镜像;
  • -v:输出每个测试用例的详细运行结果。

这两个自定义 flag 是在 test/e2e/main_test.go 的TestMain中通过标准库flag包注册的,这也是"E2E 测试是标准 Go test"这一说法的源码依据:

func TestMain(m *testing.M) { kubeconfig := flag.String( "kubeconfig", "", "kube config path, e.g. $HOME/.kube/config", ) opImage = flag.String( "operator-image", "", "operator image, e.g. quay.io/prometheus-operator/prometheus-operator", ) flag.Parse() // ... }

需要说明的是:直接运行go test时 Operator 镜像是已存在的(可以是本地构建并导入 kind 的镜像,也可以是远程仓库中的镜像)。测试框架会把该镜像写入 Operator 的 Deployment 清单中,具体逻辑见下文"测试框架如何拉起 Operator"一节。

推荐实践:通过 Makefile 运行 E2E 测试

虽然go test命令可以直接运行,但仓库在 Makefile 中封装了更完整的test-e2e目标,它会自动处理 kubeconfig 默认值、instrumented-sample-app 证书生成、镜像 tag 拼接等细节:

.PHONY: test-e2e test-e2e: KUBECONFIG?=$(HOME)/.kube/config test-e2e: test/instrumented-sample-app/certs/cert.pem test/instrumented-sample-app/certs/key.pem ## Run end-to-end tests. go test -timeout 120m -v ./test/e2e/ $(TEST_RUN_ARGS) --kubeconfig=$(KUBECONFIG) --operator-image=$(IMAGE_OPERATOR):$(TAG) -count=1

该目标的几个关键点:

  • KUBECONFIG默认取$(HOME)/.kube/config,可通过环境变量覆盖;
  • 依赖test/instrumented-sample-app/certs/下的证书,缺失时会通过 test/instrumented-sample-app/Makefile 的generate-certs目标自动生成;
  • 测试整体超时上限为120 分钟-timeout 120m);
  • -count=1禁用 Go 测试缓存,确保每次都是真实执行;
  • $(IMAGE_OPERATOR):$(TAG)中的镜像仓库默认为quay.io/prometheus-operator/prometheus-operatorTAG默认为当前 git 短提交哈希(见 Makefile);
  • 预留了TEST_RUN_ARGS变量,可向go test追加参数(例如只运行某个测试,见下文)。

也就是说,最直接的运行方式就是:

make test-e2e

make test-e2e会运行完整的 E2E 测试套件,与 Pull Request 流水线中执行的测试完全一致,确保所有控制器的功能需求都得到验证。

分控制器运行:按需裁剪测试范围

完整测试套件运行时间很长(即使在高配笔记本上也需要几十分钟甚至更久),而一次改动通常只会影响某一个控制器。为此,Makefile 提供了多个按控制器裁剪的目标,其实现原理是通过设置"排除类"环境变量来跳过不相关的测试套件(Makefile):

Makefile 目标运行内容等价环境变量组合(其余 EXCLUDE 变量设为非空)
make test-e2e-alertmanager仅 Alertmanager 相关测试EXCLUDE_ALERTMANAGER_TESTS=(不排除,其他全排除)
make test-e2e-prometheusPrometheus 测试(有限命名空间权限场景)EXCLUDE_PROMETHEUS_TESTS=(不排除)
make test-e2e-prometheus-all-namespaces常规 Prometheus 测试(全命名空间)EXCLUDE_PROMETHEUS_ALL_NS_TESTS=(不排除)
make test-e2e-thanos-rulerThanosRuler 相关测试EXCLUDE_THANOSRULER_TESTS=(不排除)
make test-e2e-operator-upgrade验证由上一版本 Operator 管理的监控栈升级到当前版本后仍正常EXCLUDE_OPERATOR_UPGRADE_TESTS=(不排除)
make test-e2e-prometheus-upgrade验证兼容矩阵内一系列 Prometheus 版本可依次升级EXCLUDE_PROMETHEUS_UPGRADE_TESTS=(不排除)
make test-e2e-feature-gates验证处于 feature gate 之后的特性EXCLUDE_FEATURE_GATED_TESTS=(不排除)

这些排除变量的作用在 test/e2e/main_test.go 中实现,例如:

func skipPrometheusAllNSTests(t *testing.T) { if os.Getenv("EXCLUDE_PROMETHEUS_ALL_NS_TESTS") != "" { t.Skip("Skipping Prometheus all namespace tests") } }

当对应环境变量非空时,相关测试套件会被t.Skip跳过。CI 中始终运行全部测试,但本地开发时通过跳过无关套件可以显著缩短反馈循环。

只运行单个测试

如果正在调试某个具体用例,可以结合TEST_RUN_ARGS与 Go 的-run参数精确锁定目标。例如只运行TestPrometheusRuleCRDValidation/valid-rule-names子测试:

TEST_RUN_ARGS="-run TestPrometheusRuleCRDValidation/valid-rule-names" make test-e2e-prometheus

TEST_RUN_ARGS会被拼接到go test命令中,配合-run正则即可只执行匹配的测试函数。

搭建本地测试集群与准备镜像

推荐使用 Kind

E2E 测试需要在真实集群上运行,官方推荐使用 KinD(Kubernetes in Docker):它足够轻量,能在小型笔记本上运行,同时也是项目 CI 使用的集群方案。Minikube 也是可选方案。

仓库在 test/e2e/kind-conf.yaml 中提供了 CI 所用的集群配置,包含两个关键设计:

  • kubelet 同步频率降为 10 秒:将 kubelet 同步挂载的 ConfigMap 与 Secret 的间隔从默认 1 分钟降到 10 秒,加速配置变更在容器中的传播,从而加快测试速度;
  • worker 节点打上可用区标签:两个 worker 分别标记为topology.kubernetes.io/zone: zone-azone-b,用于拓扑感知分片(topology sharding)类测试。

使用该配置创建集群:

kind create cluster --config test/e2e/kind-conf.yaml

构建镜像并加载到集群

在运行自动化 E2E 测试之前,需要先构建镜像并把它们加载进本地集群。使用 Docker 时执行:

KIND_CONTEXT=e2e make test-e2e-images

test-e2e-images目标(Makefile)会依次构建三个镜像并通过kind load加载进名为e2e的 kind 集群:

  • prometheus-operator(Dockerfile)
  • prometheus-config-reloader(cmd/prometheus-config-reloader/Dockerfile)
  • admission-webhook(cmd/admission-webhook/Dockerfile)

KIND_CONTEXT的默认值就是e2e(Makefile),因此如果集群名不是e2e,需要显式覆盖。

使用 podman 的注意事项

在 macOS 上使用 podman 运行 kind 时,建议用4个 CPU 和8 GiB内存创建 podman machine,资源不足会导致 E2E 测试因集群资源匮乏而失败:

podman machine init --cpus=4 --memory=8192 --rootful --now

随后用 podman 构建并加载镜像:

CONTAINER_CLI=podman KIND_CONTEXT=e2e make test-e2e-images

设置CONTAINER_CLI=podman后,Makefile 会改用podman save导出镜像归档,再用kind load image-archive加载。

测试套件的组织与测试入口

顶层测试函数一览

test/e2e/main_test.go 是 E2E 测试的入口文件,其中定义了多个顶层测试函数,每个函数对应一类测试场景:

顶层测试函数验证场景源码位置
TestAllNSOperator 监听全部命名空间(含 Alertmanager、Prometheus、ThanosRuler、多 Operator 并存)main_test.go#L168-L225
TestMultiNSOperator 只监听指定命名空间main_test.go#L360-L369
TestDenylistOperator 配置了拒绝监听的命名空间main_test.go#L372-L383
TestPromInstanceNs设置--prometheus-instance-namespace时的多场景行为main_test.go#L386-L401
TestRepairPolicyOperator 能修复损坏的 StatefulSetmain_test.go#L404-L413
TestAlertmanagerInstanceNs设置--alertmanager-instance-namespace时的多场景行为main_test.go#L416-L427
TestOperatorUpgrade从上一稳定小版本升级 Operator 后监控栈仍正常main_test.go#L430-L440
TestGatedFeaturesfeature gate 之后的特性(DaemonSet Agent、status 子资源、拓扑分片等)main_test.go#L447-L487
TestPrometheusVersionUpgrade兼容矩阵中各 Prometheus 版本可依次升级main_test.go#L490-L506

其中TestAllNS内部的 Prometheus 套件覆盖了非常广泛的场景,从 main_test.go#L264-L335 可以看到包括但不限于:CRD 校验、RemoteWrite 与 TLS、集群创建/删除/扩缩容、ServiceMonitor/PodMonitor 选择、Sharding/Resharding、Thanos 集成、UTF-8 指标与标签支持、状态条件(Degraded/Unavailable)等。

TestMain:测试的初始化与升级测试基础

TestMain 除了注册 flag,还做了两件关键的事情:

  1. 读取../../VERSION确定当前版本,并计算出"上一稳定小版本"与"下一小版本"(当前开发目标版本)。VERSION文件当前内容为0.94.0(见 VERSION)。
  2. 初始化两套测试框架
    • previousVersionFramework:使用上一稳定版本(如v0.93.x)的 Operator 镜像与示例资源目录,服务于 Operator 升级测试;
    • framework:使用传入的--operator-image与当前仓库的example/目录、test/framework/resources/目录,服务于常规测试。

这也解释了升级类测试的运作方式:它们会先用旧版本 Operator 部署并管理一套监控栈,再升级到当前版本,验证旧资源在升级后依旧被正确协调。

测试框架如何工作

Framework 对象与客户端初始化

E2E 测试的底层能力由 test/framework 包提供。Framework结构体(framework.go#L66-L81)聚合了与 Kubernetes 交互所需的全部客户端:

  • KubeClient:标准 Kubernetes client;
  • MonClientV1/MonClientV1alpha1/MonClientV1beta1:monitoring 组 v1 / v1alpha1 / v1beta1 三个 API 版本的客户端(对应pkg/apis/monitoring下的 CRD 类型);
  • APIServerClient:API 扩展客户端,用于操作 CRD 本身;
  • HTTPClient:复用 API Server 的 HTTP 客户端;
  • MasterHostRestConfig:API Server 地址与 REST 配置。

New()(framework.go#L84-L143)通过clientcmd.BuildConfigFromFlags("", kubeconfig)从 kubeconfig 构建连接配置,创建上述所有客户端,并校验集群至少存在一个节点,否则直接报错。

拉起 Operator:CreateOrUpdatePrometheusOperatorWithOpts

每个测试在运行前,都会通过CreateOrUpdatePrometheusOperatorWithOpts(framework.go#L254-L557)在集群中完整部署一套 Prometheus Operator,其流程包括:

  1. 基于 example/rbac/prometheus-operator/prometheus-operator-deployment.yaml 等清单创建 ServiceAccount、ClusterRole、ClusterRoleBinding;
  2. 依次创建并等待所有 CRD 就绪:Alertmanager、PodMonitor、Probe、Prometheus、PrometheusRule、ServiceMonitor、ThanosRuler、AlertmanagerConfig(v1alpha1/v1beta1)、PrometheusAgent,以及可选的 ScrapeConfig(通过EnableScrapeConfigs控制);
  3. 为 Operator 生成自签名证书并写入 Secret;
  4. 将 Operator Deployment 的镜像替换为--operator-image传入的镜像,并同步推导prometheus-config-reloaderadmission-webhook的镜像 tag;
  5. 根据测试需要注入启动参数,例如--namespaces--deny-namespaces--prometheus-instance-namespaces--alertmanager-instance-namespaces--feature-gates等;
  6. 若开启EnableAdmissionWebhook,还会部署 admission-webhook 服务,并配置 PrometheusRule 的变更/校验 webhook、AlertmanagerConfig 的校验 webhook 与 v1alpha1/v1beta1 转换 webhook;
  7. 返回一组 finalizer 函数,供测试结束(Cleanup)时回收资源。

PrometheusOperatorOpts(framework.go#L207-L218)集中表达了上述可配置项,包括命名空间白名单/黑名单、Prometheus/Alertmanager 实例命名空间、是否启用 admission webhook、ClusterRoleBinding、ScrapeConfig、附加参数与启用的 feature gate。

例如TestAllNS中通过如下方式部署 Operator(main_test.go#L176-L184):

finalizers, err := framework.CreateOrUpdatePrometheusOperatorWithOpts( ctx, operatorFramework.PrometheusOperatorOpts{ Namespace: ns, EnableAdmissionWebhook: true, ClusterRoleBindings: true, EnableScrapeConfigs: true, }, )

测试上下文与失败诊断

每个测试还会通过framework.NewTestCtx(t)(context.go#L103-L196)创建独立的TestCtx,其职责包括:

  • 生成唯一的命名空间:以测试名加时间戳为前缀,保证测试之间互不干扰;
  • 管理资源回收:所有创建的集群资源都通过AddFinalizerFn注册清理函数,测试结束(无论成功失败)时由Cleanup并行执行;
  • 失败诊断收集:当测试失败时,自动收集当前集群中的关键信息用于排查,包括工作负载资源(Alertmanager/Prometheus/ThanosRuler/PrometheusAgent)、配置资源(ServiceMonitor/PodMonitor/Probe/PrometheusRule/ScrapeConfig/AlertmanagerConfig)、Kubernetes 资源(StatefulSet/DaemonSet/Pod/Service/ConfigMap/Secret,其中 Secret 中的内容会被脱敏为obfuscated)、Pod 日志与事件。

诊断信息默认输出到 stdout;设置环境变量E2E_DIAGNOSTIC_DIRECTORY后,会改为按测试名分目录写入文件,便于归档分析:

E2E_DIAGNOSTIC_DIRECTORY=/tmp/e2e-diag make test-e2e-prometheus

手动运行 Operator:run-external.sh

除了完整的自动化测试,scripts/run-external.sh 提供了"手动测试"场景:它会在你的 kind 集群中检查所有前置条件,然后以本地编译的 Operator 二进制直接运行,适合开发调试。

./scripts/run-external.sh -c

该脚本的主要行为:

  • -c / --use-default-context:使用当前 kubeconfig 的默认 context;也可以直接传入 context 名;
  • -f / --no-operator-run-check:跳过"集群中不能已有 prometheus-operator 运行"的检查(脚本默认会检查并拒绝在已有 Operator 的集群上运行,避免冲突);
  • 从 kubeconfig 中提取 API Server 地址、CA、客户端证书与密钥;
  • 执行make operator构建本地二进制;
  • 通过kubectl apply --server-side --force-conflicts安装 example/prometheus-operator-crd-full 下的全部 CRD,并等待其 Established;
  • 以前台方式运行./operator,日志输出到tmp/operator.log

它支持通过环境变量定制运行参数,例如REPAIR_POLICY(StatefulSet 修复策略)、FEATURE_GATES(feature gate 列表)、LOG_LEVEL(日志级别)等。

常见问题与调试建议

  • 测试总是超时或卡住:检查 kind 集群资源是否充足(尤其是 podman 场景,建议 4 CPU / 8 GiB),以及镜像是否已正确加载进集群——go test不会自动构建镜像,遗漏make test-e2e-images是常见原因。
  • kubeconfig 路径错误:直接运行go test时必须显式传--kubeconfig;使用make test-e2e时默认取$HOME/.kube/config,可用KUBECONFIG=...覆盖。
  • 只想跑某类测试:优先选择 Makefile 中对应的分目标,或自行组合EXCLUDE_*环境变量;调试单个用例用TEST_RUN_ARGS="-run 测试名"
  • 测试失败需要排查:设置E2E_DIAGNOSTIC_DIRECTORY让框架在失败时把集群状态、Pod 日志、事件落盘;也可以参照TestAllNS末尾对 Operator Pod 重启次数的断言逻辑(main_test.go#L211-L224),自行检查 Operator 是否意外重启。

小结

Prometheus Operator 的 E2E 测试是一套完整的、可在本机复现的自动化测试体系:以 test/e2e/README.md 的三条前置条件与一条go test命令为起点,配合 Makefile 的test-e2e系列目标、test/e2e/main_test.go 的套件编排与EXCLUDE_*跳过机制、test/framework 的集群操作能力,你可以在本机完整复现 CI 中的验证流程,也可以精确裁剪测试范围来加速开发反馈循环。无论是提交新功能、修复缺陷,还是验证 Operator 升级兼容性,这套 E2E 测试都能在真实集群环境中给出最可信的答案。

  • 云原生
  • 可观测性

【免费下载链接】prometheus-operator

Prometheus Operator creates/configures/manages Prometheus clusters atop Kubernetes

项目地址:https://gitcode.com/gh_mirrors/pr/prometheus-operator
点击查看免费下载

相关推荐

上一篇:使用 SpeechBrain 在 CommonVoice 14.0 上训练 CTC + 注意力 Seq2Seq 多语言语音识别系统
下一篇:OpenMontage Remotion 技能实战:共享组件、自定义转场与项目时序约定全解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 14:53:24

PyCaret 平台运维指南:备份、升级、可观测性与弹性扩展实战

【免费下载链接】pycaret Open-source, low-code AutoML platform for Python. PyCaret 4.0: sklearn-native engine React control plane. 项目地址: https://gitcode.com/gh_mirrors/py/pycaret 点击查看 免费下载 PyCaret 4.0 的 sklearn 原生引擎之上构建了完…

作者头像 李华