如何用Terraform部署Google VM实例并复制本地代码,正确使用file provisioner
Terraform部署VM并预置启动代码的两种方案
一、简化方案:用Cloud-Init/User-Data直接嵌入代码
主流云厂商(AWS、Azure、GCP)的VM都支持cloud-init,无需额外配置SSH连接,VM启动时自动完成文件写入和代码执行,完美避开私有仓库认证的麻烦。
示例代码(以AWS EC2为例)
resource "aws_instance" "app_vm" { ami = "ami-0c55b159cbfafe1f0" # 替换为你的目标AMI instance_type = "t2.micro" user_data = <<-EOF #cloud-config # 将本地代码内容写入VM指定路径 write_files: - path: /opt/my_app/start_script.sh content: | #!/bin/bash echo "启动预设代码执行中..." # 这里替换为你的实际业务代码逻辑 # 比如:python3 /opt/my_app/main.py permissions: '0755' # 启动时执行脚本 runcmd: - /opt/my_app/start_script.sh EOF }
优势
- 无需额外配置SSH连接,依赖VM原生启动机制
- 代码直接嵌入Terraform配置,无需维护外部仓库或认证信息
- 支持写入多个文件、设置权限,满足基本预置需求
二、正确使用File Provisioner
如果需要复制大量文件或复杂目录结构,file provisioner是合适的选择,核心是配置正确的SSH连接信息。
示例代码(以AWS EC2为例)
resource "aws_instance" "app_vm" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" # 分配公网IP,确保Terraform能访问VM的SSH端口 associate_public_ip_address = true # 引用提前创建好的SSH密钥对 key_name = "my_ssh_key_pair" # 复制本地目录到VM provisioner "file" { source = "./local_app_code/" # 本地要复制的目录(末尾加/表示复制目录内内容) destination = "/opt/my_app/" # VM上的目标路径 connection { type = "ssh" user = "ec2-user" # 根据AMI调整:Ubuntu用ubuntu,CentOS用ec2-user private_key = file("~/.ssh/my_ssh_key.pem") # 本地私钥文件路径 host = self.public_ip # 自动获取VM的公网IP } } # 可选:执行启动脚本 provisioner "remote-exec" { inline = [ "chmod +x /opt/my_app/start_script.sh", "/opt/my_app/start_script.sh" ] connection { type = "ssh" user = "ec2-user" private_key = file("~/.ssh/my_ssh_key.pem") host = self.public_ip } } }
注意事项
- 确保Terraform运行环境能访问VM的22端口(公网IP直接访问,私有网络需配置VPN或堡垒机)
- 本地私钥文件权限需设为
600(Linux/macOS),避免SSH连接报错 - 如果复制单个文件,source直接写文件路径即可,无需末尾加/
- 其他云厂商调整点:
- Azure:connection中用
admin_username和private_key,host用private_ip_address或public_ip_address - GCP:默认用户是
ubuntu,host用self.network_interface.0.access_config.0.nat_ip
- Azure:connection中用
内容的提问来源于stack exchange,提问作者Joe Moore
相关产品推荐
相关产品推荐

