You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS CDK部署Linux EC2实例:重启后cfn-signal执行异常

问题根源

你遇到的问题核心在于Linux和Windows上的CloudFormation Init执行机制差异:Windows的cfn-init在实例重启后会自动恢复执行未完成的Config Set步骤,但Linux的cfn-init是一次性执行的——重启会直接终止当前的cfn-init进程,且重启后不会自动续上之前的流程。

从你的cfn-init.log就能看出来:日志里显示的Running config cfn-signal是重启前执行的,但reboot命令会立即终止所有进程,导致cfn-signal根本没来得及完成发送信号的操作,而重启后没有机制触发它再次执行,最终CloudFormation栈因为收不到信号超时失败。

解决方案

要让Linux实例重启后自动发送cfn-signal,你需要把信号发送逻辑设置为开机自启动任务,而不是依赖Config Set的后续步骤。下面是具体的CDK代码修改方案:

修改后的CDK代码

testInit = ec2.CloudFormationInit.from_config_sets(
    config_sets={ "test_configsets" : ["change_hostname", "reboot"] },
    configs={
        "change_hostname" : ec2.InitConfig([
            # 修改主机名
            ec2.InitCommand.shell_command("> /etc/hostname ; echo testInstance > /etc/hostname", key = "change_hostname"),
            # 创建systemd服务文件,用于开机时发送CFN信号
            ec2.InitFile.from_string(
                file_name="/etc/systemd/system/cfn-signal-on-boot.service",
                content=core.Fn.sub("""
[Unit]
Description=Send CloudFormation success signal after system boot
After=network.target

[Service]
Type=oneshot
ExecStart=/opt/aws/bin/cfn-signal -e 0 --stack ${AWS::StackId} --resource TestInstance --region ${AWS::Region}
RemainAfterExit=true

[Install]
WantedBy=multi-user.target
"""),
                key="cfn-signal-service-file"
            ),
            # 启用该systemd服务,确保开机自动执行
            ec2.InitCommand.shell_command("systemctl enable cfn-signal-on-boot.service", key="enable-signal-service")
        ]),
        "reboot" : ec2.InitConfig([
            ec2.InitCommand.shell_command("reboot", key = "reboot")
        ])
    }
)

方案说明

  1. 移除原有的cfn-signal Config Set:不再依赖Config Set的后续步骤,避免重启前执行信号发送被中断。
  2. 添加systemd自启动服务:
    • 创建一个systemd服务文件,指定在网络就绪后执行cfn-signal命令,确保网络可用后再发送信号
    • 通过systemctl enable设置服务开机自启,保证实例重启后自动触发
  3. 重启实例:修改主机名并配置好自启动任务后,执行重启操作。实例重启后,systemd会自动触发信号发送,CloudFormation就能收到完成信号,栈创建成功。

额外优化建议

  • 如果你觉得systemd配置太繁琐,也可以用crontab的@reboot任务替代:
    ec2.InitCommand.shell_command(core.Fn.sub("echo '@reboot /opt/aws/bin/cfn-signal -e 0 --stack ${AWS::StackId} --resource TestInstance --region ${AWS::Region}' >> /var/spool/cron/root"), key="add-cron-signal")
    
    不过systemd是Linux系统的标准服务管理工具,可靠性更高。
  • 修改主机名时,建议同时执行hostnamectl set-hostname testInstance让主机名即时生效(虽然重启后也会生效,但即时生效能避免一些中间状态问题)。

内容的提问来源于stack exchange,提问作者Sheldon Carter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 14:58:14