cloud-init [353.3]

Рейтинг: 71.7% · 16 голосов
Специализация LPIC-3 305 (v3.0): KVM/QEMU и libvirt, Xen, образы дисков, контейнеры (namespaces/cgroups, LXC/LXD, Docker), оркестрация (Compose, Swarm, Kubernetes, Helm), Vagrant/Packer/cloud-init.
Ответить
Аватара пользователя
Sergey_Sysadmin
Сообщения: 134
Зарегистрирован: 11 май 2026, 05:31

cloud-init [353.3]

Сообщение Sergey_Sysadmin »

Оглавление курса (16)
  1. Введение в LPIC-3 305: виртуализация и контейнеризация
  2. Концепции и теория виртуализации [351.1]
  3. Xen [351.2]
  4. QEMU и KVM [351.3]
  5. Управление ВМ через libvirt [351.4, часть 1]
  6. libvirt: виртуальные сети и пулы хранилищ [351.4, часть 2]
  7. Управление образами дисков ВМ [351.5]
  8. Концепции контейнеризации [352.1]
  9. LXC и LXD [352.2]
  10. Docker: образы и контейнеры [352.3, часть 1]
  11. Docker: тома, сети, логирование, ресурсы [352.3, часть 2]
  12. Оркестрация контейнеров
  13. Облачные инструменты: OpenStack и Terraform [353.1]
  14. Packer [353.2]
  15. cloud-init [353.3] (вы здесь)
  16. Vagrant [353.4]
Урок 14. cloud-init [353.3]

Вы запускаете инстанс в облаке или из своего шаблона KVM, и через минуту он уже с правильным hostname, вашим SSH-ключом, нужными пакетами и смонтированным диском. Никто руками туда не заходил. Это работа cloud-init - стандарта де-факто первичной инициализации виртуальных машин. В этом уроке разберём, откуда инстанс берёт свои настройки (datasources), как устроены user-data и meta-data, какие модули и в каком порядке отрабатывают, и главное - как чинить, когда инициализация молча не сработала.

Изображение

Как это работает

cloud-init - это набор Python-программ и systemd-юнитов, который запускается на первой загрузке свежего инстанса. Его задача - привести идентичный для всех образ к уникальной рабочей конфигурации. Образ один, а инстансов из него тысячи, и каждому нужны свои hostname, ключи, сеть. cloud-init вытаскивает эти различия снаружи, а не зашивает их в образ.

Данные приходят из двух логических потоков. meta-data - это то, что про инстанс знает платформа: instance-id, регион, hostname, сетевые параметры, публичный IP. Их формирует гипервизор или облачный контроллер, администратор их обычно не пишет. user-data - это то, что задаёт пользователь: что установить, кого создать, что выполнить. Вот user-data вы и пишете руками.

Источник, откуда всё это читается, называется datasource. Их много: EC2 (метаданные по адресу 169.254.169.254), Azure, GCE, OpenStack, а для своих стендов - NoCloud, где данные лежат на примонтированном ISO с меткой cidata или передаются через ядро. На раннем этапе загрузки утилита ds-identify перебирает признаки (DMI-строки, метки разделов, ядровые параметры) и решает, в каком мы облаке. Результат кэшируется в /run/cloud-init/, чтобы не гадать заново.

Загрузка разбита на четыре стадии, привязанные к systemd-таргетам. Стадия local (cloud-init-local.service) поднимается до сети - тут определяется datasource и применяется сетевая конфигурация. Стадия network (cloud-init.service) - сеть уже есть, монтируются диски, готовится база. Стадия config (cloud-config.service) - основная масса модулей. Стадия final (cloud-final.service) - то, что должно идти последним: пакеты, пользовательские скрипты, runcmd. Разбиение нужно, чтобы, например, сеть встала до того, как мы полезем ставить пакеты из интернета.

Что именно отрабатывает на каждой стадии, задаёт /etc/cloud/cloud.cfg тремя списками: cloud_init_modules, cloud_config_modules, cloud_final_modules. Каждый модуль отвечает за свою область - users-groups, ssh, write-files, disk-setup, runcmd, packages. user-data в формате cloud-config просто передаёт этим модулям параметры в YAML.

Команды и примеры

Минимальный user-data, покрывающий типовые задачи администратора. Первая строка #cloud-config обязательна - по ней cloud-init понимает формат.

Код: Выделить всё

#cloud-config
hostname: web01
fqdn: web01.example.lan

users:
  - name: deploy
    groups: [sudo]
    shell: /bin/bash
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    ssh_authorized_keys:
      - ssh-ed25519 AAAAC3Nz... deploy@laptop

write_files:
  - path: /etc/myapp/config.yml
    permissions: '0640'
    owner: root:root
    content: |
      env: prod
      workers: 4

disk_setup:
  /dev/vdb:
    table_type: gpt
    layout: true
fs_setup:
  - device: /dev/vdb1
    filesystem: ext4
    label: data
mounts:
  - [ /dev/vdb1, /srv/data, ext4, "defaults,nofail", "0", "2" ]

runcmd:
  - [ systemctl, enable, --now, myapp.service ]
  - curl -fsS https://example.lan/bootstrap | bash
Установка пакетов различается по семействам только содержимым, синтаксис cloud-config один:

Код: Выделить всё

#cloud-config
package_update: true
package_upgrade: true
packages:
  - nginx
  - jq
  - htop
На Debian 13 / Ubuntu 24.04 под капотом это apt-get update и apt-get install, на RHEL 10 / Fedora 41+ - dnf install. cloud-init сам выбирает менеджер по дистрибутиву, вам разницу писать не нужно.

Локальный стенд без облака - datasource NoCloud. Готовим seed-ISO и цепляем к ВМ:

Код: Выделить всё

# создаём два файла
printf 'instance-id: iid-001\nlocal-hostname: lab01\n' > meta-data
cp my-user-data user-data

# Debian/Ubuntu: пакет с genisoimage/xorriso
apt install cloud-image-utils xorriso
cloud-localds seed.iso user-data meta-data

# RHEL/Fedora: тот же ISO вручную
dnf install xorriso
xorriso -as mkisofs -output seed.iso -volid cidata -joliet -rock user-data meta-data
Метка тома обязана быть cidata - именно по ней ds-identify опознаёт NoCloud. Подключаете seed.iso вторым CD к ВМ и загружаетесь.

Диагностика. Главные команды, которые надо знать на экзамене и в бою:

Код: Выделить всё

cloud-init status --wait --long     # ждёт завершения, печатает стадию и ошибки
cloud-init analyze blame            # что дольше всего тормозило загрузку
cloud-init analyze show             # таймлайн по стадиям
cloud-init schema --system          # валидация применённого cloud-config
cloud-init query userdata           # показать, что реально прилетело
cloud-init query ds.meta_data       # разобранные meta-data
Логи и состояние лежат в двух местах. /var/log/cloud-init.log - подробный лог всех модулей, /var/log/cloud-init-output.log - чистый stdout/stderr скриптов и runcmd (тут ловите ошибки своих команд). Текущее состояние и кэш datasource - в /run/cloud-init/ (стирается при ребуте) и /var/lib/cloud/ (живёт между загрузками).

Перегенерация для повторного теста на том же образе:

Код: Выделить всё

cloud-init clean --logs --reboot
clean удаляет семафоры из /var/lib/cloud/, и при следующей загрузке cloud-init отработает с нуля, будто инстанс свежий.

Частые грабли
  • Забыли первую строку #cloud-config или поставили пробел перед ней - cloud-init воспримет user-data как обычный скрипт и YAML не применится. Ошибки при этом может и не быть в очевидном месте.
  • Битый YAML: табы вместо пробелов, неэкранированные двоеточия в content. Прогоняйте cloud-init schema --system или валидатор YAML до деплоя.
  • Модули по умолчанию отрабатывают только на первой загрузке (семафор per-instance). Поменяли user-data и ребутнули - ничего не произошло, пока не сделаете cloud-init clean или не смените instance-id.
  • runcmd выполняется на стадии final, поздно. Если команде нужна сеть или пакет - убедитесь, что пакет в packages, а не ставится тут же руками без гарантии порядка.
  • Метка seed-ISO не cidata - NoCloud не подхватится, инстанс молча уйдёт в дефолт. Проверяйте blkid.
  • disk_setup и fs_setup не трогают уже размеченный диск без явного overwrite - защита от потери данных, но люди думают, что модуль не работает.
  • Путаница логов: свои ошибки скриптов ищите в cloud-init-output.log, а не в основном cloud-init.log.
Мини-лаба
  • Поднимите чистую ВМ из официального cloud-образа Debian 13 или Fedora 41 в локальном KVM.
  • Напишите user-data: создайте пользователя с вашим SSH-ключом и sudo без пароля, установите пакет htop, через write_files положите /etc/motd.
  • Соберите seed.iso через cloud-localds (или xorriso с volid cidata), прицепите к ВМ, загрузитесь.
  • Зайдите по SSH созданным пользователем, проверьте htop и содержимое motd.
  • Выполните cloud-init status --long и cloud-init analyze blame, найдите самый долгий модуль.
  • Сломайте YAML намеренно (отступ табом), пересоберите ISO, сделайте cloud-init clean --reboot и поймайте ошибку в schema и логах.
  • Восстановите конфиг, добавьте runcmd с записью даты в файл, убедитесь, что он отработал ровно один раз после повторного clean.
Контрольные вопросы
  • Чем meta-data отличается от user-data и кто формирует каждый из них?
  • Перечислите четыре стадии загрузки cloud-init и какому событию (сеть, диски) соответствует каждая.
  • Как ds-identify определяет, что инстанс работает в datasource NoCloud, и какая метка тома для этого нужна?
  • Почему изменённый user-data не применяется после простого reboot и как заставить cloud-init отработать заново?
  • В каком файле искать ошибку команды из runcmd, а в каком - ошибку самого модуля?
  • Какие три списка в /etc/cloud/cloud.cfg управляют набором модулей и чем отличается их время выполнения?
👍4 ❤️4 🔥 😄 🤔4
Аватара пользователя
kimjungjin
Сообщения: 1
Зарегистрирован: 19 май 2026, 09:27

Re: cloud-init [353.3]

Сообщение kimjungjin »

А если я через console уже руками поправил hostname, а потом cloud-init на следующей загрузке его обратно переписывает - это из-за чего? Думал он только на первой загрузке работает.
👍 ❤️ 🔥1 😄 🤔
Аватара пользователя
lester
Сообщения: 1
Зарегистрирован: 30 май 2026, 22:43

Re: cloud-init [353.3]

Сообщение lester »

Подтверждаю про cidata: собрал seed.iso с другой меткой тома, ВМ грузилась в дефолт и молчала. blkid сразу показал косяк, поменял volid и всё подхватилось.
👍 ❤️ 🔥 😄 🤔
Ответить
← Предыдущая глава
Packer [353.2]
Следующая глава →
Vagrant [353.4]

Все главы курса «LPIC-3 305: виртуализация и контейнеризация»

Поделиться темой: ✈ Telegram VK

Вернуться в «LPIC-3 305: виртуализация и контейнеры»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость