Virtualization concept page: Type-1 hypervisors (ESXi, KVM, Xen, Hyper-V) vs Type-2 (VirtualBox, Parallels), hardware-assisted virtualization (Intel VT-x, AMD-V), paravirtualization, live migration, containers vs VMs, microVMs (Firecracker for AWS Lambda/Fargate). Three scenarios: VM lifecycle (create/boot/live-migrate), VM vs container resource isolation showing container escape blast radius, microVM cold start (<150ms). Includes ADR for choosing VM vs container vs microVM.
"VM = виртуальное железо (own kernel). Container = виртуальный user-space (shared kernel). microVM = VM с минимальным kernel: изоляция от VM, cold start как у container."
Виртуализация — это слой, на котором стоит вся современная cloud-индустрия. Без неё нет EC2, нет Kubernetes, нет Lambda, нет multi-tenancy. Но "виртуализация" — это не одна технология, а целое семейство, и выбор между bare-metal, VM, container и microVM напрямую определяет три вещи в вашей системе.
Cold start. Lambda стартует за ~125 мс, EC2-инстанс — за 30-60 секунд, контейнер — за 100 мс, bare-metal сервер бутится минутами. Если вы строите serverless API с burst-нагрузкой — 60 секунд cold-start вас убьёт. Если вы крутите long-running JVM-приложение — 125 мс vs 30 секунд значения не имеет, зато имеет значение overhead памяти и CPU.
Изоляция (трастовая граница). Container escape (CVE-2019-5736 в runc, Dirty COW) пробивает shared kernel — атакующий получает root на host и доступ ко всем соседним контейнерам. VM escape требует уязвимости в гипервизоре, что на порядки реже. Если у вас выполняется untrusted user code (как Lambda) — shared kernel недопустим, нужен микро-VM.
Density и billing. Bare-metal: 1 workload на хост. VM: десятки. Container: сотни. microVM: тысячи. Это напрямую транслируется в $/час: чем выше плотность, тем дешевле каждый tenant. Именно поэтому AWS Lambda — это microVM, а не контейнер: им нужна изоляция VM при плотности и cold-start контейнера.
И ещё одно: понимание уровней абстракции защищает от паники, когда что-то ломается. "Pod не стартует" — это уровень оркестратора. "Container не стартует" — runtime. "Host не отвечает" — гипервизор. "Все VM на host тормозят" — noisy neighbor через гипервизор. Без модели слоёв вы не поймёте, на каком этаже искать проблему.
Архитектура снизу вверх — это пирамида абстракций, где каждый следующий слой получает иллюзию, что под ним честное железо:
Application (ваш код)
User-space (libc, runtime)
OS Kernel (syscalls, scheduler)
Hypervisor (Ring -1, trap-and-emulate) <- VMware ESXi, KVM, Xen
Hardware (Intel VT-x, AMD-V)
Контейнер выкидывает слой "Hypervisor" и шарит "OS Kernel" между всеми контейнерами — отсюда дешёвый старт и слабая изоляция. microVM возвращает гипервизор, но делает kernel минимальным (Firecracker — 50K LOC vs миллионы у Xen), чтобы boot был быстрым.
Три ключевых правила:
Четыре группы side-by-side, демонстрирующие разные модели виртуализации:
Edges — это физические соединения в архитектуре (как VT-x trap, vCPU scheduling, KVM ioctl), а не направления данных. Анимация идёт по тем же edges в обоих направлениях.
Полный жизненный цикл VM на Type-1 гипервизоре: hypervisor занимает Ring -1, аллоцирует vCPU и RAM, бутит guest (BIOS -> bootloader -> kernel init), обрабатывает VMEXIT/VMRESUME для privileged operations. Затем — live migration: pre-copy RAM на target host итерациями (пока VM работает), потом короткий stop-and-copy для финальных dirty pages и регистров CPU. Downtime ~100 мс, TCP-соединения живут, клиенты ничего не замечают. Это магия VMware vMotion / KVM live migration, на которой держится maintenance больших кластеров.
Сценарий показывает разницу трастовых границ. Untrusted контейнер C ловит CVE-2019-5736 (real exploit, runc 2019) — malicious binary перезаписывает /proc/self/exe, получает root на host kernel. С этого момента всё кончено: атакующий читает /proc/<pid>/environ соседних контейнеров (credentials, secrets), доступ ко всем shared resources. Тот же untrusted workload в VM: guest kernel exploit даёт root в guest — но это всё ещё guest. Соседняя VM-2 недоступна (отдельный address space, отдельный kernel), VM escape требует уязвимости в гипервизоре, что на порядки реже. Вывод: для multi-tenant с untrusted code shared kernel недопустим.
Покадровая разбивка Lambda invocation: t=0ms Firecracker fork и читает 5MB vmlinux, t=10ms KVM_CREATE_VM ioctl и allocate 128MB guest memory, t=30ms минимальный kernel boot (no PCI, no ACPI, no USB — голый KVM), t=80ms init и runtime (Node.js/Python), t=120ms handler loaded, t=125ms READY. Параллельно поднимаются microVM #2 и #3. После выполнения AWS держит warm pool ~5-15 мин (warm starts ~1-5 мс), потом idle timeout убивает microVM. Главная мысль: microVM = strong isolation (own kernel) + container-like cold start. Multi-tenant без compromise — поэтому AWS перенесли Lambda с контейнеров на Firecracker в 2018.
Контекст. Команда строит multi-tenant платформу: часть workload — long-running web services (Node.js/JVM), часть — batch jobs, часть — user-supplied код (как AWS Lambda). Варианты: bare-metal, Type-1 VM, container, microVM. Цена ошибки: containers для untrusted code → container escape; VMs для микросервисов → деньги в overhead и медленный CI/CD; microVM для долгоживущего web-сервиса → лишний слой без выгоды.
Решение. Trust boundary решает всё, плотность — вторично.
| Workload | Изоляция | Выбор | Почему |
|---|---|---|---|
| Trusted микросервис | Достаточно cgroups | Container | Shared kernel ОК (код наш), 100мс старт, плотность |
| Compliance (PCI, HIPAA), legacy stack | Сильная | VM (KVM/ESXi) | 30-60s boot не важно для long-running, regulator хочет VM |
| Untrusted user code, serverless | Сильная | microVM (Firecracker) | 125мс боль приемлема, own kernel закрывает container escape |
| Latency-critical, GPU, HFT | Любая | Bare-metal / dedicated | Любой hypervisor добавляет jitter |
Defaults: trusted → container, untrusted → microVM, regulated → VM, latency-critical → bare-metal.
m5.metal).