Поиск по сайту:

Введение в сценарии Cloud-Config


Введение

Программа cloud-init, доступная в последних дистрибутивах (только Ubuntu 14.04 и CentOS 7 на момент написания этой статьи), может потреблять и выполнять данные из user-data поле службы метаданных DigitalOcean. Этот процесс ведет себя по-разному в зависимости от формата информации, которую он находит. Одним из самых популярных форматов скриптов в user-data является формат файла cloud-config.

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

Общая информация о Cloud-Config

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

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

YAML-форматирование

Файл написан с использованием формата сериализации данных 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 это, между прочим, указывает на то, что мы определяем только одного пользователя.

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

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

К настоящему моменту вы уже должны иметь практические знания формата YAML и чувствовать себя комфортно, работая с информацией, используя правила, которые мы обсуждали выше.

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

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

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

Общий формат пользовательских определений:

#cloud-config
users:
  - first_user_parameter
    first_user_parameter
    
  - second_user_parameter
    second_user_parameter
    second_user_parameter
    second_user_parameter

Каждый новый пользователь должен начинаться с дефиса. Каждый пользователь определяет параметры в парах ключ-значение. Для определения доступны следующие ключи:

  • имя: имя пользователя учетной записи.
  • primary-group: основная группа пользователя. По умолчанию это будет созданная группа, соответствующая имени пользователя. Любая указанная здесь группа должна уже существовать или должна быть явно создана (мы обсудим это позже в этом разделе).
  • группы: здесь могут быть перечислены любые дополнительные группы, разделенные запятыми.
  • gecos: поле для дополнительной информации о пользователе.
  • shell: оболочка, которая должна быть установлена для пользователя. Если вы не установите этот параметр, будет использоваться самая простая оболочка sh.
  • expiredate: дата истечения срока действия учетной записи в формате ГГГГ-ММ-ДД.
  • sudo: строка sudo, используемая, если вы хотите определить привилегии sudo без поля имени пользователя.
  • lock-passwd: по умолчанию установлено значение \True. Установите значение \False, чтобы пользователи могли входить в систему с паролем.
  • passwd: хешированный пароль для учетной записи.
  • ssh-authorized-keys: список полных открытых ключей SSH, которые следует добавить в файл authorized_keys этого пользователя в его каталоге .ssh.
  • неактивный: логическое значение, которое сделает учетную запись неактивной.
  • система: если \True, эта учетная запись будет системной без домашнего каталога.
  • homedir: используется для переопределения /home/ по умолчанию, который создается и устанавливается в противном случае.
  • ssh-import-id: идентификатор SSH для импорта из LaunchPad.
  • selinux-user: это можно использовать для установки пользователя SELinux, который должен использоваться для входа в эту учетную запись.
  • no-create-home: установите значение \True, чтобы не создавать каталог /home/ для пользователя.
  • 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 — это логическое значение, которое определяет, нужно ли менять пароль при первой загрузке или нет. По умолчанию это \Истина.

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

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

Для записи файлов на диск следует использовать директиву write_files.

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

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

Доступные ключи для настройки элемента write_files:

  • путь: абсолютный путь к месту в файловой системе, куда должен быть записан файл.
  • content: содержимое, которое должно быть помещено в файл. Для многострочного ввода вы должны начать блок, используя символ вертикальной черты (|) в строке \content, за которым следует блок с отступом, содержащий содержимое. Двоичные файлы должны включать \!!binary и пробел перед к вертикальной черте.
  • владелец: учетная запись пользователя и группа, которым должно быть предоставлено право владения файлом. Они должны быть указаны в формате \имя пользователя:группа.
  • разрешения: восьмеричный набор разрешений, которые должны быть предоставлены для этого файла.
  • кодировка: необязательная спецификация кодировки для файла. Это может быть \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.

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

Для управления пакетами необходимо помнить о нескольких связанных настройках и директивах.

Чтобы обновить базу данных apt в дистрибутивах на основе Debian, вы должны установить для директивы package_update значение \true. Это синоним вызова 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 для учетных записей пользователей и демона SSH.

Вы можете управлять ключами SSH в директиве users, но вы также можете указать их в специальном разделе ssh_authorized_keys. Они будут добавлены в файл author_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.

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

#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, который представляет собой список, каждый из которых содержит доверенный сертификат CA:

#cloud-config
ca-certs:
  remove-defaults: true
  trusted:
    - |
      -----BEGIN CERTIFICATE-----
      your_CA_cert
      -----END CERTIFICATE-----

Настройте resolv.conf для использования определенных DNS-серверов.

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

В соответствии с директивой resolv_conf вы можете управлять настройками с помощью серверов имен, searchdomains, domain и . параметры элементы.

Директива 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 принимает безразмерное значение, которое представляет собой количество секунд ожидания завершения cloud-init перед запуском обратного отсчета delay.

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

#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, вы можете следовать нашему руководству по использованию cloud-config для выполнения базовой настройки сервера здесь.