Terraform部署私有子网EC2时user_data经cloud-init执行失败如何解决
问题根因分析
报错核心是私有子网内的EC2实例执行apt update时无法连接公网的Ubuntu软件源,网络不通导致安装失败。
排查思路
- 检查Terraform资源依赖配置
Terraform默认并行创建资源,若未显式配置依赖,EC2实例可能在NAT网关、私有子网路由规则完全生效前就启动并执行cloud-init脚本,此时公网出口尚未就绪,直接导致apt请求超时。不要仅依赖NAT网关资源创建完成,需确保私有子网的路由规则已经配置并关联完成。 - 检查VPC路由配置
- 私有子网关联的路由表是否存在
0.0.0.0/0路由条目,下一跳指向NAT网关 - NAT网关是否部署在公有子网(公有子网路由表需存在
0.0.0.0/0指向互联网网关IGW的路由) - NAT网关是否已成功绑定弹性公网IP(EIP)
- 私有子网关联的路由表是否存在
- 检查访问控制配置
- EC2实例关联的安全组出方向是否允许80、443端口的TCP流量访问
0.0.0.0/0 - 私有子网关联的网络ACL(NACL)出方向允许80、443端口流量,入方向允许临时端口(1024-65535)的返回流量
- EC2实例关联的安全组出方向是否允许80、443端口的TCP流量访问
解决方案
1. 显式配置Terraform资源依赖
在EC2资源中添加depends_on参数,依赖私有子网的公网路由配置完成,示例如下:
resource "aws_instance" "vray_instance" { ami = "ami-00399ec92321828f5" instance_type = "t2.micro" key_name = aws_key_pair.vray_key_pair.key_name vpc_security_group_ids = [aws_security_group.vray_security_group_web.id] subnet_id = aws_subnet.vray_privated_subnet[0].id user_data = file("${path.cwd}/install_el_apache.sh") # 新增依赖,替换为你实际的NAT网关、私有子网路由资源ID depends_on = [ aws_nat_gateway.your_nat_gateway, aws_route.private_subnet_nat_route ] tags = { Name = "Instance Web Server" } }
2. 优化user_data脚本增加重试逻辑
无需硬编码延迟,给apt update增加重试逻辑,适配网络就绪的等待时间,修改install_el_apache.sh内容如下:
#!/bin/bash echo "*** Installing apache2" # 新增重试逻辑,直到apt update成功或重试10次 RETRY_COUNT=0 MAX_RETRY=10 until sudo apt-get update || [ $RETRY_COUNT -eq $MAX_RETRY ] do echo "apt update失败,等待网络就绪,5秒后重试,剩余重试次数:$((MAX_RETRY - RETRY_COUNT))" sleep 5 RETRY_COUNT=$((RETRY_COUNT + 1)) done if [ $RETRY_COUNT -eq $MAX_RETRY ]; then echo "apt update重试多次仍失败,退出安装" exit 1 fi sudo apt-get install -y apache2 sudo systemctl start apache2 sudo systemctl enable apache2 echo "<h1>Web server Task2 with Terraform</h1>" | sudo tee /var/www/html/index.html echo "*** Completed Installing apache2"
内容的提问来源于stack exchange,提问作者Ray Escobar
相关产品推荐
相关产品推荐

