Kubernetes DRA 动态资源分配升级/降级端到端测试套件test/e2e_dra运行指南与源码解析【免费下载链接】kubernetesProduction-Grade Container Scheduling and Management项目地址: https://gitcode.com/GitHub_Trending/kuber/kubernetesKubernetes 官方主仓库在test/e2e_dra目录维护了一套面向 DRADynamic Resource Allocation动态资源分配的跨版本升级/降级测试套件它通过真实运行 kube-apiserver、kubelet 等二进制先拉起上一个次版本previous minor release的集群再原地升级到当前源码、随后回滚降级以验证 DRA 各特性在版本演进中的前后兼容性。本指南基于该目录下的 README 并结合源码实现完整梳理其定位、前置条件、三类运行方式与一键脚本、内部编排机制、子测试功能覆盖面与 Feature Gate 使用帮助你在本地复现这类测试并理解其设计意图。这套测试套件是什么不是普通 e2e也不是普通集成测试从 README 的定义看test/e2e_dra是一个“自带自动升级/降级测试”的 DRA 测试套件在概念上它类似于集成测试——会启动/停止集群组件kube-apiserver、kubelet、etcd 等并针对这些组件运行测试但它拥有独立目录因为它的启动方式与其他集成测试、单元测试不同行为上更像一套E2E端到端套件。两者最核心的差异在于启动方式普通集成测试在进程内构造 apiserver而该套件是直接运行真实的 Kubernetes 可执行文件actual binaries并依赖 hack/local-up-cluster.sh 提供集群启停的逻辑与配置步骤。因此该脚本对宿主机有额外的权限与准备要求详见下文“环境准备”。测试入口定义在 test/e2e_dra/upgradedowngrade_test.go以标准 Go 测试函数TestUpgradeDowngrade形态存在无需 ginkgo CLI 即可调用。为什么必须独占目录、不能并入 test-integration该目录被刻意独立出来的原因从 README 与代码可以归纳为三点需要make test而非make test-integrationmake test-integration体系假定由测试框架自己管理 etcd而这里的local-up-cluster.sh本身就想自行启动 etcd二者会冲突。README 明确指出 “make testinstead ofmake test-integrationis intentional”。需要宿主机级权限脚本要创建/清理/var/run/kubernetes、/var/lib/kubelet/plugins等系统目录并修改属主普通集成测试不具备该前提。需要跨版本下载与版本判定套件要从远端拉取上一个次版本的 server 二进制包再与本地的当前源码版本做对照见后文“升级/降级编排机制”这种能力无法在单进程集成测试里模拟。辅助启动逻辑集中在test/utils/localupcluster包localupcluster.go、cmd.go测试代码通过localupcluster.New()创建集群句柄调用Start/Modify/Stop控制集群生命周期。环境准备与前置条件README 给出的前置条件可拆解为四步顺序执行即可1. 确保 hack/local-up-cluster.sh 可用local-up-cluster.sh是整个测试的基础设施必须能在你的机器上独立工作sudo必须可用脚本需要 root 权限执行清理与建目录按你的环境设置必要环境变量如代理、网络等。2. 确保三个关键目录可写测试驱动DRA driver以本地文件系统模式运行并挂载相关 socket 与设备路径因此以下目录必须对运行测试的用户可写/var/lib/kubelet/plugins/var/lib/kubelet/plugins_registry/var/run/cdi这三个路径分别对应 kubelet 插件CSI/DRA 插件注册与 CDIContainer Device Interface容器设备注入的运行目录。也可以直接使用仓库自带的 test/e2e_dra/run.sh它会用sudo完成清理、建目录与chown详见下文。3. 用 make 构建二进制make构建产物默认输出到_output/local/bin/linux/amd64取决于你的GOOS/GOARCH。测试运行时 kube-apiserver、kubelet 等实际组件二进制就取自这里。4. 导出测试所需环境变量环境变量必填含义KUBERNETES_SERVER_BIN_DIR是指向make构建出的 server 二进制目录如$(pwd)/_output/local/bin/linux/amd64按你的 GOOS/GOARCH 调整。测试入口若发现该变量为空会直接以 Fatal 退出见 upgradedowngrade_test.goKUBERNETES_SERVER_CACHE_DIR否下载的旧版本 release 二进制的缓存目录如bin_dir/cache-dir。设置后多次测试调用间可复用已下载的 release 二进制避免重复下载未设置时每次使用临时目录ARTIFACTS否组件日志文件的持久化存放目录未设置时日志写入测试的临时 tmp 目录。从 localupcluster.go 看若设置且测试失败集群现场如 kind 目录会被保留供排查缓存目录的机制细节可见 upgradedowngrade_test.go测试会按“上个版本的版本号”在缓存目录下建子目录并在子目录中已存在组件二进制时直接跳过下载解压步骤。另需注意README 示例中的缓存路径写的是.../linx/amd64/cache-dirlinx疑为linux的笔误而官方脚本 run.sh 使用$(go env GOOS)/$(go env GOARCH)动态生成路径可直接照搬。三种运行方式方式一以 Go test 直接运行推荐go test -v -count1 -timeout1h ./test/e2e_dra要点不需要 ginkgo CLI。-count1确保每次调用都真实执行默认 Go 会缓存测试结果-v使测试输出在运行时即可见。方式二在 dlv 调试器中运行dlv test ./test/e2e_dra -- -test.v适合在断点调试 DRA 驱动或 apiserver 交互逻辑时使用--之后的-test.v会被透传给测试二进制。方式三通过 make test 接入仓库标准测试框架make test KUBE_TIMEOUT-timeout1h WHATtest/e2e_dra FULL_LOGtrue KUBE_TEST_ARGS-count1刻意使用make test而非make test-integration原因正如上文所述local-up-cluster.sh自己会启动 etcdKUBE_TIMEOUT-timeout1h提供充裕的超时整套流程含下载旧版本、三次集群生命周期切换FULL_LOGtrue对应-test.v让输出实时可见KUBE_TEST_ARGS-count1关闭测试缓存。一键脚本 run.sh为简化“从零开始”的繁琐清理与权限操作仓库提供了 test/e2e_dra/run.sh它负责清理旧状态 → 设置权限 → 再执行命令行指定的任意命令./test/e2e_dra/run.sh go test ./test/e2e_dra从脚本源码看它实际做了这些事sudo rm -rf /var/run/kubernetes /var/run/cdi \ /var/lib/kubelet/plugins_registry /var/lib/kubelet/plugins \ /var/lib/kubelet/*_state /var/lib/kubelet/checkpoints /tmp/artifacts sudo mkdir /var/run/kubernetes /var/lib/kubelet/plugins_registry \ /var/lib/kubelet/plugins /var/run/cdi sudo chown $(id -u) /var/run/kubernetes /var/lib/kubelet/plugins_registry \ /var/lib/kubelet/plugins /var/run/cdi ARTIFACTS/tmp/artifacts KUBERNETES_SERVER_BIN_DIR$(pwd)/_output/local/bin/$(go env GOOS)/$(go env GOARCH) KUBERNETES_SERVER_CACHE_DIR${KUBERNETES_SERVER_BIN_DIR}/cache-dir ... exec $即它会自动删除并重建 kubelet 的 plugins/plugins_registry、/var/run/kubernetes、/var/run/cdi清掉 kubelet 状态与 checkpoint、临时 artifacts把上述目录属主改为当前用户把ARTIFACTS固定为/tmp/artifacts并自动导出KUBERNETES_SERVER_BIN_DIR与KUBERNETES_SERVER_CACHE_DIR最后exec $原样执行你传入的命令。因此最稳妥的复现姿势是./test/e2e_dra/run.sh make ./test/e2e_dra/run.sh go test -v -count1 -timeout1h ./test/e2e_dra升级/降级编排机制主测试函数的源码级拆解真正驱动整套流程的是 upgradedowngrade_test.go 中的testUpgradeDowngrade。将其按阶段拆开来看测试流程大致如下判定当前源码版本 → 确定上一个次版本 │ ▼ 下载并解压上个次版本的 server 二进制cache 命中则跳过 │ ▼ 用上个次版本二进制启动集群0-initial-maj.min │ ▼ 阶段一各子测试在旧版本上运行返回升级后继续的回调 │ ▼ 用当前源码二进制热替换组件1-gitVersion │ ▲ kubelet 重启会清空所有 ResourceSlice → 等待驱动重新发布 ▼ 阶段二各子测试在升级后集群上运行返回降级后继续的回调 │ ▼ 回滚到上个次版本二进制2-restored-maj.min │ ▲ 再次等待 ResourceSlice 重建 ▼ 阶段三各子测试在降级后集群上收尾/验证1. 判定“上一个次版本”与 alpha.0 特例测试用sourceVersion执行 hack/print-workspace-status.sh 解析出当前源码的gitVersion从而得到major与previousMinor minor - 1源码位置。存在一个值得注意的版本号特例若 gitVersion 形如x.y.z-alpha.0即下一个开发周期刚开始、master 已把版本号提前则会把previousMinor再减一。代码注释给出的理由有两点其一在-rc.0左右的代码冻结期master 已自报为下一版本的-alpha.0若不特判就会悄悄改变原本已验证过的版本偏移version skew组合历史上确实因此坏过一次其二新周期早期与上一版本的差异很小往前多退一个版本更能测出有意义的差异。2. 获取上一个次版本的 server 二进制随后通过serverDownloadURL源码位置构造 Kubernetes 官方 release 下载地址先按stable前缀请求major.previousMinor的版本号文本文件若返回 404该 minor 尚无 stable 发布则回退尝试latest前缀最终得到 server tarball 下载 URL。下载解压时代码只从中挑选出localupcluster.KubeClusterComponents列出的集群组件kube-apiserver、kubelet 等写入binDir源码位置。3. 三层回调initial → upgraded → downgraded这是本套件最有特色的编码模式。每个子测试不是一个孤立的函数而是一串“链式回调”类型定义见源码type initialTestFunc func(tCtx ktesting.TContext, builder *drautils.Builder) upgradedTestFunc type upgradedTestFunc func(tCtx ktesting.TContext) downgradedTestFunc type downgradedTestFunc func(tCtx ktesting.TContext)阶段一执行initialTestFunc在旧版本集群上做一轮验证然后返回阶段二函数阶段二在升级后的集群上执行返回的函数并再次返回阶段三函数阶段三在降级回滚后的集群上执行最终函数通常做清理与终态校验。由于每个子测试都要在三种集群状态下接力builder被配置为子测试结束时不删除对象b.SkipCleanup true让 ResourceClaim、Pod 等对象存活到整个测试结束见 upgradedowngrade_test.go。驱动以IsLocal true的“本地文件系统模式”运行socket 在本机直接打开避免因 apiserver 重启导致经由代理的间歇性错误与延迟。4. 升级/降级的集群操作用旧版本二进制首次拉起集群cluster.Start(..., 0-initial-maj.min, binDir, env, )升级cluster.Modify(..., 1-gitVersion, ModifyOptions{BinDir: dir})dir即KUBERNETES_SERVER_BIN_DIR指向的当前源码产物目录源码位置。代码注释说明暂未细分为“先升 apiserver → 控制面组件 → 再重启 kubelet”而是整体替换后做前后对比文件内留有TODO降级调用cluster.Modify(..., 2-restored-maj.min, restoreOptions)用保存的选项回滚源码位置每次Modify后由于kubelet 重启后不记得之前有哪些驱动在运行会清空全部 ResourceSlice因此框架调用waitForSlices轮询最长 5 分钟等待各驱动的 ResourceSlice 重建完成waitForSlices 源码。子测试若声明driverResources nil则需自行等待 slice 重建。5. 子测试的运行顺序与隔离性子测试注册在一个 Go map 中源码位置而map 迭代顺序是不确定的因此 README/注释都强调子测试之间运行顺序不定每个子测试必须自包含——它们共享同一个集群但各自拥有独立的 driver 与设备互不依赖。子测试覆盖的 DRA 功能面主测试在三个阶段统一驱动以下子测试各自对应目录下的独立文件子测试名覆盖功能相关文件core-dra核心 DRA 流程创建外部 ResourceClaim → 创建引用它的 Pod → 验证 Pod 就绪/设备注入升级后再建新 ClaimPod 验证新版本行为降级后显式清理coredra_test.goresource-claim-device-status资源声明设备状态ResourceClaimDeviceStatus在跨版本后的读写/展示resourceclaimstatus_test.godevice-taints设备污点DeviceTaints规则devicetaints_test.gopartitionable-devices可分区设备PartitionableDevices的跨版本行为partitionabledevices_test.goextended-resource-explicit/extended-resource-implicitDRA 扩展资源ExtendedResource两种资源类型路径显式/隐式extendedresources_test.gopool-name-field-selector-fallbackResourceSlice 池名字段选择器的回退逻辑该子测试额外把驱动配置为ReconcilePoolWithName并使用特权客户端poolnamefieldselector_test.go以 coredra_test.go 的coreDRA为例可以看到阶段三清理时因 apiserver 已重启、连接是“陈旧连接”删除请求偶尔会报EOF甚至出现pods ...: User kubernetes-admin cannot get resource ...之类的间歇性 403因此清理必须放进Eventually重试循环而非一次性调用。这对你自行扩展子测试有直接借鉴意义。此外同一目录下还有不参与TestUpgradeDowngrademap 的独立测试featuregatecycle_test.go入口TestFeatureGateCycle用于验证 Feature Gate 开关翻转周期下的 DRA 行为compatibilitygroups_test.go 与 workloadresourceclaims_test.go分别提供compatibilityGroupsGateCycle、workloadResourceClaimsGateCycle从命名与实现结构可以推断它们测试的是“门控gate被关闭后对应能力的行为”与前者的 gate cycle 测试构成互补。启动环境RUNTIME_CONFIG 与 FEATURE_GATES测试拉起旧版本集群时注入的环境变量源码位置本身即是 DRA 特性配置的权威样例localUpClusterEnv : map[string]string{ RUNTIME_CONFIG: resource.k8s.io/v1beta1,resource.k8s.io/v1beta2,resource.k8s.io/v1alpha3, FEATURE_GATES: DynamicResourceAllocationtrue,DRADeviceTaintRulestrue,DRADeviceTaintstrue,DRAExtendedResourcetrue,DRAPartitionableDevicestrue, }RUNTIME_CONFIG同时开启resource.k8s.io组的v1beta1、v1beta2、v1alpha3三个 API 版本。这与升级/降级测试的诉求强相关上一版本集群可能只提供旧版本 API而当前源码可能已推进到新版本 API三者并存才能让新旧二进制与客户端在 skew 期间互操作注意本地运行的 driver 本身是“本地文件系统模式”因此注释说明无需ALLOW_PRIVILEGED1。FEATURE_GATES显式打开涉及升级路径的 DRA 特性门控。以当前仓库 pkg/features/kube_features.go 中记录的版本生命周期为参照可看出该套件刻意覆盖“默认值/状态跨版本会发生变化”的特性Feature Gate演进轨迹出自本仓库 kube_features.goDynamicResourceAllocationDRA 的总开关GA 于 1.36 并 LockToDefaultDRADeviceTaints1.33 Alpha默认关→ 1.36 Beta默认开→ 1.37 GA默认开、未锁默认值DRADeviceTaintRules1.35 Alpha默认关→ 1.36 Beta依赖一个默认关闭的 Beta API故仍默认关→ 1.37 GA 默认开DRAExtendedResource1.34 Alpha默认关→ 1.36 Beta默认开→ 1.37 GA 并 LockToDefault计划 1.40 移除DRAPartitionableDevices1.33 Alpha默认关→ 1.36 Beta默认开这些跨 minor 版本“默认值翻转”或“API 版本迁移”正是升级/降级测试要捕捉的回归点例如当旧版本默认关闭某 gate、新版本默认开启时升级前后对 ResourceSlice、ResourceClaim 语义的处理必须一致kubelet 全量清空并重建 ResourceSlice 的机制也需要在两侧都成立。常见问题与实战要点综合 README、run.sh 与测试源码运行与扩展本套件时有几个高价值经验不要对单个子测试的运行顺序做假设子测试存于 map、以 map 遍历方式执行顺序不定新增子测试时请保证自包含并自备 driver 与设备。ResourceSlice 会被 kubelet 整体清空每次升级/降级导致 kubelet 重启后所有已发布 ResourceSlice 都被抹掉。若你的子测试自己管理 slice必须在回调中自行等待重建而不是假设它还在。陈旧连接需要重试apiserver 重启后客户端连接会残留清理对象时请用Eventually重试包裹容忍EOF与偶发 403coredra_test.go 是现成范例。依赖下载可能较慢首次运行会下载上一 minor 的 server tarball务必设置-timeout1h级别的超时多次迭代调试验证时设置KUBERNETES_SERVER_CACHE_DIR可显著提速。调试技巧dlv test ./test/e2e_dra -- -test.v可断点调试ktesting.SetDefaultVerbosity(2)设置了默认日志级别注释提示驱动操作排障时可用-v5查看更多细节见 upgradedowngrade_test.go。日志定位不设ARTIFACTS时日志落在测试临时目录设置后落在指定目录且 localupcluster.go 会在失败时保留集群现场供排查。宿主目录权限是最大坑点/var/lib/kubelet/plugins、/var/lib/kubelet/plugins_registry、/var/run/cdi不可写、或sudo不可用都会在local-up-cluster.sh阶段失败直接使用仓库的 run.sh 可规避手工遗漏。延伸阅读仓库内路径套件说明test/e2e_dra/README.md一键清理/权限/运行脚本test/e2e_dra/run.sh升级降级主流程与子测试注册test/e2e_dra/upgradedowngrade_test.go集群生命周期封装Start/Modify/Stoptest/utils/localupcluster/localupcluster.go、test/utils/localupcluster/cmd.go底层集群启动脚本hack/local-up-cluster.sh版本号来源脚本hack/print-workspace-status.shDRA Feature Gate 版本演进定义pkg/features/kube_features.goDRA 驱动的测试辅助工具test/e2e/dra/utils被本套件大量引用【免费下载链接】kubernetesProduction-Grade Container Scheduling and Management项目地址: https://gitcode.com/GitHub_Trending/kuber/kubernetes创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考