Перейти к основному содержимому

Что нового в 3.2.0

Дата выпуска: 28 сентября 2026

Релиз почти целиком про обновление узлов. Скрипт vStack.update.sh теперь сам переводит узел с линии 2.x на 3.x, а неудачная загрузка нового ядра больше не оставляет узел на приглашении загрузчика: при следующей перезагрузке он поднимается на прежнем ядре. Второе заметное изменение касается ВМ. Контроллер vm сообщает Center, чем закончился процесс bhyve, и перестал тихо перезапускать машину после аварии гипервизора.

Порядок обновления узла описан в «Обновление до 3.2».

Что проверить до обновления​

  • Переход с 2.x на 3.x запускается только с флагом --allow-major-upgrade. Ставьте его, только когда мажор действительно меняется. На рядовом обновлении флаг отключает защиту от случайной смены мажора.
  • Автоподъём ВМ после аварии в Center 3.2.0 работает только с узлами на vStack OS 3.2.0. Узлы со старым агентом не передают причину выключения, и упавшая машина остаётся выключенной. Подробнее в релиз-нотах Center 3.2.0.
  • Программным клиентам контроллера vm нужно повторять vms-start. Об этом ниже, в разделе про ВМ.

Переход узла с линии 2.x на 3.x​

Скрипт обновления проводит узел с линии 2.x (FreeBSD 13.2) на 3.x (FreeBSD 14.2) без ручных обходов. Раньше он такой переход отклонял. А если запрет снимали руками, у root пропадала оболочка, узел терял SSH, и часть компонентов молча оставалась от старой линии.

  • Переход включается явным флагом. --allow-major-upgrade снимает оба запрета: по мажору vStack и по мажору FreeBSD-runtime. Направление перехода пишется в лог полными версиями. Без флага всё работает как раньше, только текст отказа теперь называет нужный флаг.
  • Прогон доходит до конца. При смене мажора скрипт повторяет обновление каталога pkg с ABI целевой линии. Базу он ставит раньше контроллеров, чтобы порты новой линии не тянули за собой базовые библиотеки. Настройки узла возвращаются поимённо из копии, снятой до обновления. Прежний поголовный возврат .pkgsave откатывал /boot на старый мажор (узел грузился с новым userland и старым ядром) и оставлял в /etc rc-скрипты прежней линии. На узле без pkgbase прогон больше не обрывается молча с кодом 1.
  • SSH-доступ сохраняется. Скрипт определяет оболочку root по master.passwd, доустанавливает её пакет из целевого репозитория и проверяет, что она запускается. Если оболочки нет, прогон завершается кодом 6, а --reboot игнорируется: после перезагрузки на узел было бы не зайти. Подменять оболочку на /bin/sh скрипт не станет.
  • Состав узла сверяется с целевым релизом. Обязательные пакеты целевого релиза доустанавливаются. Компоненты, у которых сменилось имя пакета, ставятся по карте переименований. Пакеты без преемника и недоехавшие перечисляются в выводе. --install-missing доставляет всё недостающее.
  • Вытесненные пакеты видны. Если pkg при согласовании заменил установленный пакет конфликтующим, пропавший пакет попадает в итоговую сводку (раздел «REMOVED by reconciliation»). Код возврата и --reboot от этого не меняются, решение за администратором.
  • Тюнинг в /boot не теряется. loader.conf, loader.conf.local и device.hints сохраняются и восстанавливаются вместе с /etc.
  • Изменённые конфиги названы. Скрипт перечисляет файлы .pkgsave в /etc и /usr/local/etc, которые отличались от новой версии и удаляются при смене мажора, и печатает путь к полной копии /etc до обновления. По ней придётся сверить руками то, что поимённо не возвращается: ttys, crontab, newsyslog.conf, pam.d.
  • Сервисы. Перезапускаются только те, для которых на узле есть rc-скрипт. Отсутствующий сервис из списка больше не роняет прогон кодом 5, а сбой установленного сервиса по-прежнему даёт 5. Если в ходе смены мажора ставилась база, перезапуск сервисов пропускается (до перезагрузки новый userland работает на старом ядре), в лог уходит NOTICE.
  • Итоговая сводка. В конце скрипт печатает и сохраняет рядом с бэкапами сводку: версии до и после, добавленные, недоехавшие и вытесненные пакеты, пакеты без преемника, файлы .pkgnew, результат pkg check -d -a и напоминание не делать zpool upgrade.
  • Попутно исправлено. Каталог резервной копии /etc назывался с точностью до секунды, и два прогона в одну секунду могли восстановить чужую копию. Снимок версий пакетов терял все пакеты vStack-* из-за поиска с учётом регистра.

Защита ядра и загрузчика​

Обновление базы (--base) переустанавливает ядро и пишет в /boot. Раньше сразу после этого шла перезагрузка, и если новое ядро не грузилось, узел висел на приглашении OK, пока его не восстанавливали с консоли или с носителя. Теперь так:

  • Прежнее ядро копируется в <каталог ядра>_prev до обновления. Если места не хватает, обновление не выполняется. Проверку можно обойти флагом --no-kernel-backup.
  • Новое ядро проверяется до перезагрузки по пути из loader.conf: файл на месте, формат ELF, размер, число модулей, непустой linker.hints. Если версия ядра расходится с установленным пакетом, будет предупреждение. Не прошла проверка — перезагрузки нет, код 3.
  • Новое ядро грузится один раз, с автооткатом. На время обновления загрузка по умолчанию смотрит на сохранённое прежнее ядро, а новое выбирается одноразово (nextboot -k). Не загрузилось — следующая перезагрузка поднимет узел на прежнем, консоль для этого не нужна. После удачной загрузки rc-скрипт vstack_boot_marker снимает одноразовые настройки. Если узел поднялся на прежнем ядре, настройки остаются, а в syslog (daemon.err) пишется ошибка. Отключается флагом --no-fallback.
  • Загрузчик на ESP обновляется. Прошивка грузит копию загрузчика с EFI-раздела, и раньше её не обновлял ни pkg, ни скрипт. Узел мог грузиться старым загрузчиком с новым ядром. Теперь /boot/loader.efi копируется на тот EFI-раздел, с которого узел загружен, а прежний файл остаётся рядом как .prev. На ESP попадает только корректное EFI-приложение (PE32+, от 128 КБ), обрезанный или недокачанный загрузчик туда не запишется. Отключается флагом --no-esp.
  • Запись /boot подтверждается до перезагрузки. Скрипт делает fsync по файлам и каталогам /boot, включая загрузчик на ESP. Без подтверждения --reboot игнорируется, прогон завершается кодом 7. Если в системе нет fsync(1), выполняется sync с предупреждением, что гарантии нет.

Коды возврата vStack.update.sh​

КодЧто случилось
1Ошибка в аргументах
2Недоступен репозиторий или версия, не получен ключ, либо смена мажора запрошена без --allow-major-upgrade
3Пакеты или ядро
4/etc
5Сервисы
6Оболочка root
7Запись /boot не подтверждена

Ограничения​

  • Автооткат срабатывает при перезагрузке. Узел, который после неудачной загрузки стоит на приглашении загрузчика, сам не перезагрузится. Нужен внешний ресет через IPMI или BMC.
  • При переходе с узла без pkgbase (линия 2.x) страховки прежним ядром нет.

ВМ: исход завершения процесса bhyve​

Контроллер vm сообщает Center, чем закончился процесс bhyve. По этим данным Center отличает аварию от штатного выключения гостем. В Center 3.2.0 на них построен автоподъём ВМ после аварии, см. релиз-ноты Center 3.2.0.

  • Блок data.exit в терминальных событиях ВМ. Он есть у событий, которые публикуются по факту завершения процесса bhyve: Offline, Deleted, Suspended, Suspend_failed с progress = 100. Ключи:

    • code — исходный код выхода bhyve до нормализации статуса;
    • signal — номер сигнала. SIGTERM и SIGKILL теперь различимы, хотя в статусе оба по-прежнему сведены к 1;
    • initiator — кто послал сигнал: none, command или timeout;
    • method — команда, в рамках которой он послан;
    • description — расшифровка кода или сигнала для человека.

    Все пять ключей есть всегда, неизвестное значение передаётся как null, так что ноль отличим от отсутствия данных. code и signal взаимоисключающи. У событий прогресса блока нет, процесс там ещё жив. Существующие поля событий не менялись. Причину контроллер не классифицирует, это решает Center.

  • Аварийно завершившаяся ВМ остаётся выключенной. Раньше SIGSEGV и SIGABRT, а также ошибка 4 у ВМ, прожившей меньше 7 секунд, подменялись нулём («гость просит перезапуск»). Машина тихо перезапускалась, и об аварии никто не узнавал. Теперь это отказ: контроллер ВМ не перезапускает, код выхода уходит в ответ на команду и в терминальное событие. Перезагрузка по запросу гостя работает как раньше. Бюджет item.hv_faults.sigabort теперь ограничивает только её частоту.

  • Повтор запуска теперь на вызывающей стороне. После аварийной смерти враппера первый vms-start может ответить отказом с кодом выхода bhyve (например, status: 4). Повторите запуск через несколько секунд, и ВМ стартует. Раньше повтор делал сам враппер.

  • Запись ВМ в разделяемой памяти читается и правится под замком. Недописанную запись больше нельзя принять за чужую ВМ. Осиротевшие файлы замков контроллер убирает при старте.

Совместимость API​

RPC-контракт совместим с 3.1.0. Методы контроллеров не удалены и не переименованы, сигнатуры не менялись.

  • В контроллере Edge появились методы edge-deploy-floating-ips, edge-deploy-waf, edge-get-dhcp-leases, edge-get-dns-status.
  • Терминальные события ВМ получили блок data.exit. Расширение аддитивное.

Одно изменение поведения клиенту нужно учесть: аварийно завершившуюся ВМ контроллер vm больше не перезапускает сам, а первый vms-start после аварии враппера может вернуть отказ. Запуск нужно повторить.

Исправленные ошибки​

  • Неудачная загрузка нового ядра после обновления больше не требует восстановления с консоли или носителя (см. «Защита ядра и загрузчика»).
  • Подтверждение записи /boot работает на узлах с постоянно смонтированным ESP (штатная установка UEFI + UFS, /boot/efi в /etc/fstab). Раньше полностью прошедшее обновление завершалось кодом 7, и узел не перезагружался.
  • Рядовое обновление внутри мажора больше не требует --allow-major-upgrade на узлах 3.0 с pkgbase, где /etc/os-release кладёт пакет FreeBSD-runtime (ID=freebsd, VERSION_ID=14.2). Если os-release описывает другую ОС, проверка мажора пропускается с предупреждением. На узлах линии 2.x (ID=vstack) флаг по-прежнему обязателен.
  • Переход узла с 2.x на 3.x больше не обрывается и не оставляет узел неработоспособным. Сняты все известные барьеры: ABI целевой линии, молчаливый выход на узле без pkgbase, установка портов раньше базы, откат /boot из .pkgsave.