Основы написания скриптов cloud-config

Формат cloud-config — один из самых популярных форматов для работы с user-data.

Файлы cloud-config – это специальные скрипты, предназначенные для запуска процесса cloud-init. Обычно они используются для начальной настройки при первой загрузке сервера. В этом руководстве вы найдете базовую информацию о формате и использовании cloud-config.

Общие сведения о cloud-config

Формат cloud-config реализует декларативный синтаксис для общих элементов конфигурации, что упрощает выполнение многих задач. Он также позволяет добавлять произвольные команды для всего, что выходит за пределы предопределенных конфигураций.

Это позволяет файлу работать в качестве обычного конфигурационного файла, сохраняя при этом гибкость скрипта.

Форматирование YAML

Файл записывается с помощью формата сериализации данных YAML.

Файлы YAML, как правило, интуитивно понятны при чтении, но знать фактические правила написания таких файлов никогда не помешает.

Вот некоторые важные правила файлов YAML:

  • Отступы с пробелами указывают структуру и взаимосвязь элементов друг с другом. Элементы с большим отступом являются подпунктами первого элемента с меньшим отступом.
  • Список членов можно определить с помощью тире.
  • Записи массива создаются с помощью двоеточия (:), за которым следует пробел и значение.
  • Блоки текста имеют отступы. Чтобы указать, что блок должен быть прочитан с сохранением форматирования, используйте символ | перед блоком.

Попробуйте проанализировать формат этого файла cloud-config:

#cloud-config
users:

- name: demo
groups: sudo
shell: /bin/bash
sudo: ['ALL=(ALL) NOPASSWD:ALL']
ssh-authorized-keys:

- ssh-rsa

AAAAB3NzaC1yc2EAAAADAQABAAABAQDf0q4PyG0doiBQYV7OlOxbRjle026hJPBWD+eKHWuVXIpAiQlSElEBqQn0pOqNJZ3IBCvSLnrdZTUph4czNC4885AArS9NkyM7lK27Oo8RV888jWc8hsx4CD2uNfkuHL+NI5xPB/QT3Um2Zi7GRkIwIgNPN5uqUtXvjgA+i1CS0Ku4ld8vndXvr504jV9BMQoZrXEST3YlriOb8Wf7hYqphVMpF3b+8df96Pxsj0+iZqayS9wFcL8ITPApHi0yVwS8TjxEtI3FDpCbf7Y/DmTGOv49+AWBkFhS2ZwwGTX65L61PDlTSAzL+rPFmHaQBHnsli8U9N6E4XHDEOjbSMRX user@example.com

- ssh-rsa

AAAAB3NzaC1yc2EAAAADAQABAAABAQDcthLR0qW6y1eWtlmgUE/DveL4XCaqK6PQlWzi445v6vgh7emU4R5DmAsz+plWooJL40dDLCwBt9kEcO/vYzKY9DdHnX8dveMTJNU/OJAaoB1fV6ePvTOdQ6F3SlF2uq77xYTOqBiWjqF+KMDeB+dQ+eGyhuI/z/aROFP6pdkRyEikO9YkVMPyomHKFob+ZKPI4t7TwUi7x1rZB1GsKgRoFkkYu7gvGak3jEWazsZEeRxCgHgAV7TDm05VAWCrnX/+RzsQ/1DecwSzsP06DGFWZYjxzthhGTvH/W5+KFyMvyA+tZV4i1XM+CIv/Ma/xahwqzQkIaKUwsldPPu00jRN user@desktop
runcmd:

- touch /test.txt

Во-первых, каждый файл cloud-config должен начинаться со строки #cloud-config. Это сообщает программе cloud-init, что этот файл нужно интерпретировать как файл cloud-config. В обычных файлах скриптов в первой строке указывается интерпретатор, который должен использоваться для выполнения файла.

В приведенном выше файле есть две директивы верхнего уровня, users и runcmd. Они обе служат ключами. Значения этих ключей состоят из всех отступов после них.

Значение ключа users представляет собой единый элемент списка. Вы понимаете это, потому что следующий уровень отступов отмечен символом тире (-), который указывает элемент списка, и потому, что на этом уровне отступов имеется только одно тире. В случае с директивой users это значит, что файл определяет только одного пользователя.

Сам элемент списка содержит ассоциативный массив с большим количеством пар «ключ-значение». Это одноуровневые элементы – все они существуют на одном уровне отступов. Список содержит атрибуты пользователя.

