Выберите продукт

Debian и Ubuntu: как работает cloud-init на first boot, где искать datasource, cache и почему не применяется user-data

Разбираем, почему в Debian и Ubuntu cloud-init не применяет user-data, как определяется datasource, что хранится в /var/lib/cloud и почему first boot может не сработать повторно. Покажу понятный алгоритм диагностики, очистки cache и безопасного повторного прогона.
Debian и Ubuntu: как работает cloud-init на first boot, где искать datasource, cache и почему не применяется user-data

Cloud-init давно стал стандартным механизмом первичной инициализации виртуальных машин. На практике он отвечает за то, что сервер при первом запуске получает hostname, пользователей, SSH-ключи, сетевые параметры, пакеты, файлы и команды инициализации. Но как только что-то идет не так, начинается знакомый сценарий: инстанс поднялся, доступ по SSH есть, а user-data будто проигнорирован.

В Debian и Ubuntu почти все такие проблемы упираются в четыре вещи: выбранный datasource, кэш cloud-init, семантика first boot и порядок выполнения модулей. Если понимать, как cloud-init принимает решение «это новый инстанс» или «я уже все делал», диагностика становится заметно проще.

Отдельно важно помнить: cloud-init — это не просто «скрипт на старте». Это набор этапов и модулей, которые исполняются в разное время загрузки. Поэтому ответ на вопрос «почему не создался пользователь, хотя команда есть в user-data» часто лежит не в YAML, а в том, что модуль уже был помечен как выполненный.

Если вы готовите шаблоны VM для CI, staging или production, эти детали особенно важны. Один неправильно очищенный образ — и новые виртуальные машины унаследуют старый instance-id, старый кэш или неожиданный datasource.

Как cloud-init мыслит: этапы запуска и логика first boot

На Debian и Ubuntu обычно работают сервисы cloud-init-local.service, cloud-init.service, cloud-config.service и cloud-final.service. Они стартуют последовательно и решают разные задачи: определение datasource, чтение metadata и user-data, применение сетевых параметров и поздний запуск модулей вроде установки пакетов и runcmd.

Термин first boot для cloud-init означает не просто «первый запуск после включения VM». Это первый запуск конкретного инстанса с точки зрения его идентичности. Обычно она определяется через instance-id, который приходит из datasource. Если cloud-init считает, что этот инстанс ему уже знаком, часть модулей повторно не выполняется.

Cloud-init запоминает не факт загрузки ОС, а состояние конкретного инстанса. Поэтому клон диска без очистки состояния часто ведет себя как уже инициализированная машина.

Из этого следует простое правило: если вы делаете шаблон из уже запущенной VM, перед публикацией нужно корректно очистить состояние cloud-init. Иначе новый сервер может не восприниматься как новый инстанс.

Что такое datasource и почему из-за него user-data не применяется

Datasource — это источник, из которого cloud-init получает metadata, user-data, vendor-data и instance-id. В зависимости от платформы это может быть NoCloud, ConfigDrive, OpenStack, EC2-совместимый источник или metadata-служба гипервизора.

Когда администратор говорит «cloud-init не применил user-data», очень часто реальная причина в другом: cloud-init не нашел ожидаемый datasource или выбрал не тот. Например, вы рассчитывали на NoCloud seed, а система определила другой источник или ушла в DataSourceNone.

Проверять datasource нужно в первую очередь:

cloud-init status --long
cloud-id
journalctl -u cloud-init -u cloud-config -u cloud-final -b
grep -R "DataSource" /var/log/cloud-init.log /var/log/cloud-init-output.log

Команда cloud-id часто сразу показывает, какой источник определился. Если ответ none, cloud-init либо не нашел datasource, либо инициализация сломалась слишком рано.

Дополнительно полезно посмотреть, что cloud-init видит прямо сейчас:

cloud-init query ds
cloud-init query userdata
cloud-init schema --system

На актуальных версиях Debian и Ubuntu этого обычно достаточно, чтобы быстро понять: проблема в получении данных или уже в их применении.

Проверка datasource и статуса cloud-init в терминале Linux

Типичные симптомы проблем с datasource

  • Не применяются SSH-ключи, хотя сама система загружается штатно.

  • Hostname остается дефолтным, хотя задан в metadata.

  • runcmd и write_files не срабатывают совсем.

  • В логах видны таймауты при поиске metadata endpoint.

  • Cloud-init определяет DataSourceNone или неожиданно выбирает другой источник.

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

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Где cloud-init хранит состояние: каталог /var/lib/cloud

Главная точка расследования — каталог /var/lib/cloud. Здесь хранится runtime-состояние cloud-init: сведения об инстансе, кэш metadata, результаты работы модулей и маркеры того, что уже было выполнено.

Когда cloud-init «упорно не делает то, что должен», почти всегда стоит заглянуть именно сюда:

find /var/lib/cloud -maxdepth 3 -type f | sort
ls -la /var/lib/cloud
ls -la /var/lib/cloud/instance
ls -la /var/lib/cloud/instances

Обычно интерес представляют такие зоны:

  • /var/lib/cloud/instance — ссылка на текущий инстанс.

  • /var/lib/cloud/instances/... — данные, привязанные к конкретному instance-id.

  • /var/lib/cloud/seed/ — seed-данные для некоторых datasource, например NoCloud.

  • /var/lib/cloud/data/ — общая служебная информация и маркеры загрузок.

  • /var/lib/cloud/sem/ и семафоры внутри instance-каталога — признаки выполнения отдельных модулей.

Именно эти файлы объясняют, почему повторный запуск не приводит к повторному применению конфигурации. Cloud-init считает, что нужный модуль уже завершался ранее, и не выполняет его второй раз без явной очистки состояния или смены идентичности инстанса.

Если вы регулярно собираете шаблоны, советую держать под рукой и материал про подготовку golden image с cloud-init: именно на этапе упаковки образа обычно закладываются будущие проблемы с first boot.

Почему first boot не считается первым: частые причины

Самый частый сценарий — создание собственного шаблона. Вы поднимаете VM, устанавливаете пакеты, настраиваете систему, делаете snapshot и ожидаете, что каждая новая машина пройдет полноценную первичную инициализацию. Но если cloud-init не очищен, новый инстанс получает старое состояние.

Вторая типичная причина — платформа или гипервизор отдает один и тот же instance-id при пересоздании. Тогда cloud-init честно считает, что это прежний инстанс, и не запускает одноразовые шаги повторно.

Третья причина — ручной дебаг с обычными перезагрузками. Администратор меняет user-data, делает reboot и ждет результата. Но cloud-init не обязан перечитывать и полностью переисполнять конфигурацию после каждого старта.

Наконец, есть банальные ошибки в самом user-data: отсутствует заголовок #cloud-config, сломан YAML, используются табы вместо пробелов, либо команда выполняется на стадии, где еще нет сети, DNS или доступного пакетного менеджера.

Что из user-data выполняется один раз, а что нет

Это важный источник путаницы. Не весь user-data трактуется одинаково. Некоторые модули cloud-init рассчитаны на одноразовое применение на инстанс, некоторые имеют другую семантику, а shell-скрипты в user-data зависят от типа содержимого и фазы выполнения.

Например, runcmd обычно выполняется на финальном этапе и не предназначен как механизм «запускать на каждом boot». Если нужна логика на каждую загрузку, лучше создавать systemd unit через cloud-init, а не пытаться использовать cloud-init как замену постоянным системным механизмам.

Пошаговый debug cloud-init в Debian и Ubuntu

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

1. Проверяем статус сервисов

systemctl status cloud-init-local.service cloud-init.service cloud-config.service cloud-final.service
cloud-init status --long

Статус done не означает, что все применилось успешно. Он говорит только о том, что жизненный цикл cloud-init завершен.

2. Смотрим логи

tail -n 200 /var/log/cloud-init.log
tail -n 200 /var/log/cloud-init-output.log
journalctl -b | grep cloud-init

/var/log/cloud-init.log показывает внутреннюю логику модулей, работу с datasource и семафорами. /var/log/cloud-init-output.log особенно полезен для диагностики ошибок в командах из runcmd.

3. Проверяем реально выбранный datasource

cloud-id
cloud-init query ds
grep -n "DataSource" /var/log/cloud-init.log

Если datasource не тот, дальнейший разбор YAML мало поможет. Сначала исправляем источник metadata.

4. Проверяем, что cloud-init увидел как user-data

cloud-init query userdata
cloud-init query instance_id
cloud-init query --all

Это помогает быстро разделить две проблемы: данные вообще не прочитаны или они прочитаны, но не применены.

5. Изучаем маркеры в /var/lib/cloud

find /var/lib/cloud -type f | sort | less
find /var/lib/cloud -type f | grep -E "sem|instance-id|result|status"

Если нужные семафоры уже есть, становится понятно, почему повторная перезагрузка ничего не меняет.

6. Проверяем синтаксис cloud-config

cloud-init schema --config-file /root/user-data.yaml

Эта проверка отлично ловит ошибки в YAML, особенно в блоках write_files, users, apt и многострочных командах.

Если вы разворачиваете машины в облаке, где нужен полный контроль над окружением, удобнее тестировать такие сценарии на отдельном VDS, а не на боевом шаблоне.

Администратор изучает содержимое /var/lib/cloud и кэш cloud-init на сервере

Когда нужен cloud-init clean и что он реально делает

Команда cloud-init clean — это не волшебная кнопка починки, а инструмент очистки локального состояния. Она удаляет кэш, служебные маркеры и подготавливает систему к повторному восприятию инстанса или новому циклу инициализации.

Базовый вариант:

cloud-init clean
reboot

Полезно знать и расширенные варианты, если они доступны в вашей версии пакета:

cloud-init clean --logs
cloud-init clean --machine-id
cloud-init clean --seed

Практический смысл опций такой:

  • --logs очищает логи, но для дебага использовать его лучше только после сохранения нужной информации.

  • --machine-id полезен при подготовке шаблонов, чтобы не тащить идентичность системы дальше.

  • --seed затрагивает seed-данные и нужен не во всех сценариях.

После clean обычно выполняют перезагрузку. Но если datasource по-прежнему недоступен или отдает тот же instance-id, очистка лишь маскирует настоящую причину.

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

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Безопасный повторный прогон cloud-init при тестировании

Во время отладки часто хочется быстро проверить измененный user-data без пересоздания VM. Это возможно, но важно не путать повторный прогон модулей с реальным сценарием первого старта. Некоторые модули неидемпотентны: могут повторно создать файлы, поменять конфиг или попытаться переустановить пакеты уже в другом состоянии системы.

Для аккуратного теста лучше использовать временную VM или snapshot. Базовый порядок такой:

  1. Соберите текущие логи и статус.

  2. Сохраните копию исходного user-data.

  3. Выполните cloud-init clean.

  4. Перезагрузите систему.

  5. Сразу после загрузки проверьте статус и логи.

Для лабораторной отладки отдельных стадий существуют и ручные команды:

cloud-init init
cloud-init modules --mode=config
cloud-init modules --mode=final

Но это инструмент для понимания механики, а не полная замена реального first boot. Если нужен еще один прикладной сценарий, посмотрите разбор отладки user-data на VDS.

Практические причины, почему user-data не применяется

Неверный формат user-data

Для cloud-config нужен заголовок #cloud-config. Отступы YAML критичны. Табуляции недопустимы. Особенно часто ошибки встречаются в многострочных блоках и вложенных структурах.

Datasource недоступен или выбран неверно

Metadata endpoint не отвечает, NoCloud seed не найден, ConfigDrive не смонтирован или cloud-init выбирает неожиданный источник.

Кэш содержит старое состояние

Клон VM или шаблон был снят после уже выполненного cloud-init. Нужные модули помечены как завершенные, поэтому повторно не запускаются.

Команды выполняются не на той стадии

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

Ошибка внутри самой команды

Cloud-init мог дойти до runcmd, но конкретная shell-команда завершилась с ошибкой. Тогда внешне кажется, что user-data не применился, хотя проблема в правах, путях, окружении или доступности сети.

Как готовить шаблон Debian или Ubuntu правильно

Если вы собираете собственные образы для виртуализации, самое важное — выпускать их в нейтральном состоянии. Иначе отладка новых VM быстро превращается в лотерею.

Перед snapshot или публикацией шаблона обычно стоит:

  • проверить, что cloud-init установлен и включен;

  • убедиться, что datasource для целевой платформы поддерживается;

  • очистить состояние cloud-init;

  • при необходимости корректно очистить machine-id;

  • не оставлять временные ключи, токены и отладочные файлы.

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

Минимальный runbook для аварийной диагностики

Когда времени мало, можно идти по короткому сценарию:

cloud-init status --long
cloud-id
journalctl -u cloud-init -u cloud-config -u cloud-final -b
tail -n 100 /var/log/cloud-init.log
tail -n 100 /var/log/cloud-init-output.log
cloud-init query --all
find /var/lib/cloud -maxdepth 3 -type f | sort

Если стало ясно, что причина в старом состоянии, а не в datasource и не в синтаксисе, тогда:

cloud-init clean
reboot

После перезагрузки повторяем те же проверки и сравниваем результат. Такой подход почти всегда быстрее, чем сразу лезть в ручное редактирование внутренних файлов cloud-init.

Итоги

В Debian и Ubuntu cloud-init чаще всего «ломается» не сам по себе, а из-за непонимания его модели состояния. Сначала он должен найти правильный datasource, затем распознать инстанс как новый, а потом применить user-data в нужных стадиях. Все, что мешает хотя бы одному из этих шагов, выглядит как «cloud-init ничего не сделал».

Поэтому рабочая стратегия всегда одна: проверить datasource, посмотреть логи, изучить /var/lib/cloud, понять, был ли это действительно первый запуск, и только потом использовать cloud-init clean. Для шаблонов и golden image это особенно критично, потому что ошибка легко тиражируется на весь парк VM.

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

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: nftables sets с timeout и interval для динамических списков IP OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: nftables sets с timeout и interval для динамических списков IP

Показываю, как в Debian и Ubuntu применять nftables sets для больших списков IP, временных банов и диапазонов адресов. Разберём ti ...
Debian/Ubuntu: как исправить x509: certificate signed by unknown authority в Docker, containerd и kubelet OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить x509: certificate signed by unknown authority в Docker, containerd и kubelet

Если Docker, containerd или kubelet на Debian/Ubuntu не могут скачать образ из registry и отвечают x509: certificate signed by unk ...
Debian/Ubuntu: как исправить stale file handle в NFS OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить stale file handle в NFS

Ошибка stale file handle в NFS на Debian и Ubuntu обычно появляется после перезагрузки сервера, failover, отката snapshot или пере ...