Kata Containers для Docker в 2024

5be93a003e0193b1fe7d7da337056b69.png

Kata Containers по факту сейчас основной способ запустить контейнеры в изолированной виртуальной машине для большей безопасности. По работе мне приходится запускать образы контейнеров, которым я не всегда могу полностью доверять. Раньше я использовал для этого виртуальною машину в Virtualbox в связке с Docker-Machine, но так как Docker-Machine с 2021 года больше не развивается, я решил рассмотреть варианты замены.

И я был очень удивлен, узнав, что в OpenSuse Tumbleweed, на который я мигрировал после 16 лет с Ubuntu, нет готовых пакетов для Kata Containers. Более того, при этом есть контейнеры для Firecracker microvm, специально созданным в AWS для запуска Linux контейнеров в изолированной среде. Но так как пакеты для Firecracker так же шли без Firecracker-Containerd runtime, я вернулся к идее попробовать Kata Containers.

В 2024 официальная документация Kata Containers гласит, что готовые пакеты доступны только в репозиториях дистрибутивов Fedora и Centos, а так же для Ubuntu через Snap пакеты. В остальных же случаях, например в моем, единственными вариантами остается сборка из исходников или установка уже собранных бинарных файлов из Github с помощью специального скрипта kata-manager.sh. Сами разработчики в документации предлагают именно второй вариант.

Сам скрипт kata-manager.sh просто распакует архив выбранного релиза с Github в /opt/kata, создаст конфиги в /etc/kata-containers/ и настроит симлинки в /usr/bin/ для kata-runtime, kata-collect-data.sh и containerd-shim-kata-v2. Этого уже будет достаточно, чтобы вызов docker run --runtime io.containerd.run.kata.v2 создавал контейнер в виртуальной машине Qemu (по умолчанию) с 1 cpu и 2 gb ram. Интересный факт: containerd ищет runtime в PATH по специальной схеме, и io.containerd.run.kata.v2 превращается в поиск containerd-shim-kata-v2 в PATH без необходимости настраивать что-либо в конфигах.

Чем такая установка хуже установки из пакетов вашего дистрибутива Linux: в данный момент Kata Containers поставляется с собственным полным набором гипервизоров (Qemu, Firecracker, etc…), образов системы для запуска и прочих необходимых файлов, никак не завися от внешних компонентов. И естественно все эти компоненты нужно обновлять в целях обеспечения безопасности. А в данном случае обновлять приходится на свой страх и риск, полностью заменяя файлы предыдущей версии на непроверенные новые. К примеру, у меня в версии 3.6.0 из коробки не заработал Fireckracker. В случае пакетов дистрибутива есть хотя бы шанc на то, что их тестируют как следует. Еще одним последствием обновления будет потенциальная необходимость перезапуска все уже запущенных контейнеров с новой версией, но это будет верным и для установки из пакетов.

Конечно куда более лучшим решением является установка каждой версии в свой отдельный путь. Итак, устанавливаем нужную нам версию с Github:

VERSION=3.8.0
DIR="/opt/kata_$VERSION"
PACKAGE="kata-static-$VERSION-$(uname -m | sed -e 's/x86_64/amd64/' -e 's/aarch64\|arm64/arm64/' -e 's/ppc64le/ppc64le/' -e 's/s390x/s390x/').tar.xz"

curl -LO https://github.com/kata-containers/kata-containers/releases/download/$VERSION/$PACKAGE

sudo mkdir -p "$DIR"

sudo tar -xJf "$PACKAGE" --strip-components=3 -C "$DIR"

Содержимое должно быть успешно распаковано:

$ ll $DIR
total 20
drwxr-xr-x 1 root root   110 Aug 25 12:24 ./
drwxr-xr-x 1 root root   150 Aug 25 12:15 ../
drwxr-xr-x 1 root root   490 Aug 21 17:53 bin/
drwxr-xr-x 1 root root    50 Aug 15 20:52 include/
drwxr-xr-x 1 root root    70 Aug 15 20:52 lib/
drwxr-xr-x 1 root root    30 Aug  9 12:45 libexec/
drwxr-xr-x 1 root root     6 Aug 21 18:01 runtime-rs/
drwxr-xr-x 1 root root   154 Aug 21 18:02 share/
-rw-r--r-- 1 root root    29 Aug 21 18:08 VERSION
-rw-r--r-- 1 root root 13678 Aug 21 18:08 versions.yaml

Есть много доступных гипервизоров на выбор, по умолчанию используется Qemu:

$ ll $DIR/share/defaults/kata-containers/
total 420
drwxr-xr-x 1 root root   906 Aug 21 18:02 ./
drwxr-xr-x 1 root root    30 Aug 21 18:01 ../
-rw-r--r-- 1 root root 10930 Aug 21 18:02 configuration-acrn.toml
-rw-r--r-- 1 root root 19799 Aug 21 18:02 configuration-clh.toml
-rw-r--r-- 1 root root 16708 Aug 21 18:02 configuration-fc.toml
-rw-r--r-- 1 root root 29756 Aug 21 18:02 configuration-qemu-coco-dev.toml
-rw-r--r-- 1 root root 28990 Aug 21 18:02 configuration-qemu-nvidia-gpu-snp.toml
-rw-r--r-- 1 root root 28964 Aug 21 18:02 configuration-qemu-nvidia-gpu-tdx.toml
-rw-r--r-- 1 root root 29631 Aug 21 18:02 configuration-qemu-nvidia-gpu.toml
-rw-r--r-- 1 root root 28098 Aug 21 18:02 configuration-qemu-se.toml
-rw-r--r-- 1 root root 27635 Aug 21 18:02 configuration-qemu-sev.toml
-rw-r--r-- 1 root root 29032 Aug 21 18:02 configuration-qemu-snp.toml
-rw-r--r-- 1 root root 28798 Aug 21 18:02 configuration-qemu-tdx.toml
-rw-r--r-- 1 root root 29649 Aug 21 18:02 configuration-qemu.toml
-rw-r--r-- 1 root root 13910 Aug 21 18:02 configuration-remote.toml
-rw-r--r-- 1 root root 17523 Aug 21 18:02 configuration-stratovirt.toml
lrwxrwxrwx 1 root root    23 Aug 21 18:02 configuration.toml -> configuration-qemu.toml
-rw-r--r-- 1 root root 10232 Aug 21 18:03 genpolicy-settings.json
-rw-r--r-- 1 root root 36237 Aug 21 18:03 rules.rego
drwxr-xr-x 1 root root   280 Aug 21 18:01 runtime-rs/

Подробнее про конфигурацию можно прочитать здесь и здесь.

Теперь нам остается только создать необходимы симлинки:

sudo ln -s $DIR /opt/kata
sudo ln -s /opt/kata/share/defaults/kata-containers /etc/kata-containers
sudo ln -s /opt/kata/bin/containerd-shim-kata-v2 /usr/bin/containerd-shim-kata-v2
sudo ln -s /opt/kata/bin/kata-runtime /usr/bin/kata-runtime

Проверяем, что все сработало, запустив контейнер busybox:

$ sudo docker run --runtime io.containerd.run.kata.v2 busybox uname -a
Linux 88c1b982e983 6.1.62 #1 SMP Wed Jul 17 13:00:20 UTC 2024 x86_64 GNU/Linux

Чтобы сделать Kata рантаймом по умолчанию, нужно в /etc/docker/daemon.json добавить "default-runtime": "io.containerd.run.kata.v2":

$ cat /etc/docker/daemon.json
{
  "default-runtime": "io.containerd.run.kata.v2"
}

И перезагрузить docker:

sudo systemctl reload docker

Проверяем:

$ sudo docker run busybox uname -a
Linux 88c1b982e983 6.1.62 #1 SMP Wed Jul 17 13:00:20 UTC 2024 x86_64 GNU/Linux

В будущем при установке новой версии нам нужно будет всего лишь поменять симлинк:

sudo rm -f /opt/kata
sudo ln -s $DIR /opt/kata

Если же мы хотим иметь возможность использовать разные версии Kata runtime без переключения симлинка /opt/kata, то нам придется использовать пару хаков. Сложность заключается в том, что в исполняемые файлы Kata местами намертво зашит путь /opt/kata, а так же два пути конфигурационных файлов:

$ kata-runtime --show-default-config-paths
/etc/kata-containers/configuration.toml
/opt/kata/share/defaults/kata-containers/configuration.toml

Конфиги можно переопределить с помощью переменной KATA_CONF_FILE. Так же containerd-shim-kata-v2 будет искать kata-runtime в PATH. Все это можно решить с помощью скрипта-обертки.

Теперь нам нужно обновить все файлы для использование нашего нового пути вместо /opt/kata:

grep -rlI '/opt/kata' "$DIR" | sudo xargs sed -i "s|/opt/kata|$DIR|g"

К сожалению, это не решит проблему с вшитым в Qemu путем для поиска bios, поэтому нам все же понадобится симлинка /opt/kata. Если вы еще ее не создали, то пора:

sudo ln -s $DIR /opt/kata

Хорошая новость заключается в том, что благодаря изменениям в конфигах kata-runtime будет использовать именно свои собственные образы системы и бинарные файлы, а не находящиеся по умолчанию в /etc/opt.

Осталось создать скрипты для запуска containerd-shim-kata-v2:

cat < /dev/null
#!/bin/sh
export KATA_CONF_FILE="$DIR/share/defaults/kata-containers/configuration.toml"
export PATH="$DIR/bin:\$PATH"
exec $DIR/bin/containerd-shim-kata-v2 "\$@"
EOF

