K3s 测试体系全景指南:Unit、Integration、Docker、Install、E2E 与性能测试实战
【免费下载链接】k3sLightweight Kubernetes项目地址: https://gitcode.com/GitHub_Trending/k3/k3s
K3s 是一个面向边缘、开发环境和生产小规模集群的轻量级 Kubernetes 发行版,其质量保障依赖一套分层清晰、覆盖从函数级到整集群运维级的完整测试体系。本文基于仓库中的 tests/TESTING.md 测试标准文档,结合 tests/integration/README.md、tests/e2e/README.md、tests/perf/README.md 以及真实的测试源码,系统讲解 K3s 七类测试的适用场景、框架选型、命名规范与运行方法。读完本文,你将掌握 K3s 每种测试"何时写、怎么写、怎么跑"的完整标准,能够为 K3s 贡献新测试或在本地复现其 CI 测试流程。
一、K3s 测试体系总览
K3s 的测试体系共分七种形式,覆盖从单元级"白盒"验证到大规模集群"黑盒"运维验证的完整链路:
| 测试类型 | 验证层次 | 核心工具 | 典型运行时机 |
|---|---|---|---|
| 单元测试(Unit) | 单个包内的函数/组件 | Go 标准 testing + gotests | PR 验证、覆盖率统计 |
| 集成测试(Integration) | 跨多个 Go 包的功能 | Ginkgo + Gomega | PR 验证 |
| Docker 测试 | 容器化的多节点集群 | Docker + Ginkgo | Drone CI test 阶段 |
| 安装测试(Install) | 各发行版上的安装与运行 | Vagrant | 每晚定时 + install.sh 变更时 |
| 性能测试(Performance) | 大规模集群伸缩 | Terraform + clusterloader2 | 专项压测 |
| 端到端测试(E2E) | 多节点集群配置与运维 | Ginkgo + Vagrant | 每晚 QA |
| Distros 测试框架 | 特性级集群验证 | distros-test-framework | 验收测试 |
本文之后所有命令均在 k3s 仓库根目录下执行(tests/TESTING.md 的原始约定)。
二、单元测试(Unit Tests):白盒验证包内逻辑
2.1 何时写单元测试
当某个**包内(package)**的组件或函数需要验证时,就应当编写单元测试。单元测试用于"白盒"(white box)测试,即直接调用被测函数、深入其内部实现细节进行验证。
2.2 框架:Table Driven Test + gotests 自动生成
K3s 的所有单元测试遵循 Go 社区的 Table Driven Test 风格——用一个结构体切片定义输入与期望输出,通过循环驱动同一段断言逻辑。具体生成上,K3s 使用 gotests 工具自动生成测试骨架:
- gotests 内置于 VS Code 的 Go 扩展中,也支持其他主流编辑器的集成,或通过命令行直接运行;
- K3s 提供了一套自定义模板来扩展生成测试的功能,位于 contrib/gotests_templates(包含
header.tmpl、function.tmpl、inputs.tmpl、results.tmpl等,用于定制测试文件的包声明、导入、输入输出构造等代码骨架)。
使用命令行调用自定义模板:
gotests --template_dir=<PATH_TO_K3S>/contrib/gotests_templates在 VS Code 中,则编辑 Go 扩展设置Go: Generate Tests Flags,把--template_dir=<PATH_TO_K3S>/contrib/gotests_templates添加为一个 item 即可。
为便于单元测试的创建,K3s 还提供了 tests/unit.go 辅助函数,其中最核心的两个是:
GenerateDataDir(cnf *config.Control):在/tmp/k3s/<随机字符串>/创建临时数据目录,并把最新目录软链接到/tmp/k3s/latest/,从而模拟/var/lib/rancher/k3s的目录结构;GenerateRuntime(cnf *config.Control):创建临时数据目录并配置好config.ControlRuntime所需的全部证书密钥(调用deps.CreateRuntimeCertFiles与deps.GenServerDeps),同时重置 Prometheus 注册器以避免测试覆盖指标注册时发生 panic;CleanupDataDir(cnf *config.Control):清理上述临时目录及latest软链接。
2.3 格式规范
- 单元测试文件必须放在被测文件所在的包内;
- 文件名规则:
<被测文件>_test.go; - 函数名规则:
Test_Unit<被测函数>或Test_Unit<接收者>_<被测方法>。
原文档以 pkg/etcd/etcd_test.go 为例(当前仓库中 etcd 包的测试实际拆分为 pkg/etcd/etcd_linux_test.go 与 pkg/etcd/resolver_test.go),命名即遵循上述规范。在仓库中还可以看到大量遵循Test_Unit...命名的用例,例如 pkg/clientaccess/token_test.go、pkg/agent/containerd/config_test.go 等。
2.4 运行与覆盖率
go test ./pkg/... -run Unit单元测试直接调用函数,因此是 K3s代码覆盖率指标的主要驱动者。仓库中的 GitHub Actions 工作流 .github/workflows/unitcoverage.yaml 印证了这一点——它在 push/PR 时于 Ubuntu 24.04 与 Windows 2022 上分别执行:
go test -coverpkg ./pkg/... -coverprofile coverage.out ./pkg/... -run Unit go tool cover -func coverage.out并把coverage.out上传到 Codecov 进行覆盖率统计。可见单元测试在 K3s 中承担着"覆盖率守门员"的角色。
三、集成测试(Integration Tests):黑盒验证跨包功能
3.1 何时写集成测试
当需要验证横跨多个 Go 包的特定功能时——通常通过导出函数调用,更多时候通过 CLI 命令——就应当编写集成测试。集成测试用于"黑盒"(black box)测试,不关心内部实现,只验证外部行为。
详细说明见 tests/integration/README.md。
3.2 框架:BDD 风格 Ginkgo + Gomega
K3s 的集成测试采用**行为驱动开发(BDD)**风格,具体使用 Ginkgo 和 Gomega 驱动。初始化测试时可用ginkgo bootstrap命令生成骨架。为便于 K3s CLI 测试,可复用tests/util/cmd.go中的辅助函数(仓库当前将其与tests/client.go中的 Kubernetes API 辅助函数合并,见下文)。
3.3 格式规范
- 所有集成测试放在
tests/integration/<测试名>/目录下; - 文件名:
<测试名>_int_test.go; - 函数名:
Test_Integration<测试名>。
以 tests/integration/localstorage/localstorage_int_test.go 为例,其结构展示了完整的 BDD 组织方式:
BeforeSuite中调用testutil.K3sStartServer("--cluster-init")启动带--cluster-init(嵌入式 etcd)参数的 k3s server;Describe/When/It三级描述依次验证:默认 Deployment(coredns、local-path-provisioner、metrics-server、traefik)就绪 → 创建 PVC → 创建 Pod → 在kubectl get pvc/pv/pod中可见 → 存储目录权限(/var/lib/rancher/k3s/storage为 0700、卷目录为 0777、文件为 644)→ 非 root Pod 可写卷 → 正确删除;AfterSuite中若测试失败则调用K3sSaveLog、K3sCopyPodLogs、K3sDumpResources收集现场,随后K3sKillServer杀掉 server 并K3sCleanup清理。
该测试引用的tests.CheckDefaultDeployments定义在 tests/client.go 中,它检查 kube-system 命名空间下 coredns、local-path-provisioner、metrics-server、traefik 四个默认 Deployment 是否全部达到就绪副本数。同文件还提供了CheckDeployments、NodesReady、AllPodsUp、GetDaemonsetReady、ParseNodes/ParsePods、GetNodeIPs/GetPodIPs(支持双栈场景)等一系列跨测试框架复用的 Kubernetes API 断言工具函数。
3.4 运行方式
集成测试无需预先准备 k3s 集群——每个测试会自行拉起并销毁所需的 k3s server。注意:集成测试必须以 root 运行,sudo 用户需加上sudo -E env "PATH=$PATH"前缀:
go test ./tests/integration/... -run Integration -ginkgo.v -test.v要生成 JUnit 报告,则使用 Ginkgo CLI:
ginkgo --junit-report=result.xml ./tests/integration/...在已有单节点集群上运行:通过编译期标志指定,若 server 配置不满足测试要求则自动跳过:
go test -ldflags "-X 'github.com/k3s-io/k3s/tests/integration.existingServer=True'" ./tests/integration/... -run Integration -ginkgo.v -test.v通过 Sonobuoy 插件运行:K3s 提供了 Sonobuoy 插件方式在已有单节点集群上执行集成测试:
./scripts/build-tests-sonobuoy sudo KUBECONFIG=/etc/rancher/k3s/k3s.yaml sonobuoy run --plugin ./dist/artifacts/k3s-int-tests.yaml查看状态并取回结果:
sudo KUBECONFIG=/etc/rancher/k3s/k3s.yaml sonobuoy status sudo KUBECONFIG=/etc/rancher/k3s/k3s.yaml sonobuoy retrieve sudo KUBECONFIG=/etc/rancher/k3s/k3s.yaml sonobuoy results <TAR_FILE_FROM_RETRIEVE>四、Docker 测试:容器化的集群冒烟验证
Docker 测试将多个 K3s 节点以容器形式组成集群,用于验证基础功能。这类测试在 Drone CI 管道的test阶段运行。
从仓库源码可以看到其具体形态:以 tests/docker/autoimport/autoimport_test.go 为例,测试通过docker.NewTestConfig("rancher/systemd-node")创建容器节点配置,tc.ProvisionServers(1)拉起 server 容器,然后断言镜像自动导入(auto import)功能——在/var/lib/rancher/k3s/agent/images/写入镜像列表文件后,用k3s ctr images list检查镜像是否被打上io.cattle.k3s.pinned=pinned与io.cri-containerd.pinned=pinned标签。这与 pkg/agent/containerd 及 pkg/spegel 的镜像分发实现相呼应。
tests/docker 目录下的测试还包括 basics、bootstraptoken、cacerts、conformance、dualstack、etcd、hardened、lazypull、nixsnapshotter、scale、secretsencryption、selinux、skew、snapshotrestore、svcpoliciesandfirewall、t4、token、upgrade 等,覆盖了从基础启动到证书轮换、快照恢复、双栈网络等广泛功能面。
五、安装测试(Install Tests):多发行版安装验证
5.1 覆盖范围
安装测试是定义在 tests/install 下的一组测试,用于验证 K3s 在多种操作系统上的安装与运行。测试本体是描述单节点安装的 Vagrantfile,可通过 Vagrant 的libvirt和virtualboxprovider 快速拉起:
- 安装脚本(tests/install)触发的测试:每晚定时运行,并在 install.sh 变更时额外触发
- CentOS 9 Stream
- Rocky Linux 8(作为 RHEL 8 的替身)
- Rocky Linux 9(作为 RHEL 9 的替身)
- Fedora 40
- Leap 15.6(作为 SLES 的替身)
- Ubuntu 24.04
仓库中还可见 tests/install/alma-10、tests/install/opensuse-microos 等更多发行版目录。
5.2 格式
新增安装测试时,请复制既有 Vagrantfile 的主流风格。理想情况下,用于附加断言的 box 应支持默认的libvirtprovider,从而能直接被 GitHub Actions 的 Install Test Workflow 使用。
以 tests/install/rocky-9/Vagrantfile 为例,其结构展示了完整模式:
- 通过
ENV['TEST_INSTALL_SH'] ||= '../../../install.sh'指定被测安装脚本路径,INSTALL_K3S_CHANNEL默认取latest; config.vm.box = "bento/rockylinux-9",boot_timeout读取TEST_VM_BOOT_TIMEOUT环境变量;load "../install_util.rb"加载 tests/install/install_util.rb 中定义的辅助函数;- provisioner 依次执行:禁用防火墙 → 添加 bin 路径 → 上传 install.sh → 通过
vagrant-k3s插件执行安装(配置selinux: true、token: 'vagrant')→ 等待 node 就绪 → 等待 CoreDNS / local-storage / metrics-server / traefik →kubectl get node,all -A -o wide→ 检查进程 → 检查 cgroup v2 → 挂载/卸载目录验证。
tests/install/install_util.rb 中的每个辅助函数都是一个具名 provisioner:
| 辅助函数 | provisioner 名称 | 作用 |
|---|---|---|
waitForNodeReady | k3s-wait-for-node | 等待 node Ready(最多 300s,轮询 5s) |
waitForCoreDns | k3s-wait-for-coredns | 等待 coredns Deployment rollout 完成(120s),失败时收集 describe/log |
waitForLocalStorage | k3s-wait-for-local-storage | 等待 local-path-provisioner 就绪(120s) |
waitForMetricsServer | k3s-wait-for-metrics-server | 等待 metrics-server 就绪(180s,启动最慢) |
waitForTraefik | k3s-wait-for-traefik | 等待 traefik 就绪(120s) |
kubectlStatus | k3s-status | 输出kubectl get node,all -A -o wide |
checkK3sProcesses | k3s-procps | 检查 k3s/kube/container 相关进程 |
checkCGroupV2 | cgroupv2 | 运行k3s check-config验证 cgroups V2 |
mountDirs/checkMountPoint/unmountDir | k3s-mount-directory等 | 验证 server 目录挂载、检查挂载点、卸载并清理 |
注意这些 provisioner 都带有run: ENV['CI'] == 'true' ? 'never' : 'once'逻辑——在 CI 中默认不自动执行,而是由 workflow 显式调用,以避免慢 runner 上的超时问题(下文运行章节会说明)。
5.3 框架:Vagrant 插件与 Provider
Vagrant 新手可参考 Hashicorp 官方的入门教程。需要特别注意:
libvirtprovider 必须先安装vagrant-libvirt插件,且宿主机的 libvirtd 服务必须已安装并运行;- 另外还需要
vagrant-scp和vagrant-k3s插件。
三者可一次性安装:
vagrant plugin install vagrant-scp vagrant-k3s vagrant-libvirt5.4 环境变量
可在 CLI 上设置或导出后再调用 Vagrant:
| 变量 | 默认值 | 说明 |
|---|---|---|
TEST_VM_CPUS | 2 | 客户机使用的 vCPU 数量 |
TEST_VM_MEMORY | 2048 | 客户机使用的内存(MB) |
TEST_VM_BOOT_TIMEOUT | 600 | Vagrant 等待机器启动并可达的秒数 |
5.5 运行
安装脚本测试的运行方式是进入对应 fixture 目录执行vagrant up,例如:
cd tests/install/rocky-8 vagrant up # 以下 provisioner 是可选的。GitHub Actions CI 中会显式调用它们, # 以避免慢 runner 上的超时问题 vagrant provision --provision-with=k3s-wait-for-node vagrant provision --provision-with=k3s-wait-for-coredns vagrant provision --provision-with=k3s-wait-for-local-storage vagrant provision --provision-with=k3s-wait-for-metrics-server vagrant provision --provision-with=k3s-wait-for-traefik vagrant provision --provision-with=k3s-status vagrant provision --provision-with=k3s-procps仓库中的 .github/workflows/install.yaml 展示了 CI 侧的完整流程:它会在 push 到 main/master 或 PR 变更install.sh、tests/install/**、channel.yaml等路径时触发,matrix 覆盖 centos-9、alma-10、rocky-9、fedora、opensuse-leap、ubuntu-2404,设置INSTALL_K3S_SKIP_DOWNLOAD: binary使用本地构建的二进制,并通过vagrant provision --provision-with=...显式执行上述各验证步骤;同时还有一个单独的 nightly 工作流 .github/workflows/nightly-install.yaml 负责每晚定时运行。
六、性能测试(Performance Tests):Terraform 驱动的大规模压测
性能测试使用Terraform在 AWS 上自动化构建和测试大规模 K3s 集群部署,支持普通集群与 HA 集群(N 个主节点、N 个 worker 节点),存储后端支持:
- MySQL RDS
- Postgres RDS
- Etcd
- SQLite
脚本分为三个部分:server(部署存储后端 + N 个主节点)、agents(部署 k3s agent)、tests(运行 clusterloader2 压测)。server 部分还会额外创建用于 Prometheus 部署的 agent 节点,clusterloader2 会部署 prometheus 与 grafana。测试部分使用clusterloader2的一个 fork(kubernetes/perf-tests 的分支,仅修改了日志记录并移除了 etcd 指标探测),以 docker 化方式运行,报告保存在tests/<test_name>-<random-number>。当前可用的测试为load test与density test。
完整说明见 tests/perf/README.md。其配置集中在 tests/perf/scripts/config,核心变量如下:
主变量
| 变量 | 说明 |
|---|---|
CLUSTER_NAME | AWS 上的集群名,会作为集群各组件的前缀 |
DOMAIN_NAME | k3s 主节点的 Loadbalancer DNS 名称 |
ZONE_ID | AWS route53 zone id(用于修改 DNS 名称) |
K3S_VERSION | 集群使用的 K3s 版本 |
EXTRA_SSH_KEYS | 添加到服务器的公钥 |
PRIVATE_KEY_PATH | clusterloader2 用于 SSH 收集指标用的私钥 |
DEBUG | k3s server 的调试模式 |
数据库变量
| 变量 | 说明 |
|---|---|
DB_ENGINE | 数据库类型:mysql、postgres或etcd |
DB_INSTANCE_TYPE | mysql/postgres 的 RDS 实例类型(etcd 内部解析db.*系列) |
DB_NAME | 数据库名(仅 postgres 和 mysql) |
DB_USERNAME | 数据库用户名(仅 postgres 和 mysql) |
DB_PASSWORD | 数据库密码(仅 postgres 和 mysql) |
DB_VERSION | 数据库版本 |
K3S Server 变量
| 变量 | 说明 |
|---|---|
SERVER_HA | 是否启用 HA 模式;不启用则使用 sqlite 作为存储后端 |
SERVER_COUNT | k3s 主节点数量 |
SERVER_INSTANCE_TYPE | k3s server 的 EC2 实例类型 |
K3S Agent 变量
| 变量 | 说明 |
|---|---|
AGENT_NODE_COUNT | 创建的 k3s agent 数量 |
AGENT_INSTANCE_TYPE | k3s agent 的 EC2 实例类型 |
Prometheus server 变量
| 变量 | 说明 |
|---|---|
PROM_WORKER_NODE_COUNT | 为 prometheus 部署创建的 k3s agent 数量 |
PROM_WORKER_INSTANCE_TYPE | k3s prometheus agent 的 EC2 实例类型 |
使用方式:tests/perf下的 Makefile 按 section 执行不同任务:
cd tests/perf make apply # 构建 db、server、agent 三层,并部署 kubeconfig 到 tests/kubeconfig.yaml make test # 修改 tests/perf/tests/load/config.yaml 后启动 clusterloader2 压测 make destroy # 销毁集群 make clean # 清理七、端到端测试(E2E Tests):多节点集群运维验证
7.1 定位与覆盖
E2E 测试覆盖多节点 K3s 配置与管理:集群启动(bringup)、升级(update)、拆除(teardown)等,横跨多种操作系统。E2E 测试每晚作为 K3s 质量保证(QA)的一部分运行。
7.2 框架
与集成测试相同,E2E 使用 Ginkgo 与 Gomega,但底层依赖Vagrant提供集群配置。测试包含两部分:
Vagrantfile:描述并配置测试所用的虚拟机;<TEST_NAME>.go:调用vagrant up并控制实际集群测试的 Go 测试文件。
一个 E2E 测试的构成示例可参考 tests/e2e/validatecluster/validatecluster_test.go。仓库 tests/e2e 目录下还有 dualstack、embeddedmirror、externalip、multus、privateregistry、rootless、rotateca、s3、secretsencryption、splitserver、startup、tailscale、wasm、btrfs 等场景化测试,每个均自带 Vagrantfile。
7.3 环境搭建
Vagrant:请从官网下载最新版(当前 2.2.19)。不要使用发行版内置包——它们往往过旧或不包含使部分插件正常工作所需的 ruby 库扩展。
Libvirt:按操作系统官方指南安装 libvirt/qemu。例如 Ubuntu 24.04:
sudo apt install ruby-libvirt qemu-kvm libvirt-daemon-system libvirt-clients ebtables dnsmasq-base libxslt-dev libxml2-dev libvirt-dev zlib1g-dev ruby-dev libguestfs-tools(Ubuntu 20.04 将qemu-kvm换为qemu;其他发行版参考 tests/e2e/README.md 中给出的 openSUSE、Debian、Fedora 指南。)
Vagrant 插件:
vagrant plugin install vagrant-libvirt vagrant-scp vagrant-k3s vagrant-reloadKubectl(Linux 示例):
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl7.4 运行
E2E 测试通常作为每晚的 Jenkins QA 任务运行;本地运行也可,但可能需要额外配置。默认情况下所有 E2E 测试以libvirt作为底层 VM provider,VirtualBox作为备用 provider。
全套 E2E 测试:
go test -timeout=15m ./tests/e2e/... -run E2E单个测试:
go test -timeout=15m ./tests/e2e/validatecluster/... -run E2E # 或者 go test -timeout=15m ./tests/e2e/... -run E2EClusterValidation生成 JUnit 报告:
ginkgo --junit-report=result.xml ./tests/e2e/...注意:go test默认超时是 10 分钟,因此必须使用-timeout标志;而ginkgo默认超时为 1 小时,无需额外指定。
7.5 调试
测试失败时,集群和虚拟机会保留在失败现场,启动日志保留在vagrant.log中:
vagrant status:查看节点列表;vagrant ssh <NODE>:SSH 进入节点排查;- 排查结束或准备重跑时,用
vagrant destroy -f移除故障集群。
八、Distros 测试框架
distros 测试框架的验收测试(acceptance tests)是一种可定制的集群创建与验证方式:先按需求创建集群,再对其执行校验,从而验证特定功能和需求的满足情况。该框架由 rancher/distros-test-framework 项目提供,适合对 K3s 的具体特性做定制化验收。
九、如何贡献新测试
K3s 欢迎各类新测试与测试更新。若要新增或修改测试,请提交 PR,且PR 标题必须包含<测试名称> (Created/Updated)字样,例如Etcd Snapshot (Updated),以便维护者快速识别变更性质。
总结
K3s 的测试体系是一个典型的"金字塔 + 多维矩阵"结构:底层是覆盖pkg/各包逻辑、由 gotests 模板驱动、直接贡献覆盖率指标的单元测试;中层是以 Ginkgo/Gomega BDD 风格验证跨包功能的集成测试和容器化的 Docker 测试;上层则是以 Vagrant 驱动的多发行版安装测试与 E2E 测试,以及以 Terraform + clusterloader2 驱动的大规模性能测试。无论你希望为某个包补充单元用例、为某个功能新增集成测试,还是参与多发行版安装验证,都可以直接以本文给出的规范、命名约定与运行命令为起点,向 K3s 提交符合标准的测试贡献。
【免费下载链接】k3sLightweight Kubernetes项目地址: https://gitcode.com/GitHub_Trending/k3/k3s
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考