如何等待私有子网中启动的EC2实例的user data执行完成?
我之前也碰到过一模一样的问题——私有子网里的EC2实例没法通过公网访问CloudFormation服务,导致cfn-signal根本发不出信号,Stack直接卡在WaitCondition超时失败。核心原因就是私有子网默认没有出站公网访问能力,而cfn-signal需要和CloudFormation的公共API端点通信才能完成信号传递。
给你几个经过验证的解决方案,你可以根据自己的场景选择:
方案1:配置NAT网关实现出站公网访问
这是最直接的办法,让私有子网里的EC2能通过NAT网关访问公网,这样cfn-signal就能正常和CloudFormation通信了。步骤如下:
- 在你的VPC的公有子网里创建一个NAT网关(记得给它分配弹性IP)
- 更新私有子网的路由表,添加一条默认路由(
0.0.0.0/0)指向这个NAT网关 - 确保EC2实例的安全组允许出站HTTPS(443)流量到公网
优点:配置简单,适用于已经有公有子网的场景;缺点:NAT网关有持续的运行成本,适合长期稳定的环境。
方案2:使用CloudFormation VPC接口端点(推荐)
如果不想走公网,也不想承担NAT网关的成本,这个方案更合适——通过VPC接口端点让EC2在内部网络里访问CloudFormation服务,完全不需要公网。
具体配置步骤:
- 在你的VPC中创建一个Interface类型的VPC端点,服务名称为
com.amazonaws.<你的区域>.cloudformation(比如com.amazonaws.us-east-1.cloudformation) - 把这个端点关联到你的私有子网
- 确保EC2实例的安全组允许出站HTTPS(443)流量到VPC端点的安全组
- 确保VPC端点的安全组允许来自EC2安全组的HTTPS(443)入站流量
CloudFormation模板片段示例:
CloudFormationVPCEndpoint: Type: AWS::EC2::VPCEndpoint Properties: ServiceName: !Sub 'com.amazonaws.${AWS::Region}.cloudformation' VpcId: !Ref YourVPC SecurityGroupIds: - !Ref VPCEndpointSecurityGroup SubnetIds: - !Ref YourPrivateSubnet1 - !Ref YourPrivateSubnet2 PrivateDnsEnabled: true # 开启后EC2可直接用默认CloudFormation域名访问端点,无需额外配置
开启PrivateDnsEnabled后,cfn-signal会自动使用VPC端点,不需要修改任何命令参数,非常方便。
优点:完全内网访问,安全性更高,成本远低于NAT网关;缺点:需要额外配置VPC端点,但一次配置后长期受益。
额外注意事项
- 确保你的EC2实例里安装了
aws-cfn-bootstrap工具(Amazon Linux 2/2023默认预装,Ubuntu等系统需要手动安装,比如sudo apt-get install aws-cfn-bootstrap) - User Data里的
cfn-signal命令要正确指定WaitCondition的Handle URL和Stack名称,示例:
#!/bin/bash # 这里是你的user data执行逻辑,比如安装软件、配置服务 yum install -y nginx systemctl start nginx # 发送信号给CloudFormation WaitCondition /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WaitConditionHandle --region ${AWS::Region}
- 如果用的是Amazon Linux 2023,
cfn-signal的路径是/usr/bin/cfn-signal,注意调整路径。
内容的提问来源于stack exchange,提问作者Surajit Kundu
相关产品推荐
相关产品推荐

