我的场景
在 CloudFormation 模板中,我有一个 VPC、一个公共子网和一个私有子网。在公共子网中,我有一个实例中的 amazons NAT AMI。在私有子网中,我在内部 LoadBalancer 后面有一个自动缩放组。此自动缩放组有一个 LaunchConfig,用于安装带有演示网页的 httpd。
问题
在此私有子网自动扩展组中启动的 EC2 实例未安装 Web 服务器。这导致我的 ELB 失败并回滚整个 cloudformation 堆栈。但是,我可以在创建后通过 SSH 进入,在那里我可以成功 wget 互联网网页并手动使用 yum install httpd。这通过使 ELB 检查顺利通过来修复我的 cloudFormation 堆栈。/var/log/cloudinit-output.log 表示实例在初始化期间无法解析 amazon yum 存储库。
我感觉这可能是由于在 NAT 实例完全启动并运行之前,在新的 EC2 实例中启动了 LaunchConfig。我尝试将“DependsOn”:“NATInstance”添加到 AutoScaling 组,但这并没有解决问题。
你能帮我吗?
答案1
Cloudwatcher 的回答是正确的,但我想为将来遇到类似问题的人详细说明。
当资源发出信号表示已完成时,CloudFormation 模板中的“DependsOn”属性就会得到满足。默认情况下,我认为这是亚马逊创建资源的时候。在我的示例中,NAT 实例实际上已经创建,这是实例发出信号的时候。但是,实例内的配置和设置尚未完成,因此在其他实例尝试使用 NAT 之前,NAT 仍处于非运行状态。然后其他实例失败,因为它们无法通过 NAT 实例获得互联网连接。
您可以手动覆盖默认信号。这意味着您可以执行操作,然后在完成后发出信号。然后,依赖它的所有其他资源的“DependsOn”属性将正常工作。您可以通过在 EC2 实例中使用一些 amazon 帮助脚本来执行此操作,特别是“cfn-init”和“cfn-signal”。在 EC2 实例(或自动扩展组)的“UserData”属性中,您可以 yum install aws-cfn-bootstrap 来获取脚本(或您正在使用的任何包管理器)。然后,您可以在 UserData 中执行初始化步骤,一旦完成,然后使用 cfn-signal 发出资源已完成的信号。这是我的示例:
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash -xe\n",
"yum update -y aws-cfn-bootstrap\n",
"wget <<URL FOR YOUR INIT BASH SCRIPT HERE>> -O - | bash\n",
"/opt/aws/bin/cfn-init -v ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource <RESOURCE TO SIGNAL HERE> ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
"/opt/aws/bin/cfn-signal -e $? ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource <RESOURCE TO SIGNAL HERE> ",
" --region ", { "Ref" : "AWS::Region" }, "\n"
]]}}
我希望这可以帮助别人。
答案2
关于安全组和允许流量,有几件事需要考虑。但具体到 NAT,请确保在 NAT 启动配置中你没有发出
/opt/aws/bin/cfn-signal
直到您的设置和传递脚本完成。鉴于您“依赖”NAT,因此在 CloudFormation 堆栈收到此信号之前,它不会继续。
[编辑] 如果今天(2015-12-18)之后还有人看到这个,那么你真的应该考虑转移 AWS 提供的 NAT 管理服务。https://aws.amazon.com/about-aws/whats-new/2015/12/introducing-amazon-vpc-nat-gateway-a-managed-nat-service/