Вопрос или проблема
Я хочу запускать некоторые контейнеры через systemd, и у каждого из них есть связанный файл compose, так что должно быть возможно написать только один файл unit для systemd и указать файл compose как имя экземпляра. Таким образом, файл unit будет содержать что-то вроде:
ExecStart=/usr/local/bin/docker-compose -f %i.yaml up
Однако эта аккуратная схема нарушается некоторыми зависимостями между контейнерами. Обычно с такими зависимостями справляются с помощью декларации Requires
в файле unit, но в этой ситуации есть только один файл unit. Вопрос: возможно ли настроить зависимости вне какого-либо файла unit, и если да, то как?
Пример: n-tier-app.yaml зависит от basic-services.yaml
Определите зависимости в файлах drop-in <unit>.d/
для каждой инстанции. Например, если у вас есть шаблон [email protected]
, вы можете дополнительно настроить отдельные экземпляры через [email protected]/foo.conf
и [email protected]/deps.conf
.
Нет возможности определить зависимости с упорядочиванием вне какого-либо файла unit, но необходимость определения их вне какого-либо файла unit является избыточной, учитывая заявленную цель создания зависимостей между экземплярами одного и того же unit.
Зависимости без упорядочивания можно определить аналогично описанному выше, путем создания символьных ссылок на какой-либо unit в <unit>.requires/
или <unit>.wants/
. Это работает с шаблонами, потому что имеет значение только имя символьной ссылки; она может указывать на несуществующий файл (например, на ../[email protected]
), так как systemd вручную разрешает его базу до unit. Однако это ограничено Wants/Requires и поэтому обычно полезно только для добавления зависимости из unit типа .target, который имеет специальную возможность автоматически добавлять After ко любой зависимости – следовательно, <unit>.d/*.conf
предпочтительнее для всех других случаев.
Ответ или решение
В системе systemd управлять зависимостями между контейнерами можно не только посредством фиксации зависимостей внутри самих unit-файлов. Ваша задача развернуть контейнеры с использованием systemd, где каждый контейнер связан с отдельным .compose-файлом. В этом случае, если у каждого контейнера существует зависимость от другого, мы можем воспользоваться возможностями systemd для их описания, избегая изменения основного шаблона unit-файла.
Теория: Управление зависимостями в systemd
systemd предлагает различные способы управления зависимостями между сервисами. Зависимости можно задавать с помощью деклараций Requires
, Wants
, After
и Before
.
- Requires: обозначает жесткую зависимость. Если указанный сервис не запущен или не может быть запущен, то и сам сервис не будет запущен.
- Wants: более гибкая зависимость. systemd попытается запустить указанный сервис, но если он будет недоступен, основной сервис всё равно может быть запущен.
- After/Before: используются для задания порядка запуска сервисов, без указания на необходимость их сосуществования.
Пример: Применение .d/ drop-in файлов
Чтобы управлять зависимостями без прямого редактирования основного unit-файла, можно использовать drop-in файлы, которые размещаются в директориях unit.d/
. Например, в вашем случае, у вас есть шаблонный unit-файл <подразделение>@.service
, через который управляются различные инстанции контейнеров.
Чтобы правильным образом выставить зависимость между инстанциями:
-
Создайте директорию для drop-in файлов для конкретной инстанции сервиса. Пусть это будет
/etc/systemd/system/[email protected]/instance_name.d/
. -
Создайте конфигурационные файлы для каждой инстанции, где можно конкретизировать зависимости. Например,
dependency.conf
может содержать:[Unit] Requires=basic-services@instance_name.service After=basic-services@instance_name.service
-
Добавление дополнительных зависимостей в instance_name.d/:
Дополнительно, для реализации зависимости обязательно наличие symlink в директориюwants/
илиrequires/
. Например:ln -s /etc/systemd/system/basic-services@basic_services.service /etc/systemd/system/[email protected]/instance_name.wants/basic-services@basic_services.service
Применение: Практическая реализация и учет ограничений
Использование drop-in файлов для управления зависимостями позволяет гибко изменять настройки для каждой инстанции без необходимости модификации оригинального шаблонного unit-файла. Это особенно полезно в случаях, когда количество управляемых контейнеров растет, и.к. он позволяет централизовать изменения конфигураций и облегчает их тестирование.
Преимущества такого подхода:
- Гибкость: Возможность изменять настройки для каждой инстанции отдельно.
- Контроль: Управление порядком запуска и точек отказа на уровне systemd.
- Снижение рисков: Позволяет тестировать изменения на одной инстанции, прежде чем применять их массово.
Ограничения и рекомендации:
- Не следует пренебрегать тестированием конфигурации на живой системе. Проведите тесты на полном цикле запуска/остановки контейнеров в тестовом окружении.
- Убедитесь, что все symlink создаются корректно и указывают на существующие файлы, чтобы избежать ошибок поиска units.
Внедрение описанных методов позволит оптимально управлять зависимостями containers и их orchestration, поддерживая чистоту и организованность конфигурационных файлов systemd. Это особенно актуально в сложных деплоях, где наличие и правильная последовательность запуска сервисов критичны для работы всего приложения.