Когда время перезагрузки имеет значение или почему IBM использует CRIU на мейнфреймах
В современном мире, когда светлое будущее прочат микросервисам, кажется странным заниматься технологиями, которые помогают обновлять код без перезагрузки. Ведь микросервисы и контейнеры куда проще «убить» и создать заново. Тем не менее, мы продолжаем работу над системой живой миграции CRIU, и нам в этом активно помогают ребята из IBM. Почему? Попробуем объяснить.
На волне всеобщей виртуализации, конвергенции и успеха контейнерных архитектур, патчинг начинает казаться чем-то рудиментарным. Зачем заниматься установкой обновлений и перезагрузкой, когда можно взять и создать контейнер заново? И это чистая правда для тех случаев, когда речь идет о пользовательских приложениях и сервисах, разработке и тестировании. Но как показывает практика, инфраструктура, на которой все это крутится, требует совершенно иного подхода. Стабильность и постоянная доступность тяжёлых сервисов, таких как базы данных, позволяют микросервисам запускаться в любой момент и использовать любые данные.
Для всех очевидно, что системы, которые долго запускаются и разогреваются, не должны перезагружаться слишком часто, а лучше всего – чтобы они и вовсе никогда не перезагружались. И чем мощнее система, и чем больше от неё зависит микросервисов, тем менее выгодной выглядит остановка ее работы с целью перезагрузки. Одним из примеров решения подобной задачи является технология ReadyKernel, которая позволяет устанавливать обновления хостовой ОС Linux, на которой работает множество виртуальных машин и контейнеров, без ее перезарузки. Другое решение для снижения простоев различных сервисов предлагает наш проект CRIU.
CRIU становится стандартом
Несмотря на те сомнения, которые встретили CRIU на этапе становления этого OpenSource инструмента (впрочем, впервые выступившего с планшетом Гейтса тоже подняли на смех), сегодня CRIU интегрирован в контейнеры OpenVZ, Docker, LXC, CoreOS; входит в дистрибутивы Linux Ubuntu, Debian, OpenSUSE, Altlinux и ряд других, а также поддерживается разработчиками из разных компаний, включая IBM. Кстати, любопытно, что именно «Голубой гигант» сделал один из самых масштабных вкладов в CRIU – сегодня инструмент работает сразу на нескольких платформах: x86_64, ARM, aarch64, PPC64 и s390. И две из них – PowerPC64 и s390 – являются детищами IBM. О поддержке инструмента на последней был объявлено буквально летом 2017 года.
Для того, чтобы объяснить, почему крупнейшей компании в области разработки аппаратных платформ и ПО требуются такие инструменты, нужно немного вникнуть в суть самого проекта. CRIU позволяет «заморозить» приложение, чтобы запустить его потом на другом хосте или в другом контейнере. При правильном применении этого инструмента, приложение не должно даже догадываться о том, что его переместили, продолжая работать, как ни в чем не бывало. Как уже говорилось, это совершенно не нужно микросервисам, но оказывается очень полезно для тех задач, которые решают в том числе на мейнфреймах.
Микропроцессорная архитектура для высокопроизводительных серверов s390 является уникальной, IBM развивает ее в своей линейке мейнфреймов. Многопроцессорные и многопоточные системы позволяют работать с огромными массивами данных, что накладывает свои особенности на архитектуру ОС и приложений. Летом 2017 года в CRIU пришли патчи от разработчиков из IBM, которые делают возможным использовании CRIU на s390. Дело в том, что CRIU представляет собой низкоуровневый инструмент, его код близок к коду ядра, и поэтому требуется его адаптация к каждой новой архитектуре. Чтобы CRIU начал работать, нужно было реализовать поддержку платформенно-специфических функций. От простого к сложному разработчики IBM обеспечили поддержку системных вызовов, собственных типов данных, описателей виртуального адресного пространства процессов, добавили нужные настройки компилятора, образы для регистров, нужные трамплины для паразитного кода, который мы внедряем в процесс для его «заморозки», а также архитектурную специфику типа TLS/GOT. Познакомиться с содержанием проделанной работы можно здесь:
|
#include "common/asm/linkage.h"
.section .head.text, "ax"
/*
* Entry point for parasite_service()
*
* Addresses of symbols are exported in auto-generated criu/pie/parasite-blob.h
*
* Function is called via parasite_run(). The command for parasite_service()
* is stored in global variable __export_parasite_cmd.
*
* Load parameters for parasite_service(unsigned int cmd, void *args):
*
* - Parameter 1 (cmd) : %r2 = *(uint32 *)(__export_parasite_cmd + pc)
* - Parameter 2 (args): %r3 = __export_parasite_args + pc
*/
ENTRY(__export_parasite_head_start)
larl %r14,__export_parasite_cmd
llgf %r2,0(%r14)
larl %r3,__export_parasite_args
brasl %r14,parasite_service
.long 0x00010001 /* S390_BREAKPOINT_U16: Generates SIGTRAP */
__export_parasite_cmd:
.long 0
END(__export_parasite_head_start)
|
Пользователи платформ IBM сталкиваются с достаточно большим количеством софта, который оказывается слишком тяжёлым для манипуляций а-ля «убить, создать заново». В массивных приложениях гораздо удобнее сохранять состояние сервисов, например, чтобы при потере питания восстановить работу быстрее. Возможность мигрировать контейнеры в «живом» состоянии позволяет освобождать сервера для обслуживания или производить балансировку нагрузки и так далее.
И это касается не только мейнфреймов. Участие IBM в проекте CRIU не ограничивается архитектурой s390. Несколько лет назад мы получили от IBM патчи для поддержки PPC64. Эти решения IBM предназначены для рабочих станций и серверов «попроще» — не мейнфреймов. Но самый интересный вклад, который разработчики IBM внесли в проект CRIU – это технология «ленивой миграции».
Происходит это следующим образом: контейнер перемещается с одного хоста на другой без содержимого своей памяти. Такой подход позволяет на порядок сократить размер образов, и он очень эффективен для тех приложений, которые держат в памяти огромные массивы данных. Например, если мы говорим о JVM, её полный образ может занимать десятки мегабайт (и это без учёта той памяти, которую выделит себе работающая в ней программа), в то время как его размер без содержимого памяти составит несколько десятков килобайт. Благодаря этому миграция происходит в разы быстрее, снижая паузу в работе. Суть того, что делают дополнения от IBM заключается в возможности обеспечить удаленный доступ к памяти и ее асинхронную миграцию при необходимости.
Тем не менее, существует немало задач, когда систему нужно все-таки перезагрузить. И здесь также полезна возможность остановить приложение. CRIU позволяет остановить контейнер, перезагрузить систему, и запустить контейнер в ней заново. Таким образом, мы решаем проблему патчинга для тяжелых ситуаций, когда не получается обновить систему без перезагрузки.
Заключение
Расширенная поддержка проекта CRIU позволяет говорить о том, что сегодня каждый разработчик может использовать возможность «заморозки» и «живой миграции» приложений уже на 5 различных архитектурах. Вклад IBM в развитие проекта позволил не только использовать возможности CRIU на мейфреймах и серверах PPC64, но применять механизмы «ленивой миграции» на других платформах.
Более того, происходящие изменения сподвигли нас на создание отдельной библиотеки Compel, которая позволяет заражать процессы паразитным кодом, заставляя выполнять определенные инструкции. Сегодня Compel используется в проекте CRIU, а также в новой системе живого патчинга приложений. О ней и о самой библиотеке Compel мы расскажем в следующем посте.