Rancher 测试框架实战指南:从集成测试编写到本地运行与配置详解
【免费下载链接】rancherComplete container management platform项目地址: https://gitcode.com/GitHub_Trending/ra/rancher
导读
本文基于 Rancher 仓库中的 tests/README.md 及配套的集成测试文档,系统讲解 Rancher 测试框架的整体结构与使用方式。你将掌握:集成测试(Integration)与验证测试(Validation)的适用场景与前置要求、基于 Shepherd 与 testify Suite 编写测试的规范、make ci全流程与面向外部 Rancher 实例的本地迭代两种运行方式,以及config.yaml测试配置的每个字段含义。文中所有结论均可回溯到仓库中的文档、源码与 Makefile 目标进行验证。
Rancher 测试框架概述
Rancher 测试框架(Rancher Test Framework)为编写集成测试与验证测试提供了一整套工具。它的核心职责有两项:
- 管理被测外部服务之间的交互——测试需要连接运行中的 Rancher 实例、下游集群等外部服务;
- 帮助在测试结束后清理资源——通过 Session 机制跟踪并回收测试创建的资源,避免测试之间相互干扰。
从组织架构上看,框架被划分为三个学科(disciplines):
| 学科 | 职责 |
|---|---|
| framework(框架) | 若干核心库,用于让测试写得同构、一致,降低不同测试套件之间的写法差异 |
| clients(客户端) | 封装与 Rancher、Kubernetes、k3d 等外部服务交互的客户端 |
| extensions(扩展) | 提供可复用的测试扩展能力,如用户、Token、命名空间、注册表等场景的辅助函数 |
其中 framework 是核心库层,clients 与 extensions 分别对应文档中提到的 clients 与 extensions 两个补充章节(当前仓库内以tests/v2下的集成测试、tests/v2prov下的 provisioning 测试等实际用例体现)。
运行前置要求(Requirements)
集成测试(Integration)
运行 Rancher 集成测试需要准备:
- 一个可访问 URL 的运行中 Rancher 实例;
- 管理员(admin)用户的Rancher 访问 Token;
- Go 1.22或更高版本(仓库根目录
go.mod声明了 Go 版本要求,tests/v2/integration/setup/README.md 提到 Go 1.24+); - k3d(用于创建下游集群,setup 文档建议 v5.8.3 或兼容版本)。
验证测试(Validation)
验证测试与集成测试的前置要求相同,但不同测试套件可能还需要云厂商的凭据(例如 AWS、Azure 等),具体以各套件的配置文件说明为准。
核心概念:Integration vs Validation
理解这两类测试的边界,是正确选择测试落点的基础:
| 维度 | 集成测试(Integration) | 验证测试(Validation) |
|---|---|---|
| 外部依赖 | 不依赖任何外部配置或其他外部服务 | 依赖外部服务,必须提供配置文件才能运行 |
| 运行时长 | 短运行,因为每次 PR 都会在 CI 中执行 | 较长,按需运行 |
| 云厂商访问密钥 | 不需要 | 可能需要 |
简而言之:集成测试追求“快速、无外部依赖、可反复在 CI 执行”;验证测试追求“在真实外部环境中做深度验证”,因此需要配置文件与可能的云凭据。
测试框架:Shepherd
Rancher 的测试框架名为Shepherd,是 Rancher 官方维护的独立测试框架仓库(当前仓库通过 Go module 依赖引用它,例如 tests/v2/integration/setup/main.go 中导入github.com/rancher/shepherd/clients/k3d、github.com/rancher/shepherd/pkg/session等包)。Shepherd 提供了:
- 客户端封装(
clients/rancher、clients/k3d); - 会话管理(
pkg/session); - 配置加载(
pkg/config); - 名称生成(
pkg/namegenerator); - 扩展功能(
extensions/token、extensions/users等)。
编写测试时优先使用框架客户端,是保证资源可清理、测试可复用的关键。
如何编写测试(How to Write Tests)
测试存放位置
测试应创建在:
tests/v2/integration目录下——对应仓库内的集成测试;- 独立的 tests 仓库——对应验证测试。
依据上文 Integration vs Validation 的边界决定落点。
分组与组织
- 开发者可以按需将测试分组到文件和包中,但原则是:让下一位开发者容易找到,且与同一时间点运行的其他测试归组;
- 文件内部,测试应分组为Suite(基于
github.com/stretchr/testify/suite); - 一个 Suite 应在其所有测试间共享客户端(clients)和会话(session);
- 一个 Suite 内的测试应测试同一类功能并复用 Suite 资源。
例如:如果要验证不同项目角色对项目资源的访问权限,可以把所有角色对应的测试放进同一个 Suite,并共享同一个项目。这样每个测试都不必重复创建项目,显著节省时间——这正是仓库中 tests/v2/integration/rbac/rtbs_test.go 的做法。
Suite 的代码骨架
以 tests/v2/integration/rbac/rtbs_test.go 为实例,可以看到一个典型 Suite 的写法:
type RTBTestSuite struct { suite.Suite client *rancher.Client project *management.Project session *session.Session downstreamClusterID string } func (p *RTBTestSuite) SetupSuite() { p.downstreamClusterID = "local" testSession := session.NewSession() p.session = testSession client, err := rancher.NewClient("", testSession) p.Require().NoError(err) p.client = client // 在 Suite 内共享一个项目,所有测试复用 projectConfig := &management.Project{ ClusterID: p.downstreamClusterID, Name: "TestProject", } testProject, err := client.Management.Project.Create(projectConfig) p.Require().NoError(err) p.project = testProject } func (p *RTBTestSuite) TearDownSuite() { client, err := p.client.WithSession(p.session) p.Require().NoError(err) err = client.Management.Project.Delete(p.project) p.Require().NoError(err) p.session.Cleanup() }文件末尾通过suite.Run(t, new(RTBTestSuite))启动测试(见 rtbs_test.go)。
命名规范
- 测试名中不能包含
/:因为/用于表示测试套件(sub-test)层级,包含该字符会造成测试结构上的歧义。例如-run TestRTBTestSuite/TestUserVsUserBaseGlobalRoleVisibility中的/用于选中 Suite 内的具体子测试。
资源清理与 Session
- 测试应尽可能使用框架客户端,确保测试创建的资源会被清理,不干扰其他测试;
- 每个测试都有责任在下一个测试运行前,完整清理自己创建的所有资源;
- 资源跟踪依赖Session机制:会话(Session)会记录测试过程中创建的资源,并在结束时统一清理。上述
SetupSuite/TearDownSuite中session.NewSession()与p.session.Cleanup()的配对,就是这一机制的落地。更细粒度的做法是为单个测试创建子会话(sub-session),实现测试级隔离(见newSubSession)。
运行测试的两种方式
仓库中的 tests/v2/integration/README.md 给出了两条完整运行路径。
方式一:完整 CI 运行(make ci,推荐用于验证)
make ci流程说明:
- 在由
Dockerfile.runtime构建的 Rancher 运行时容器内执行scripts/test; scripts/test会搭建并启动 Rancher;- Rancher 启动时用k3s创建 local 集群并部署 CRD;
- Rancher 与 local 集群就绪后,运行测试套件。
该方法理论上开箱即用地支持 Mac 与 Linux。需要注意:整个集成测试过程会消耗较多 CPU 与内存——出现意外超时往往意味着计算资源不足,出现影响容器调度的 OOM 则意味着内存不足。
方式二:针对外部 Rancher 实例本地运行(适合迭代开发)
该方式将测试指向一个已经在运行的 Rancher 实例,而不是在容器内重新拉起一个,适合开发调试。快速上手(复制即用):
# 1. 启动 Rancher(如果尚未运行) export RANCHER_IP=$(ifconfig | grep 'inet ' | grep -v 127.0.0.1 | head -1 | awk '{print $2}') docker run -d --name rancher-server --restart=unless-stopped \ -p 80:80 -p 443:443 --privileged \ -e CATTLE_SERVER_URL="https://${RANCHER_IP}" \ -e CATTLE_BOOTSTRAP_PASSWORD="admin" \ -e CATTLE_DEV_MODE="yes" \ -e CATTLE_AGENT_IMAGE="rancher/rancher-agent:v2.14-head" \ rancher/rancher:v2.14-head # 2. 创建 k3d 下游集群并生成 config.yaml export CATTLE_BOOTSTRAP_PASSWORD="admin" export CATTLE_AGENT_IMAGE="rancher/rancher-agent:v2.14-head" make integration-setup # 3. 运行测试 make integration-test-local对应的 Makefile 目标定义在 Makefile:
make integration-setup:构建 setup 二进制(tests/v2/integration/bin/integrationsetup),连接 Rancher、创建 k3d 下游集群,并将连接信息写入tests/v2/integration/config.yaml;make integration-test-local:读取config.yaml并运行完整测试套件(CGO_ENABLED=0 go test -v -failfast -timeout 30m -p 1 ./tests/v2/integration/...)。
如果之前已生成过config.yaml,可以直接跳过第 2 步执行第 3 步。
分步详解
Step 1:启动 Rancher Server
export RANCHER_IP=$(ifconfig | grep 'inet ' | grep -v 127.0.0.1 | head -1 | awk '{print $2}') docker run -d --name rancher-server --restart=unless-stopped \ -p 80:80 -p 443:443 \ --privileged \ -e CATTLE_SERVER_URL="https://${RANCHER_IP}" \ -e CATTLE_BOOTSTRAP_PASSWORD="admin" \ -e CATTLE_DEV_MODE="yes" \ -e CATTLE_AGENT_IMAGE="rancher/rancher-agent:v2.14-head" \ rancher/rancher:v2.14-head等待 Rancher 就绪:
until curl -sk "https://${RANCHER_IP}/ping" | grep -q pong; do echo "waiting for Rancher..."; sleep 5; doneStep 2:构建并运行 Integration Setup
setup 程序负责连接 Rancher、创建 k3d 下游集群并导入、最后写出测试配置文件:
# 构建 setup 二进制(在仓库根目录执行) cd tests/v2/integration ./scripts/build-integration-setup # 产出: tests/v2/integration/bin/integrationsetup # 运行 setup(回到仓库根目录) cd ../../.. export CATTLE_BOOTSTRAP_PASSWORD="admin" export CATTLE_AGENT_IMAGE="rancher/rancher-agent:v2.14-head" export CATTLE_TEST_CONFIG=$(pwd)/tests/v2/integration/config.yaml ./tests/v2/integration/bin/integrationsetupsetup 程序会自动探测 Rancher 主机 IP、生成 admin Token、创建 k3d 集群、导入 Rancher,并把连接信息写入CATTLE_TEST_CONFIG指定的路径。
Step 3(可选):手动创建config.yaml
如果已有带导入集群的 Rancher 实例,可以跳过 setup 二进制直接创建配置文件,字段说明见下文“配置参考”。
Step 4:运行测试
export CATTLE_TEST_CONFIG=$(pwd)/tests/v2/integration/config.yaml # 运行全部集成测试 go test -v -timeout 30m -failfast -p 1 ./tests/v2/integration/... # 运行指定测试套件 go test -v -count=1 -timeout 30m -run TestChartsTestSuite ./tests/v2/integration/catalogv2/ # 运行套件内的具体测试 go test -v -count=1 -run TestRTBTestSuite/TestUserVsUserBaseGlobalRoleVisibility ./tests/v2/integration/rbac/ # 仅运行 Steve API 测试(仅 local 集群,无需下游集群) go test -v -count=1 -run TestSteveLocal ./tests/v2/integration/steveapi/常用go test参数
| 参数 | 示例 | 说明 |
|---|---|---|
-timeout | -timeout 30m | 整个测试二进制的硬性截止时间。默认10 分钟,对需要拉取外部仓库的 catalog 类测试来说太短,完整套件建议30m |
-run | -run TestChartsTestSuite | 只运行匹配正则的测试/套件;支持/选择子测试:-run Suite/TestName |
-count | -count=1 | 禁用测试结果缓存。运行集成测试时应始终加-count=1确保是全新执行 |
-v | -v | 详细输出,逐个打印测试名与 PASS/FAIL,便于定位挂起的测试 |
-failfast | -failfast | 首个测试失败即停止,CI 中用于避免失败后继续浪费资源 |
-p | -p 1 | 并行构建/运行的测试包数量。集成测试必须为1,避免资源冲突 |
配置参考
config.yaml
测试配置文件的路径由环境变量CATTLE_TEST_CONFIG指定。最小示例:
rancher: adminToken: "token-xxxxx:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" host: "192.168.1.100" # Rancher 主机(不含 https://,末尾无斜杠) clusterName: "my-k3d-cluster" # Rancher 中导入的下游集群名称 insecure: true cleanup: true全部支持字段:
| 字段 | 类型 | 说明 | 是否必填 |
|---|---|---|---|
rancher.adminToken | string | 用于 admin API 访问的 Bearer Token。可在 Rancher UI 获取:用户头像 → Account & API Keys → Create API Key(No Scope) | 是 |
rancher.host | string | Rancher 服务器主机名或 IP(不含协议 scheme、末尾无斜杠) | 是 |
rancher.clusterName | string | Rancher 中下游集群的名称。下游相关测试必填;仅测 local 集群时填local | 是 |
rancher.insecure | bool | 跳过 TLS 校验,适用于自签名证书。默认false | 否 |
rancher.cleanup | bool | 测试是否删除其创建的资源。默认true | 否 |
rancher.adminPassword | string | admin 密码(adminToken的替代方案) | 否 |
rancher.caFile | string | 用于 TLS 校验的 CA 证书文件路径 | 否 |
rancher.caCerts | string | 内联 PEM 编码的 CA 证书 | 否 |
环境变量
| 变量 | 使用者 | 说明 |
|---|---|---|
CATTLE_TEST_CONFIG | 测试 + setup | 必填。config.yaml的绝对路径。运行测试或 setup 二进制前必须导出 |
CATTLE_BOOTSTRAP_PASSWORD | 仅 setup | Rancher 首次登录的引导密码。默认admin |
CATTLE_AGENT_IMAGE | 仅 setup | Rancher agent 的完整镜像引用(如rancher/rancher-agent:v2.14-head),导入 k3d 集群时使用 |
CATTLE_RANCHER_HOST | 仅 setup | 覆盖自动探测的 Rancher 主机(如192.168.1.100:443或localhost:8443)。未设置时,setup 二进制通过探测机器出站 IP 确定主机 |
关于主机探测机制,tests/v2/integration/setup/main.go 给出了实现细节:默认通过向8.8.8.8:80建立 UDP socket 读取本地地址来获取出站 IP,并用fmt.Sprintf("%s:443", ip)拼出host;当CATTLE_RANCHER_HOST非空时直接使用该值。rancherConfig中的AdminToken、Host、Cleanup、ClusterName、AdminPassword字段均由 setup 程序生成并写入配置。
测试套件一览(Test Suites)
仅使用local集群的测试不需要下游集群,只需基础config.yaml即可运行;标记为“需要下游集群”的测试,必须通过rancher.clusterName引用已导入的集群:
| 目录 | 测试函数 | 测试内容 | 需要下游集群? |
|---|---|---|---|
catalogv2/ | TestChartsTestSuite | Chart 安装、容忍度、pull-through | 是 |
catalogv2/ | TestClusterRepoTestSuite | ClusterRepo CRUD、OCI 仓库 | 否 |
catalogv2/ | TestSystemChartsVersionSuite | 系统 chart 版本约束 | 否 |
catalogv2/ | TestUIPluginSuite | UI 插件扩展 | 否 |
catalogv2/ | TestRancherManagedChartsSuite | Rancher 托管的 Helm chart | 否 |
clusters/ | TestK8sProxy | 经 Rancher 的 K8s API 代理 | 是 |
projects/ | TestResourceQuotaTestSuite | 命名空间资源配额 | 否 |
projects/ | TestProjectUserTestSuite | 项目级用户访问 | 否 |
rbac/ | TestRTBTestSuite | 角色/ClusterRole 模板绑定、features、impersonation、projects | 否(使用local) |
steveapi/ | TestSteveLocal | Steve 资源列表 API(local 集群) | 否 |
steveapi/ | TestSteveDownstream | 下游集群上的 Steve API | 是(当前跳过) |
users/ | TestUserTestSuite | 用户 CRUD 操作 | 否 |
authconfigs/ | TestAuthConfig | 认证配置管理 | 否 |
serviceaccount/ | TestSATestSuite | ServiceAccount Token 处理 | 否 |
上述目录均位于仓库tests/v2/integration/下,例如 tests/v2/integration/catalogv2、tests/v2/integration/rbac。
测试环境搭建细节(Test Setup Details)
集成测试的 setup 逻辑分布在scripts/test与 tests/v2/integration/setup/main.go 中。后者主要承担四项职责:
- 生成并保存测试配置文件,供集成测试使用;
- 创建一个用户及对应 Token,供测试访问 Rancher;
- 在 local 集群中创建新的测试命名空间,并以 Secret 形式部署 Docker 容器注册表凭据;
- 在
default命名空间部署两个注册表。
scripts/test中对应流程可参看其build-integration-setup、integrationsetup、go integration tests三段调用。
注册表(Registry)搭建
setup 过程中部署的两个注册表各有分工:
- 第一个注册表按常规方式配置,支持镜像的 push 与 pull;
- 第二个注册表配置为pull-through 缓存,唯一目的是缓存下游集群创建容器时拉取的镜像,以加速测试过程。
创建注册表的同时,会向上述测试命名空间部署对应的 Secret。随后,由scripts/ci本地构建的 cattle cluster agent 镜像会被推送到第一个注册表,供下游集群拉取。两个注册表的配置会被合并,用于创建集成测试使用的测试集群——合并后的注册表配置正是下游集群能够访问 local 集群内注册表的关键。
下游集群的供应方式
集成测试 setup 中创建下游集群的方式,与 v2 provisioning 测试完全一致:通过github.com/rancher/rancher/tests/v2prov/cluster包提供的cluster.New()函数创建。该函数利用 Rancher 的 v2 provisioning 功能,在测试命名空间中创建一个运行 machine provisioner 的容器;machine provisioner 再创建systemd-node容器,由其自建一个内嵌的 Kubernetes 集群。最终的整体形态为:
- 一个运行 Rancher 运行时环境的 Docker 容器,其中:
scripts/test正在运行:- 集成测试
- Rancher
- Rancher 的 “local” 集群(k3s 集群),其中运行:
- 若干容器(网络相关组件,以及 rancher-webhook 等 Rancher 特有组件)
- 一个
systemd-node容器,其中运行:- “下游集群”:一个运行 cluster agent 及其他 Rancher 下游组件的 k3s 集群
这一嵌套架构说明:一次make ci实际上在同一运行时环境内容纳了 Rancher 服务器、local 集群与下游集群三层结构,这也是它对 CPU 与内存要求较高的原因。
小结
Rancher 测试框架以 Shepherd 为核心,将测试划分为 framework、clients、extensions 三个层次,并明确区分“快速、无外部依赖”的集成测试与“需要外部服务与配置”的验证测试。编写测试时遵循“Suite 共享客户端与会话、测试名不含/、优先使用框架客户端、测试自行清理资源”的规范,即可写出同构、可复用、可清理的测试。运行时既可通过make ci在容器内一键完成端到端验证,也可通过make integration-setup+make integration-test-local对已运行的 Rancher 实例做快速迭代;config.yaml的字段与CATTLE_*系列环境变量则提供了从 Token、主机、集群名到 TLS 校验、资源清理策略的完整可控项。
【免费下载链接】rancherComplete container management platform项目地址: https://gitcode.com/GitHub_Trending/ra/rancher
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考