sudo chmod +x "/usr/bin/containerd-shim-kata_$(echo "$VERSION" | sed 's/\./_/g')-v2"

И kata-runtime:

cat < /dev/null
#!/bin/sh
export KATA_CONF_FILE="$DIR/share/defaults/kata-containers/configuration.toml"
export PATH="$DIR/bin:\$PATH"
exec $DIR/bin/kata-runtime "\$@"
EOF

sudo chmod +x "/usr/bin/kata-runtime-$VERSION"

Проверяем:

$ echo "io.containerd.run.kata_$(echo "$VERSION" | sed 's/\./_/g').v2"
io.containerd.run.kata_3_8_0.v2

$ sudo docker run --runtime io.containerd.run.kata_3_8_0.v2 busybox uname -a
Linux 88c1b982e983 6.1.62 #1 SMP Wed Jul 17 13:00:20 UTC 2024 x86_64 GNU/Linux

По умолчанию Kata runtime запускает виртуальную машину с 1 cpu и 2 gb ram. Чтобы переопределить эти параметры, нам нужно передать docker run параметры --cpus (-c у меня не заработала) и -m или --memory, причем заданные параметры будут прибавляться к параметрам по умолчанию, то есть --cpus 1 --memory 512m приведет к использованию 2 cpu и 2.5 gb memory. При этом реальная память хоста не блокируется на эти 2.5 gb, а используется в меру необходимости.

Все остальное, вроде сети, должно работать по умолчанию. Например мы можем получить ответ от nginx:

$ sudo docker run -d --name nginx nginx
8663b33cad7e5b820be85468aa760e6ea34fc870adf7d924922788266041c898

$ sudo docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx
172.17.0.2

$ curl 172.17.0.2



Welcome to nginx!



Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.

Thank you for using nginx.

Монтирование тоже работает нормально:

$ sudo docker run --runtime io.containerd.run.kata_3_8_0.v2 -v /tmp:/tmp busybox ls /tmp
dbus-1b94OvKJfW
sddm-auth-ad8346f2-fbc8-4b74-9c03-e33d1136248e
systemd-private-a2ad86d46c374394957b41737f945998-ModemManager.service-tsH78Z
systemd-private-a2ad86d46c374394957b41737f945998-bluetooth.service-Bct8TG
systemd-private-a2ad86d46c374394957b41737f945998-dbus-broker.service-mpkAbN
systemd-private-a2ad86d46c374394957b41737f945998-fwupd.service-1Uiyrr
systemd-private-a2ad86d46c374394957b41737f945998-iio-sensor-proxy.service-1IKcZf
systemd-private-a2ad86d46c374394957b41737f945998-irqbalance.service-VvFZzU
systemd-private-a2ad86d46c374394957b41737f945998-polkit.service-58al8n
systemd-private-a2ad86d46c374394957b41737f945998-power-profiles-daemon.service-U13kul
systemd-private-a2ad86d46c374394957b41737f945998-systemd-logind.service-r2T6Xu
systemd-private-a2ad86d46c374394957b41737f945998-upower.service-aUQ6HX
tmp.CERJypVFNb
tmp.Lk54RYD5Tl
tmp.OWS9PKcNm8
tmp.cUYADP9m4f
tmp.hTZnG0skQ4
tmp.k3XnzrTg2k
tmp.mFpNhgIVQT
tmp.mvGoSlep7Z
tmp.nIDfmAGIo2
tmp.yQNEJyMj86

$ sudo docker run --runtime io.containerd.run.kata_3_8_0.v2 -v /tmp:/tmp busybox mount
none on / type virtiofs (rw,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev type tmpfs (rw,nosuid,size=65536k,mode=755)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666)
sysfs on /sys type sysfs (ro,nosuid,nodev,noexec,relatime)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,relatime)
cgroup on /sys/fs/cgroup/devices type cgroup (ro,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (ro,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (ro,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (ro,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/perf_event type cgroup (ro,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/freezer type cgroup (ro,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/pids type cgroup (ro,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/blkio type cgroup (ro,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/memory type cgroup (ro,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/cpuset type cgroup (ro,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd)
mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime)
shm on /dev/shm type tmpfs (rw,relatime)
none on /tmp type virtiofs (rw,relatime)
kataShared on /etc/resolv.conf type virtiofs (rw,relatime)
kataShared on /etc/hostname type virtiofs (rw,relatime)
kataShared on /etc/hosts type virtiofs (rw,relatime)
tmpfs on /proc/timer_list type tmpfs (rw,nosuid,size=65536k,mode=755)
proc on /proc/bus type proc (ro,relatime)
proc on /proc/fs type proc (ro,relatime)
proc on /proc/irq type proc (ro,relatime)
proc on /proc/sys type proc (ro,relatime)

ps: если вы ищете Senior или Lead DevOps в Европе — welcome:
— linkedin
— github

© Habrahabr.ru