Как использовать systemd-nspawn для восстановления Linux-системы

Автор оригинала: Kevin P. Fleming
  • Перевод
Перевод статьи подготовлен специально для студентов курса «Администратор Linux».





Разбираемся со способностью systemd запускать контейнеры для восстановления корневой файловой системы поврежденной системы.

До тех пор пока будут существовать системы GNU/Linux, системным администраторам будет необходимо восстанавливаться после повреждения корневой файловой системы, случайных изменений конфигурации или других ситуаций, которые не дают системе загрузиться в «нормальное» состояние.


Обычно дистрибутивы Linux предлагают одну или несколько опций меню во время загрузки (например, в меню GRUB), которые можно использовать для восстановления поврежденной системы; зачастую они загружают систему в однопользовательском режиме с отключением большинства системных служб. В худшем случае пользователь может изменить командную строку ядра в загрузчике, чтобы использовать стандартную оболочку в качестве процесса init (PID 1). Этот метод является наиболее сложным и чреват затруднениями, которые могут привести к потере времени и фрустрации, в то время как система нуждается в восстановлении.

Самое главное, что все эти методы предполагают, что у поврежденной системы есть какая-либо физическая консоль, но в эпоху облачных вычислений на это уже нельзя полагаться. Без физической консоли есть всего несколько вариантов (если они еще окажутся доступными), чтобы повлиять на процесс загрузки таким образом. Даже физические машины могут оказаться небольшими встроенными устройствами, которые не имеют простой в использовании консоли, а поиск подходящих кабелей и адаптеров последовательного порта и настройка эмулятора терминала, все для использования консоли на последовательном порту в условиях работы с чрезвычайной ситуацией, зачастую достаточно сложны.

Когда доступна другая система (той же архитектуры и в целом аналогичной конфигурации), общий способ упростить процесс восстановления заключается в извлечении запоминающих устройств из поврежденной системы и подключении их к рабочей системе в качестве вторичных устройств. В физических системах это обычно не вызывает затруднений, и большинство платформ облачных вычислений также могут это поддерживать, поскольку они позволяют смонтировать корневой том хранилища поврежденного инстанса в другом инстансе.

После того, как корневая файловая система подключена к другой системе, решение проблемы повреждения файловой системы осуществляется с помощью fsck и других инструментов. Устранение ошибок конфигурации, поврежденных пакетов или других проблем может быть более сложным, поскольку для них требуется монтировать файловую систему и находить и изменять правильные файлы конфигурации или базы данных.

Использование systemd


До появления systemd способом исправления конфигурации на практике было редактирование файлов конфигурации с помощью текстового редактора. Поиск необходимых файлов и понимание их содержимого является отдельной задачей, которая выходит за рамки данной статьи.

Когда система GNU/Linux использует systemd, многие изменения конфигурации лучше всего выполнять с помощью инструментов, которые она предоставляет — например, для включения и отключения служб требуется создание или удаление символических ссылок в различных местах. Инструмент systemctl используется для внесения этих изменений, но для его использования требуется, чтобы экземпляр systemd работал и прослушивал запросы (по шине D-Bus). Когда корневая файловая система смонтирована как дополнительная файловая система на другом компьютере, работающий экземпляр systemd не может быть использован для внесения этих изменений.

Ручной запуск systemd целевой системы также нецелесообразен, поскольку он спроектирован как PID 1 процесс для управления всеми другими процессами, который может конфликтовать с уже запущенным экземпляром в системе, используемой для исправления.

К счастью, systemd имеет возможность запускать контейнеры — полностью инкапсулированные системы GNU/Linux с собственным PID 1 и средой, в которой используется различный функционал пространства имен, предлагаемый ядром Linux. В отличие от таких инструментов, как Docker и Rocket, systemd не требуется образ контейнера для запуска контейнера; он может запустить его с root-правами в любой точке существующей файловой системы. Это делается с помощью инструмента systemd-nspawn, который создаст необходимые пространства имен системы и запустит начальный процесс в контейнере, а затем предоставит консоль. В отличие от chroot, который изменяет только видимый корень файловой системы, этот тип контейнера будет иметь отдельное пространство имен файловой системы, подходящие файловые системы, смонтированные в /dev, /run и /proc, а также отдельное пространство имен процессов и IPC. Посетите основной ресурс systemd-nspawn, чтобы узнать больше о его возможностях.

Пример для демонстрации того, как это работает


В этом примере запоминающее устройство, содержащее корневую файловую систему поврежденной системы, подключено к работающей системе, где оно отображается как /dev/vdc. Имя устройства будет различаться в зависимости от количества существующих запоминающих устройств, типа устройства и метода, используемого для подключения его к системе. Корневая файловая система может использовать все устройство хранения или находиться в разделе внутри устройства; поскольку наиболее распространенная (простая) конфигурация помещает корневую файловую систему в первый раздел устройства, в этом примере будет использоваться /dev/vdc1. Обязательно замените имя устройства в приведенных ниже командах на правильное имя устройства вашей системы.

Поврежденная корневая файловая система также может быть более сложной, чем отдельная файловая система на устройстве; это может быть том в LVM или на наборе устройств, объединенных в RAID-массив. В этих случаях нужно выполнить необходимые шаги для создания и активации логического устройства, содержащего файловую систему, прежде чем оно будет доступно для монтирования. Опять же, эти шаги выходят за рамки этой статьи.

Необходимые приготовления


Во-первых, убедитесь, что установлен инструмент systemd-nspawn — большинство дистрибутивов GNU/Linux не устанавливают его по умолчанию. Он предоставляется пакетом systemd-container в большинстве дистрибутивов, поэтому используйте менеджер пакетов вашего дистрибутива для его установки. Инструкции в этом примере были протестированы с использованием Debian 9, но должны работать аналогично в любом современном дистрибутиве GNU/Linux.

Для использования приведенных ниже команд почти наверняка потребуются root-права, поэтому вам нужно будет либо войти в систему как root, использовать sudo для получения оболочки с root-правами или добавить к каждой команде префикс sudo.

Проверьте и смонтируйте файловую систему


Сначала используйте fsck для проверки структур и содержимого целевой файловой системы:

$ fsck /dev/vdc1

Если он обнаружит какие-либо проблемы с файловой системой, ответьте на вопросы соответствующим образом, чтобы исправить их. Если файловая система серьезно повреждена, она не подлежит восстановлению, и в этом случае вам придется искать другие способы извлечения ее содержимого.

Теперь создайте временный каталог и смонтируйте в него целевую файловую систему:

$ mkdir /tmp/target-rescue
$ mount /dev/vdc1 /tmp/target-rescue

Когда файловая система смонтирована, запустите контейнер с ней в качестве корневой файловой системы:

$ systemd-nspawn --directory /tmp/target-rescue --boot -- --unit rescue.target

Аргументы командной строки для запуска контейнера:

  • --directory /tmp/target-rescue предоставляет путь к корневой файловой системе контейнера.
  • --boot ищет подходящую программу инициализации в корневой файловой системе контейнера и запускает ее, передавая ей параметры из командной строки. В этом примере целевая система также использует systemd в качестве PID 1 процесса, поэтому остальные параметры предназначены для него. Если целевая система, которую вы восстанавливаете, использует какой-либо другой инструмент в качестве PID 1 процесса, вам необходимо соответствующим образом настроить параметры.
  • — отделяет параметры для systemd-nspawn от тех, которые предназначены для PID 1 процесса контейнера.
  • --unit rescue.target сообщает systemd в контейнере имя цели, которую он должен попытаться достичь в процессе загрузки. Чтобы упростить операции восстановления в целевой системе, загрузите ее в режиме «восстановления», а не в обычном многопользовательском режиме.

Если все пойдет хорошо, вы должны увидеть вывод, который выглядит примерно так:

Spawning container target-rescue on /tmp/target-rescue.
Press ^] three times within 1s to kill container.
systemd 232 running in system mode. (+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
Detected virtualization systemd-nspawn.
Detected architecture arm.

Welcome to Debian GNU/Linux 9 (Stretch)!

Set hostname to <test>.
Failed to install release agent, ignoring: No such file or directory
[  OK  ] Reached target Swap.
[  OK  ] Listening on Journal Socket (/dev/log).
[  OK  ] Started Dispatch Password Requests to Console Directory Watch.
[  OK  ] Reached target Encrypted Volumes.
[  OK  ] Created slice System Slice.
         Mounting POSIX Message Queue File System...
[  OK  ] Listening on Journal Socket.
         Starting Set the console keyboard layout...
         Starting Restore / save the current clock...
         Starting Journal Service...
         Starting Remount Root and Kernel File Systems...
[  OK  ] Mounted POSIX Message Queue File System.
[  OK  ] Started Journal Service.
[  OK  ] Started Remount Root and Kernel File Systems.
         Starting Flush Journal to Persistent Storage...
[  OK  ] Started Restore / save the current clock.
[  OK  ] Started Flush Journal to Persistent Storage.
[  OK  ] Started Set the console keyboard layout.
[  OK  ] Reached target Local File Systems (Pre).
[  OK  ] Reached target Local File Systems.
         Starting Create Volatile Files and Directories...
[  OK  ] Started Create Volatile Files and Directories.
[  OK  ] Reached target System Time Synchronized.
         Starting Update UTMP about System Boot/Shutdown...
[  OK  ] Started Update UTMP about System Boot/Shutdown.
[  OK  ] Reached target System Initialization.
[  OK  ] Started Rescue Shell.
[  OK  ] Reached target Rescue Mode.
         Starting Update UTMP about System Runlevel Changes...
[  OK  ] Started Update UTMP about System Runlevel Changes.
You are in rescue mode. After logging in, type "journalctl -xb" to view
system logs, "systemctl reboot" to reboot, "systemctl default" or ^D to
boot into default mode.
Give root password for maintenance
(or press Control-D to continue):

В этом выводе вы можете увидеть запуск systemd в качестве процесса init в контейнере и определение того, что он выполняется внутри контейнера, чтобы он мог соответствующим образом настроить свое поведение. Для приведения контейнера в рабочее состояние запускаются различные юнит-файлы, затем запрашивается root-пароль целевой системы. Вы можете ввести root-пароль здесь, если вы хотите запросить оболочку с root-правами, или вы можете нажать Ctrl + D, чтобы продолжить процесс запуска, который будет отображать обычное приглашение входа в консоль.

Когда вы выполните необходимые изменения в целевой системе, нажмите Ctrl +] три раза подряд; это завершит работу контейнера и вернет вас в исходную оболочку. Оттуда вы можете выполнить очистку, размонтировав файловую систему целевой системы и удалив временный каталог:

$ umount /tmp/target-rescue
$ rmdir /tmp/target-rescue

Вот и все! Теперь вы можете извлечь запоминающие устройства целевой системы и вернуть их обратно.

Идея использовать systemd-nspawn таким образом, особенно параметр --boot, возникла из вопроса, опубликованного на StackExchange. Спасибо Shibumi и kirbyfan64sos за полезные ответы на этот вопрос!

Больше ресурсов по Linux


OTUS. Онлайн-образование
591,99
Цифровые навыки от ведущих экспертов
Поделиться публикацией

Комментарии 10

    +1
    ЗАНУДА_МОДЕ=ON
    Ну если пишете что все/большинство команд требуют рута, то стоит шел приглашение рутовое использовать (# вместо $).
      –4
      абсолютно не согласен. нельзя давать ни малейшего упоминания, что можно зайти под пользователем root, а уже тем более выполнить команду.

      пароль от пользователя root должен быть в строжайшем секрете и открываться с двух апрувов.
      касательно статьи — я бы принудительно редактировал все статьи, которые советуют войти как root.
        0
        root — это инструмент. Да, инструмент опасный. Да, инструмент требующий повышенной ответственности, но инструмент. Нельзя запретить болгарку, потому что она очень опасна. Надо просто научиться ей пользоваться. Я не вижу ничего плохого в том, чтобы использовать root, но только тогда, когда это необходимо и только там, где это необходимо.
          +1
          А я то думал что я зануда :)
            0
            По-моему, вы зря минусуете человека. Это ведь явно сарказм.
          0
          Вы можете ввести root-пароль здесь, если вы хотите запросить оболочку с root-правами, или вы можете нажать Ctrl + D, чтобы продолжить процесс запуска, который будет отображать обычное приглашение входа в консоль.


          Вот тут я не понял — если нажать Ctrl + D то под каким тогда пользователем будет логин в системе?

          Просто к примеру в Ubuntu штатно под рутом не войти (он залочен). Но sudo воспользоватся может только конкретные пользователи (участники группы admin). Так вот войти под админом как-то нужно, но под ним входить тоже, по идее, нужно с паролем…
            0
            хм… попробовал на xubuntu 18.04 (root — залочен, пациентом был снимок btrfs корня).

            В Ubuntu выводится такое приглашение после загрузки контейнера:
            You are in rescue mode. After logging in, type "journalctl -xb" to view
            system logs, "systemctl reboot" to reboot, "systemctl default" or "exit"
            to boot into default mode.
            Press Enter for maintenance
            (or press Control-D to continue): 
            

            Если нажать просто Enter то попадаю в консоль восстановления под рутом.
            А если нажать CTRL + D то выбрасывает на tty login и таргет уже не rescue.target а default target: там multiuser и даже graphical пытался GUI в контейнере загрузить (неуспешно конечно).

            т.е. в rescue.target можно попасть только рутом… что вобщем-то логично.
            +2
            Если уж мы удосужились вытащить диски и переставить их в другую машину, то зачем все эти пляски с systemd, если по сути надо просто смонтировать диск (ну если надо — то прогнать fsck) и поправить файлы, которые испортились?
              +1
              А как определить, какие испортились? Для этого грузим систему, смотрим на ошибки и вручную их исправляем. Можно, конечно, сразу после fsck унести диск на родную систему и делать это там, но и вариант с контейнером имеет право на жизнь. Особенно если вы сделали копию диска и хотите поиграться с ней, не гоняя fsck на оригинальном носителе.
              0
              А не проще настроить резервное копирование и восстановить систему при необходимости? Или бэкап для слабаков?

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое