CI: migrate Vagrant to Lima

Vagrant is no longer well maintained: e.g., its apt repository does not
provide packages for Ubuntu 26.04 (hashicorp/vagrant#13811), and recent
Fedora boxes are no longer published to HashiCorp's registry, so the CI
had to download the box file manually from Fedora mirrors.

The test scripts in the Vagrantfile were split out to script/vm/*.sh .
The scripts depend on neither Vagrant nor Lima, and can be used with
other VM environments too.

Assisted-by: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
Akihiro Suda
2026-07-08 08:35:38 +09:00
parent cb66686cbb
commit a42b09aaa6
10 changed files with 354 additions and 443 deletions

View File

@@ -598,8 +598,8 @@ jobs:
${{github.workspace}}/report/*.xml
${{github.workspace}}/report/*.log
integration-vagrant:
name: Vagrant integration
integration-vm:
name: VM integration
if: github.event_name != 'merge_group'
runs-on: ubuntu-latest
timeout-minutes: 60
@@ -609,44 +609,42 @@ jobs:
fail-fast: false
matrix:
include:
- box: fedora/44-cloud-base
- template: fedora-44
cgroup_driver: cgroupfs
runc: runc
- box: fedora/44-cloud-base
- template: fedora-44
cgroup_driver: systemd
runc: runc
- box: fedora/44-cloud-base
- template: fedora-44
cgroup_driver: cgroupfs
runc: crun
- box: fedora/44-cloud-base
- template: fedora-44
cgroup_driver: systemd
runc: crun
# We have to keep EL8 to test old glibc, cgroup, kernel, etc.
# The image was changed from rockylinux/8 to almalinux/8,
# as the former one no longer works:
# https://github.com/containerd/containerd/pull/10297
- box: almalinux/8
- template: almalinux-8
cgroup_driver: cgroupfs
runc: runc
- box: almalinux/8
- template: almalinux-8
cgroup_driver: systemd
runc: runc
- box: almalinux/9
- template: almalinux-9
cgroup_driver: cgroupfs
runc: runc
- box: almalinux/9
- template: almalinux-9
cgroup_driver: systemd
runc: runc
- box: almalinux/10
- template: almalinux-10
cgroup_driver: cgroupfs
runc: runc
- box: almalinux/10
- template: almalinux-10
cgroup_driver: systemd
runc: runc
env:
BOX: ${{ matrix.box }}
LIMA_TEMPLATE: ${{ matrix.template }}
CGROUP_DRIVER: ${{ matrix.cgroup_driver }}
RUNC_FLAVOR: ${{ matrix.runc }}
LIMA_WORKDIR: /go/src/github.com/containerd/containerd
steps:
- name: Show the host info
run: |
@@ -658,49 +656,36 @@ jobs:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: lima-vm/lima-actions/setup@55627e31b78637bf254a8b2a14da8ea7d12564e5 # v1.1.0
id: lima-actions-setup
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: /root/.vagrant.d
key: vagrant-${{ matrix.box }}
- name: Set up vagrant
run: |
# Canonical's Vagrant 2.2.19 dpkg cannot download Fedora 38 image: https://bugs.launchpad.net/vagrant/+bug/2017828
# So we have to install Vagrant >= 2.3.1 from the upstream: https://github.com/opencontainers/runc/blob/v1.1.8/.cirrus.yml#L41-L49
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo sed -i 's/^Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/ubuntu.sources
sudo apt-get update
sudo apt-get install -y libvirt-daemon libvirt-daemon-system vagrant ovmf
# https://github.com/vagrant-libvirt/vagrant-libvirt/issues/1725#issuecomment-1454058646
sudo cp /usr/share/OVMF/OVMF_VARS_4M.fd /var/lib/libvirt/qemu/nvram/
sudo systemctl enable --now libvirtd
sudo apt-get build-dep -y ruby-libvirt
sudo apt-get install -y --no-install-recommends libxslt-dev libxml2-dev libvirt-dev ruby-bundler ruby-dev zlib1g-dev
sudo env VAGRANT_DISABLE_STRICT_DEPENDENCY_ENFORCEMENT=1 vagrant plugin uninstall fog-json || true
sudo env VAGRANT_DISABLE_STRICT_DEPENDENCY_ENFORCEMENT=1 vagrant plugin install fog-json --plugin-version 1.2.0
sudo env VAGRANT_DISABLE_STRICT_DEPENDENCY_ENFORCEMENT=1 vagrant plugin install vagrant-libvirt
path: ~/.cache/lima
key: lima-${{ steps.lima-actions-setup.outputs.version }}-${{ matrix.template }}
- name: Boot VM
# --plain keeps the guest pristine (no guest agent, no mounts, no port forwards)
run: limactl start --plain --name=default --cpus=2 --memory=4 --disk=60 "template:$LIMA_TEMPLATE"
- name: Copy the source code to the VM
env:
# $LIMA_WORKDIR does not exist yet
LIMA_WORKDIR: /
run: |
if [ "$BOX" = "fedora/44-cloud-base" ]; then
# fedora/41-cloud-base seems the last version available in https://portal.cloud.hashicorp.com/vagrant/discover/fedora
# Download the box file with curl (with retry) to handle flaky Fedora mirrors
curl -fL --retry 5 --retry-delay 5 --retry-all-errors \
--connect-timeout 30 --max-time 600 \
-o /tmp/fedora.box \
https://download.fedoraproject.org/pub/fedora/linux/releases/44/Cloud/x86_64/images/Fedora-Cloud-Base-Vagrant-libvirt-44-1.7.x86_64.vagrant.libvirt.box
sudo vagrant box add fedora/44-cloud-base /tmp/fedora.box
rm -f /tmp/fedora.box
fi
sudo BOX=$BOX RUNC_FLAVOR=$RUNC_FLAVOR vagrant up --no-tty
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'
- name: Provision the VM
run: lima sudo RUNC_FLAVOR="$RUNC_FLAVOR" script/vm/provision.sh
- name: test-integration
run: sudo BOX=$BOX RUNC_FLAVOR=$RUNC_FLAVOR vagrant up --provision-with=selinux,install-runc,install-gotestsum,test-integration
run: lima sudo RUNC_FLAVOR="$RUNC_FLAVOR" script/vm/test-integration.sh
- name: test-cri-integration
run: sudo BOX=$BOX CGROUP_DRIVER=$CGROUP_DRIVER RUNC_FLAVOR=$RUNC_FLAVOR vagrant up --provision-with=selinux,install-runc,install-gotestsum,test-cri-integration
run: lima sudo CGROUP_DRIVER="$CGROUP_DRIVER" RUNC_FLAVOR="$RUNC_FLAVOR" script/vm/test-cri-integration.sh
- name: test-cri
run: sudo BOX=$BOX CGROUP_DRIVER=$CGROUP_DRIVER RUNC_FLAVOR=$RUNC_FLAVOR vagrant up --provision-with=selinux,install-runc,install-gotestsum,test-cri
run: lima sudo CGROUP_DRIVER="$CGROUP_DRIVER" script/vm/test-cri.sh
- name: dump-dmesg
if: always()
run: sudo BOX=$BOX vagrant ssh -c "sudo dmesg -T -f kern"
env:
# $LIMA_WORKDIR may not exist if an earlier step failed
LIMA_WORKDIR: /
run: lima sudo dmesg -T -f kern
tests-cri-in-userns:
name: "CRI-in-UserNS"

View File

@@ -16,4 +16,3 @@ _site/
releases/*.tar.gz
releases/*.tar.gz.sha256sum
_output/
.vagrant/

1
.gitignore vendored
View File

@@ -11,4 +11,3 @@ _site/
releases/*.tar.gz
releases/*.tar.gz.sha256sum
_output/
.vagrant/

348
Vagrantfile vendored
View File

@@ -1,348 +0,0 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Copyright The containerd Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Vagrantfile for Fedora and EL
Vagrant.configure("2") do |config|
config.vm.box = ENV["BOX"] ? ENV["BOX"].split("@")[0] : "fedora/44-cloud-base"
# BOX_VERSION is deprecated. Use "BOX=<BOX>@<BOX_VERSION>".
config.vm.box_version = ENV["BOX_VERSION"] || (ENV["BOX"].split("@")[1] if ENV["BOX"])
memory = 4096
cpus = 2
disk_size = 60
config.vm.provider :virtualbox do |v, o|
v.memory = memory
v.cpus = cpus
# Needs env var VAGRANT_EXPERIMENTAL="disks"
o.vm.disk :disk, size: "#{disk_size}GB", primary: true
v.customize ["modifyvm", :id, "--firmware", "efi"]
end
config.vm.provider :libvirt do |v|
v.memory = memory
v.cpus = cpus
v.machine_virtual_size = disk_size
# https://github.com/vagrant-libvirt/vagrant-libvirt/issues/1725#issuecomment-1454058646
# Needs `sudo cp /usr/share/OVMF/OVMF_VARS_4M.fd /var/lib/libvirt/qemu/nvram/`
v.loader = '/usr/share/OVMF/OVMF_CODE_4M.fd'
v.nvram = '/var/lib/libvirt/qemu/nvram/OVMF_VARS_4M.fd'
end
config.vm.synced_folder ".", "/vagrant", type: "rsync"
config.vm.provision 'shell', path: 'script/resize-vagrant-root.sh'
# Disabled by default. To run:
# vagrant up --provision-with=upgrade-packages
# To upgrade only specific packages:
# UPGRADE_PACKAGES=selinux vagrant up --provision-with=upgrade-packages
#
config.vm.provision "upgrade-packages", type: "shell", run: "never" do |sh|
sh.upload_path = "/tmp/vagrant-upgrade-packages"
sh.env = {
'UPGRADE_PACKAGES': ENV['UPGRADE_PACKAGES'],
}
sh.inline = <<~SHELL
#!/usr/bin/env bash
set -eux -o pipefail
dnf -y upgrade --refresh ${UPGRADE_PACKAGES}
SHELL
end
# To re-run, installing CNI from RPM:
# INSTALL_PACKAGES="containernetworking-plugins" vagrant up --provision-with=install-packages
#
config.vm.provision "install-packages", type: "shell", run: "once" do |sh|
sh.upload_path = "/tmp/vagrant-install-packages"
sh.env = {
'INSTALL_PACKAGES': ENV['INSTALL_PACKAGES'],
}
sh.inline = <<~SHELL
#!/usr/bin/env bash
set -eux -o pipefail
dnf -y makecache --refresh
dnf -y install \
container-selinux \
curl \
gcc \
git \
iptables \
libseccomp-devel \
libselinux-devel \
lsof \
make \
strace \
kernel-modules-extra-$(uname -r) \
${INSTALL_PACKAGES}
modprobe xt_comment
SHELL
end
# EL does not have /usr/local/{bin,sbin} in the PATH by default
config.vm.provision "setup-etc-environment", type: "shell", run: "once" do |sh|
sh.upload_path = "/tmp/vagrant-setup-etc-environment"
sh.inline = <<~SHELL
#!/usr/bin/env bash
set -eux -o pipefail
cat >> /etc/environment <<EOF
PATH=/usr/local/go/bin:/usr/local/bin:/usr/local/sbin:$PATH
EOF
source /etc/environment
SHELL
end
# To re-run this provisioner, installing a different version of go:
# GO_VERSION="1.14.6" vagrant up --provision-with=install-golang
#
config.vm.provision "install-golang", type: "shell", run: "once" do |sh|
sh.upload_path = "/tmp/vagrant-install-golang"
sh.env = {
'GO_VERSION': ENV['GO_VERSION'] || "1.26.5",
}
sh.inline = <<~SHELL
#!/usr/bin/env bash
set -eux -o pipefail
curl -fsSL "https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz" | tar Cxz /usr/local
cat >> /etc/profile.d/sh.local <<EOF
GOPATH=\\$HOME/go
PATH=\\$GOPATH/bin:\\$PATH
export GOPATH PATH
git config --global --add safe.directory /vagrant
EOF
source /etc/profile.d/sh.local
SHELL
end
config.vm.provision "setup-gopath", type: "shell", run: "once" do |sh|
sh.upload_path = "/tmp/vagrant-setup-gopath"
sh.inline = <<~SHELL
#!/usr/bin/env bash
source /etc/environment
source /etc/profile.d/sh.local
set -eux -o pipefail
mkdir -p ${GOPATH}/src/github.com/containerd
ln -fnsv /vagrant ${GOPATH}/src/github.com/containerd/containerd
SHELL
end
config.vm.provision "install-runc", type: "shell", run: "once" do |sh|
sh.upload_path = "/tmp/vagrant-install-runc"
sh.env = {
'RUNC_FLAVOR': ENV['RUNC_FLAVOR'] || "runc",
}
sh.inline = <<~SHELL
#!/usr/bin/env bash
source /etc/environment
source /etc/profile.d/sh.local
set -eux -o pipefail
${GOPATH}/src/github.com/containerd/containerd/script/setup/install-runc
type runc
runc --version
chcon -v -t container_runtime_exec_t $(type -ap runc)
SHELL
end
config.vm.provision "install-cni", type: "shell", run: "once" do |sh|
sh.upload_path = "/tmp/vagrant-install-cni"
sh.env = {
'CNI_BINARIES': 'bridge dhcp flannel host-device host-local ipvlan loopback macvlan portmap ptp tuning vlan',
}
sh.inline = <<~SHELL
#!/usr/bin/env bash
source /etc/environment
source /etc/profile.d/sh.local
set -eux -o pipefail
cd ${GOPATH}/src/github.com/containerd/containerd
script/setup/install-cni
PATH=/opt/cni/bin:$PATH type ${CNI_BINARIES} || true
SHELL
end
config.vm.provision "install-cri-tools", type: "shell", run: "once" do |sh|
sh.upload_path = "/tmp/vagrant-install-cri-tools"
sh.env = {
'CRI_TOOLS_VERSION': ENV['CRI_TOOLS_VERSION'] || '16911795a3c33833fa0ec83dac1ade3172f6989e',
'GOBIN': '/usr/local/bin',
}
sh.inline = <<~SHELL
#!/usr/bin/env bash
source /etc/environment
source /etc/profile.d/sh.local
set -eux -o pipefail
${GOPATH}/src/github.com/containerd/containerd/script/setup/install-critools
type crictl critest
critest --version
SHELL
end
config.vm.provision "install-containerd", type: "shell", run: "once" do |sh|
sh.upload_path = "/tmp/vagrant-install-containerd"
sh.inline = <<~SHELL
#!/usr/bin/env bash
source /etc/environment
source /etc/profile.d/sh.local
set -eux -o pipefail
cd ${GOPATH}/src/github.com/containerd/containerd
make BUILDTAGS="seccomp 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*}
./script/setup/config-containerd
SHELL
end
config.vm.provision "install-gotestsum", type: "shell", run: "once" do |sh|
sh.upload_path = "/tmp/vagrant-install-gotestsum"
sh.inline = <<~SHELL
#!/usr/bin/env bash
source /etc/environment
source /etc/profile.d/sh.local
set -eux -o pipefail
${GOPATH}/src/github.com/containerd/containerd/script/setup/install-gotestsum
sudo cp ${GOPATH}/bin/gotestsum /usr/local/bin/
SHELL
end
config.vm.provision "install-failpoint-binaries", type: "shell", run: "once" do |sh|
sh.upload_path = "/tmp/vagrant-install-failpoint-binaries"
sh.inline = <<~SHELL
#!/usr/bin/env bash
source /etc/environment
source /etc/profile.d/sh.local
set -eux -o pipefail
${GOPATH}/src/github.com/containerd/containerd/script/setup/install-failpoint-binaries
chcon -v -t container_runtime_exec_t $(type -ap containerd-shim-runc-fp-v1)
containerd-shim-runc-fp-v1 -v
SHELL
end
# SELinux is Enforcing by default.
# To set SELinux as Disabled on a VM that has already been provisioned:
# SELINUX=Disabled vagrant up --provision-with=selinux
# To set SELinux as Permissive on a VM that has already been provsioned
# SELINUX=Permissive vagrant up --provision-with=selinux
config.vm.provision "selinux", type: "shell", run: "never" do |sh|
sh.upload_path = "/tmp/vagrant-selinux"
sh.env = {
'SELINUX': ENV['SELINUX'] || "Enforcing"
}
sh.inline = <<~SHELL
/vagrant/script/setup/config-selinux
/vagrant/script/setup/config-containerd
SHELL
end
# SELinux is Enforcing by default (via provisioning) in this VM. To re-run with SELinux disabled:
# SELINUX=Disabled vagrant up --provision-with=selinux,test-integration
#
config.vm.provision "test-integration", type: "shell", run: "never" do |sh|
sh.upload_path = "/tmp/test-integration"
sh.env = {
'RUNC_FLAVOR': ENV['RUNC_FLAVOR'] || "runc",
'GOTEST': ENV['GOTEST'] || "go test",
'GOTESTSUM_JUNITFILE': ENV['GOTESTSUM_JUNITFILE'],
'GOTESTSUM_JSONFILE': ENV['GOTESTSUM_JSONFILE'],
}
sh.inline = <<~SHELL
#!/usr/bin/env bash
source /etc/environment
source /etc/profile.d/sh.local
set -eux -o pipefail
rm -rf /var/lib/containerd-test /run/containerd-test
cd ${GOPATH}/src/github.com/containerd/containerd
go test -v -count=1 -race ./core/metrics/cgroups
make integration EXTRA_TESTFLAGS="-timeout 15m -no-criu -test.v" TEST_RUNTIME=io.containerd.runc.v2 RUNC_FLAVOR=$RUNC_FLAVOR
SHELL
end
# SELinux is Enforcing by default (via provisioning) in this VM. To re-run with SELinux disabled:
# SELINUX=Disabled vagrant up --provision-with=selinux,test-cri-integration
#
config.vm.provision "test-cri-integration", type: "shell", run: "never" do |sh|
sh.upload_path = "/tmp/test-cri-integration"
sh.env = {
'GOTEST': ENV['GOTEST'] || "go test",
'GOTESTSUM_JUNITFILE': ENV['GOTESTSUM_JUNITFILE'],
'GOTESTSUM_JSONFILE': ENV['GOTESTSUM_JSONFILE'],
'GITHUB_WORKSPACE': '',
'CGROUP_DRIVER': ENV['CGROUP_DRIVER'],
'RUNC_FLAVOR': ENV['RUNC_FLAVOR'] || "runc",
}
sh.inline = <<~SHELL
#!/usr/bin/env bash
source /etc/environment
source /etc/profile.d/sh.local
set -eux -o pipefail
cleanup() {
rm -rf /var/lib/containerd* /run/containerd* /tmp/containerd* /tmp/test* /tmp/failpoint* /tmp/nri*
}
cleanup
cd ${GOPATH}/src/github.com/containerd/containerd
# cri-integration.sh executes containerd from ./bin, not from $PATH .
make BUILDTAGS="seccomp selinux no_btrfs no_devmapper no_zfs" binaries bin/cri-integration.test
chcon -v -t container_runtime_exec_t ./bin/{containerd,containerd-shim*}
CONTAINERD_RUNTIME=io.containerd.runc.v2 ./script/test/cri-integration.sh
cleanup
SHELL
end
# SELinux is Enforcing by default (via provisioning) in this VM. To re-run with SELinux disabled:
# SELINUX=Disabled vagrant up --provision-with=selinux,test-cri
#
config.vm.provision "test-cri", type: "shell", run: "never" do |sh|
sh.upload_path = "/tmp/test-cri"
sh.env = {
'GOTEST': ENV['GOTEST'] || "go test",
'REPORT_DIR': ENV['REPORT_DIR'],
'CGROUP_DRIVER': ENV['CGROUP_DRIVER'],
'RUNC_FLAVOR': ENV['RUNC_FLAVOR'] || "runc",
}
sh.inline = <<~SHELL
#!/usr/bin/env bash
source /etc/environment
source /etc/profile.d/sh.local
set -eux -o pipefail
systemctl disable --now containerd || true
rm -rf /var/lib/containerd /run/containerd
function cleanup()
{
journalctl -u containerd > /tmp/containerd.log
cat /tmp/containerd.log
systemctl stop containerd
}
selinux=$(getenforce)
if [[ $selinux == Enforcing ]]; then
setenforce 0
fi
systemctl enable --now ${GOPATH}/src/github.com/containerd/containerd/containerd.service
if [[ $selinux == Enforcing ]]; then
setenforce 1
fi
trap cleanup EXIT
ctr version
skip_tests=(
'HostIpc is true'
)
if [[ $CGROUP_DRIVER == "systemd" ]]; then
skip_tests+=("should terminate with exitCode 137 and reason OOMKilled")
fi
skip_test_args=$(IFS='|'; echo "${skip_tests[*]}")
critest --parallel=$[$(nproc)+2] --ginkgo.skip="${skip_test_args}" --report-dir="${REPORT_DIR}"
SHELL
end
end

View File

@@ -1,43 +0,0 @@
#!/usr/bin/env bash
# Copyright The containerd Authors.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -eu -o pipefail
# Rocky Linux doesn't have growpart by default.
(growpart -h > /dev/null) || dnf -y install cloud-utils-growpart
df_line=$(df -T / | grep '^/dev/')
if [[ "$df_line" =~ ^/dev/([a-z]+)([0-9+]) ]]; then
dev="${BASH_REMATCH[1]}"
part="${BASH_REMATCH[2]}"
# growpart prints "NOCHANGE" when the partition is already at max size
out=$(growpart "/dev/$dev" "$part" 2>&1) || grep -q "^NOCHANGE:" <<< "$out"
fstype=$(echo "$df_line" | awk '{print $2}')
if [[ "$fstype" = 'btrfs' ]]; then
btrfs filesystem resize max /
elif [[ "$fstype" = 'xfs' ]]; then
xfs_growfs -d /
else
echo "Unknown filesystem: $df_line"
exit 1
fi
elif [[ "$df_line" =~ ^/dev/mapper/ ]]; then
echo "TODO: support device mapper: $df_line"
else
echo "Failed to parse: $df_line"
exit 1
fi

40
script/vm/README.md Normal file
View File

@@ -0,0 +1,40 @@
# VM scripts
The scripts in this directory run the containerd integration tests inside a
virtual machine (Fedora or an EL distribution, with SELinux Enforcing by
default). They are used by the `integration-vm` job in
`.github/workflows/ci.yml`, but do not depend on [Lima](https://lima-vm.io)
and can be used with other VM environments too.
## Local usage with Lima
```bash
# 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 --name=default --cpus=2 --memory=4 --disk=60 template:fedora-44
# 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
# Provision the guest (packages, Go, runc, CNI plugins, cri-tools, containerd, ...).
lima sudo script/vm/provision.sh
# Run the test suites.
lima sudo script/vm/test-integration.sh
lima sudo CGROUP_DRIVER=systemd script/vm/test-cri-integration.sh
lima sudo CGROUP_DRIVER=systemd script/vm/test-cri.sh
# Clean up.
limactl delete -f default
```
## Environment variables
- `provision.sh`: `GO_VERSION`, `RUNC_FLAVOR` (`runc` or `crun`), `SELINUX`
(`Enforcing`, `Permissive`, or `Disabled`), `INSTALL_PACKAGES`
- `test-integration.sh`: `RUNC_FLAVOR`
- `test-cri-integration.sh`: `CGROUP_DRIVER` (empty or `systemd`), `RUNC_FLAVOR`
- `test-cri.sh`: `CGROUP_DRIVER` (empty or `systemd`), `REPORT_DIR`

118
script/vm/provision.sh Executable file
View File

@@ -0,0 +1,118 @@
#!/usr/bin/env bash
# Copyright The containerd Authors.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Provisions a virtual machine for running the containerd integration
# tests. Expects Fedora or an EL distribution as the guest OS.
#
# The containerd source tree has to be copied into the guest beforehand,
# and this script has to be executed as the root user inside the guest.
# See README.md in this directory for the usage.
#
set -eux -o pipefail
if [[ "$(id -u)" != "0" ]]; then
echo "must be executed as the root user" >&2
exit 1
fi
script_dir="$(cd -- "$(dirname -- "$0")" > /dev/null 2>&1; pwd -P)"
containerd_dir="$(cd -- "${script_dir}/../.." > /dev/null 2>&1; pwd -P)"
: "${GO_VERSION:=1.26.5}"
: "${RUNC_FLAVOR:=runc}"
: "${SELINUX:=Enforcing}"
: "${INSTALL_PACKAGES:=}"
export GOPATH="${GOPATH:-/go}"
export PATH="/usr/local/go/bin:${GOPATH}/bin:/usr/local/bin:/usr/local/sbin:${PATH}"
# Install the packages
dnf -y makecache --refresh
# shellcheck disable=SC2086
dnf -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
# Install 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
# The source tree is copied from the host: it may be owned by a non-root user,
# and may be labeled with the SELinux context of the directory it was copied to
git config --system --add safe.directory "${containerd_dir}"
if type -p restorecon > /dev/null; then
restorecon -R "${containerd_dir}"
fi
# Set up $GOPATH/src/github.com/containerd/containerd
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
cd "${containerd_dir}"
# Install runc (pass RUNC_FLAVOR=crun to install crun as runc)
RUNC_FLAVOR="${RUNC_FLAVOR}" script/setup/install-runc
type runc
runc --version
# "type -ap" may print the same file under multiple names, e.g., on
# distros where /usr/local/sbin is merged into /usr/local/bin
type -ap runc | sort -u | xargs chcon -v -t container_runtime_exec_t
# Install CNI plugins
script/setup/install-cni
CNI_BINARIES="bridge dhcp flannel host-device host-local ipvlan loopback macvlan portmap ptp tuning vlan"
# shellcheck disable=SC2086
PATH="/opt/cni/bin:${PATH}" type ${CNI_BINARIES} || true
# Install cri-tools
GOBIN=/usr/local/bin script/setup/install-critools
type crictl critest
critest --version
# Install containerd
make BUILDTAGS="seccomp 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*}
# Install gotestsum
script/setup/install-gotestsum
cp "${GOPATH}/bin/gotestsum" /usr/local/bin/
# Install failpoint binaries
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 -v
# Configure SELinux (pass SELINUX=Disabled or SELINUX=Permissive to weaken it)
# and establish /etc/containerd/config.toml
SELINUX="${SELINUX}" script/setup/config-selinux
script/setup/config-containerd

View File

@@ -0,0 +1,49 @@
#!/usr/bin/env bash
# Copyright The containerd Authors.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Runs the CRI integration tests inside a virtual machine
# provisioned with provision.sh.
#
set -eux -o pipefail
if [[ "$(id -u)" != "0" ]]; then
echo "must be executed as the root user" >&2
exit 1
fi
script_dir="$(cd -- "$(dirname -- "$0")" > /dev/null 2>&1; pwd -P)"
containerd_dir="$(cd -- "${script_dir}/../.." > /dev/null 2>&1; pwd -P)"
export CGROUP_DRIVER="${CGROUP_DRIVER:-}"
export RUNC_FLAVOR="${RUNC_FLAVOR:-runc}"
export GOTEST="${GOTEST:-go test}"
export GITHUB_WORKSPACE="${GITHUB_WORKSPACE:-}"
export GOPATH="${GOPATH:-/go}"
export PATH="/usr/local/go/bin:${GOPATH}/bin:/usr/local/bin:/usr/local/sbin:${PATH}"
cleanup() {
rm -rf /var/lib/containerd* /run/containerd* /tmp/containerd* /tmp/test* /tmp/failpoint* /tmp/nri*
}
cleanup
cd "${containerd_dir}"
# cri-integration.sh executes containerd from ./bin, not from $PATH .
make BUILDTAGS="seccomp selinux no_btrfs no_devmapper no_zfs" binaries bin/cri-integration.test
chcon -v -t container_runtime_exec_t ./bin/{containerd,containerd-shim*}
CONTAINERD_RUNTIME=io.containerd.runc.v2 ./script/test/cri-integration.sh
cleanup

72
script/vm/test-cri.sh Executable file
View File

@@ -0,0 +1,72 @@
#!/usr/bin/env bash
# Copyright The containerd Authors.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Runs critest against containerd (running as a systemd unit) inside a
# virtual machine provisioned with provision.sh.
#
set -eux -o pipefail
if [[ "$(id -u)" != "0" ]]; then
echo "must be executed as the root user" >&2
exit 1
fi
script_dir="$(cd -- "$(dirname -- "$0")" > /dev/null 2>&1; pwd -P)"
containerd_dir="$(cd -- "${script_dir}/../.." > /dev/null 2>&1; pwd -P)"
: "${CGROUP_DRIVER:=}"
: "${REPORT_DIR:=}"
export GOPATH="${GOPATH:-/go}"
export PATH="/usr/local/go/bin:${GOPATH}/bin:/usr/local/bin:/usr/local/sbin:${PATH}"
systemctl disable --now containerd || true
rm -rf /var/lib/containerd /run/containerd
cleanup() {
journalctl -u containerd > /tmp/containerd.log
cat /tmp/containerd.log
systemctl stop containerd
}
selinux=$(getenforce)
if [[ $selinux == Enforcing ]]; then
setenforce 0
fi
systemctl enable --now "${containerd_dir}/containerd.service"
if [[ $selinux == Enforcing ]]; then
setenforce 1
fi
trap cleanup EXIT
ctr version
skip_tests=(
'HostIpc is true'
)
if [[ $CGROUP_DRIVER == "systemd" ]]; then
skip_tests+=("should terminate with exitCode 137 and reason OOMKilled")
fi
skip_test_args=$(
IFS='|'
echo "${skip_tests[*]}"
)
critest_args=(--parallel=$(($(nproc) + 2)) --ginkgo.skip="${skip_test_args}")
if [[ -n $REPORT_DIR ]]; then
mkdir -p "${REPORT_DIR}"
critest_args+=(--report-dir="${REPORT_DIR}")
fi
critest "${critest_args[@]}"

40
script/vm/test-integration.sh Executable file
View File

@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Copyright The containerd Authors.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Runs the containerd integration tests inside a virtual machine
# provisioned with provision.sh.
#
set -eux -o pipefail
if [[ "$(id -u)" != "0" ]]; then
echo "must be executed as the root user" >&2
exit 1
fi
script_dir="$(cd -- "$(dirname -- "$0")" > /dev/null 2>&1; pwd -P)"
containerd_dir="$(cd -- "${script_dir}/../.." > /dev/null 2>&1; pwd -P)"
: "${RUNC_FLAVOR:=runc}"
export GOTEST="${GOTEST:-go test}"
export GOPATH="${GOPATH:-/go}"
export PATH="/usr/local/go/bin:${GOPATH}/bin:/usr/local/bin:/usr/local/sbin:${PATH}"
rm -rf /var/lib/containerd-test /run/containerd-test
cd "${containerd_dir}"
go test -v -count=1 -race ./core/metrics/cgroups
make integration EXTRA_TESTFLAGS="-timeout 15m -no-criu -test.v" TEST_RUNTIME=io.containerd.runc.v2 RUNC_FLAVOR="${RUNC_FLAVOR}"