Сколько родилось отличных проектов open source, потому что у кого-то руки чесались что-то попробовать! Именно так было и в случае с Firecracker. В 2014 году компания Amazon запустила AWS Lambda, которую позиционировала как «бессерверную» вычислительную платформу. В AWS Lambda пользователь может задать функцию — скажем, десять строк кода на Python — а Lambda в ответ достроит всю требуемую инфраструктуру, чтобы сработала цепочка: прибывает HTTP-запрос, вызывается функция, запрос обрабатывается, и, наконец, генерируется ответ.
Чтобы этот сервис работал безопасно и эффективно, Amazon нужно было разработать механизм, который позволял бы с минимальными издержками запускать виртуальные машины. Так появился Firecracker. Это монитор виртуальных машин (VMM), работающий совместно с Linux KVM. Он запросто создаёт «микро-VM» и управляет ими.
Почему Firecracker можно использовать с FreeBSD?
В июне 2022 года я занялся портированием FreeBSD, чтобы подружить её с Firecracker. Перечислю факторы, пробудившие во мне такой интерес.
Во-первых, я много работал, стараясь ускорить процесс загрузки FreeBSD, и хотел протестировать, какие процессы достижимы при использовании минимального гипервизора.
Во-вторых, при портировании FreeBSD на новые платформы всегда удобно выявлять баги, возникающие как в FreeBSD, так и на этих платформах.
В-третьих, в настоящее время AWS Lambda поддерживается только с Linux. Мне всегда очень хотелось расширить доступность FreeBSD на AWS (пусть я и не могу повлиять на то, насколько активно Lambda подхватывается в сообществе, поддержка Firecracker в данном случае — необходимое предварительное условие).
Но в первую очередь мне хотелось попробовать просто потому, что Firecracker существует. Это интересная платформа, и я заинтересовался, удастся ли мне заставить её работать.
Запуск ядра FreeBSD
Притом, что Firecracker проектировался с учётом одной из потребностей Lambda — запускать ядра Linux — уже в 2020 году в доступе имелись патчи, позволявшие наряду с «linuxboot» использовать режим загрузки PVH. В FreeBSD режим загрузки PVH поддерживается при применении Xen, поэтому я решил для начала испробовать этот вариант.
Здесь я столкнулся с первой проблемой: Firecracker может загрузить ядро FreeBSD в память. Но он не может найти тот адрес («точку входа в ядро»), с которого код ядра должен начинать выполняться. В соответствии с загрузочным протоколом PVH, это значение указывается в «заметке ELF». Это особая запись метаданных, которая хранится в файлах формата ELF (Executable and Linker Format). Оказывается, что существует два типа ELF-заметок: PT_NOTE
и SHT_NOTE
, а FreeBSD не предоставляет их в том формате, который нужен Firecracker. Оказалось, чтобы это исправить, достаточно немного изменить скрипт-линковщик ядра FreeBSD, после чего Firecracker стал нормально запускаться с ядром FreeBSD.
Всё шло гладко примерно в течение 1 микросекунды.
Ранний этап отладки
Во FreeBSD встроен замечательный отладочный функционал. Но, если работа ядра аварийно завершится ещё до окончания инициализации отладчика, либо ещё не будет готова к работе последовательная консоль, этот функционал едва ли вам пригодится. В данном случае наблюдается выход из процесса Firecracker — из чего я делаю вывод, что гостевая FreeBSD столкнулась с тройной ошибкой (triple fault) — но это всё, что удалось выяснить.
Правда, оказалось, что с этой информацией вполне можно приступать к делу, если проявить немного изобретательности. Если при выполнении ядра FreeBSD программа натыкается на инструкцию hlt, то процесс Firecracker продолжает работать, но использует при этом 0% процессорного времени хоста (так как в данном случае виртуализуется ЦП в состоянии останова). В принципе, я вполне мог отличить ситуации «FreeBSD рухнула до данного момента» и «FreeBSD рухнула после данного момента», вставляя в программу инструкцию hlt
. В случае, если процесс Firecracker вылетал, это означало, что он аварийно завершился, ещё не дойдя до этой инструкции. Соответственно, пуск процесса в данном случае можно назвать «бинарным разделением ядра» (kernel bisect). Известен приём, когда список коммитов дробится методом бинарного поиска, чтобы найти именно тот коммит, в котором зародился баг (как при использовании команды git bisect). Таким же бинарным поиском можно проверить и код запуска ядра, чтобы найти тот фрагмент кода, из-за которого валится FreeBSD.
Гипервызовы Xen
Такой подход первым делом вывел меня на гипервызовы Xen. Загрузочный режим PVH исходно сформировался как загрузочный режим Xen/PVH. Фактически, входная точка PVH для FreeBSD предназначена именно для загрузки под Xen. Поэтому из устройства самого кода весьма логично следует, что программа работает под Xen, а значит, в ней можно выполнять гипервызовы Xen. KVM (который предоставляет функционал ядра, используемый Firecracker) — это, конечно же, не Xen, так что в нём нет этих гипервызовов. При попытке использовать любой такой вызов происходил обвал виртуальной машины. Сначала я попробовал бесхитростный обходной манёвр: просто закомментировал все гипервызовы Xen. Позже я добавил код, который перед выполнением вызовов проверял, имеет ли CPUID сигнатуру Xen: например, печатал вывод отладки в отладочной консоли Xen.
Правда, был среди гипервызовов Xen и такой, что обеспечивал ключевой элемент функционала, а именно — извлекал карту физической памяти. Разумеется, внутри гипервизора «физическая» память лишь виртуально считается физической. Там черепахи до самого низа. Здесь нас спасает то, что Xen/PVH задним числом объявили нулевой версией загрузочного режима PVH. В версии 1 и выше указатель на карту памяти передаётся через страницу PVH start_info (а указатель на эту страницу предоставляется в регистре в тот момент, когда начинает работать виртуальный ЦП). Мне требовалось написать код, который использовал бы карту памяти из версии PVH 1, а не добывал бы информацию об этой карте через гипервызов Xen, но это было достаточно просто.
Другая, смежная, проблема проистекала из того, как именно Xen и Firecracker располагают структуры в памяти. Тогда как Xen сначала загружает ядро, а потом ставит в конец страницу start_info, Firecracker располагает страницу start_info по фиксированному низкому адресу, а уже после этого загружает ядро. Должно было бы работать нормально, но этот PVH‑код из FreeBSD — который писали в расчёте на работу с Xen — предполагает, что будет свободна память, расположенная сразу после страницы start_info, и этой памятью можно будет воспользоваться как черновиком (scratch space). В Firecracker такая практика быстро привела бы к затиранию исходного стека ядра — результат далеко не оптимальный! Эту проблему удалось исправить, немного изменив PVH-код из FreeBSD: теперь он выделял область-черновик уже после того, как гипервизор успеет инициализировать все области памяти.
С ACPI или без него!
На платформах x86 система FreeBSD, как правило, использует ACPI (усовершенствованный интерфейс управления конфигурацией и питанием), при помощи которого может узнать, на каком именно аппаратном обеспечении она работает (а иногда может и управлять этим оборудованием). Кроме обнаружения через ACPI таких штук, которые принято считать «устройствами» — это могут быть диски, сетевые адаптеры, т.д. — FreeBSD также узнаёт через ACPI о таких фундаментальных компонентах, как ЦП и контроллеры прерываний.
Firecracker целенаправленно сделан минималистичным, и поэтому он не реализует ACPI. Но FreeBSD неуютно, когда она не может определить, сколько ядер процессора у неё в распоряжении, или где находятся связанные с ними контроллеры прерываний.
К счастью, во FreeBSD поддерживается историческая спецификация Intel MultiProcessor, в которой эта важнейшая информация сообщается через структуру данных «MPTable». Эта структура данных не входит в базовую (GENERIC) конфигурацию ядра, но для работы с Firecracker нам всё равно потребовалась бы урезанная конфигурация ядра. Поэтому оказалось, что легко добавить таблицу mptable для устройств и далее работать с информацией, предоставляемой Firecracker.
Правда… это не сработало. FreeBSD по-прежнему не удавалось найти требуемую информацию. Оказалось, в Linux есть баги, из-за которых не всегда удаётся найти и правильно разобрать структуру MPTable. Firecracker же, спроектированный в расчёте на загрузку Linux, предоставляет MPTable именно в Linux-совместимой форме, которая, однако, не соответствует стандарту. У FreeBSD здесь используется отдельная реализация, строго следующая стандарту. Поэтому с ней не только не удавалось найти неверно расположенную MPTable, но и разобрать найденную MPTable, если она содержала синтаксические ошибки.
Так что теперь во FreeBSD есть новая опция ядра: можно добавить в конфигурацию options MPTABLE_LINUX_BUG_COMPAT, если вам требуется совместимость «до единого бага» с Linux-ориентированной обработкой MPTable. С такими корректировками FreeBSD удалось чуть дальше продвинуться с загрузкой Firecracker.
Последовательная консоль
Последовательный порт — это одно из немногих эмулированных устройств, предоставляемых Firecracker. Он именно эмулируется, а не виртуализуется, как блочные и сетевые устройства Virtio. На самом деле, в типичной конфигурации, из которой запускается Firecracker, стандартный ввод и вывод процесса Firecracker превращаются в порты последовательного ввода и вывода на виртуальной машине. Создаётся впечатление, что гостевая ОС — просто ещё один процесс, работающий под вашей командной оболочкой (в некотором смысле, так и есть). Как минимум, именно так всё и должно работать.
Вот так, пытаясь поднять FreeBSD внутри Firecracker, к этому моменту я смог загрузить ядро FreeBSD с диска, на котором обладал правами администратора, а затем скомпилировать и образ ядра. Рабочего виртуализованного драйвера диска у меня пока не было, но я уже смог читать в консоли вывод, получаемый от ядра. Но после того, как в консоль вышел весь вывод ядра, FreeBSD вошла в пользовательскую часть загрузочного процесса; после этого я получил в вывод консоли ещё 16 символов, а затем работа остановилась.
Забавно, что ровно такие же симптомы я наблюдал и более чем десятью годами ранее, когда впервые пытался заставить FreeBSD работать на инстансах EC2. В QEMU обнаружился баг, из-за которого УАПП (универсальный асинхронный приёмопередатчик, он же UART, universal asynchronous receiver-transmitter) не отправлял прерывания в момент опустошения очереди FIFO. FreeBSD успевала записать 16 байт в УАПП, после чего больше ничего не писала, а ждала прерывания, которое так и не приходило. Современные инстансы EC2 работают на платформе Nitro от Amazon, но в те давние времена на EC2 использовались Xen, а для эмуляции устройств использовался код из QEMU. Каким-то образом за 10 лет этот баг в QEMU удалось исправить, но ровно такой же баг попал в реализацию Firecracker. Но мне повезло: тот костыль, который я в своё время вставлял в ядро FreeBSD — hw.broken_txfifo=”1” — по-прежнему можно было использовать. Поэтому проблему с консольным выводом удалось решить, добавив настраиваемую версию этого загрузчика (поскольку Firecracker загружает ядро напрямую, минуя загрузчик, значение требовалось компилировать перед записью в ядро и далее использовать это значение как переменную окружения).
Затем я обнаружил, что ввод через консоль также нарушен: FreeBSD не реагировала, что бы я там ни писал. Фактически, как показала трассировка процесса Firecracker, сам Firecracker даже ничего не читал из консоли, так как «полагал», что очередь FIFO на стороне получателя в эмулированном УАПП заполнена до отказа. Так я нашёл ещё один баг в Firecracker: при инициализации УАПП FreeBSD заполняет мусором FIFO-очередь на стороне получателя (чтобы измерить размер этой очереди), а затем сбрасывает FIFO, записывая в управляющий регистр FIFO. В Firecracker управляющий регистр FIFO не реализован, поэтому инструмент остаётся с забитой очередью FIFO. Логично, что именно поэтому он даже не пытается читать ещё какие-либо символы и довносить в неё. Здесь я добавил ещё один обходной манёвр, чтобы работать с FreeBSD. Если ассерт LSR_RXRDY сохраняется и после того, как мы попытались сбросить FIFO через соответствующий управляющий регистр (а это означает, что FIFO не опустошена, несмотря на команду) — мы далее продолжаем читать и отбрасывать символы один за другим, и так до тех пор, пока FIFO не опустеет. После такой поправки Firecracker стал признавать, что FreeBSD готова принимать дополнительный ввод из последовательного порта, и у нас получилась последовательная консоль с двусторонним движением.
Устройства Virtio
Да, системе без дисков или сети всё-таки можно найти применение, но если мы хотим добиться с FreeBSD чего-либо существенного, то без этих устройств нам не обойтись. Firecracker поддерживает блочные и сетевые устройства Virtio и предоставляет их виртуальным машинам в виде mmio (устройств ввода/вывода, отображаемых на память). Сначала заставим их работать под FreeBSD: добавим в конфигурацию ядра Firecracker опцию device virtio_mmio.
Далее нам требуется рассказать FreeBSD, как найти виртуализованные устройства. FreeBSD рассчитывает на то, что устройства mmio можно будет найти через FDT (плоское дерево устройств). Это механизм, часто применяемый во встраиваемых системах. Но Firecracker передаёт параметры устройств через командную строку ядра при помощи директив вида virtio_mmio.device=4K@0x1001e000:5. Второй шаг, чтобы заставить их работать в FreeBSD: напишем код для синтаксического разбора таких директив и для создания узлов виртуальных устройств virtio_mmio. (Как только мы создадим узел устройства, включается стандартный процесс FreeBSD для зондирования устройств, и ядро автоматически определяет тип устройства Virtio, а затем подцепляет к нему соответствующий драйвер).
Но если у нас несколько устройств — скажем, дисковое и сетевое — то с Firecracker возникает другая проблема. Он передаёт директивы так, как принято в Linux, то есть как последовательности пар ключ/значение через командную строку ядра. FreeBSD, в свою очередь, разбирает содержимое командной строки ядра как переменные окружения… то есть, если через командную строку передано две директивы virtio_mmio.device=, сохраняется из них только одна. Чтобы это исправить, я переписал старый фрагмент кода ядра, касающийся синтаксического разбора, так, чтобы он решал проблему дублирования переменных, прикрепляя к ним числовой суффикс. В итоге имеем virtio_mmio.device= для одного устройства и virtio_mmio.device_1= для второго.
Сделав всё это, я, наконец, добился, чтобы FreeBSD успешно загружалась и обнаруживала все свои устройства. Но с дисковыми устройствами возникла ещё одна проблема: если я не очищал виртуальную машину перед завершением работы, то при следующей загрузке к файловой системе применялась команда fsck, и в ядре возникала паника. Выяснилось, что fsck — это одна из немногих штук в FreeBSD, провоцирующая операции дискового ввода/вывода, не выровненные по страницам памяти, а блочный драйвер Virtio для FreeBSD вызывает панику ядра при попытке передать Firecracker такой невыровненный ввод/вывод.
Когда при операции ввода/вывода пересекается граница между страницами памяти — а именно так и происходит при постраничном вводе/выводе, не выровненном по страницам — физические сегменты ввода/вывода обычно располагаются прерывисто. Большинство устройств приспособлено к обработке таких запросов ввода/вывода, где указывается последовательность сегментов, к которым нужно обратиться. Firecracker же — исключение из этого правила, так как он крайне минималистичен. Он принимает всего один буфер с данными; то есть, если буфер пересекает границу страниц в памяти, его нельзя просто разбить на части так, как это делалось бы с другими реализациями Virtio. К счастью, в FreeBSD специально предусмотрена система busdma, позволяющая купировать такие осложнения с устройствами.
Пожалуй, сложнее всего было наладить именно этот аспект взаимодействия FreeBSD с Firecracker, но после нескольких попыток я, наконец, довёл его до ума: модифицировал блочный драйвер Virtio для FreeBSD, приспособив его к работе с busdma. Тогда невыровненные запросы начинают «зеркалиться» (т. е., копироваться во временный буфер) — и так удаётся справиться с ограничениями реализации Virtio в Firecracker.
Обнаруженные варианты оптимизации
Как только мне удалось наладить работу FreeBSD с Firecracker, сразу стало ясно, что требуется внести ещё некоторые доработки. Почти сразу я заметил, что, хотя тестируемая мной виртуальная машина и располагает 128 МБ оперативной памяти, с системой едва удаётся работать, а процессы то и дело приходится принудительно завершать, так как память в системе полностью кончается. Утилита top(1) показала, что почти половина системной памяти находится в связанном («wired») состоянии, что выглядит странно. Я ещё немного покопался в системе и обнаружил, что busdma резервирует 32 МБ памяти на отзеркаленные страницы. Разумеется, это гораздо больше, чем нужно. Учитывая ограничения Firecracker и тот факт, что отзеркаленные страницы обычно не выделяются сплошным куском, каждая дисковая операция ввода/вывода должна использовать не более одной полной зеркальной страницы, то есть 4 КБ. Так при помощи специального патча busdma мне удалось сократить эту статью расхода памяти до 512 КБ: я оставил резервирование зеркальных страниц только для таких устройств, которые поддерживают небольшое количество сегментов ввода/вывода.
Генератор случайных чисел, действующий в ядре FreeBSD, обычно получает энтропию от физических устройств, но при работе с виртуальными машинами это не такой уж надёжный источник. В качестве резервного источника энтропии в системах с архитектурой x86 используется инструкция RDRAND, позволяющая получать от ЦП случайные значения. Но в таком случае на каждом запросе можно получить очень мало энтропии, а мы запрашиваем энтропию лишь раз в 100 мс. Когда я изменил систему сбора энтропии так, что стало возможно при каждом шаге запрашивать достаточно энтропии, чтобы полностью засеять генератор случайных чисел Fortuna, удалось сократить длительность загрузки ещё на 2,3 секунды.
При первичной загрузке FreeBSD записывает ID того хоста, на котором работает. Обычно он берётся с железа при помощи переменной окружения smbios.system.uuid. Эту переменную загрузчик устанавливает, исходя из информации, полученной от BIOS или UEFI. Но под Firecracker загрузчика нет, и, соответственно, ID не предоставляется. У меня была предусмотрена резервная система, которая программно генерировала случайный ID на таких системах, где нет валидного аппаратного ID. Но вдобавок я выводил предупреждение и выжидал 2 секунды, чтобы пользователь успевал его прочитать. Далее я изменил этот код так, чтобы предупреждение выводилось на две секунды в случае, если железо предоставит недействительный ID, однако незаметно и быстро возвращалось к работе, если железо вообще не предоставляет ID.
Протокол IPv6 регламентирует, что система должна сначала дождаться «обнаружения дублирующихся адресов» (DAD), а только затем использовать адрес IPv6. В rc.d/netif после поднятия интерфейсов мы дожидались IPv6 DAD лишь в случае, если на каком-либо из наших сетевых интерфейсов был активирован режим IPv6. Здесь возникала всего одна проблема: у нас на петлевом интерфейсе режим IPv6 был активирован всегда! Я изменил логику так: дожидаться DAD лишь в том случае, когда режим IPv6 активирован на каком-нибудь интерфейсе, кроме петлевого. Так удалось ускорить загрузку ещё на 2 секунды — если другая система пыталась использовать тот же адрес IPv6, что и мы на нашем lo0, то возникали проблемы посерьёзнее простой коллизии адресов!
При перезагрузке FreeBSD выводила сообщение a message (“Rebooting...”), а затем ожидала 1 секунду, «пока printf завершит работу, и результат будет прочитан». Казалось, что пользы в этом минимум, так как обычно сразу видишь, что система перезагружается. Теперь есть опция kern.reboot_wait_time sysctl, по умолчанию равная нулю.
При завершении работы или перезагрузке системы процессор BSP в FreeBSD (ЦП #0) ждёт, пока другие ядра не просигнализируют, что остановились… а затем выжидает ещё 1 секунду, чтобы убедиться, что и сам может остановиться. Я избавился от этой лишней секунды ожидания.
Когда все простые варианты оптимизации закончились, я раскрыл TSLOG и принялся рассматривать флейм-диаграммы загрузочного процесса. Firecracker отлично подходит для такой работы по двум причинам: во-первых, в минималистичной среде исключаются многие шумы, поэтому чётче просматривается сигнал. Во-вторых, поскольку под Firecracker виртуальные машины запускаются исключительно быстро, тестировать изменения в ядре FreeBSD также удавалось влёт. Зачастую я успевал менее чем за 30 секунд собрать новое ядро, запустить и сгенерировать новую флейм-диаграмму.
Такое исследование при помощи TSLOG навело меня ещё на ряд возможных оптимизаций:
У lapic_init был цикл на 100000 итераций, позволявший откалибровать, сколько времени уходит на выполнение lapic_read_icr_lo. Сократив этот цикл до 1000 итераций, я смог выиграть ещё 10 мс.
ns8250_drain вызывал DELAY после считывания каждого символа. Я изменил этот шаг так: проверить LSR_RXRDY и делать задержку, только если в данный момент считывать нечего. Так удалось ускорить загрузку ещё на 27 мс.
FreeBSD использует лист CPUID, применяемый в большинстве гипервизоров для оглашения тактовых частот у TSC и локального APIC. Firecracker, в отличие от VMWare, QEMU и EC2, этого не реализует. Добавив в Firecracker поддержку этого листа CPUID, я скостил со времени загрузки FreeBSD ещё 20 мс.
FreeBSD устанавливает kern.nswbuf (чтобы управлять количеством буферов, выделяемых под различные временные цели) равным 256, независимо от размера системы. Задав здесь 32 * mp_ncpus, я смог сократить время загрузки на 5 мс при работе на небольшой виртуальной машине (1 ядро).
Функция FreeBSD mi_startup, запускающая машинно-независимые процедуры инициализации систем, определяет порядок вызова функций методом пузырьковой сортировки. Да, это было разумно в 90-е (когда приходилось упорядочивать сравнительно немного процедур). Но сегодня таких процедур уже более 1000, и пузырьковая сортировка — слишком медленный вариант. Я заменил её на быструю сортировку и сэкономил ещё 2 мс.
Действующая в FreeBSD процедура инициализации vm_mem готовит структуры vm_page для всей доступной физической памяти. Даже на относительно небольших виртуальных машинах со 128 МБ оперативной памяти в таком случае требовалось инициализировать 32768 таких структур, на что уходило несколько мс. Я изменил этот код, задав ленивую инициализацию структур vm_page по мере выделения памяти. Так я выручил ещё 2 мс.
Firecracker выделяет память под гостевую VM при помощи анонимного mmap, но Linux не задаёт структуры подкачки страниц для всего адресного пространства гостевой VM. В результате при первом чтении каждой страницы возникала ошибка, на исправление которой уходило примерно 20 000 циклов ЦП (когда Linux отображал страницу в память. Я добавил флаг MAP_POPULATE к вызову mmap в Firecracker, тем самым сэкономив ещё 2 мс.
Состояние дел
FreeBSD грузится под Firecracker — причём очень быстро. Учитывая пока не зафиксированные патчи (как в FreeBSD, так и в Firecracker), при работе на виртуальной машине с 1 ЦП и 128 МБ оперативной памяти ядро FreeBSD успевает загрузиться менее чем за 20 мс. Ниже приведена флейм-диаграмма загрузочного процесса.
![Рис. 1: Флейм-диаграмма загрузочного процесса FreeBSD 14 под Firecracker. Рис. 1: Флейм-диаграмма загрузочного процесса FreeBSD 14 под Firecracker.](https://habrastorage.org/getpro/habr/upload_files/856/5ed/54b/8565ed54b4a23e2d8820dbafb6f8c8bc.png)
Многое ещё предстоит сделать. Нужно не только зафиксировать все вышеупомянутые патчи и добавить поддержку загрузочного режима с PVH в магистральную ветку Firecracker, но и многое «подчистить». Учитывая, что исторически загрузочный режим PVH восходит к Xen, код, применяемый при загрузке PVH, по-прежнему перемешан с кодом для поддержки Xen. Если их разделить, то всё существенно упростится. Аналогично, сейчас невозможно собрать ядро FreeBSD arm64 без поддержки PCI или ACPI. Если найти и удалить излишние зависимости, то получится более компактное ядро FreeBSD/Firecracker (и, кстати, мы сократим загрузку ещё на несколько микросекунд — ведь 25 нс уходит, чтобы проверить, нужно ли резервировать память для Intel GPU).
Более амбициозная идея — проверить, удастся ли портировать Firecracker для работы на FreeBSD. В какой‑то момент понимаешь, что виртуальная машина — это всего лишь виртуальная машина, и, хотя Firecracker создавался для работы с Linux KVM, нет никаких базовых причин, по которым он не смог бы работать с пространством ядра в гипервизоре bhyve из FreeBSD.
Все, кто хочет поэкспериментировать с FreeBSD под Firecracker, могут собрать ядро FreeBSD 14.0 в конфмгурации amd64 FIRECRACKER и свериться с веткой feature/pvh branch из проекта Firecracker. Если же окажется, что эта ветка больше не существует — значит, её втянули в основную часть дерева Firecracker.