Google открыл gVisor, гибрид системы виртуализации и контейнеров
Как сообщает opennet.ru компания Google представила проект gVisor, в рамках которого подготовлен новый открытый runtime для обеспечения изолированного запуска контейнеров, соответствующих требованиям спецификации Open Container Initiative (OCI). gVisor может применяться в качестве слоя в Docker и Kubernetes, заменяя предлагаемый в них штатный runtime. Код gVisor написан на языке Go и поставляется под лицензией Apache 2.0.
При разработке gVisor была поставлена задача создания решения для выполнения контейнеров более легковесного чем системы виртуализации, но обеспечивающего сходный с ними уровень изоляции. Ключевым компонентом gVisor является собственное ядро, которое написано на языке Go и реализует большинство системных вызовов ядра Linux. Язык Go выбран для обеспечения дополнительной защиты, благодаря встроенным средствам контроля типов и границ блоков памяти, исключению проблем use-after-free, защите от переполнений стека и наличию детектора состояний гонки.
Ядро gVisor выполняется как обычный непривилегированный процесс и обеспечивает работу изолированного окружения контейнера. По аналогии с системами виртуализации в каждом подобном окружении используется свое ядро и набор виртуализированных устройств, отделенных от хост-системы и других контейнеров. Ядро gVisor обрабатывает все системные вызовы от приложений, изолируя их от остальной системы. При этом, gVisor не просто транслирует системные вызовы приложений в запросы к ядру Linux, а самостоятельно реализует основные примитивы ядра (сигналы, ФС, блокировки, маппинг памяти, неименованные каналы и т. п.) и выстраивает предоставляемые приложениям обработчики системных вызовов на основе данных примитивов. Так как ядро gVisor реализовано в форме обычного процесса, то для реализации функциональности примитивов выполняется обращение к ограниченному набору штатных системных вызовов основного ядра Linux (по аналогии с UML - User Mode Linux).
Подобный подход предоставляет высокую гибкость в управлении ресурсами и более низкие накладные расходы по сравнению с VM, но ценой этому становится повышение накладных расходов при обработке системных вызовов и ограниченная совместимость с приложениями. В настоящее время реализовано около 200 наиболее часто применяемых системных вызов. Некоторые системные вызовы и параметры пока не реализованы, также отсутствует поддержка части иерархии /proc и /sys, что требует особого отношения при подборе программ для запуска в контейнерах gVisor. Из работающих с gVisor приложений отмечены Node.js, Java 8, MySQL, Jenkins, Apache httpd, Redis, PHP, Tomcat, WordPress и MongoDB. Из пока не работающих приложений можно отметить nginx, Elasticsearch и PostgreSQL.
Для организации доступа к частям основной файловой системы хост-окружения применяется специальный процесс-прокси Gofer, взаимодействующий с ядром gVisor при помощи протокола 9P. Для доступа к сети в ядре gVisor реализован собственный сетевой стек (netstack), поддерживающий отслеживание состояний соединения и пересборку пакетов. Netstack полностью изолирован от сетевого стека ядра Linux и взаимодействует с внешним миром через виртуальное устройство, работающее в отдельном пространстве имен. Для особых ситуаций предусмотрен режим прямого проброса сетевых соединений, ценой снижения уровня изоляции. Для переключения контекста и реализации маппинга памяти предлагается использовать Ptrace или KVM.
Напомним, что в обычных контейнерах применяется общее для всех изолированных окружений ядро Linux с разграничением доступа к ресурсам на уровне cgroups и namespaces, что является слабым звеном безопасности, так как не все ресурсы ограничиваются, а уязвимость в ядре Linux компрометирует всю систему изоляции. В условиях, требующих надежной изоляции приложений применяется метод запуска каждого контейнера в отдельной виртуальной машине со своим ядром и системным окружением, но по сравнению с контейнерами на базе cgroups и namespaces указанный способ требует существенно больше ресурсов и тратит много времени на запуск. В рамках проекта Kata развивается runtime на базе гипервизора и специальных урезанных окружений с оптимизированным ядром Linux, который частично решает указанные проблемы.