# runc, runsc, kata - container runtimes _Контейнеры (бонус) · LinuxLab Knowledge Base_ **TL;DR:** runc - стандартный OCI-runtime, namespaces+cgroups+seccomp. runsc/gVisor - userspace-ядро для дополнительной изоляции. kata - облегчённая VM на контейнер. Performance ↔ isolation trade-off. ## Что есть OCI Runtime Подсистема которая берёт **OCI bundle** ([[oci-spec|spec]]: `config.json` + `rootfs/`) и запускает контейнер. Что именно делает, её решение, главное чтобы соответствовало OCI runtime spec. Три популярных варианта в 2026: | Runtime | Подход | Trade-off | |---------|--------|-----------| | **runc** | namespaces + cgroups + seccomp в host kernel | максимум performance, минимум изоляции | | **runsc** (gVisor) | userspace-kernel перехватывает syscall'ы | ~30% slower, гораздо больше isolation | | **kata-containers** | каждый контейнер в lightweight VM | ~5% overhead, VM-grade isolation | | **crun** | альтернатива runc на C, faster startup | как runc по isolation | | **youki** | runc-compatible на Rust | как runc | ## runc, референс Создан Docker/OCI как **минимальный эталон**. Открытый код, в каждом дистро. Под капотом всех общих контейнерных стеков (Docker, containerd, CRI-O, podman), runc или его replacement (crun). Что делает runc при `runc run myctr`: 1. Читает `config.json` 2. Создаёт [[namespaces|namespaces]] (PID, NET, MNT, IPC, UTS, USER) 3. Настраивает [[cgroups|cgroups]] (memory, cpu) 4. Применяет [capabilities](/kb/capabilities.md) dropping (CAP_DROP) 5. Применяет [seccomp](/kb/seccomp.md) profile 6. Применяет AppArmor/SELinux profile если задан 7. `chroot` в `rootfs` 8. `exec` указанной в config команды Всё это, **в host kernel**. Контейнер видит host'овое ядро, использует тот же VFS, тот же scheduler. Изоляция, namespaces. Прямой запуск без Docker: ```bash # Подготовить bundle mkdir -p mycontainer/rootfs cd mycontainer docker export $(docker create alpine) | tar -C rootfs -xf - runc spec # создаст config.json # отредактировать config.json под нужды # Запустить sudo runc run mycontainer-id # Управление runc list runc kill mycontainer-id KILL runc delete mycontainer-id ``` Это уровень "ниже Docker". Используют когда нужно понять, что именно происходит, или для embedded-сценариев. ## runc, где он в Docker stack'е ``` docker / podman │ ▼ containerd (или CRI-O) │ ▼ containerd-shim (один на контейнер, переживает рестарт containerd) │ ▼ runc (запускает init-процесс, потом exit'ит) │ ▼ init процесс контейнера (PID 1 в pid-namespace) ``` shim нужен чтобы переживать рестарт higher-level менеджеров. runc, короткоживущий, отрабатывает и умирает. ## crun, альтернатива на C Тот же контракт, что runc, но: - Написан на C (runc, Go), startup faster - Меньше memory footprint - Default в podman / RHEL 8+ Полностью drop-in replacement: containerd конфигом можно переключить с runc на crun, всё работает. Используй когда стартуете много короткоживущих контейнеров (CI, k8s job's, function-as-a-service). ## runsc / gVisor, userspace kernel Концепция: между application syscall и host kernel поставить **userspace-kernel** (gVisor's "Sentry"), который перехватывает большинство syscall'ов и реализует их сам. ``` app (внутри контейнера) │ syscall ▼ Sentry (gVisor userspace-kernel) │ ограниченное подмножество host-syscall'ов ▼ host kernel ``` Плюсы: - **Не привязан к host kernel** для большинства syscall'ов эксплойт kernel CVE сложнее - **Меньше attack surface**: ~50 host syscalls вместо ~400 - **Без VM**, startup быстрый (доли секунды) Минусы: - **Performance hit**, 10-50% в зависимости от нагрузки - **Не все syscalls работают**, пограничные сетевые/file features могут не поддерживаться (`io_uring`, например, частично) - **Не все workload подходят**, БД с iouring или AIO будут страдать Запуск: ```bash # Установка curl -fsSL https://gvisor.dev/archive.key | sudo gpg --dearmor ... apt install runsc # Регистрация в Docker cat /etc/docker/daemon.json { "runtimes": { "runsc": { "path": "/usr/bin/runsc" } } } systemctl restart docker # Использовать docker run --runtime=runsc -it alpine ``` Где применяется: - **Google App Engine / Cloud Run**, внутри - **Untrusted code execution** (online code playgrounds) - **Multi-tenant CI**, где шаренный кластер запускает чужой код ## kata-containers, VM-based Каждый контейнер запускается в **lightweight VM** (через qemu/cloud-hypervisor/firecracker). Плюс: - **Hardware-grade isolation**, VM boundary, не namespace boundary - Совместимость почти 100%, внутри VM настоящее Linux-ядро - Поддержка GPU passthrough, custom kernels Минус: - **Overhead** в RAM (~50-200 MB на контейнер для VM) - **Startup slower**, 1-2 сек вместо < 100ms - **Nested virtualization** в облаках бывает запрещена ```bash # k8s через crio, runtimeClass apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: kata handler: kata --- apiVersion: v1 kind: Pod metadata: name: secure-pod spec: runtimeClassName: kata containers: - name: app image: myapp:v1 ``` Используется в: - **AWS Lambda + Firecracker**, не Kata, но ту же идею - **Kata on AKS / Azure Container Instances** - **Confidential containers** (CoCo), Kata + AMD SEV / Intel TDX для unencrypted-memory-protection ## Сравнение | Признак | runc | runsc / gVisor | kata-containers | |---------|------|-----------------|------------------| | Изоляция | namespaces | userspace kernel | VM | | Performance | 100% (baseline) | ~70-90% | ~95% | | Memory overhead | ~few MB | ~30 MB на Sentry | ~50-200 MB на VM | | Startup | ~100 ms | ~150 ms | ~1-2 sec | | Compatibility | 100% | ~85% | ~99% | | Use case | default everywhere | untrusted code | multi-tenant secure | | Где default | Docker, containerd, CRI-O, k8s | Google Cloud Run | OCI confidential | ## RuntimeClass в k8s k8s allows multiple runtimes side-by-side: ```yaml apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: gvisor handler: runsc --- apiVersion: v1 kind: Pod spec: runtimeClassName: gvisor # этот pod через gVisor containers: [...] ``` Default, пусто (== runc). Опционально можно отдельные namespaces / labels форсить на untrusted-runtime. ## Когда что-то пошло не так - **`exec format error`**, multi-arch image, runtime запускает binary не своей архитектуры. Pull правильный platform. - **`OCI runtime exec failed: exec failed`**, entrypoint не существует или не executable в rootfs. `chmod +x` или проверь путь. - **runsc workload падает с unsupported syscall**, `runsc --strace` или `dmesg` от gVisor покажет какой; иногда `--platform=ptrace` fallback (медленнее, шире совместимость). - **Kata медленно стартует**, обычно cold-start cloud-hypervisor. `enable_template = true` в configuration.toml для prebooted-VM. - **runc-update не работает на cgroup'ы**, на cgroupv1 vs v2 разные пути. Современные runc оба умеют, но containerd может не передавать новый формат. - **`Unknown runtime` в Docker**, не зарегистрирован в `/etc/docker/daemon.json` либо `systemctl restart docker` не сделан. ## Альтернативы и связанные - **firecracker**, VMM, не runtime, но Kata может его использовать - **bubblewrap (bwrap)**, как runc для Flatpak; не OCI-compatible - **lxc/lxd**, старая, не OCI; больше "system contains" вместо "application contains" - **systemd-nspawn**, встроенная контейнеризация systemd; тоже не OCI ## Команды ```bash runc spec ``` Сгенерить дефолтный config.json для bundle - точка старта ```bash sudo runc run mycontainer ``` Запустить из текущей директории (где config.json + rootfs/) ```bash runc list ``` Все запущенные runc-контейнеры на хосте - debug-tool ```bash docker run --runtime=runsc -it alpine ``` Запустить через gVisor - изоляция выше, но не все syscalls работают ```bash kubectl describe pod mypod | grep -i runtime ``` Какой RuntimeClass используется для pod'а в k8s ```bash ctr run --runtime=io.containerd.runsc.v1 docker.io/alpine alpine sh ``` Прямой запуск в containerd с указанием runtime ```bash runsc --platform=ptrace run mycontainer ``` Force ptrace-platform - fallback при unsupported KVM или kvm-unfriendly host ## См. также - [OCI spec - стандарт контейнеров](/kb/oci-spec.md) - [Linux namespaces](/kb/namespaces.md) - [cgroups (v2)](/kb/cgroups.md) - [seccomp - фильтр системных вызовов](/kb/seccomp.md) - [Kubernetes pod lifecycle - от Pending до Terminated](/kb/kubernetes-pod-lifecycle.md) - [Docker storage drivers - overlay2, btrfs, zfs](/kb/docker-storage-drivers.md) - [kubelet - архитектура агента ноды Kubernetes](/kb/kubelet-internals.md)