
containerd 虚拟机集成测试指南基于 Lima 在 Fedora/EL 上运行完整测试套件【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerd本文以 script/vm/README.md 为核心系统讲解 containerd 项目如何在虚拟机Fedora 或 EL 发行版默认 SELinux Enforcing中运行集成测试涵盖虚拟机准备、环境初始化Go、runc、CNI 插件、cri-tools、containerd 本体、三套测试套件test-integration.sh、test-cri-integration.sh、test-cri.sh的执行方式与全部可调环境变量。读完本文你将掌握与 CI 中integration-vm任务完全一致的本机复现方法并能深入理解每个脚本在源码层的实现细节。一、这套 VM 脚本解决什么问题containerd 的集成测试对运行环境有较高要求需要内核模块、SELinux 策略、runc/crun 运行时、CNI 网络插件、CRI 工具链等一整套依赖。直接在宿主机上运行既不安全也不可复现。script/vm/目录下的脚本正是为此设计——它们在一个全新的虚拟机中完成全链路环境搭建与测试执行保证测试结果与 CI 一致。这些脚本被 .github/workflows/ci.yml 中的integration-vm任务使用但不依赖 Lima 本身同样可以配合其他 VM 环境如 QEMU、VirtualBox 或云主机使用。脚本约定的目标操作系统是Fedora 或 EL 发行版RHEL/CentOS/AlmaLinux 等默认在SELinux Enforcing模式下运行这是它区别于一般测试脚本的最大特点——确保 containerd 在强制 SELinux 策略下依然行为正确。script/vm/目录共包含 4 个脚本职责划分如下脚本职责provision.sh在客户机内初始化环境软件包、Go、runc、CNI、cri-tools、containerd、gotestsum、failpoint 二进制test-integration.sh运行 containerd 核心集成测试make integrationtest-cri-integration.sh运行 CRI 插件集成测试cri-integration.testtest-cri.sh以 systemd 单元方式启动 containerd运行critest一致性测试二、使用 Lima 在本机复现Lima 是 macOS/Linux 上常用的虚拟机管理工具。下面的流程摘自 script/vm/README.md可完整复现 CI 行为。1. 启动一台干净的虚拟机# Boot a plain VM. template:almalinux-8, -9, and -10 are tested too. # --plain keeps the guest pristine (no guest agent, no mounts, no port forwards). limactl start --plain --namedefault --cpus2 --memory4 --disk60 template:fedora-44关键点说明--plain保持客户机原始状态——不安装 guest agent、不做目录挂载、不做端口转发。这正是测试所需的隔离环境。--cpus2 --memory4 --disk60CI 中同样采用此配置见 ci.yml。官方测试过的模板template:fedora-44、template:almalinux-8、-9、-10。其中 AlmaLinux 8 保留了旧版 glibc、cgroup 与内核用于验证兼容性CI 注释明确说明 We have to keep EL8 to test old glibc, cgroup, kernel, etc.见 ci.yml。2. 拷贝源码树到客户机# Copy the source tree into the guest. limactl cp -r . default:containerd lima bash -c sudo mkdir -p /go/src/github.com/containerd sudo mv ~/containerd /go/src/github.com/containerd/containerd export LIMA_WORKDIR/go/src/github.com/containerd/containerd把源码放到/go/src/github.com/containerd/containerd并非随意为之——provision 脚本会建立$GOPATH/src/github.com/containerd/containerd的软链接见下文 provision.sh 分析使仓库位于 Go 模块的标准导入路径上。LIMA_WORKDIR变量供后续lima命令切换到该目录使用。3. 初始化客户机# Provision the guest (packages, Go, runc, CNI plugins, cri-tools, containerd, ...). lima sudo script/vm/provision.sh该步骤耗时较长需要联网下载软件包、Go 工具链、runc 源码与各测试工具详见第三节。4. 运行测试套件# Run the test suites. lima sudo script/vm/test-integration.sh lima sudo CGROUP_DRIVERsystemd script/vm/test-cri-integration.sh lima sudo CGROUP_DRIVERsystemd script/vm/test-cri.sh三行命令依次对应三类测试核心集成测试、CRI 集成测试、CRI 一致性测试critest。CGROUP_DRIVERsystemd表示以 systemd cgroup 驱动运行——在采用 systemd 作为 init 的发行版上这是生产环境的典型配置与 cgroupfs 驱动分别覆盖两条路径CI 矩阵对两者都会测试见 ci.yml。5. 清理limactl delete -f default三、环境变量一览原文档给出了各脚本支持的全部环境变量此处完整保留并补充默认值均来自脚本源码脚本环境变量取值/默认值作用provision.shGO_VERSION默认1.27.1要安装的 Go 工具链版本RUNC_FLAVORrunc或crun默认runc安装哪种低层运行时crun 会被安装为runc同名二进制SELINUXEnforcing/Permissive/Disabled默认Enforcing客户机的 SELinux 模式INSTALL_PACKAGES默认空追加安装的额外软件包空格分隔会拼入 dnf install 命令test-integration.shRUNC_FLAVORrunc或crun默认runc指定测试使用的运行时 flavortest-cri-integration.shCGROUP_DRIVER空cgroupfs或systemdCRI 插件的 cgroup 驱动RUNC_FLAVORrunc或crun默认runc指定测试使用的运行时 flavortest-cri.shCGROUP_DRIVER空cgroupfs或systemdCRI 插件的 cgroup 驱动REPORT_DIR默认空非空时critest会额外生成测试报告到该目录另有几个脚本内部使用的变量源码中: ${VAR:default}形式声明GOTEST默认go testtest-integration.sh 与 test-cri-integration.sh、GOPATH默认/go、GITHUB_WORKSPACEtest-cri-integration.sh 中转发给内部脚本默认空。四、深入 provision.sh客户机初始化全流程provision.sh 是整套流程的基础必须在客户机内以root身份执行脚本开头显式检查id -u非 root 直接报错退出见 provision.sh。它依次完成以下工作1. 安装系统软件包通过dnf安装测试所需依赖provision.shdnf -y install \ container-selinux \ curl gcc git iptables \ libseccomp-devel libselinux-devel \ lsof make strace which \ kernel-modules-extra-$(uname -r) \ ${INSTALL_PACKAGES} modprobe xt_comment几个值得注意的细节container-selinux提供容器运行所需的 SELinux 策略模块libseccomp-devel与libselinux-devel是编译 containerdseccomp/selinux build tag的开发头文件。kernel-modules-extra-$(uname -r)按当前内核版本精确匹配安装为测试提供额外内核模块。modprobe xt_comment加载 iptables 的 comment 匹配模块供 CNI 网络插件使用。${INSTALL_PACKAGES}未加引号展开# shellcheck disableSC2086注释了该意图便于传入以空格分隔的多个包名。2. 安装 Go 工具链GOARCH$(uname -m | sed -e s/x86_64/amd64/ -e s/aarch64/arm64/) curl -fsSL https://dl.google.com/go/go${GO_VERSION}.linux-${GOARCH}.tar.gz | tar Cxz /usr/local从uname -m映射出GOARCHx86_64→amd64aarch64→arm64下载对应架构的官方二进制包解压到/usr/local。3. 处理源码树属主与 SELinux 标签源码是从宿主机拷贝进来的属主可能是非 root 用户且文件可能带有宿主机目录的 SELinux 上下文provision.shgit config --system --add safe.directory ${containerd_dir} if type -p restorecon /dev/null; then restorecon -R ${containerd_dir} figit config --system --add safe.directory把源码目录标记为 git 安全目录避免dubious ownership错误。restorecon -R递归恢复文件的默认 SELinux 上下文防止后续执行时被策略拦截。4. 建立 GOPATH 布局mkdir -p ${GOPATH}/src/github.com/containerd if [[ ${containerd_dir} ! ${GOPATH}/src/github.com/containerd/containerd ]]; then ln -fnsv ${containerd_dir} ${GOPATH}/src/github.com/containerd/containerd fi若源码不在标准位置则在/go/src/github.com/containerd/containerd建立指向实际源码的软链接保证 Go 构建工具能找到正确的导入路径。5. 安装低层运行时runc/crunRUNC_FLAVOR${RUNC_FLAVOR} script/setup/install-runc type runc runc --version type -ap runc | sort -u | xargs chcon -v -t container_runtime_exec_tinstall-runc 根据RUNC_FLAVOR二选一runc从runc-version文件读取固定版本脚本头部注释说明该版本与 go.mod 中 runc 模块保持一致git clone 后以BUILDTAGSseccomp编译并make installcrun直接下载对应版本的预编译 crun 二进制保存为/usr/local/sbin/runc即以 runc 之名充当 runc 使用。安装后执行chcon -t container_runtime_exec_t为二进制打上容器运行时执行标签这是 SELinux Enforcing 下容器能够启动的前提之一。6. 安装 CNI 插件与 cri-toolsscript/setup/install-cni CNI_BINARIESbridge dhcp flannel host-device host-local ipvlan loopback macvlan portmap ptp tuning vlan PATH/opt/cni/bin:${PATH} type ${CNI_BINARIES} || true GOBIN/usr/local/bin script/setup/install-critools type crictl critest critest --versionCNI 插件安装到/opt/cni/bintype逐一确认 11 个标准插件存在|| true允许校验不中断脚本。cri-tools 提供crictlCRI 调试客户端与critestCRI 一致性测试工具critest --version确认版本。7. 编译安装 containerd 本体make BUILDTAGSseccomp selinux no_btrfs no_devmapper no_zfs binaries install type containerd containerd --version chcon -v -t container_runtime_exec_t /usr/local/bin/{containerd,containerd-shim*}采用seccomp selinux开启安全特性用no_btrfs no_devmapper no_zfs关闭不需要的快照器缩减构建面。对containerd及所有containerd-shim*二进制设置container_runtime_exec_tSELinux 标签。8. 安装 gotestsum 与 failpoint 二进制script/setup/install-gotestsum cp ${GOPATH}/bin/gotestsum /usr/local/bin/ script/setup/install-failpoint-binaries type -ap containerd-shim-runc-fp-v1 | sort -u | xargs chcon -v -t container_runtime_exec_t containerd-shim-runc-fp-v1 -vgotestsum用于格式化测试输出containerd-shim-runc-fp-v1是带 failpoint 注入能力的 shim供故障注入类集成测试使用对应integration/failpoint/目录。9. 配置 SELinux 与 containerdSELINUX${SELINUX} script/setup/config-selinux script/setup/config-containerdconfig-selinux 按SELINUX变量配置模式Disabled若/sys/fs/selinux已挂载则setenforce 0并卸载Enforcing挂载 selinuxfs 并setenforce 1Permissive挂载 selinuxfs 并setenforce 0其他值直接报错退出。config-containerd 生成/etc/containerd/config.tomlversion 2 [plugins.io.containerd.snapshotter.v1.overlayfs] slow_chown true [plugins] [plugins.io.containerd.grpc.v1.cri] enable_selinux true # 仅当 SELinux 非 Disabled 时为 true两个配置点均有明确目的slow_chown true规避内核 5.19 时 overlayfs 快照器不支持 idmap mount 的问题报错信息为 snapshotter overlayfs doesnt support idmap mounts on this host, configureslow_chownto allow a slower and expensive fallback对内核 ≥ 5.19 可安全忽略该注释与关联 issue 见 config-containerd。enable_selinux动态由getenforce的结果决定SELinux 处于 Enforcing/Permissive 时为trueDisabled 时为false。五、三套测试脚本的源码级解析1. test-integration.sh核心集成测试test-integration.sh 执行两步L37-L40rm -rf /var/lib/containerd-test /run/containerd-test cd ${containerd_dir} go test -v -count1 -race ./core/metrics/cgroups make integration EXTRA_TESTFLAGS-timeout 15m -no-criu -test.v TEST_RUNTIMEio.containerd.runc.v2 RUNC_FLAVOR${RUNC_FLAVOR}先清理可能残留的测试数据目录保证干净起点。单独运行go test -race对core/metrics/cgroups包做竞态检测覆盖 cgroups 指标采集路径。make integration是主入口EXTRA_TESTFLAGS传入-timeout 15m超时上限、-no-criu跳过 CRIU 检查点/恢复相关测试、-test.v详细输出TEST_RUNTIMEio.containerd.runc.v2指定使用 runc v2 shim 运行时。2. test-cri-integration.shCRI 插件集成测试test-cri-integration.sh 聚焦 containerd 内置 CRI 插件L43-L48cleanup cd ${containerd_dir} make BUILDTAGSseccomp selinux no_btrfs no_devmapper no_zfs binaries bin/cri-integration.test chcon -v -t container_runtime_exec_t ./bin/{containerd,containerd-shim*} CONTAINERD_RUNTIMEio.containerd.runc.v2 ./script/test/cri-integration.sh cleanupbin/cri-integration.test是编译出的 CRI 集成测试二进制脚本注释特别说明该测试从./bin目录执行 containerd而不是从$PATHtest-cri-integration.sh因此必须先在仓库内完成make binaries。cleanup()函数会清空/var/lib/containerd*、/run/containerd*、/tmp/containerd*、/tmp/test*、/tmp/failpoint*、/tmp/nri*确保测试间互不污染L39-L41。3. test-cri.shCRI 一致性测试critesttest-cri.sh 把 containerd 作为systemd 单元启动再运行critestL37-L71systemctl disable --now containerd || true rm -rf /var/lib/containerd /run/containerd ... systemctl enable --now ${containerd_dir}/containerd.service ... critest --parallel$(($(nproc) 2)) --ginkgo.skip${skip_test_args}值得注意的实现细节先systemctl disable --now containerd停掉系统自带的 containerd再用仓库根目录的 containerd.service 启动测试版本保证测试对象是本次构建的二进制。SELinux 处理getenforce为 Enforcing 时先setenforce 0启动服务、再恢复setenforce 1让服务进程能在启动过程中正常初始化L46-L53。trap cleanup EXIT无论成败退出前都会通过journalctl -u containerd导出完整日志到/tmp/containerd.log并打印便于排障L40-L44。跳过列表skip_testsL57-L62HostIpc is true始终跳过当CGROUP_DRIVERsystemd时额外跳过 should terminate with exitCode 137 and reason OOMKilledsystemd cgroup 驱动下 OOM 行为与 cgroupfs 存在差异。并行度设为nproc 2最大化利用客户机 CPUREPORT_DIR非空时通过--report-dir输出测试报告。六、CI 中的矩阵化使用.github/workflows/ci.yml中的integration-vm任务ci.yml展示了这些脚本的完整组合方式。矩阵维度包括模板fedora-44主测版本、almalinux-8验证旧 glibc/cgroup/内核、almalinux-9、almalinux-10cgroup 驱动cgroupfs与systemd两条路径全覆盖运行时runc与crun。任务流水线与本地流程一一对应limactl start --plain启动 →limactl cp -r .拷贝源码 → 按LIMA_TEMPLATE、CGROUP_DRIVER、RUNC_FLAVOR三个环境变量注入矩阵值 → 依次执行provision.sh、test-integration.sh、test-cri-integration.sh、test-cri.sh最后无论成败都执行dmesg -T -f kern导出内核日志用于诊断ci.yml。七、常见问题与使用建议必须以 root 执行四个脚本开头都有id -u ! 0检查。在 Lima 下用lima sudo调用在其他 VM 环境请先切换为 root。SELinux 相关报错若容器无法启动优先检查二进制 SELinux 标签chcon -t container_runtime_exec_t与enable_selinux配置临时弱化可设SELINUXPermissive或SELINUXDisabled重新运行 provision。更换运行时设置RUNC_FLAVORcrun即可用 crun 替代 runc 验证另一条 OCI 运行时路径注意 crun 会被安装为/usr/local/sbin/runc名称。更换 Go 版本通过GO_VERSION环境变量控制当前默认值为1.27.1provision.sh。追加系统包INSTALL_PACKAGESpkg1 pkg2会被直接拼入dnf install适合按需补充内核模块或调试工具。获取测试日志test-cri.sh的 containerd 日志始终被导出到/tmp/containerd.log集成测试失败时配合 CI 的dmesg -T -f kern可快速定位内核层面问题。八、小结script/vm/这套脚本把 containerd 集成测试的环境准备 测试执行完整自动化从零开始依次完成软件包安装、Go 工具链、runc/crun、CNI 插件、cri-tools、containerd 构建安装、SELinux 与 containerd 配置再到核心集成测试、CRI 集成测试与critest一致性测试的串行执行。得益于与 CIintegration-vm任务完全一致的脚本与参数开发者可以在本地 Lima 虚拟机中 1:1 复现 CI 测试矩阵是提交 PR 前自测与排查 CI 失败的有力工具。若需调整环境细节环境变量一览 一节给出了全部可调入口。【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考