Cloud

cloud-init

Стандартный механизм первичной настройки облачных серверов: при первом запуске машина сама применяет переданную ей конфигурацию.

Что такое cloud-init

cloud-init — стандартный механизм первичной настройки виртуальных машин в облаке. При первом запуске сервер забирает конфигурацию, переданную при создании, и применяет её сам: заводит пользователей, кладёт SSH-ключи, настраивает сеть, ставит пакеты, выполняет команды.

Именно cloud-init объясняет, почему в облаке свежесозданная машина сразу пускает вас по ключу, хотя вы ничего не настраивали. Он предустановлен в официальных облачных образах Ubuntu, Debian, RHEL, Rocky, AlmaLinux и является отраслевым стандартом: один и тот же файл работает и в OpenStack, и в AWS, и в Proxmox.

Задача у него узкая — довести машину от «пустой образ» до «готова принимать управление». Дальше начинается зона Ansible и CI/CD.

Как он получает конфигурацию

Создание сервера с --user-data
    ↓
datasource: метаданные по 169.254.169.254, ConfigDrive или NoCloud
    ↓
Стадии: local → init (после поднятия сети) → config → final
    ↓
Модули: users-groups → write_files → packages → runcmd
    ↓
Отметка в /var/lib/cloud/ — при перезагрузке не повторяется

Ключевое: user-data отрабатывает один раз, при первой загрузке. Это регулярный источник недоумения — правка конфигурации у существующего сервера ничего не даёт, нужен либо новый сервер, либо cloud-init clean.

Пример конфигурации

Файл начинается строкой #cloud-config — без неё содержимое не считается конфигурацией:

#cloud-config
users:
  - name: deploy
    groups: [sudo, docker]
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    ssh_authorized_keys:
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... deploy@workstation
ssh_pwauth: false
disable_root: true
package_update: true
packages: [docker.io, nvidia-driver-550, nvtop]
write_files:
  - path: /etc/docker/daemon.json
    content: '{ "default-runtime": "nvidia" }'
runcmd:
  - systemctl enable --now docker
  - nvidia-smi -L > /var/log/gpu-inventory.log

Порядок модулей фиксирован: write_files отрабатывает раньше runcmd, поэтому в командах уже можно опираться на созданные файлы.

Отладка

cloud-init status --wait            # дождаться завершения: done или error
cloud-init schema --system          # проверить синтаксис применённого конфига
cat /var/log/cloud-init-output.log  # вывод команд — сюда смотреть при ошибке
sudo cloud-init clean --logs --reboot   # сбросить отметку и прогнать заново

Проверять YAML лучше до создания сервера: ошибка отступа не откатывается, а тихо оставляет машину недонастроенной, причём cloud-init status может вернуть done — модуль просто не выполнился.

Типовые грабли:

  • Забыт #cloud-config в первой строке — файл проигнорирован целиком.
  • Ожидание идемпотентности. cloud-init не Ansible: он не приводит систему к состоянию, а выполняет шаги один раз.
  • Слишком много логики в runcmd. Десятки команд превращают его в нечитаемый скрипт без обработки ошибок. Порог простой: поднять машину и передать управление Ansible или IaC-инструменту.

Зачем это на GPU-серверах

На арендованных GPU-машинах cloud-init экономит больше всего времени: серверы здесь берут под задачу и удаляют после неё, а окружение каждый раз одинаковое — драйвер NVIDIA, CUDA, NVIDIA Container Toolkit, Docker. Описав это один раз, вы поднимаете десять одинаковых облачных серверов под распределённое обучение без ручной установки драйверов и без расхождений версий, которые потом ловятся как «работает только на первом узле».

Практичный компромисс: тяжёлое (драйверы, CUDA) запекать в образ, а через cloud-init подавать только изменчивое — ключи, конфиги, номер узла. Установка драйвера при каждом старте добавляет минуты к оплачиваемому времени.

Связанные термины

  • Облачный сервер — то, что настраивает cloud-init
  • SSH-ключ — самое частое содержимое user-data
  • OpenStack — передаёт user-data при создании инстанса
  • Ansible — принимает эстафету после первичной настройки
  • GitOps / IaC — подход, частью которого является cloud-init
  • NVIDIA Driver — типичная задача для GPU-серверов

Готовы запустить GPU-задачу?

Запустить GPU-сервер