Как создать гибкие сервисы для кластера CoreOS с файлами модулей Fleet

Вступление

Установки CoreOS используют ряд инструментов для упрощения кластеризации, а сервисы Docker легко управляются. В то время как + etcd + участвует в соединении отдельных узлов и предоставлении области для глобальных данных, большинство реальных задач управления и администрирования служб включают работу с демоном + fleet +.

В previous гид мы рассмотрели основы использования Команда + fleetctl + для управления сервисами и членами кластера. В этом руководстве мы кратко коснулись файлов модулей, используемых парком для определения сервисов, но это были упрощенные примеры, используемые для предоставления работающего сервиса для изучения + fleetctl +.

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

Предпосылки

Чтобы завершить это руководство, мы предполагаем, что у вас есть кластер CoreOS, настроенный, как описано в нашем https://www.digitalocean.com/community/tutorials/how-to-set-up-a-coreos-cluster-on -digitalocean [руководство по кластеризации]. Это оставит вас с тремя серверами, названными так:

  • coreos-1

  • coreos-2

  • coreos-3

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

Мы также будем считать, что вы прочитали наше руководство по использованию https://www.digitalocean.com/community/tutorials/how-to-use-fleet-and-fleetctl-to-manage-your-coreos-cluster как использовать fleetctl]. Вы должны иметь практические знания + fleetctl +, чтобы вы могли отправлять и использовать эти файлы модулей вместе с кластером.

Когда вы выполните эти требования, перейдите к остальной части руководства.

Разделы и типы файлов блоков

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

В то время как службы являются наиболее распространенным типом модулей, настроенным с помощью CoreOS, на самом деле существуют другие типы модулей, которые можно определить. Это подмножество доступных для обычных файлов модулей + systemd +. Каждый из этих типов определяется типом, используемым в качестве суффикса файла, например + example.service +:

  • * service *: это наиболее распространенный тип файла модуля. Он используется для определения службы или приложения, которое может быть запущено на одной из машин в кластере.

  • * socket *: Определяет детали о сокете или сокетоподобных файлах. К ним относятся сетевые сокеты, сокеты IPC и буферы FIFO. Они используются для вызова сервисов, запускаемых при обнаружении трафика в файле.

  • * устройство *: определяет информацию об устройстве, доступную в дереве устройств udev. Systemd создаст их по мере необходимости на отдельных хостах для устройств ядра на основе правил udev. Они обычно используются для заказа проблем, чтобы убедиться, что устройства доступны, прежде чем пытаться подключить.

  • * mount *: определяет информацию о точке монтирования для устройства. Они названы в честь точек монтирования, на которые они ссылаются, с косыми чертами, замененными черточками.

  • * automount *: Определяет точку автомонтирования. Они следуют тем же правилам именования, что и модули монтирования, и должны сопровождаться соответствующим блоком монтирования. Они используются для описания по требованию и параллельного монтажа.

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

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

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

Единичные файлы - это простые текстовые файлы, заканчивающиеся точкой и одним из приведенных выше суффиксов. Внутри они организованы по разделам. Для + fleet + большинство файлов модулей будет иметь следующий общий формат:

[Unit]



[Service]




[X-Fleet]

Заголовки разделов и все остальное в файле модуля чувствительны к регистру. Секция + [Unit] + используется для определения общей информации о юните. Опции, которые являются общими для всех типов юнитов, обычно размещаются здесь.

Секция + [Service] + используется для установки директив, специфичных для сервисных единиц. Большинство (но не все) из указанных выше типов юнитов имеют связанные разделы для информации, специфичной для юнитов. Посетите generic systemd файл руководства пользователя systemd для ссылок на различные типы модулей, чтобы увидеть больше информации.

Секция + [X-Fleet] + используется для установки требований к планированию для устройства для использования с + fleet +. Используя этот раздел, вы можете требовать, чтобы выполнялись определенные условия, чтобы планировать блок на хосте.

Строительство Главного Сервиса

Для этого раздела мы начнем с варианта файла модуля, описанного в нашем https://www.digitalocean.com/community/tutorials/how-to-create-and-run-a-service-on-a-coreos -cluster [базовое руководство по запуску служб на CoreOS]. Файл называется + apache.1.service + и будет выглядеть так:

[Unit]
Description=Apache web server service

# Requirements
Requires=etcd.service
Requires=docker.service
Requires=apache-discovery.1.service

# Dependency ordering
After=etcd.service
After=docker.service
Before=apache-discovery.1.service

[Service]
# Let processes take awhile to start up (for first run Docker containers)
TimeoutStartSec=0

# Change killmode from "control-group" to "none" to let Docker remove
# work correctly.
KillMode=none

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Pre-start and Start
## Directives with "=-" are allowed to fail without consequence
ExecStartPre=-/usr/bin/docker kill apache
ExecStartPre=-/usr/bin/docker rm apache
ExecStartPre=/usr/bin/docker pull /apache
ExecStart=/usr/bin/docker run --name apache -p ${COREOS_PUBLIC_IPV4}:80:80 \
/apache /usr/sbin/apache2ctl -D FOREGROUND

# Stop
ExecStop=/usr/bin/docker stop apache

[X-Fleet]
# Don't schedule on the same machine as other Apache instances
X-Conflicts=apache.*.service

Начнем с раздела + [Unit] +. Здесь основная идея состоит в том, чтобы описать единицу и установить информацию о зависимости. Начнем с набора требований. Мы использовали жесткие требования для этого примера. Если бы мы хотели, чтобы + fleet + пытался запустить дополнительные сервисы, но не останавливался при сбое, мы могли бы вместо этого использовать директиву + Wants +.

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

Для раздела + [Service] + мы отключаем время ожидания запуска службы. При первом запуске службы на хосте контейнер должен быть извлечен из реестра Docker, который учитывает время ожидания запуска. По умолчанию это значение составляет 90 секунд, что, как правило, будет достаточно времени, но для более сложных контейнеров это может занять больше времени.

Затем мы устанавливаем killMode в none. Это используется потому, что обычный режим уничтожения (control-group) иногда приводит к сбою команд удаления контейнера (особенно при попытке опции Docker + - rm +). Это может вызвать проблемы при следующем перезапуске.

Мы извлекаем файл среды, чтобы у нас был доступ к + COREOS_PUBLIC_IPV4 + и, если во время создания была включена частная сеть, к переменным среды + COREOS_PRIVATE_IPV4 +. Они очень полезны для настройки контейнеров Docker для использования информации их конкретного хоста.

Строки + ExecStartPre используются для снятия остатков с предыдущих запусков, чтобы убедиться, что среда выполнения чистая. Мы используем + = - + в первых двух из них, чтобы указать, что + systemd + должен игнорировать и продолжать, если эти команды не выполняются. Из-за этого Docker попытается уничтожить и удалить предыдущие контейнеры, но не будет беспокоиться, если не сможет их найти. Последний предварительный запуск используется для обеспечения запуска самой последней версии контейнера.

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

Раздел + [X-Fleet] + содержит простое условие, заставляющее + fleet + планировать службу на машине, на которой еще не запущена другая служба Apache. Это простой способ сделать службу высокой доступности, заставляя дублированные службы запускаться на разных компьютерах.

Основные выносы для строительства основных услуг

В приведенном выше примере мы рассмотрели довольно простую конфигурацию. Однако мы можем извлечь из этого много уроков, которые помогут нам в создании сервисов в целом.

Некоторое поведение, которое следует учитывать при создании основного сервиса:

  • * Отдельная логика для зависимостей и упорядочения *: Разметьте свои зависимости с помощью директив + Требуется = + или + Wants = + в зависимости от того, должен ли строящийся вами модуль потерпеть неудачу, если зависимость не может быть выполнена. Разделяйте порядок с помощью отдельных строк + After = + и + Before = +, чтобы вы могли легко настроить, если требования изменятся. Отделение списка зависимостей от упорядочения может помочь в отладке в случае проблем с зависимостями.

  • * Обработка регистрации службы с помощью отдельного процесса *: Ваша служба должна быть зарегистрирована с помощью + etcd +, чтобы воспользоваться преимуществами обнаружения служб и динамических функций конфигурации, которые это позволяет. However, это должно быть обработано отдельным контейнером «sidekick», чтобы сохранить логику отдельно. Это позволит вам более точно сообщать о состоянии службы с точки зрения внешней стороны, а это необходимо для других компонентов.

  • * Знайте о возможности истечения времени ожидания вашего сервиса *: рассмотрите возможность корректировки директивы + TimeoutStartSec +, чтобы обеспечить более длительное время запуска. Установка этого значения в «0» отключит время ожидания запуска. Это часто необходимо, потому что бывают ситуации, когда Docker должен получить изображение (при первом запуске или при обнаружении обновлений), что может значительно увеличить время инициализации службы.

  • * Настройте KillMode, если ваша служба не останавливается полностью *: Помните о опции + KillMode +, если ваши службы или контейнеры, кажется, останавливаются нечисто. Установка этого значения в «none» может иногда решить проблемы с вашими контейнерами, не удаляемыми после остановки. Это особенно важно, когда вы называете свои контейнеры, так как Docker не сможет работать, если контейнер с тем же именем был оставлен после предыдущего запуска. Посмотрите documentation на KillMode для получения дополнительной информации

  • * Очистка среды перед запуском *: В связи с вышеупомянутым пунктом обязательно очищайте предыдущие контейнеры Docker при каждом запуске. Не следует предполагать, что предыдущий запуск службы завершился, как ожидалось. Эти строки очистки должны использовать спецификатор + = - +, чтобы позволить им молча завершаться ошибкой, если очистка не требуется. Хотя вы должны обычно останавливать контейнеры с помощью + docker stop +, вы, вероятно, должны использовать + docker kill + во время очистки.

  • * Получение и использование информации, специфичной для хоста, для переносимости службы. * Если вам необходимо привязать службу к определенному сетевому интерфейсу, извлеките файл + / etc / environment +, чтобы получить доступ к + COREOS_PUBLIC_IPV4 + и, если настроено, , + COREOS_PRIVATE_IPV4 +. Если вам нужно знать имя хоста машины, на которой работает ваш сервис, используйте системный спецификатор +% H +. Чтобы узнать больше о возможных спецификаторах, ознакомьтесь с systemd документами спецификаторов. В разделе + [X-Fleet] + будут работать только спецификаторы +% n +, +% N +, +% i + и +% p +.

Создание службы анонса Sidekick

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

Этот файл, как было указано в файле основного модуля, называется + apache-discovery.1.service + и выглядит так:

[Unit]
Description=Apache web server etcd registration

# Requirements
Requires=etcd.service
Requires=apache.1.service

# Dependency ordering and binding
After=etcd.service
After=apache.1.service
BindsTo=apache.1.service

[Service]

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Start
## Test whether service is accessible and then register useful information
ExecStart=/bin/bash -c '\
 while true; do \
   curl -f ${COREOS_PUBLIC_IPV4}:80; \
   if [ $? -eq 0 ]; then \
     etcdctl set /services/apache/${COREOS_PUBLIC_IPV4} \'{"host": "%H", "ipv4_addr": ${COREOS_PUBLIC_IPV4}, "port": 80}\' --ttl 30; \
   else \
     etcdctl rm /services/apache/${COREOS_PUBLIC_IPV4}; \
   fi; \
   sleep 20; \
 done'

# Stop
ExecStop=/usr/bin/etcdctl rm /services/apache/${COREOS_PUBLIC_IPV4}

[X-Fleet]
# Schedule on the same machine as the associated Apache service
X-ConditionMachineOf=apache.1.service

Мы запускаем сервис sidekick почти так же, как и основной сервис. Мы опишем назначение модуля, прежде чем перейти к информации о зависимостях и логике упорядочения.

Первым новым элементом здесь является директива + BindsTo = +. Эта директива заставляет данное устройство следовать командам запуска, останова и перезапуска, отправляемым указанному устройству. По сути, это означает, что мы можем управлять обоими этими подразделениями, управляя основным модулем, как только оба загружены в + fleet +. Это односторонний механизм, поэтому управление подручным не повлияет на основной блок.

Для раздела + [Service] + мы снова получаем файл + / etc / environment +, потому что нам нужны переменные, которые он содержит. Директива + ExecStart = + в данном случае представляет собой короткий скрипт + bash +. Он пытается подключиться к основным службам, используя интерфейс и порт, который был выставлен.

Если соединение установлено успешно, команда + etcdctl + используется для установки ключа на общедоступный IP-адрес хост-машины в + / services / apache + в + etcd +. Значением этого является объект JSON, содержащий информацию о сервисе. Срок действия ключа истекает через 30 секунд, поэтому, если устройство неожиданно выйдет из строя, устаревшая служебная информация не останется в + etcd +. В случае сбоя соединения ключ удаляется немедленно, поскольку невозможно проверить доступность службы.

Этот цикл включает в себя 20-секундную команду сна. Это означает, что каждые 20 секунд (до 30-секундного тайм-аута клавиши «+ etcd +») данный аппарат повторно проверяет наличие основного блока и сбрасывает ключ. Это в основном обновляет TTL на ключе, так что он будет считаться действительным еще 30 секунд.

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

Для раздела + [X-Fleet] + мы должны убедиться, что этот модуль запущен на том же сервере, что и основной модуль. Хотя это не позволяет устройству сообщать о доступности службы удаленным машинам, важно, чтобы директива + BindsTo = + работала правильно.

Основные выносы для создания сервисов Sidekick

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

  • * Проверьте фактическую доступность основного блока *: важно действительно проверить состояние основного блока. Не думайте, что основной блок доступен только потому, что был инициализирован помощник. Это зависит от дизайна и функциональности основного блока, но чем надежнее ваш чек, тем более вероятным будет ваше состояние регистрации. Проверка может быть любой, что имеет смысл для устройства, от проверки конечной точки + / health до попытки подключиться к базе данных с клиентом.

  • * Зацикливайте логику регистрации для регулярной повторной проверки *: проверка доступности службы при запуске важна, но также важно регулярно проверять ее. Это может отловить случаи непредвиденных сбоев службы, особенно если они как-то приводят к остановке контейнера. Пауза между циклами должна быть скорректирована в соответствии с вашими потребностями путем сопоставления важности быстрого обнаружения с дополнительной нагрузкой на ваш основной блок.

  • * Используйте флаг TTL при регистрации в etcd для автоматической отмены регистрации при сбоях *: Неожиданные сбои устройства-помощника могут привести к устаревшей информации об обнаружении в + etcd +. Чтобы избежать конфликтов между зарегистрированным и фактическим состоянием ваших услуг, вам следует дать тайм-аутам свои ключи. С помощью приведенной выше конструкции зацикливания вы можете обновить каждый ключ до истечения времени ожидания, чтобы убедиться, что срок действия ключа никогда не истечет, пока выполняется помощник. Интервал ожидания в вашем цикле должен быть немного меньше, чем интервал ожидания, чтобы обеспечить правильную работу этой функции.

  • * Регистрируйте полезную информацию в etcd, а не просто в качестве подтверждения *: Во время вашей первой итерации бокового удара вас может заинтересовать только точная регистрация в + etcd +, когда модуль запущен. Однако это упущенная возможность предоставить много полезной информации для использования другими службами. Хотя эта информация может и не понадобиться сейчас, она станет более полезной, когда вы создадите другие компоненты с возможностью чтения значений из + etcd + для их собственных конфигураций. Сервис + etcd + - это глобальное хранилище значений ключей, поэтому не забудьте использовать его, предоставляя ключевую информацию. Хранение деталей в объектах JSON - это хороший способ передать несколько частей информации.

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

Флот-специфические соображения

Хотя файлы модулей + fleet + по большей части ничем не отличаются от обычных файлов модулей + + systemd +, существуют некоторые дополнительные возможности и подводные камни.

Наиболее очевидным отличием является добавление раздела под названием + [X-Fleet] +, который можно использовать для указания + fleet + о том, как принимать решения о планировании. Доступные варианты:

  • * X-ConditionMachineID *: Это можно использовать для указания точного компьютера для загрузки устройства. Предоставленное значение является полным идентификатором машины. Это значение можно получить из отдельного члена кластера, изучив файл + / etc / machine-id +, или через + fleetctl +, введя команду + list-machines -l +. Требуется полная строка идентификатора. Это может потребоваться, если вы используете базу данных с каталогом данных, который хранится на определенном компьютере. Если у вас нет особых причин использовать это, старайтесь избегать этого, потому что это снижает гибкость устройства.

  • * X-ConditionMachineOf *: эту директиву можно использовать для планирования этого устройства на том же компьютере, на котором загружено указанное устройство. Это полезно для юнитов-помощников или для объединения связанных юнитов.

  • * X-Conflicts *: это противоположно приведенному выше объявлению, так как оно указывает файлы модулей, которые не могут быть запланированы этим модулем. Это полезно для простой настройки высокой доступности путем запуска нескольких версий одной и той же службы, каждая на разных компьютерах.

  • * X-ConditionMachineMetadata *: используется для указания требований к планированию на основе метаданных доступных компьютеров. В столбце «METADATA» вывода + fleetctl list-machines + вы можете увидеть метаданные, которые были установлены для каждого хоста. Чтобы установить метаданные, передайте их в файл + cloud-config + при инициализации экземпляра сервера.

  • * Global *: это специальная директива, которая принимает логический аргумент, указывающий, должно ли это быть запланировано на всех машинах в кластере. Только условные метаданные могут использоваться вместе с этой директивой.

Эти дополнительные директивы дают администратору большую гибкость и мощь в определении того, как службы должны работать на доступных машинах. Они оцениваются перед передачей их экземпляру + systemd + конкретной машины на этапе + fleetctl load +.

Это подводит нас к следующему моменту, о котором следует помнить при работе с соответствующими подразделениями в + fleet +. Утилита + fleetctl + не оценивает требования зависимостей вне раздела + [X-Fleet] + файла модуля. Это приводит к некоторым интересным проблемам при работе с сопутствующими блоками в + fleet +.

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

Таким образом, если у вас есть как основной, так и дополнительный блок, отправленный, но не загруженный, в + fleet +, введите + fleetctl start main.service +, а затем попытайтесь запустить модуль + main.service +. Тем не менее, поскольку модуль + sidekick.service + еще не загружен и поскольку + fleetctl + не будет оценивать информацию о зависимостях, чтобы вывести модули зависимости через процесс загрузки и запуска, модуль + main.service + завершится ошибкой , Это связано с тем, что после того, как машинный экземпляр + systemd + обработает модуль + main.service +, он не сможет найти + sidekick.service +, когда it оценивает зависимости. Модуль + sidekick.service + никогда не загружался на машину.

Чтобы избежать этой ситуации при работе с сопутствующими блоками, вы можете одновременно запускать сервисы вручную, не полагаясь на директиву + BindsTo = +, переводящую помощника в рабочее состояние:

fleetctl start main.service sidekick.service

Другой вариант заключается в том, чтобы убедиться, что блок помощника загружен, по крайней мере, при работе основного блока. На этапе загрузки выбирается машина, и файл модуля передается в локальный экземпляр + systemd +. Это гарантирует, что зависимости удовлетворены, и что директива + BindsTo = + сможет правильно выполняться для вызова второго модуля:

fleetctl load main.service sidekick.service
fleetctl start main.service

Имейте это в виду, если ваши связанные юниты не реагируют правильно на ваши команды + fleetctl +.

Экземпляры и шаблоны

Одна из самых мощных концепций при работе с + fleet + - это шаблоны модулей.

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

Файлы шаблонов могут быть идентифицированы с помощью + @ + в их имени файла. В то время как обычный сервис принимает эту форму:

.service

Файл шаблона может выглядеть так:

@.service

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

@.service

Имя базового блока можно получить из файла модуля с помощью спецификатора +% p +. Аналогично, к данному идентификатору экземпляра можно получить доступ с помощью +% i +.

Файл основного блока как шаблон

Это означает, что вместо создания файла основного модуля с именем + apache.1.service + с содержимым, которое мы видели ранее, вы можете создать шаблон с именем + apache @ .service +, который выглядит следующим образом:

[Unit]
Description=Apache web server service on port %i

# Requirements
Requires=etcd.service
Requires=docker.service
Requires=apache-discovery@%i.service

# Dependency ordering
After=etcd.service
After=docker.service
Before=apache-discovery@%i.service

[Service]
# Let processes take awhile to start up (for first run Docker containers)
TimeoutStartSec=0

# Change killmode from "control-group" to "none" to let Docker remove
# work correctly.
KillMode=none

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Pre-start and Start
## Directives with "=-" are allowed to fail without consequence
ExecStartPre=-/usr/bin/docker kill apache.%i
ExecStartPre=-/usr/bin/docker rm apache.%i
ExecStartPre=/usr/bin/docker pull /apache
ExecStart=/usr/bin/docker run --name apache.%i -p ${COREOS_PUBLIC_IPV4}:%i:80 \
/apache /usr/sbin/apache2ctl -D FOREGROUND

# Stop
ExecStop=/usr/bin/docker stop apache.%i

[X-Fleet]
# Don't schedule on the same machine as other Apache instances
X-Conflicts=apache@*.service

Как видите, мы изменили зависимость + apache-discovery.1.service +, чтобы она была + apache-discovery @% i.service +. Это будет означать, что если у нас есть экземпляр этого модульного файла с именем + apache @ 8888.service +, для этого потребуется помощник с именем + apache-discovery @ 8888.service +. +% I + был заменен идентификатором экземпляра. В этом случае мы используем идентификатор для хранения динамической информации о том, как работает наш сервис, в частности порт, на котором будет доступен сервер Apache.

Чтобы заставить это работать, мы меняем параметр + docker run +, который выставляет порты контейнера на порт хоста. В файле статического модуля мы использовали параметр «+ $ {COREOS_PUBLIC_IPV4}: 80: 80 », который отображал порт 80 контейнера на порт 80 хоста в общедоступном интерфейсе IPv4. В этом файле шаблона мы заменили это на ` $ {COREOS_PUBLIC_IPV4}:% i: 80 +`, так как мы используем идентификатор экземпляра, чтобы сообщить нам, какой порт использовать. Умный выбор идентификатора экземпляра может означать большую гибкость в вашем файле шаблона.

Само имя Docker также было изменено, чтобы оно также использовало уникальное имя контейнера на основе идентификатора экземпляра. Помните, что контейнеры Docker не могут использовать символ + @ +, поэтому нам пришлось выбрать другое имя из файла модуля. Мы модифицируем все директивы, которые работают с контейнером Docker.

В разделе + [X-Fleet] + мы также изменили информацию о расписании, чтобы распознавать эти экземпляры вместо статического типа, который мы использовали ранее.

Блок «Помощник» как шаблон

Мы можем выполнить аналогичную процедуру, чтобы адаптировать наш модуль для работы с шаблонами.

Наш новый блок сообщника будет называться + apache-discovery @ .service + и будет выглядеть так:

[Unit]
Description=Apache web server on port %i etcd registration

# Requirements
Requires=etcd.service
Requires=apache@%i.service

# Dependency ordering and binding
After=etcd.service
After=apache@%i.service
BindsTo=apache@%i.service

[Service]

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Start
## Test whether service is accessible and then register useful information
ExecStart=/bin/bash -c '\
 while true; do \
   curl -f ${COREOS_PUBLIC_IPV4}:%i; \
   if [ $? -eq 0 ]; then \
     etcdctl set /services/apache/${COREOS_PUBLIC_IPV4} \'{"host": "%H", "ipv4_addr": ${COREOS_PUBLIC_IPV4}, "port": %i}\' --ttl 30; \
   else \
     etcdctl rm /services/apache/${COREOS_PUBLIC_IPV4}; \
   fi; \
   sleep 20; \
 done'

# Stop
ExecStop=/usr/bin/etcdctl rm /services/apache/${COREOS_PUBLIC_IPV4}

[X-Fleet]
# Schedule on the same machine as the associated Apache service
X-ConditionMachineOf=apache@%i.service

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

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

Мы также изменяем регистрируемый «порт» на «+ etcd », чтобы он использовал тот же идентификатор экземпляра. С этим изменением данные JSON, устанавливаемые в ` etcd +`, являются полностью динамическими. Он выберет имя хоста, IP-адрес и порт, на котором запущена служба.

Наконец, мы снова изменим условие в разделе + [X-Fleet] +. Мы должны убедиться, что этот процесс запущен на той же машине, что и экземпляр основного блока.

Создание единиц из шаблонов

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

И + fleet +, и + systemd + могут обрабатывать символические ссылки, что дает нам возможность создавать ссылки с полными идентификаторами экземпляров на файлы шаблона, например:

Это создаст две ссылки, называемые + apache @ 8888.service + и + apache-discovery @ 8888.service +. Каждый из них имеет всю информацию, необходимую для + fleet + и + systemd + для запуска этих юнитов. Однако они обращены к шаблонам, чтобы мы могли вносить любые необходимые изменения в одном месте.

Затем мы можем отправить, загрузить или запустить эти сервисы с помощью + fleetctl + следующим образом:

Если вы не хотите создавать символические ссылки для определения ваших экземпляров, другой вариант - отправить сами шаблоны в + fleetctl +, например так:

Вы можете создавать экземпляры модулей из этих шаблонов прямо из + fleetctl +, просто назначая идентификаторы экземпляров во время выполнения. Например, вы можете запустить тот же сервис, набрав:

Это устраняет необходимость в символических ссылках. Некоторые администраторы предпочитают механизм связывания, поскольку это означает, что у вас есть файлы экземпляров, доступные в любое время. Он также позволяет вам передавать каталог в + fleetctl +, чтобы все запускалось сразу.

Например, в вашем рабочем каталоге у вас может быть подкаталог с именем «+ templates » для ваших файлов шаблонов и подкаталог с именем « instances » для экземпляров связанных версий. Вы могли бы даже иметь один с именем ` static +` для не шаблонных модулей. Вы можете сделать это так:

mkdir templates instances static

Затем вы можете переместить ваши статические файлы в + static, а ваши файлы шаблонов в` + templates`:

mv apache.1.service apache-discovery.1.service static
mv [email protected] [email protected] templates

Отсюда вы можете создавать ссылки на экземпляры, которые вам нужны. Давайте запустим наш сервис на портах + 5555 +, + 6666 + и + 7777 +:

Затем вы можете запустить все свои экземпляры одновременно, набрав что-то вроде:

cd ..
fleetctl start instances/*

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

Заключение

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

В later guide мы расскажем, как настроить ваши контейнеры для использования информации, которую вы регистрируете с помощью + etcd +. Это может помочь вашим службам получить практические знания о фактической среде развертывания, чтобы передавать запросы в соответствующие контейнеры в серверной части.

Related