我正在构建基于 Ubuntu 16.04 AMI 的 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
...
但是 cloud-final 有RemainAfterExit=yes
,这意味着它永远不会完成,所以我的服务永远不会启动。
如何配置 AWS Ubuntu 来启动我的服务后用户数据脚本已经运行了吗?
答案1
使用
[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 所拥有的一样,它就起作用了。
答案2
提出的解决方案维格有效。但我认为可以改进。
在我的示例中,我尝试在 cloud-init 完成后运行 Puppet 代理。
在我的例子中,我们希望 Puppet 仅在 Cloud Init 完成设置后运行。为了实现这一点,我们需要修改其systemd
单元的设置。
我们感兴趣的服务和目标的默认执行顺序如下:1. cloud-init-local.service 2. cloud-init.service 3. cloud-config.target 4. basic.target 5. cloud-config.service 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
答案3
您可能要做的是让用户数据脚本写入一个文件以表明它已完成(在脚本末尾),并让其他服务在接近末尾的某个地方启动,并让它首先监视文件。当它注意到文件正在创建(或时间戳正在更新,或内容已更改,等等)时,然后启动其余服务并正常退出。
答案4
构建于维格:
我尝试用 来做这件事pm2
。它有一个创建的启动脚本,pm2-ubuntu.service
所以我对其进行了修改。
但我还发现里面还有一个符号链接/etc/systemd/system/multi-user.target.wants
需要移动到/etc/systemd/system/cloud-init.target.wants
。所以可能还有其他类似的阻塞。
希望有所帮助。