В этой статье мы на простом примере разберёмся, что же такое виртуализация, чем она отличается от контейнеризации и какие задачи она позволяет решить. Статья разбирает азы технологии, поэтому будет много упрощений и мы не станем вдаваться в тонкости реализации технологии.
Представьте, что у вас есть мощный сервер под управлением Ubuntu 22.04 и вы хотите запустить на нём несколько приложений. Однако есть проблема:
- Первое приложение работает только на операционной системе FreeBSD, которая пока не ставится на ваш сервер — нет драйверов на свежий процессор или видеокарту.
- Второе приложение написано очень давно — ещё на .NET Framework 1.1, и ему для корректной работы нужна Windows Server 2003. Несмотря на обратную совместимость, корректно оно будет работать только на этой платформе. Причём это приложение крайне критично для вашего бизнеса, но обновлять его или переписывать на более свежие технологии у вас просто нет времени — в каком-то далёком будущем вы планируете отказаться от него, написав что-то новое. Но пока имеем то, что имеем.
- Третье приложение может работать хоть на Windows Server 2003, хоть на свежей FreeBSD, хоть на Ubuntu 24.04. При этом ему важно запускаться и работать отдельно от первых двух приложений, потому что в них есть уязвимости, через которые теоретически можно получить доступ к операционной системе, после чего уже из неё сломать третье приложение или украсть важные данные, которые в нём содержатся.
Да уж, ситуация!
Что такое виртуализация и виртуальные машины
Тут-то на помощь и приходит виртуализация: с её помощью можно создать внутри операционной системы «виртуальный» компьютер со своим набором компонентов — выбрать любой процессор, оперативную память, жёсткий диск, видеокарту и т. п. Затем установить на этот виртуальный компьютер подходящую операционную систему (она называется гостевой), а уже в неё — ваше приложение.
При этом каждый такой виртуальный компьютер будет работать независимо от остальных и будет изолирован от них. И даже если какая-то машина внезапно отключится, на работе приложений из остальных машин это никак не скажется — они продолжат выполнять свои функции и обслуживать пользователей как ни в чём не бывало.
Каждый такой виртуальный компьютер — это как раз виртуальная машина. А программа, которая создаёт такой виртуальный компьютер, называется гипервизор. Гипервизоры — это такие оборотистые и шустрые Фигаро: переводчики и курьеры одновременно. К тому же они ещё и короли дипфейков:)
Представьте такую картину: владелец завода из России (ваш сервер) хочет наладить деловые связи с владельцем торговой сети из Китая (виртуальная машина), чтобы продавать в Поднебесной свою продукцию. Английского языка они не знают, но как-то взаимодействовать им надо. Они нанимают переводчика (программу-гипервизор). Вот что происходит дальше:
- Китайский бизнесмен звонит в Zoom российскому предпринимателю. В это время переводчик перехватывает звонок китайца и включает у себя программу для создания дипфейков.
- Китайский бизнесмен на китайском языке запрашивает у русского производственника товары (вычислительные ресурсы). Ему кажется, что он напрямую говорит с нашим русским заводчанином, однако на самом деле это наш хитрый переводчик генерирует дипфейк и общается на китайском.
- Переводчик набирает русского предпринимателя и включает ещё одну программу-дипфейк — чтобы уже русский предприниматель думал, что общается со своим китайским партнёром.
В итоге бизнесмены — и русский, и китайский — общаются друг с другом на своих родных языках и даже не замечают, что между ними есть кто-то ещё — им кажется, что они говорят напрямую, без всяких посредников.
То же самое происходит в виртуальных машинах: гипервизор перехватывает команды виртуальной операционной системы, которые отправлены одному типу процессоров, и переводит их на язык ОС физического сервера. Эта ОС отправляет команды своему оборудованию и производит необходимые виртуальной машине вычисления. Причём ни ОС в виртуальной машине, ни ОС на физическом сервере не понимают, что общаются друг с другом. Первой кажется, что она общается с каким-то оборудованием, а второй — что она говорит с какой-то программой.
Конечно, на практике всё гораздо сложнее, есть куча нюансов и разных видов виртуализации, но в целом работает эта технология примерно так, как мы описали выше.
Кстати, когда разработчик мобильного приложения запускает у себя в IDE эмулятор смартфона и проверяет в нём корректность работы программы — это тоже виртуализация. Когда вы запускаете на компьютере или в браузере DOSBox, чтобы поиграть в старинную игрушку, — это тоже виртуализация.
В своё время виртуализация произвела определённую революцию — раньше разработчики были привязаны к конкретному «железу», а теперь могут на одном и том же оборудовании запускать совершенно разные программы с разными требованиями к окружению. Второй плюс виртуализации — отличная переносимость. Вы один раз создаёте виртуальную машину со всеми необходимыми программами и ОС внутри неё, а потом запускаете её там, где вам нужно. Можете даже запустить несколько таких виртуальных машин, если одна уже не справляется с обработкой запросов от пользователей.
А ещё благодаря виртуализации вы можете позапускать на своём компьютере разные ОС и попробовать их в деле.
Фактически виртуализация — это метод уплотнения ресурсов. Например, у нас есть мощный сервер на 128 ядер и небольшое приложение на Python, которое мы хотим запускать отдельно от других приложений. Мы создаём виртуальную машину и запускаем приложение в ней, в итоге у нас остаётся куча свободных ресурсов под другие приложения.
Чем виртуализация отличается от контейнеризации
Но у виртуализации есть проблема — как правило, вам необходимо упаковать в каждую виртуальную машину все необходимые ресурсы: ОС, окружение, само приложение и т. п. А ведь ОС поедает немало ресурсов на поддержание самой себя, то есть в итоге вычислительная мощность расходуется нерационально.
Конечно же, эта проблема не давала покоя инженерам — столько ресурсов тратилось впустую просто на поддержание ОС, а ведь для работы программы, по идее, нужен лишь ограниченный набор необходимых зависимостей — библиотеки, интерпретаторы языка программирования и ещё какие-то компоненты, без которых приложение откажется запускаться.
Решением этой проблемы стала контейнеризация. Она сочетала в себе плюсы виртуализации (переносимость, независимость от «железа», быстрое развёртывание новых экземпляров приложения), но позволяла не тратить лишние ресурсы на поддержание работы ОС внутри виртуальной машины. Контейнеры (аналог виртуальной машины, но в контейнеризации) включают в себя только то, что непосредственно нужно для работы приложения. Однако есть важный нюанс: приложения в контейнерах должны уметь работать в ОС, которая запущена на хосте (сервере). Это принципиальное отличие от виртуализации: всё окружение контейнеров выстраивается на базе ОС, установленной на хосте, а в виртуальные машины можно поставить любую ОС.
Для каких задач подойдёт виртуализация
Виртуализация подойдёт, когда вам необходимо запустить старое приложение, работающее на устаревших технологиях (их ещё называют legacy). Кроме того, она обеспечивает более строгую изоляцию виртуальных машин по сравнению с изоляцией контейнеров. Однако при использовании виртуализации, как правило, приходится жертвовать ресурсами, необходимыми для работы гостевых ОС.
Современные приложения в большинстве случаев упаковываются в контейнеры — это быстрее и удобнее. К тому же для управления большим количеством контейнеров сделали бесплатный Open Source-инструмент — Kubernetes. Он позволяет задавать правила по запуску контейнеров, автоматически распределяет ресурсы в зависимости от нагрузки на приложения и может при необходимости запускать новые контейнеры. Kubernetes фактически стал стандартом для управления контейнерами.
Исторически так сложилось, что для виртуализации аналогов Kubernetes нет, есть лишь платные проприетарные решения. При этом контейнеризация продолжает отвоёвывать позиции, а Kubernetes становится привычным инструментом для инженеров. В такой ситуации привлекательно выглядит идея, когда инфраструктурные инженеры могут управлять виртуальными машинами так же, как контейнерами, — с помощью Kubernetes. Плюсов много: не надо изучать несколько разных решений, и контейнеры, и виртуальные машины доступны в одном интерфейсе, для них используются более-менее одинаковые команды, инженерам больше нравится работать с современными инструментами, да и пользоваться преимуществами гибкого и автоматического управления контейнерами очень хочется.
Естественно, начали появляться решения, которые позволяют управлять виртуальными машинами как контейнерами — прямо из Kubernetes. Мы тоже не остались в стороне и сделали Deckhouse Virtualization Platform — инструмент для автоматического управления множеством виртуальных машин через Kubernetes. Deckhouse Virtualization Platform основана на kubevirt и «ванильной» версии Kubernetes, прекрасно работает как в составе Deckhouse Kubernetes Platform, так и отдельно от неё, если необходимо взаимодействовать только с виртуальными машинами.
Такой подход даёт все преимущества декларативности: ты просто задаёшь системе ряд правил, а она сама разворачивает необходимое количество виртуальных машин для работы приложений, управляет ими, перераспределяет ресурсы между ними и следит, чтобы всё работало как надо. То есть виртуальные машины начинают работать бок о бок с подами (грубо говоря — с контейнерами) под управлением Kubernetes.