Следует отметить, что строки, которые вы видите, не требуют кавычек. Интерпретатор может довольно легко определить тип данных, а отступ указывает на отношение элементов, что легко прочитать как человеку, так и программе.

Теперь можно приступить к изучению некоторых наиболее распространенных директив cloud-config.

Управление пользователями и группами

Чтобы определить нового пользователя в системе, используйте директиву users, которую вы уже видели в вышеприведенном примере.

Общий формат директивы таков:

#cloud-config
users:

- first_user_parameter

first_user_parameter

- second_user_parameter

second_user_parameter

second_user_parameter

second_user_parameter

Запись каждого нового пользователя начинается с тире. Здесь доступны следующие ключи:

  • name: имя пользователя.
  • primary-group: основная группа пользователя. По умолчанию это будет группа, которая совпадает с именем пользователя. Любая группа, указанная здесь, должна уже существовать или должна быть создана явно (об этом немного позже).
  • groups: дополнительные группы пользователя, перечисленные через запятую.
  • gecos: дополнительные сведения о пользователе.
  • shell: оболочка, в которой работает пользователь. По умолчанию устанавливается sh, если не было установлено другое значение.
  • expiredate: срок действия учетной записи в формате YYYY-MM-DD.
  • sudo: необходима пользователям с привилегиями sudo.
  • lock-passwd: по умолчанию имеет значение True.Чтобы включить парольную аутентификацию, измените значение на False.
  • passwd: хешированный пароль пользователя.
  • ssh-authorized-keys: список открытых SSH-ключей, которые нужно добавить в файл authorized_keys в каталог .ssh.
  • inactive: логическое значение, которое приведет к отключению учетной записи.
  • system: значение True сделает эту учетную запись системным аккаунтом без домашнего каталога.
  • homedir: переопределяет /home/<username> по умолчанию.
  • ssh-import-id: ID SSH, который нужно импортировать из LaunchPad.
  • selinux-user: настраивает пользователя SELinux, который должен использоваться для входа в эту учетную запись.
  • no-create-home: установите значение True, чтобы не создавать каталог /home/<username> для этого пользователя.
  • no-user-group: установите значение True, чтобы не создавать одноименной группы для этого пользователя.
  • no-log-init: установите True, чтобы не запускать базы данных входа пользователя.

Помимо некоторой базовой информации, такой как ключ name, вам нужно определить области, в которых значения будут отличаться от значения по умолчанию.

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

Для примера определения пользователя можно использовать вышеприведенный cloud-config:

#cloud-config
users:

- name: demo

groups: sudo
shell: /bin/bash
sudo: ['ALL=(ALL) NOPASSWD:ALL']
ssh-authorized-keys:

- ssh-rsa

AAAAB3NzaC1yc2EAAAADAQABAAABAQDf0q4PyG0doiBQYV7OlOxbRjle026hJPBWD+eKHWuVXIpAiQlSElEBqQn0pOqNJZ3IBCvSLnrdZTUph4czNC4885AArS9NkyM7lK27Oo8RV888jWc8hsx4CD2uNfkuHL+NI5xPB/QT3Um2Zi7GRkIwIgNPN5uqUtXvjgA+i1CS0Ku4ld8vndXvr504jV9BMQoZrXEST3YlriOb8Wf7hYqphVMpF3b+8df96Pxsj0+iZqayS9wFcL8ITPApHi0yVwS8TjxEtI3FDpCbf7Y/DmTGOv49+AWBkFhS2ZwwGTX65L61PDlTSAzL+rPFmHaQBHnsli8U9N6E4XHDEOjbSMRX user@example.com

- ssh-rsa

AAAAB3NzaC1yc2EAAAADAQABAAABAQDcthLR0qW6y1eWtlmgUE/DveL4XCaqK6PQlWzi445v6vgh7emU4R5DmAsz+plWooJL40dDLCwBt9kEcO/vYzKY9DdHnX8dveMTJNU/OJAaoB1fV6ePvTOdQ6F3SlF2uq77xYTOqBiWjqF+KMDeB+dQ+eGyhuI/z/aROFP6pdkRyEikO9YkVMPyomHKFob+ZKPI4t7TwUi7x1rZB1GsKgRoFkkYu7gvGak3jEWazsZEeRxCgHgAV7TDm05VAWCrnX/+RzsQ/1DecwSzsP06DGFWZYjxzthhGTvH/W5+KFyMvyA+tZV4i1XM+CIv/Ma/xahwqzQkIaKUwsldPPu00jRN user@desktop

