我在 AWS CloudFormation 中收到以下错误消息:"Failed to receive X resource signal(s) within the specified duration." 如何解决此错误?
简短描述
当 Amazon Elastic Compute Cloud(Amazon EC2)实例、Auto Scaling 组或 WaitCondition 未在 CreationPolicy 属性指定的时间段内成功从一个或多个实例收到信号时,您会收到此错误消息。
发生以下任何场景时会出现此错误:
- 场景 1:AWS CloudFormation 堆栈的一个或多个实例上未安装 cfn-signal 脚本。
- 场景 2:AWS CloudFormation 模板中存在语法错误或不正确的值。
- 场景 3:CreationPolicy 属性的 Timeout 属性值过低。
- 场景 4:cfn-signal 不是由 Amazon EC2 实例发送的。
**注意:**此错误的问题排查场景仅适用于通过 Linux 实例创建的 AWS CloudFormation 堆栈。这些场景不适用于 Windows 实例。有关更多信息,请参阅如何解决堆栈创建问题。
解决方法
在按照问题排查场景中的步骤执行操作之前,请将 AWS CloudFormation 堆栈的失败时回滚选项设置为否。
场景 1:AWS CloudFormation 堆栈的一个或多个实例上未安装 cfn-signal 脚本
要确认是否已在配置为向 AWS CloudFormation 资源发送信号的实例中安装 cfn-signal 脚本,请完成以下步骤:
1. 使用 SSH 连接到 Linux 实例。
2. 确认已使用以下任一命令安装 cfn-signal 脚本。
要确认 cfn-signal 脚本是否位于您的目录中,请运行以下命令:
$ sudo find / -name cfn-signal
/opt/aws/bin/cfn-signal
/opt/aws/apitools/cfn-init-1.4-30.amzn2/bin/cfn-signal
要确认是否已安装包含 cfn-signal 脚本的 AWS CloudFormation 帮助程序脚本软件包,请运行以下命令:
$ sudo rpm -q aws-cfn-bootstrap
aws-cfn-bootstrap-1.4-30.amzn2.noarch
**重要提示:**前述命令仅适用于使用 RPM Package Manager 的分发。
**注意:**默认情况下,AWS CloudFormation 帮助程序脚本安装在亚马逊云机器镜像(AMI)上。如果未安装 AWS CloudFormation 帮助程序脚本,请参阅 CloudFormation 帮助程序脚本参考,查看安装说明。
场景 2:AWS CloudFormation 模板中存在语法错误或不正确的值
要确认是否已将 UserData 属性配置为向由 CreationPolicy 属性指定的 AWS CloudFormation 资源发送信号,请完成以下步骤:
1. 在代码编辑器中,打开堆栈的 AWS CloudFormation 模板,然后找到 UserData 属性部分。
2. 检查错误,包括语法错误、缺少空格、拼写错误和其他排印错误。
3. 确认堆栈、资源和区域属性值是否正确。
**注意:**如果您使用包含 UserData 属性并调用 cfn-signal 脚本的引导脚本,则应检查引导脚本中是否存在语法错误或不正确的值。
如果选择在 cfn-init 命令键中发送信号,请在 cfn-init 日志中查找有关信号的信息。要搜索 cloud-init 日志或 cfn-init 日志中的错误,请使用 SSH 连接 Amazon EC2 实例。然后,通过在以下日志中搜索关键词“error”或“failure”来查找详细的错误或故障消息。
/var/log/cloud-init-output.log
/var/log/cloud-init.log
/var/log/cfn-init.log
/var/log/cfn-init-cmd.log
/var/log/cfn-wire.log
要解析在任何 /var/log/cfn 或 /var/log/cloud-init 文件中出现“error”或“failure”一词的所有实例,请运行以下命令:
grep -ni 'error\|failure' $(sudo find /var/log -name cfn\* -or -name cloud-init\*)
**注意:**上述命令会返回文件名、行号和错误消息。
场景 3:CreationPolicy 属性的 Timeout 属性值过低
Timeout 属性的值由 CreationPolicy 属性定义。要在 cfn-signal 脚本向 AWS CloudFormation 资源发送信号之前确认该属性值是否足够高,可供任务运行,请完成以下步骤。
重要提示:以下步骤仅在实例未被终止(例如由 Auto Scaling 组终止)时适用。您已将 AWS CloudFormation 堆栈的失败时回滚选项设置为否。此选项意味着没有失败回滚,并且在删除堆栈前无法终止实例。您可以使用 SSH 连接到实例,然后继续以下问题排查步骤。
1. 在代码编辑器中,打开堆栈的 AWS CloudFormation 模板,然后找到 Timeout 属性的值。
**注意:**Timeout 属性的值是指 AWS CloudFormation 的最常等待时间,超过该时间 AWS CloudFormation 将返回错误。
2. 要估计触发 cfn-signal 脚本的时间,请使用 SSH 连接到实例,然后运行以下命令:
less /var/log/cfn-init.log
日志文件显示了向 AWS CloudFormation 资源发送 SUCCESS 信号时的时间戳。请参阅以下示例:
2019-01-11 12:46:40,101 [DEBUG] Signaling resource EC2Instance in stack XXXX with unique ID i-045a536a3dfc8ccad and status SUCCESS
3. 打开 AWS CloudFormation 控制台。
4. 要查看“Failed to receive X resource signal(s) within the specified duration”事件的资源故障时间戳,请选择事件视图。
5. 对于状态原因,请展开状态原因为“Failed to receive X resource signal(s) within the specified duration”的事件行。
6. 比较发送信号时间戳与资源故障时间戳。
**注意:**请注意,此信号是在 Amazon EC2 资源创建失败后发送的。在 Amazon EC2 资源创建之前或创建失败后发送此信号。
场景 4:cfn-signal 不是由 Amazon EC2 实例发送的。
如果您希望从 Amazon EC2 实例之外的任意位置发送信号,可以使用 SignalResource API。
例如,您可以使用 AWS Lambda 函数调用 SignalResource API,然后向 AWS CloudFormation 堆栈发送信号。在这种场景中,请通过 Amazon CloudWatch Logs 检查您的 Lambda 日志。这些日志有助于您理解为何信号没有发送到 AWS CloudFormation 堆栈。