Cloud-init — это свободно распространяемый пакет, предназначенный для настройки виртуальных машин на базе операционной системы Linux при их запуске.
В традиционной (домашней) среде системы устанавливаются либо с компакт-диска, либо с USB-накопителя. Конфигурация выполняется вручную через стандартный установщик.
Однако в облачной среде требуется регулярно конфигурировать множество систем, а также создавать, удалять и перезапускать их экземпляры. В этом случае ручная конфигурация становится непрактичной и невыполнимой задачей.
Поэтому cloud-init
решает задачи автоматической конфигурации и стандартизирует настройку виртуальных машин.
cloud
Основная задача cloud-init
— обрабатывать входные метаданные (например, параметры пользователя — user-data
) и конфигурировать виртуальную машину перед ее запуском.
Таким образом, благодаря cloud-init
можно заранее настроить сервер, установить необходимое программное обеспечение, подготовить рабочие директории и создать пользователей с определенными правами.
Облачные серверы Timeweb Cloud поддерживают работу со сценариями cloud-init
через панель управления.
В документации Timeweb Cloud есть небольшая статья, рассказывающая об использовании сценариев cloud-init непосредственно на облачных серверах Timeweb Cloud.
По сути, Timeweb Cloud имеет текстовый редактор сценариев cloud-init
, который доступен в веб-браузере. С помощью него передаются пользовательские данные непосредственно в саму утилиту перед запуском системы.
Есть несколько вариантов получения операционной системы на базе Linux вместе с утилитой cloud-init
:
Использовать специализированный образ операционной системы Linux с предустановленным cloud-init
. Таких образов множество — мы упомянем лишь самые основные.
Использовать готовые дистрибутивы от облачных провайдеров. Большинство облачных платформ поддерживают cloud-init
, хотя процедуры настройки имеют различия. Например, облачные серверы Timeweb Cloud позволяют применять сценарии cloud-init
через панель управления.
Собрать собственный образ операционной системы с помощью HashiCorp Packer.
Установить пакет cloud-init
вручную.
Ubuntu. Самый распространенный образ Unix-подобной операционной системы с cloud-init
— Ubuntu 22.04 Cloud Images. Это официальные облачные образы Ubuntu, созданные Canonical (разработчик ОС) специально для работы в общедоступных облаках. Они оптимизированы и настроены под соответствующие задачи.
Debian. Аналогично Ubuntu, у Debian есть свои специальные облачные образы — Debian Cloud.
Alma Linux. Отдельная версия дистрибутивов Linux, заточенная под развертывание в облаке — Alma Linux Cloud.
Astra Linux. У Astra Linux Special Edition есть специальные образы с поддержкой технологии cloud-init.
VMWare. Специализированный образ Photon от VMWare, предназначенный для работы в облаке, с заранее установленным cloud-init
.
Другой вариант — самостоятельная установка cloud-init
.
В операционную систему cloud-init
устанавливается как обычный пакет и существует в виде Трех служб (сервисов) для systemd
, расположенных в директории /lib/systemd/system
:
cloud-init.service
cloud-config.service
cloud-final.service
Также в пакет cloud-init
входят еще две вспомогательные службы systemd
:
cloud-init-local.service
cloud-init-hotplugd.service
Перед установкой лучше обновить список доступных репозиториев:
sudo apt update
Далее пакет cloud-init
загружается через apt
:
sudo apt-get install cloud-init
В некоторых образах Linux cloud-init
уже установлен по умолчанию. Если это так, то после выполнения команды install
система сообщит вам об этом.
Стоит добавить, что cloud-init
поддерживает дополнительные модули, которые могут расширить возможности конфигурации. Полный список модулей доступен в официальной документации.
По причине того, что cloud-init
существует в виде служб, он запускается сразу после старта утилиты systemd
— то есть в момент старта физической машины и до подключения системы к сети. Это позволяет заранее сконфигурировать сетевые настройки, шлюзы, DNS-адреса и т.д.
Можно выделить три основных этапа работы cloud-init
, за время которых конфигурируется система. На каждом этапе запускаются определенные службы cloud-init
.
До сети (init). Первоначальная, самая ранняя конфигурация еще до запуска сети. Выполняются настройка системы, настройка сетевых параметров, подготовка дискового пространства и т.д.
cloud-init-local.service
cloud-init.service
После сети (config). На этом этапе появляется сеть, поэтому выполняется установка обновлений и загрузка необходимых пакетов.
cloud-config.service
В конце (final). Завершающий этап, на котором выполняются самые последние настройки. Например, создание пользователей, назначение прав доступа и т.д.
cloud-final.service
cloud-init-hotplugd.service
В cloud-init
доступны дополнительные модули, расширяющие возможности конфигурации системы. Все они выполняются последовательно и поэтапно.
Модули могут запускаться на каждом из трех существующих этапах — зависит от конкретного случая. В конфигурационном файле запуск модулей регулируется тремя списками:
cloud_init_modules
. Модули выполняются на этапе инициализации (init
) еще до запуска сети.
cloud_config_modules
. Модули выполняются на этапе конфигурации (cloud
) уже после запуска сети.
cloud_final_modules
. Модули выполняются на заключительном этапе (final
).
В этом смысле, если развернуть описанные выше три этапа и рассмотреть их работу немного подробнее, общее число этапов будет равно пяти:
Утилита systemd
определяет, нужно ли запускать cloud-init
при загрузке системы.
Запущенный cloud-init
ищет локальные источники данных и применяет описанные конфигурации. На этом же этапе настраивается сеть.
На этапе настройки cloud-init
обрабатывает пользовательские данные и запускает модули, перечисленные в разделе cloud_init_modules
конфигурационного файла.
На этапе конфигурации cloud-init
аналогично запускает модули, описанные в разделе cloud_config_modules
конфигурационного файла.
На этапе завершения cloud-init
запускает модули, которые были описаны в разделе cloud_final_modules
конфигурационного файла. Тут же выполняется загрузка и установка указанных пакетов.
Более подробно про этапы работы cloud-init
можно узнать на отдельной странице в официальной документации.
При этом у каждого модуля есть еще один дополнительный параметр, который указывает на периодичность запуска модуля во время конфигурации системы:
per instance. Модуль запускается каждый раз при первой загрузке экземпляра системы, который клонируется или создается из сохраненного образа.
per once. Модуль запускается только один раз. То есть при старте клонов или новых экземпляров образа модуль уже не будет работать.
per always. Модуль запускается при каждой загрузке системы.
Как правило, в каждом публичном (AWS, GCP, Azure, Timeweb Cloud) или частном облаке (OpenStack, CloudStack, выделенный сервер Timeweb Cloud) есть своего рода сервис, сообщающий виртуальной машине данные об окружении.
Эти данные можно разделить на несколько типов, каждый из которых cloud-init
использует в определенном порядке:
Пользовательские данные (user-data
). Настройки и директивы, прописанные в конфигурационном файле cloud.cfg
. Данные могут представлять собой указанные файлы для запуска, пакеты для установки и сценарии оболочки. Обычно user-data
необходимы для конфигурации конкретного экземпляра виртуальной машины.
Метаданные (meta-data
). Информация об окружении. Например, имя сервера или идентификатор экземпляра системы. Метаданные используются после пользовательских данных.
Данные поставщиков (vendor-data
). Информация о поставщиках (облачных услуг) и разработчиках, которые помогают правильно настроить образ для последующего запуска в рабочей среде. Обычно vendor-data
требуется для общей конфигурации по умолчанию. Данные поставщиков используются после метаданных.
Например, метаданные могут быть доступны по адресу:
http://localhost/latest/meta-data/
Как правило, это:
Внутренний IP адрес
Публичный IP адрес
Имя сервера
Публичный SSH-ключ
Тип виртуальной машины
Пользовательские данные, которые можно редактировать, могут быть размещены по адресу:
http://localhost/latest/user-data/
Пользовательские данные используются в облаке для автоматизации разного рода шаблонов или сценариев, задача которых — устанавливать необходимое ПО, настраивать сервер, управлять конфигурациями и т.д.
То есть такие данные может использовать не только cloud-init
, но и любая другая утилита.
Cloud-init читает пользовательские данные и, если они заданы в формате, понятном cloud-init
, выполняются действия, описанные в этих данных.
Когда система загружается, cloud-init
сперва проверяет конфигурационные файлы со сценариями на языке YAML, после чего выполняет прописанные в них инструкции.
YAML (рекурсивный акроним «YAML Ain't Markup Language», т.е. «YAML не язык разметки») — это особый формат для сериализации (хранения) данных, который визуально выглядит как язык разметки, хотя таковым не является.
Основной YAML-файл с настройками cloud-init
находится по адресу /etc/cloud/cloud.cfg
.
Этот файл представляет собой основной сценарий конфигурации. В нем прописываются директивы и их параметры. При этом каждая директива соотносится с конкретным модулем cloud-init
, который выполняет свою узкую функцию.
Сценарии для cloud-init
можно писать как в виде текстовых файлов на YAML (через #cloud-config
), так и в виде обычных shell-скриптов (через #!/bin/sh
).
При этом shell-скрипты автоматически преобразовываются в формат с #cloud-config
.
Простейший пример сценария с пользовательскими данными — это задание имени хоста при загрузке виртуальной машины:
#cloud-config
hostname: my-host
fqdn: my-address.ru
manage_etc_hosts: true
#cloud-config
— указание на то, что все дальнейшие инструкции предназначены для cloud-init
и написаны в формате YAML
hostname
— короткое имя хоста
fqdn
— полное имя хоста
manage_etc_hosts
— разрешение для cloud-init
на управление файлом /etc/hosts
. Если впоследствии потребуется изменение этого файла, опция должна быть выставлена в false
. В противном случае вручную внесенные изменения будут переписаны после очередной перезагрузки с cloud-init
.
Конфигурация cloud-init
с использованием YAML должна начинаться с #cloud-config
.
На старте виртуальной машины вы можете заранее определять пользователей через директиву users
:
#cloud-config
users:
- name: userOne
gecos: This is the first user
groups: sudo
shell: sh
system: true
- name: userTwo
gecos: This is the second user
groups: sudo
shell: /bin/bash
system: false
expiredate: '2030-01-02'
Как видно, имя каждого нового пользователя начинается с тире, а сами параметры определяются в формате «ключ: значение».
Указанные параметры означают следующее:
name
. Имя учетной записи пользователя
gecos
. Небольшая информация о пользователе
groups
. Группы, к которым относится пользователь
shell
. Оболочка, устанавливаемая для пользователя. Указано значение по умолчанию в виде самой простой оболочки — sh
.
system
. Является ли учетная запись системной. Если true
, то у такого пользователя не будет домашнего каталога.
expiredate
. Дата истечения срока действия пользователя в формате «ГГГГ-ММ-ДД».
Более подробное описание всех параметров пользователя можно увидеть в примерах официальной документации.
Еще одна несложная директива — chpasswd
. С помощью нее можно перезадать пароль уже существующего пользователя. Рассмотрим конфигурацию:
#cloud-config
chpasswd:
list: |
userOne:passOne
userTwo:passTwo
userThree:passThree
expire: false
Здесь мы устанавливаем список пользователей, для которых изменяется пароль. Символ |
указывает на многострочный способ записи параметров.
Пароль записывается в явном виде. При этом параметр expire
сообщает о том, потребуется ли его изменение по истечении срока действия.
Поэтому эту директиву лучше использовать только в во время отладки, ведь установленное значение будет доступно всем пользователям системы.
В cloud-config
есть отдельная директива для обновления списка доступных пакетов — package_update
. Она является декларативным аналогом команды APT:
sudo apt-get update
Значением по умолчанию является true
— перед запуском системы cloud-init
всегда автоматически обновляет список пакетов. Отключить обновление можно так:
#cloud-config
package_update: false
Для обновления (или установки) конкретных пакетов нужна другая директива — packages
:
#cloud-config
packages:
- nginx
- nodejs
Директива runcmd
позволяет выполнять консольные команды через конфигурацию cloud-config
. Нужно просто передать список команд, которые cloud-init
последовательно запустит в во время старта системы, как если бы вы их вводили вручную:
#cloud-config
runcmd:
- echo 'Команда в виде строки!' >> /somefile.txt
- [ sh, -c, "echo 'Команда в виде списка!' >> /somefile.txt" ]
В этом примере используется два способа записи команды, которая записывает текст в файл:
В виде обычной строки
В виде YAML-списка с указанием исполняемого файла и его параметров
Однако есть похожая директива для выполнения команд — bootcmd
. Правила записи аналогичные, но есть одно важное отличие от runcmd
:
Директива runcmd
выполняет команды только при первичной загрузке системы
Директива bootcmd
выполняет команды при каждом старте системы
#cloud-config
bootcmd:
- echo 'Команда записана строкой и выполняется при каждой загрузке системы!'
- [ sh, "echo 'Команда записана списком и выполняется при каждой загрузке системы!' " ]
Директиву runcmd
можно комбинировать с директивой написания файла — write_files
.
Например, можно создать скрипт в отдельном файле и сразу же его выполнить:
#cloud-config
write_files:
- path: /run/scripts/somescript.sh
content: |
#!/bin/bash
echo 'Какой-то скрипт только что выполнился!'
permissions: '0755'
runcmd:
- [ sh, "/run/scripts/somescript.sh" ]
Параметр permissions
со значением 0755
указывает на то, что файл со скриптом будет доступен для чтения и выполнения всем, но редактирование возможно только пользователю.
Список модулей, которые будут выполняться на определенном этапе конфигурации, можно переопределять. Например, список модулей по умолчанию на этапе cloud_config_modules
выглядит так:
#cloud-config
cloud_config_modules:
- emit_upstart
- snap
- ssh-import-id
- locale
- set-passwords
- grub-dpkg
- apt-pipelining
- apt-configure
- ubuntu-advantage
- ntp
- timezone
- disable-ec2-metadata
- runcmd
- byobu
На всякий случай стоит напомнить, что этапов 3:
cloud_init_modules
cloud_config_modules
cloud_final_modules
Обратите внимание, в примере выше указана уже известная нам директива (модуль) runcmd
— предпоследняя позиция в списке. Если ее убрать, то команды, прописанные в runcmd
, не будут выполнены.
Конфигурация cloud-init
может также содержать только shell-скрипты. Для этого в начале сценария вместо привычного #cloud-config
прописывается #!/bin/sh
.
Вот пример того, как можно выполнить стандартное обновление APT и установить необходимые пакеты:
#!/bin/sh
apt-get update
apt-get -y install nodejs
apt-get -y install nginx
Флаг -y
нужен для автоматического ответа «yes» на все вопросы во время установки.
Подготовили для вас выгодные тарифы на облачные серверы
В этом руководстве было рассказано о теоретическом и практическом аспектах использования технологии cloud-init
:
Механизм работы cloud-init
Способы «общения» с cloud-init
для конфигурации системы
Написание сценариев на YAML или в виде shell-скриптов
Примеры возможных конфигураций cloud-init
Важно помнить, что cloud-init
выполняет свои функции до старта системы, после чего настроенный экземпляр следует той конфигурации (сеть, директории, пакеты, обновления), которая была в него заложена.
Утилита cloud-init
имеет поддержку модулей, каждый из которых отвечает за свой аспект конфигурации. При этом настройка системы выполняется поэтапно:
init
(до сети)
config
(после сети)
final
(в конце)
Подробная информация о технологии cloud-init
доступна на официальном сайте, который поддерживается компанией Canonical — основным разработчиком дистрибутива Ubuntu.