Я создаю AMI на основе Ubuntu 16.04 AMI.
Когда я запускаю экземпляр из своего AMI, я хочу передать сценарий пользовательских данных, который запускается перед запуском службы в AMI.
Похоже, что пользовательские данные запускаются в cloud-final.service
. Если я systemctl status cloud-final
или journalctl -u cloud-final
Я вижу результат выполнения сценария пользовательских данных.
Я попытался настроить свой файл .service для запуска службы после cloud-final.service
[Unit]
Description=My Service
After=network.service
After=cloud-final.service
...
но облачный финал имеет RemainAfterExit=yes
, что означает, что он никогда не завершается, поэтому мой сервис никогда не запускается.
Как настроить AWS Ubuntu для запуска моего сервиса после сценарий пользовательских данных был запущен?
Использовать
[Unit]
…
After=cloud-final.service
…
[Install]
WantedBy=cloud-init.target
Я тоже столкнулся с этим. journalctl
показал, что данные пользователя выполняются после multi-user
и перед целью cloud-init
был достигнут.
<timestamp> <ip_addr> systemd[1]: Reached target Multi-User System.
[snip]
<timestamp> <ip_addr> systemd[1]: Starting Execute cloud user/final scripts...
<timestamp> <ip_addr> user-data[1592]: my user data stuff
[snip]
<timestamp> <ip_addr> systemd[1]: Started Execute cloud user/final scripts.
[snip]
<timestamp> <ip_addr> systemd[1]: Reached target Cloud-init target.
Итак, я подумал, что это нужно / нужно cloud-init
вместо обычного multi-user
цель (которая может быть тем, что было у op), и это просто сработало.
Решение, предложенное vlfig работает. Но, думаю, это можно улучшить.
В моем примере я пытаюсь запустить агент Puppet после завершения cloud-init.
В моем случае мы хотели, чтобы Puppet запускался только после завершения настройки Cloud Init. Для этого нам нужно изменить настройку его systemd
Блок.
Порядок выполнения по умолчанию для интересующих нас сервисов и целей следующий: 1. cloud-init-local.service 2. cloud-init.service 3. cloud-config.target 4. basic.target 5. cloud-config. сервис 6. puppet.service 7. multi-user.target 8. cloud-final.service 9. cloud-init.target
(stag) dki@appbackend-i-0f0d3f6abd8520f12:~$ systemd-analyze --no-pager critical-chain puppet.service
The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.
puppet.service @17.737s
└─basic.target @17.291s
└─paths.target @17.290s
└─resolvconf-pull-resolved.path @17.290s
└─sysinit.target @17.282s
└─cloud-init.service @14.709s +2.572s
└─systemd-networkd-wait-online.service @13.872s +832ms
└─systemd-networkd.service @13.487s +377ms
└─network-pre.target @13.482s
└─cloud-init-local.service @6.983s +6.495s
└─var-lib.mount @11.888s
└─local-fs-pre.target @10.584s
└─keyboard-setup.service @6.506s +4.072s
└─systemd-journald.socket @6.430s
└─system.slice @6.416s
└─-.slice @3.772s
График зависимости:
Граф зависимости сервисов systemd
Заметка: Зеленые стрелки означают After=
а серые стрелки означают Wants=
Имея puppet.service
в /etc/systemd/system/multi-user.target.wants
, systemd
автоматически создает порядок зависимости типа After=puppet.service
в соответствии с https://www.freedesktop.org/software/systemd/man/systemd.target.html#Default%20Dependencies
График зависимости:
Исходный граф зависимостей сервиса Puppet
Заметка: Зеленые стрелки означают After=
а серые стрелки означают Wants=
Как следствие, если мы попытаемся запустить его After=cloud-init.target
, он создает цикл зависимости и вообще не запускается.
[Mon Jul 9 12:49:01 2019] systemd[1]: multi-user.target: Found ordering cycle on puppet.service/start
[Mon Jul 9 12:49:01 2019] systemd[1]: multi-user.target: Found dependency on cloud-init.target/start
[Mon Jul 9 12:49:01 2019] systemd[1]: multi-user.target: Found dependency on cloud-final.service/start
[Mon Jul 9 12:49:01 2019] systemd[1]: multi-user.target: Found dependency on multi-user.target/start
[Mon Jul 9 12:49:01 2019] systemd[1]: multi-user.target: Job puppet.service/start deleted to break ordering cycle starting with multi-user.target/start
Чтобы разорвать этот цикл, нам нужно отключить DefaultDependencies
директива. Таким образом мы можем добавить After=cloud-init.target
к модулю Puppet, чтобы гарантировать, что он ждет завершения Cloud-Init, прежде чем он начнет работать. Обе директивы выполняются путем создания /etc/systemd/system/puppet.service.d/override.conf
файл, который переопределяет исходные конфигурации пакета без изменения его исходного содержимого. Преимущество этого состоит в том, что мы можем обновить пакет, сохранив изменения только тех директив, которые нам действительно нужны.
График зависимости:
График зависимости сервиса Puppet впоследствии
Заметка: Зеленые стрелки означают After=
а серые стрелки означают Wants=
В результате получается следующий порядок выполнения: 1. cloud-init-local.service 2. cloud-init.service 3. cloud-config.target 4. basic.target 5. cloud-config.service 6. multi-user.target 7. cloud-final.service 8. cloud-init.target 9. puppet.service
(sand) dki@supplier-integrations-i-035c65e75762aaabd:~$ systemd-analyze --no-pager critical-chain puppet.service
The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.
puppet.service @43.300s
└─cloud-init.target @43.298s
└─cloud-final.service @33.272s +10.025s
└─multi-user.target @33.246s
└─splunk.service @13.815s +19.429s
└─basic.target @13.463s
└─sockets.target @13.463s
└─docker.socket @13.453s +10ms
└─sysinit.target @13.436s
└─cloud-init.service @10.873s +2.557s
└─systemd-networkd-wait-online.service @9.182s +1.689s
└─systemd-networkd.service @9.034s +143ms
└─network-pre.target @9.032s
└─cloud-init-local.service @854ms +8.177s
└─var-lib.mount @7.587s
└─local-fs-pre.target @1.391s
└─keyboard-setup.service @569ms +822ms
└─systemd-journald.socket @564ms
└─system.slice @564ms
└─-.slice @423ms
Вероятно, вы могли бы сделать так, чтобы сценарий пользовательских данных записал файл, означающий, что он завершен (в конце сценария), а другая служба запустилась бы где-то ближе к концу, скажем, и сначала проследила за файлом. Когда он замечает, что файл создается (или обновляется метка времени, или изменяется содержимое, что угодно), то запускает остальную часть службы и завершается как обычно.
После долгой борьбы и благодаря некоторым подсказкам, найденным в этой ветке, я наконец-то нашел решение, которое, похоже, работает для моих AMI на основе AL2.
Мой вариант использования: у меня есть AMI с уже включенным install.service
который запускает несколько скриптов для точной настройки приложения. Конечный пользователь может использовать aws
инструмент для динамического присоединения некоторых ранее существовавших томов EBS через пользовательские данные при запуске.
Вот полный файл install.service на случай, если он кому-то поможет:
[Unit]
Description=Post launch, pre-installation service
After=cloud-init.target
DefaultDependencies=no
AssertFileIsExecutable=/usr/local/bin/install-script
[Service]
Type=simple
ExecStart=/usr/local/bin/install-script
LimitNOFILE=16384
SuccessExitStatus=0
[Install]
WantedBy=default.target