Cloud-init сегодня — стандарт де-факто для автоматизации первого запуска виртуалок. На VDS он решает базовые задачи: задаёт hostname, создаёт пользователей, добавляет SSH keys, настраивает сеть, пакеты и сервисы. Сердце механики — datasource (источник данных), из которого cloud-init получает meta-data и user-data. Правильно выбранный и закреплённый datasource экономит часы рутины и предотвращает «битые» развёртывания.
Зачем cloud-init на VDS и что такое datasource
Cloud-init запускается на ранних стадиях загрузки системы и ищет, где взять инструкции и метаданные инстанса. Этот источник и есть datasource. Для VDS чаще всего применяются три варианта:
- NoCloud — автономный источник, когда вы сами предоставляете файлы
user-dataиmeta-data(через ISO-диск, конфигурационный том или каталог на файловой системе). - ConfigDrive — совместим с OpenStack «config-drive»: метаданные находятся на подключённом диске со строго определённой структурой каталогов.
- EC2 — метаданные получаются по HTTP с адреса
169.254.169.254(провайдер эмулирует API EC2 Metadata Service).
Выбор зависит от вашего окружения. Если провайдер отдаёт EC2-метаданные — используем EC2. Если платформа в духе OpenStack предоставляет «config-drive» — используем ConfigDrive. Если нужно полностью автономно (локальный гипервизор, тестовые шаблоны, ручная сборка образов) — NoCloud.
Этапы cloud-init и когда применяется datasource
Чтобы понимать, где искать ошибки, полезно помнить порядок работ:
- cloud-init-local: ранний этап, обнаружение и монтирование источника данных (ds-identify).
- cloud-init: загрузка
meta-data, применение части конфигурации. - cloud-init-network: настройка сети (если описана в
network-config). - cloud-init-final: пакеты, пользователи,
runcmd,write_filesи другое.
Почти все проблемы «не применился ключ SSH», «не настроилась сеть», «команды не выполнились» упираются в неверно выбранный или не смонтированный datasource.
Закрепляем datasource и управляем порядком поиска
Cloud-init может пробовать разные источники. Чтобы исключить случайные совпадения и ускорить загрузку, явно задайте список:
# /etc/cloud/cloud.cfg.d/90-datasource-list.cfg
# Пробуем только нужные источники, в указанном порядке
# Доступные имена чувствительны к регистру: NoCloud, ConfigDrive, Ec2, None
# Уберите те, что вам не нужны
# Если источник один, оставьте только его
# Пример: закрепить NoCloud, затем ConfigDrive, затем Ec2
# Примечание: Ec2 пишется именно Ec2
#cloud-config
datasource_list: ["NoCloud", "ConfigDrive", "Ec2", "None"]
При изменении этого списка перезапускать сервисы мало — часто нужна полная очистка состояния cloud-init (об этом ниже). Порядок важен: совпадение с неподходящим источником приведёт к «тихим» провалам.
Проверка, что выбран нужный datasource
cloud-init status --long
cloud-init collect-logs
systemctl status cloud-init-local cloud-init cloud-init-network cloud-init-final
cat /run/cloud-init/ds-identify.log
cat /var/log/cloud-init.log
cat /var/log/cloud-init-output.log
Ищите строки вида datasource: ... found или сообщения об ошибке монтирования ISO/конфиг-диска. Если выбран не тот источник — скорректируйте datasource_list и повторно выполните инициализацию.
NoCloud: быстрый старт для автономных VDS
NoCloud — идеален, когда вы полностью контролируете образ и загрузочные диски. Суть проста: вы даёте cloud-init два файла в корне тома или ISO-образа с меткой тома cidata:
user-data— инструкции для cloud-init (формат YAML c шебангом#cloud-config).meta-data— метаданные инстанса (минимумinstance-idиlocal-hostname).
Минимальные user-data и meta-data
# user-data (YAML)
#cloud-config
users:
- name: deploy
groups: ["sudo"]
shell: /bin/bash
sudo: "ALL=(ALL) NOPASSWD:ALL"
ssh_authorized_keys:
- ssh-ed25519 AAAAC3Nza... your-key-comment
packages:
- htop
- curl
runcmd:
- [ sh, -c, "echo 'Hello from cloud-init' > /etc/motd" ]
# meta-data (YAML)
instance-id: vds-001
local-hostname: vds-001
При необходимости добавьте файл network-config (см. раздел про сеть). Для систематической сборки базовых образов рекомендую материал как собрать «золотой» образ с Packer и cloud-init.
Создание seed ISO для NoCloud
Самый простой способ — утилита cloud-localds из пакета cloud-image-utils. Она создаёт ISO с правильной меткой тома cidata и разложением файлов:
apt-get update
apt-get install -y cloud-image-utils
# С DHCP (без network-config)
cloud-localds seed.iso user-data meta-data
# Со статической сетью (добавим network-config)
cloud-localds --network-config=network-config.yaml seed-static.iso user-data meta-data
Далее смонтируйте ISO к вашей виртуальной машине в панели/гипервизоре и перезапустите VDS. Если панель не позволяет монтировать ISO, можно использовать альтернативу — каталог seed на файловой системе. Если выбираете панель для управления, посмотрите наше сравнение актуальных VDS-панелей.
Seed без ISO: nocloud-net в файловой системе
Можно разместить файлы непосредственно на сервере, чтобы cloud-init нашёл их локально:
mkdir -p /var/lib/cloud/seed/nocloud-net
cp user-data /var/lib/cloud/seed/nocloud-net/user-data
cp meta-data /var/lib/cloud/seed/nocloud-net/meta-data
# Опционально
cp network-config.yaml /var/lib/cloud/seed/nocloud-net/network-config
Такой подход полезен для отладки и шаблонов «золотого образа» без использования внешних томов.
ConfigDrive: совместимость с OpenStack
ConfigDrive — это подключаемый том (обычно ISO), содержащий каталог /openstack/latest/ с файлами meta_data.json и user_data, а том имеет метку config-2. Поддерживается cloud-init напрямую.
Структура и пример содержимого
openstack/
latest/
meta_data.json
user_data
// meta_data.json (минимальный пример)
{
"uuid": "0c9b0a4e-1df7-4a40-8b66-aa11bb22cc33",
"hostname": "vds-002",
"public_keys": {
"default": "ssh-ed25519 AAAAC3Nza... your-key-comment"
}
}
# user_data (YAML)
#cloud-config
users:
- name: deploy
groups: ["sudo"]
sudo: "ALL=(ALL) NOPASSWD:ALL"
ssh_authorized_keys:
- ssh-ed25519 AAAAC3Nza... your-key-comment
package_update: true
packages: ["git", "htop"]
Создание ISO ConfigDrive
Создайте каталог со структурой и соберите ISO с меткой тома config-2:
mkdir -p cfg/openstack/latest
cp meta_data.json cfg/openstack/latest/meta_data.json
cp user_data cfg/openstack/latest/user_data
# genisoimage или mkisofs (зависит от дистрибутива)
genisoimage -output configdrive.iso -volid config-2 -joliet -rock cfg
Подключите configdrive.iso к ВМ и перезагрузите. Проверьте логи cloud-init — он должен обнаружить ConfigDrive.

EC2: когда провайдер отдаёт метаданные по HTTP
EC2-совместимые платформы публикуют meta-data и user-data по адресу 169.254.169.254. Cloud-init сам опросит сервис и применит данные. Вы можете быстро проверить доступность метаданных:
curl -s --noproxy '*' http://169.254.169.254/latest/meta-data/
curl -s --noproxy '*' http://169.254.169.254/latest/user-data
Если ответы приходят — закрепите Ec2 в datasource_list. Обратите внимание, что безопасные платформы могут требовать токен IMDSv2; cloud-init поддерживает это автоматически.
Практика: добавляем пользователей, SSH keys, пакеты и файлы
Частые задачи на первом старте VDS — создать пользователя с sudo, добавить SSH keys, установить пакеты и разложить конфиги. Пример объединённого user-data:
#cloud-config
hostname: vds-app-01
manage_etc_hosts: true
users:
- default
- name: deploy
gecos: Deploy User
groups: ["sudo", "adm"]
shell: /bin/bash
sudo: "ALL=(ALL) NOPASSWD:ALL"
ssh_authorized_keys:
- ssh-ed25519 AAAAC3Nza... your-key-comment
package_update: true
packages:
- curl
- unzip
- ca-certificates
write_files:
- path: /etc/motd
permissions: "0644"
content: |
Welcome to vds-app-01
Provisioned by cloud-init
runcmd:
- [ sh, -c, "timedatectl set-timezone Europe/Moscow" ]
- [ sh, -c, "echo 'OK' > /root/provision.flag" ]
Флаг package_update: true заставит cloud-init обновить кэш пакетов перед установкой.
Сеть: DHCP и статическая через network-config
Cloud-init поддерживает несколько форматов network-config. Практически полезны два: v1 (традиционный формат cloud-init) и v2 (Netplan). Для совместимости с Debian/Ubuntu чаще применяют v2.
DHCP (v2, Netplan)
# network-config.yaml
version: 2
ethernets:
ens3:
dhcp4: true
dhcp6: false
Статика (v2, Netplan)
# network-config.yaml
version: 2
ethernets:
ens3:
addresses:
- 203.0.113.10/24
gateway4: 203.0.113.1
nameservers:
addresses: [1.1.1.1, 8.8.8.8]

Для NoCloud добавьте файл в ISO через cloud-localds --network-config или положите его рядом с user-data/meta-data как network-config. Для ConfigDrive — проверьте поддержку вашей платформы; часто сеть настраивается отдельно, но cloud-init v2 также работает.
Повторный запуск и «чистая» отладка
Cloud-init по умолчанию одноразовый: он помечает этапы как выполненные. Чтобы применить новую конфигурацию или сменить datasource, очистите состояние и логи:
cloud-init clean --logs
rm -rf /var/lib/cloud
reboot
После перезагрузки заново проверьте выбранный источник и этапы. Для анализа длительных запусков используйте:
cloud-init analyze blame
cloud-init analyze boot
Если какие-то команды из runcmd не выполнились, ищите подробный вывод в /var/log/cloud-init-output.log.
Типичные ошибки и чек-лист
- Неправильная метка ISO: для NoCloud нужна
cidata, для ConfigDrive —config-2. - Опечатка в имени источника:
Ec2пишется именно так, а не EC2 в конфиге cloud-init. - Пустой ISO: забыли положить
user-dataилиmeta-dataв корень (NoCloud) илиopenstack/latest(ConfigDrive). - Формат файла: у
user-dataдолжен быть заголовок#cloud-configи корректный YAML; проверьте отступы. - Сеть не поднялась: неверное имя интерфейса в Netplan (проверьте
ip link), неверная маска/шлюз. - SSH keys не применились: проверьте
users, что ключи вssh_authorized_keys, и что не перепутали источники (например, EC2 отдаёт пустые данные). - Повторный запуск: не забывайте
cloud-init cleanи удаление/var/lib/cloudперед повторной проверкой.
Миграция между datasources на существующем VDS
Сценарий: вы тестировали NoCloud, а теперь платформа предоставляет EC2-метаданные. Порядок действий:
- Задайте явный порядок в
/etc/cloud/cloud.cfg.d/90-datasource-list.cfg, поместивEc2вышеNoCloudили оставив толькоEc2. - Убедитесь, что метаданные доступны: проверьте ответы
169.254.169.254. - Очистите состояние:
cloud-init clean --logs, затемrm -rf /var/lib/cloud. - Перезагрузите сервер.
- Проверьте
cloud-init status --longи логи на предмет выбранного источника.
Аналогично можно мигрировать на ConfigDrive: подключите ISO с корректной структурой, скорректируйте порядок источников, очистите состояние и перезагрузите.
Безопасность: доступ к meta-data и user-data
Все, у кого есть root-доступ, могут читать применённые файлы cloud-init и логи. На EC2-совместимых платформах не выдавайте доступ к HTTP-метадате контейнерам/пользователям без необходимости (файрволл, сетевые политики). В user-data не храните секреты в открытом виде. Для чувствительных данных используйте сторонние секрет-хранилища, KMS или зашифрованные файлы, а в cloud-init — только bootstrap-агент.
Рекомендации по выбору источника
Для управляемых VDS используйте datasource, рекомендованный платформой. Для автономных шаблонов и локальных гипервизоров — NoCloud. Для совместимости с OpenStack — ConfigDrive. EC2 удобен, если провайдер выдаёт метаданные и ключи автоматически.
С точки зрения воспроизводимости NoCloud часто выигрывает: все входные данные в одном ISO. Но для массовых развёртываний через API платформы EC2 или ConfigDrive зачастую проще и стандартнее.
Мини-чеклист перед боевым применением
- Фиксирован
datasource_listи протестирован процесс с нуля послеcloud-init clean. - SSH-доступ подтверждён: пользователь, группы, ключи работают.
- Сеть поднимается как ожидается: DHCP или статика применяются.
- Пакеты ставятся без подвисаний,
runcmdзавершается с кодом 0. - Логи чистые: нет «Traceback» и повторных таймаутов источника.
Итог
Cloud-init делает старт VDS предсказуемым, а выбор корректного datasource — ключ к стабильной автоматизации. Освоив три базовых варианта (NoCloud, ConfigDrive, EC2), вы сможете одинаково уверенно разворачивать как штучные инстансы, так и целые парки серверов. Экспериментируйте в изолированном окружении, закрепляйте источник данных, добавляйте строгие проверки и логи — и ваш первый бут каждого сервера станет повторяемым и быстрым.


