Amazon 的文档包含大量使用cfn-hup
CloudFormation 自动更新实例的示例。有关众多示例之一,请参阅https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Install-CloudWatch-Agent-New-Instances-CloudFormation.html. 这些通常最终指向以下例子这是 cfn-hup 本身的或者这是 CloudWatch 代理。
从后者我们得到一个典型的例子:
01_setupCfnHup:
files:
'/etc/cfn/cfn-hup.conf':
content: !Sub |
[main]
stack=${AWS::StackId}
region=${AWS::Region}
interval=1
mode: '000400'
owner: root
group: root
'/etc/cfn/hooks.d/amazon-cloudwatch-agent-auto-reloader.conf':
content: !Sub |
[cfn-auto-reloader-hook]
triggers=post.update
path=Resources.EC2Instance.Metadata.AWS::CloudFormation::Init.02_config-amazon-cloudwatch-agent
action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --resource EC2Instance --region ${AWS::Region} --configsets UpdateEnvironment
runas=root
mode: '000400'
owner: root
group: root
"/lib/systemd/system/cfn-hup.service":
content: !Sub |
[Unit]
Description=cfn-hup daemon
[Service]
Type=simple
ExecStart=/opt/aws/bin/cfn-hup
Restart=always
[Install]
WantedBy=multi-user.target
commands:
01enable_cfn_hup:
command: !Sub |
systemctl enable cfn-hup.service
02start_cfn_hup:
command: !Sub |
systemctl start cfn-hup.service
这与运行的 UserData 脚本结合使用pip3 install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz
。
使用这些示例,当我更新 CloudFormation 堆栈时,cfn-hup
永远不会触发。我看到了看似无害的行,例如cfn-init
/var/log/cfn-hup.log
2023-07-08 09:49:56,112 [DEBUG] CloudFormation client initialized with endpoint https://cloudformation.eu-west-2.amazonaws.com
2023-07-08 09:49:56,115 [INFO] No umask value specified in config file. Using the default one: 0o22
看起来它运行正常,那么为什么它没有检测到任何堆栈更新?
如果我cfn-hup --no-daemon
从 shell 手动运行,我的更新就会被正确检测到并按cfn-init
预期触发。
答案1
(这大概适用于任何使用 Python 3.8+ 的操作系统,但截至本文撰写时,Ubuntu 是 EC2 上唯一流行的附带 Python 3.8+ 的发行版。)
首先,眼尖的人会注意到对/opt/aws
和有一些混合的引用/usr/local
。事实上,/usr/local
这是安装 AWS 工具的地方,因此对 的引用/opt/aws
需要更新 - 但这并不能解决问题。
问题是守护进程模式下的 cfn-hup 不支持 Ubuntu 22.04 中的 Python3 版本。从 shell 手动运行cfn-hup
(不带)会生成该票证中描述的堆栈跟踪。--no-daemon
解决方案是更改cfn-hup.service
定义以安排其在非守护进程模式下定期运行。例如:
/etc/cfn/cfn-hup.conf:
content: !Sub |
[main]
stack=${AWS::StackId}
region=${AWS::Region}
interval=1
umask=022
mode: '000400'
owner: root
group: root
# Add whatever hooks are desired here
/lib/systemd/system/cfn-hup.service:
content: !Sub |
[Unit]
Description=cfn-hup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/cfn-hup -c /etc/cfn --no-daemon
[Install]
WantedBy=multi-user.target
mode: '000400'
owner: root
group: root
/lib/systemd/system/cfn-hup.timer:
content: !Sub |
[Unit]
Description=Run cfn-hup every minute
[Timer]
OnCalendar=*-*-* *:*:00
[Install]
WantedBy=timers.target
mode: '000400'
owner: root
group: root
commands:
01enable_cfn_hup:
command: systemctl daemon-reload && systemctl enable --now cfn-hup.timer