Чтобы определить группы, используйте директиву groups. Эта директива относительно проста: она просто принимает список групп, которые вы хотели бы создать.

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

#cloud-config
groups:

- group1
- group2: [user1, user2]

Изменение паролей существующих пользователей

Для уже существующих учетных записей пользователей (особенно это касается записи root) пароль можно добавить с помощью директивы chpasswd.

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

Базовый синтаксис выглядит так:

#cloud-config
chpasswd:

list: |

user1:password1
user2:password2
user3:password3

expire: False

Директива содержит два ассоциативных ключа массива. Ключ list содержит блок, в котором перечислены имена учетных записей и связанные с ними пароли. Ключ expire является логическим значением, которое определяет, нужно ли менять пароль при первой загрузке или нет. По умолчанию используется значение True.

Следует отметить, что вы можете установить пароль RANDOM или R; это значение может сгенерировать случайный пароль и записать его в /var/log/cloud-init-output.log. Имейте в виду, что этот файл доступен для любого пользователя в системе, поэтому он может быть опасен.

Запись файлов на диск

Чтобы записать файлы на диск, используйте директиву write_files.

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

Единственными обязательными ключами в этом массиве являются path (определяет путь, по которому нужно записать файл), и content (содержит данные файла).

Также write_files поддерживает такие ключи:

  • path: абсолютный путь к местоположению в файловой системе, куда должен быть записан файл.
  • content: содержимое, которое должно быть помещено в файл. Для многострочного ввода вы должны запустить блок с помощью символа | в строке content, за которым следует блок с отступом, содержащий контент. Двоичные файлы должны содержать «!! binary» и пробел перед символом |.
  • owner: пользователь и группа, которым должно быть предоставлено право собственности на файл. Они должны быть указаны в формате «username:group».
  • permissions: набор прав на этот файл.
  • encoding: опциональная спецификация кодировки файла. Это может быть b64 для файлов Base64, gzip для сжатых файлов Gzip или gz+b64 для комбинированных файлов. Если пропустить это значение, будет использоваться стандартный тип файла.

Для примера можно записать файл /test.txt с таким содержимым:

Here is a line.
Another line is here.

Раздел cloud-config , отвечающий за эту процедуру, выглядит так:

#cloud-config
write_files:

- path: /test.txt

content: |

Here is a line.
Another line is here.

Обновление и установка пакетов на сервере

Также cloud-config предоставляет несколько директив и параметров для управления пакетами.

Чтобы обновить базу apt на Debian-подобном сервере, установите значение true для директивы package_update. Это аналогично команде apt-get update.

Значение по умолчанию этой директивы — true, поэтому вам нужно беспокоиться об этой директиве, только если вы хотите ее отключить:

#cloud-config
package_update: false

Если вы хотите обновить все пакеты на сервере после его первого запуска, вы можете установить директиву package_upgrade. Это похоже на apt-get upgrade.

По умолчанию директива имеет значение false. Чтобы включить ее, измените значение на true.

#cloud-config
package_upgrade: true

Чтобы установить дополнительные пакеты, вы можете просто перечислить названия этих пакетов в директиве packages. В отличие от двух приведенных выше команд, эта директива будет работать с дистрибутивами под управлением менеджеров yum или apt.

Эти элементы могут принимать одну из двух форм. Первая – это простая строка с именем пакета. Вторая форма – это список с двумя элементами: сначала идет имя пакета, а затем номер версии.

#cloud-config
packages:

- package_1
- package_2
- [package_3, version_num]

Директива packages изменит значение apt_update на true и переопределит любые предыдущие значения.

Настройка SSH

Директива users позволяет управлять ключами SSH, но также их параметры можно указать в специальном разделе ssh_authorized_keys. Они будут добавлены в файл authorized_keys первого определенного пользователя.

Общий формат повторяет директиву users:

#cloud-config
ssh_authorized_keys:

- ssh_key_1
- ssh_key_2

Вы также можете заранее сгенерировать секретные ключи SSH и поместить их в файловую систему. Это может быть полезно, если вы хотите заранее сообщить своим клиентам информацию об этом сервере, чтобы они могли доверять серверу при работе в Интернете.

Для этого можно использовать директиву ssh_keys. Она может содержать ключи RSA, DSA или ECDSA, используя элементы rsa_private, rsa_public, dsa_private, dsa_public, ecdsa_private и ecdsa_public.

Поскольку форматирование и разрывы строк важны для закрытых ключей, не забудьте использовать при их определении блок с символом |. Кроме того, вы должны добавить начальную и конечную строку (BEGIN RSA PRIVATE KEY и END RSA PRIVATE KEY), иначе ключ не будет работать.

#cloud-config
ssh_keys:

rsa_private: |

-----BEGIN RSA PRIVATE KEY-----
your_rsa_private_key
-----END RSA PRIVATE KEY-----

rsa_public: your_rsa_public_key

Настройка доверенных сертификатов

Если ваша инфраструктура зависит от ключей, подписанных внутренним центром сертификации, вы можете сделать так, чтобы новые машины доверяли сертификатам этого ЦС, добавив информацию о сертификате. Для этого используется директива ca-certs.

Она использует два подэлемента. Первый, remove-defaults, при значении true удалит всю информацию о доверенных сертификатах, включенную по умолчанию. Это может привести к некоторым проблемам, поэтому используйте этот элемент с осторожностью.

Второй элемент, trusted, содержит список доверенных центров сертификации.

#cloud-config
ca-certs:

remove-defaults: true
trusted:

- |

-----BEGIN CERTIFICATE-----
your_CA_cert
-----END CERTIFICATE-----

Настройка resolv.conf

Если вы настроили свои собственные DNS-серверы, вы можете управлять файлом resolv.conf с помощью директивы resolv_conf. В настоящее время это работает только для дистрибутивов RHEL.

Директива resolv_conf управляет настройками с помощью элементов nameservers, searchdomains, domain и options.

Директива nameservers должна отображать список IP-адресов серверов имен. Директива searchdomains принимает список доменов и поддоменов, которые нужно найти, если пользователь указывает хост, а не домен. Директива domain устанавливает домен, который должен использоваться для любых неразрешимых запросов, а директива options содержит набор параметров, которые могут быть определены в файле resolv.conf.

Используя директиву resolv_conf, вы должны убедиться, что директива manage-resolv-conf имеет значение true. Если не сделать этого, остальные настройки будут проигнорированы.

#cloud-config
manage-resolv-conf: true
resolv_conf:

nameservers:

- 'first_nameserver'
- 'second_nameserver'

searchdomains:

- first.domain.com
- second.domain.com

domain: domain.com
options:

option1: value1
option2: value2
option3: value3

Запуск произвольных команд

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

Эта директива принимает список элементов для выполнения. Эти элементы могут быть указаны двумя разными способами, что повлияет на их обработку.

Если элемент списка является простой строкой, весь элемент будет передан процессу оболочки sh.

Второй вариант – передать список, каждый элемент которого будет выполнен таким же образом, как и команды процесса execve. Первый элемент будет интерпретироваться как команда или сценарий для запуска, а следующие элементы будут переданы в качестве аргументов для этой команды.

Любой вывод будет записан в стандартный вывод и в файл /var/log/cloud-init-output.log:

#cloud-config
runcmd:

- [ sed, -i, -e, 's/here/there/g', some_file]
- echo "modified some_file"
- [cat, some_file]

Отключение и перезапуск сервера

В некоторых случаях нужно завершить работу или перезагрузить сервер после выполнения других директив. Вы можете сделать это с помощью power_state.

Эта директива имеет четыре опции: delay, timeout, message и mode.

Опция delay указывает, когда произойдет перезапуск или завершение работы. По умолчанию ее значение now, то есть процедура начнется немедленно. Задержка перезагрузки указывается в минутах в формате +<num_of_mins>.

Параметр timeout принимает значение, которое представляет количество секунд ожидания завершения процесса cloud-init до начала обратного отсчета delay.

Поле message позволяет указать сообщение, которое будет отправлено всем пользователям системы. Опция mode задает тип инициируемого события. Это может быть poweroff (чтобы отключить сервер), reboot (чтобы перезапустить сервер) или halt (если система сама должна решить, что лучше сделать, и обычно она выключает машину):

#cloud-config
power_state:

timeout: 120
delay: "+5"
message: Rebooting in five minutes. Please save your work.
mode: reboot

Заключение

Теперь вы знаете некоторые из наиболее распространенных элементов конфигурации, доступных в cloud-config. Некоторые возможности мы не рассматривали в этом руководстве. Среди них настройка управления конфигурацией, настройка дополнительных репозиториев и регистрация внешнего URL-адреса при инициализации сервера.

Дополнительную информацию можно найти в каталоге /usr/share/doc/cloud-init/examples.

Читайте также: Начальная настройка сервера с помощью cloud-config

Tags: