Когда заходит речь о запуске виртуальных машин в Kubernetes через KubeVirt, первый вопрос, который возникает у инженеров: «А какой там оверхед?» Давайте разберём этот вопрос детально, рассмотрев каждую подсистему отдельно: вычисления, хранилище и сеть.

Оверхед на вычисления: спойлер — его нет
Чтобы понять, почему оверхеда на CPU практически нет, нужно разобраться, что такое контейнеризация с точки зрения ядра Linux.
В ядре существуют так называемые неймспейсы (namespaces) — механизм, позволяющий запускать процессы с изолированными подсистемами: отдельной сетью, отдельным mount-пространством, отдельным PID-пространством и так далее.
Ключевой момент: каждый процесс в Linux обязан запускаться в каком-то неймспейсе. Будь то хостовый неймспейс или изолированный — для ядра разницы нет. Процесс обрабатывается одинаково.
Контейнер — это просто процесс, запущенный в изолированных Linux kernel namespaces плюс cgroups. Последние — стандартный механизм ядра для ограничения ресурсов процесса. Cgroups используются не только в контейнеризации, но и в обычном systemd. Классический libvirt тоже применяет cgroups для ограничения ресурсов виртуальных машин.
А что такое виртуальная машина с точки зрения системы? Это всего лишь Linux-процесс QEMU с дополнительными разрешениями и доступом к /dev/kvm.
Если виртуалка — это просто процесс, почему бы не запускать его в контейнере? Именно это KubeVirt и делает.
Разницы нет, запущен QEMU в хостовом неймспейсе ядра или в отдельном, который создал Kubernetes. Оверхеда на вычисления нет.
Небольшая оговорка про libvirt
Есть небольшой оверхед на запуск отдельного libvirt-демона, который KubeVirt использует для настройки параметров виртуалки. Но он минимален.
Интересный архитектурный выбор: обычно запускается один libvirt на хост, управляющий множеством виртуалок. Проблема в том, что иногда он зависает, блокируя управление всеми VM на сервере. В KubeVirt пошли другим путём — отдельный libvirtd-демон на каждую виртуалку. Цена изоляции — дополнительные ресурсы на работу демона рядом с основным процессом VM. Но расход небольшой: libvirtd чаще выступает как shim-прослойка для простых операций: запуск/остановка VM, снятие снапшота, hotplug дисков и интерфейсов, запуск live-миграции.
Хранилище: зависит от подхода
В QEMU есть множество способов подключить виртуальные тома к виртуалке.
Классические варианты:
Создать файл (raw или qcow2) в файловой системе и передать его QEMU
Взять готовое блочное устройство и отдать его QEMU
В обоих случаях используется ядро в качестве посредника — файловая система или блочное устройство должны существовать в хостовой системе.
Прямое подключение: QEMU умеет самостоятельно обращаться к storage и подключать тома напрямую из user-space, минуя ядро. Поддерживаются различные драйверы: Ceph, iSCSI, NBD и другие. Например, Vitastor работает именно по такому принципу — QEMU устанавливает соединение напрямую.
Философия KubeVirt
Основной принцип KubeVirt — быть максимально нативным к Kubernetes. У команды даже есть своеобразный razor: «Если это может быть полезно и для виртуалок, и для контейнеров, это должно быть реализовано в Kubernetes, а не в KubeVirt».
Иногда это замедляет разработку VM-специфичных фич.
В контексте хранилища KubeVirt полностью опирается на сущности Kubernetes — в первую очередь на CSI-драйверы. Kubernetes ожидает, что каждый том — это Filesystem или BlockDevice. Оба режима поддерживаются и не имеют дополнительного оверхеда.
Однако прямое подключение QEMU к storage сейчас не поддерживается — в Kubernetes для этого нет подходящих абстракций.
Реальность такова, что крупный энтерпрайз чаще использует не прямое подключение, а общую файловую систему (NFS от NetApp) или блочные устройства (iSCSI). KubeVirt, кстати, умеет работать с iSCSI напрямую.
Итог по хранилищу: если сравнивать с типичными решениями — оверхеда нет. Если упираться в специфику драйверов QEMU — прямое подключение будет быстрее, но менее универсально. Generic-решения поддерживают только стандартные варианты, а под каждого вендора придётся пилить и поддерживать свою специфику.
Сеть: здесь есть нюансы
У каждого контейнера (или процесса в терминах ядра Linux) может быть свой отдельный сетевой стек с собственными интерфейсами. Для связи контейнерного network namespace с хостовым используются veth-интерфейсы — виртуальный «патчкорд», один конец которого находится в хостовом неймспейсе, другой — в контейнерном. Это база для всех контейнеров.
Снаружи логику обслуживает CNI-плагин: добавляет интерфейс в Linux bridge (как Flannel) или вешает на него eBPF-программу (как Cilium). С точки зрения системы виртуалка — такой же контейнер, как и все остальные.
Что происходит внутри контейнера
В 95% случаев для виртуалки создаётся TAP-интерфейс, который виден в хостовой системе как обычный сетевой интерфейс. Вопрос в том, как соединить его с внутренним veth-интерфейсом.
Популярные варианты:
Bridge: в ядре создаётся отдельный Linux bridge, в который добавляются внутренний конец veth и TAP-интерфейс виртуалки.
Masquerade: создаётся iptables-правило, копирующее трафик из одного интерфейса в другой.
В обоих случаях есть оверхед по latency — каждое дополнительное звено в цепочке требует дополнительных тактов процессора для обработки пакетов.
Как обойти ограничения
Оверхед небольшой, но есть способы его избежать:
macvtap-cni — биндится напрямую на физический интерфейс машины
SR-IOV — аппаратная виртуализация сети
Как и в случае с хранилищем, QEMU может быть настроен на прямую коммуникацию с SDN в user-space, минуя ядро. KubeVirt имеет ограниченную поддержку этого режима, так как опирается на спецификацию CNI.
Различные CNI-драйверы (например, Kube-OVN) реализуют параллельное API для offloading сети из ядра.
Стоит отметить, что по части сети KubeVirt имеет мощный интерфейс для написания плагинов с произвольной логикой подключения.
Выводы

KubeVirt — это компромисс между производительностью и универсальностью. Если вам нужен максимум производительности и вы готовы поддерживать специфичные решения — можно выжать больше. Если важнее стандартизация, vendor neutrality и простота поддержки — KubeVirt отлично справляется со своей задачей.
P.S. Статья основана на обсуждении в профессиональном сообществе. Благодарю участников за ценные инсайты.
Присоединяйтесь к нашему комьюнити
Комментарии (13)

andreynekrasov
21.01.2026 10:08В обоих случаях есть оверхед по latency
cilium про netkit пишет, что "latency as low as host"

kvaps Автор
21.01.2026 10:08Там проблема не в cilium, а в том что происходит внутри контейнера:
{CNI magic} [veth]<--->[veth]<--->[bridge]<--->[tap]<--->[eth0] ^-------host--------^ ^---------------pod-------------^ ^--vm--^Вот на все эти дополнительные интерфейсы тратятся драгоценные контекст свитчи.

poige
21.01.2026 10:08Вот на все эти дополнительные интерфейсы тратятся драгоценные контекст свитчи.
Опять же, чтобы яснее по терминам: «…
Context switch (переключение контекста) — это когда планировщик ядра заменяет текущий исполняющийся поток (thread) на другой поток на данном CPU. Что сохраняют/восстанавливают: регистры (GPR, флаги, PC/IP, SP), иногда FPU/SSE/AVX (лениво), kernel stack ptr, планировочные структуры; при смене адресного пространства —
mm/CR3/ASID и, возможно, TLB (или его часть).…»
А теперь по сути: «…
Пересечение veth/bridge/tap в ядре обычно даёт softirq-работу, но не сам по себе context switch; он появится только если планировщик запустит другой поток (например,
ksoftirqd,qemu-vcpu, и т.п.).Дополнительные виртуальные интерфейсы добавляют CPU-циклы (обработку в softirq), но не производят автоматических context-switch «на каждом хопе». Context switch появляется только когда ядро вынуждено: …
…»

angapov
21.01.2026 10:08У меня уже накопился богатый опыт с OpenShift Virtualization и Migration Toolkit for Virtualization в проде, я могу сказать только, что в целом после Вмвари это все пока выглядит как топор против бензопилы. В целом работает, но усилий требуется намного больше.
По сути поста в кубевирте есть один довольно неочевидный слой оверхеда, когда используются Filesystem-backed volumes типа NFS. В этом случае qemu создает на файловом вольюме qcow2 файлик, который презентуется виртуалке как диск. Внутри виртуалки уже создается вторая файловая система. И вот этот двойной слой файловой системы вносит, во-первых, сторадж оверхед в размере порядке 6% места, а во-вторых довольно ощутимо снижает иопсы, порядка 10-20%. Поэтому по возможности использовать надо только Block-based сторадж.
poige
странное построение — как минимум одно, начинается всё вполне пристойно:
но дальше эта благопристойность вдруг поворачивается вот так:
— так ненавязчиво и беззастенчиво сходу спутывается виртуализация и контейнеризация.
Кратко обозначу — претензия не про неверные данные про наличие/отсутствие оверхеда, претензия — про подмену понятий в едином повествовательном порыве.
poige
Теперь уже более предметно в плане именно что overhead'а CPU-RAM связки — без I/O, и именно что про виртуализацию. Тут уж я довольно беззастенчиво загрузил одну приличную эл-эл-модель и получил вот такое — могу сказать, что, конечно, что-то такое я и сам слышал-знал, но эт всё же, не мой day-to-day knowledge domain, так что не обессудьте. В ответ на мой запрос «но если отойти от кривых формулировок — чё там про оверхед по CPU на виртухах, и правда ведь почти нет, если исключить vm-enter/exit, которого в пр-цпе не будет в контейнерах? Я бы ещё заметил, что процессы внутри виртухи opaque для host планировщика. Давай сфокусируемся на CPU/RAM, I/O к делу не относится»:
«…
Лимитирующие факторы, которые остаются даже «в пустоте»
VM-exit никуда не деваются: любые CPUID, MSR, I/O-порт, INIT-IPI, APIC-EOI → гипервизор. В контейнере это прямые обращения к ядру, без world-switch.
Page-walk всегда двойной: при каждом TLB-miss расходится по EPT. Даже если exit нет, это +4-20 доп. memory-access на miss.
Планировщик видит только vCPU, поэтому host не может расставить реальные процессы по NUMA/LLC, пиринг потоков делает только гость. На CPU-heavy это редко больно, но на latency-чувствительных сервисах хвост растягивается именно из-за двойного планирования.
…
Итог
При compute-bound нагрузках и грамотной конфигурации (hugepages, vCPU pinning, no overcommit) оверхед KVM по CPU действительно «мал», то есть ≈ 3–5 %.
Полного нуля нет и быть не может: VM-exit и двухмерный page-walk — механически встроены в аппаратную виртуализацию; они же отличают VM от контейнера.
…»
andreynekrasov
Вы не поняли, что в статье речь не о сравнении виртуализации и контейнеризации, а о запуске виртуалок вне кубера и в кубере.
poige
Это вполне возможная трактовка, но она во-первых — на уровне «капитан очевидность», а во-2-х, тогда уж нужно сравнивать не с Kubernetes — который не более чем фреймворк-запускалка контейнеров, а — «vanilla Linux process vs он-же-в контейнере», сам k8s тут ничего нового не добавляет. Так что исходное «странный тезис» остаётся в силе — менее странным он от этого не становится, возможно даже наоборот.
andreynekrasov
imho в этой заметке нет каких то вторых-третьих слоёв, искать их там нет смысла :) просто "а что будет, если запускать виртуалки в кубере".
> сам k8s тут ничего нового не добавляет
это краткое содержание этой статьи :)
Некоторые люди почему то не хотят запускать что то в контейнерах, а хотят запускать виртуалки. То есть для них рассматривать контейнеры нет смысла под любым углом.
poige
О да, но стоит разделять слойность и двусмысленность. Первой нет, а вот вторая — как уже очевидно, во все поля. А так, вообще, если автор реально решил посветить себя описанию оверхеда контейнеризации — через «кубер» — то всё и того хуже. ;)
kvaps Автор
Спасибо за критику. Для эксперта данная статья действительно покажется на уровне «капитан очевидность» и она намеренно такая.
Нам часто поступают вопросы вроде «вы запускаете виртуалки в контейнерах, а какой там оверхед?», я постарался максимально подробно разобрать этот вопрос в формате рассуждения.
poige
np, единственное (всё же) — если ЦА не эксперты и даже не medium, для них тем более нужно гораздо чётче, без прыжков между разными понятиями, потому что им такой винегрет разобрать тем более не удастся.
iwram
Согласен.
Маркетологи компании, отдайте обратно аккаунт Андрею. В дополнение можно почитать доку https://docs.kernel.org/virt/kvm/api.html
И другие "уменьшаторы" накладных расходов описаны на популярном ресурсе.
Печально, что от обычной нормальной базы пытаются уйти в другие абстракции - которые на более высоком уровне якобы решат проблемы лежащие ниже.