You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform部署Azure虚拟机时使用旧公网IP导致remote-exec执行异常问题求助

Terraform部署Azure虚拟机时使用旧公网IP导致remote-exec执行异常问题求助

我现在遇到一个Terraform部署Azure虚拟机的棘手问题,想请各位大佬帮忙排查下:

我写了azure.tf用来部署Azure虚拟机,之后通过SSH连接到机器上运行Ansible playbook。但每次执行terraform apply时,remote-exec和local-exec总是会用上之前已销毁虚拟机的旧公网IP,可我在Azure门户里查看新创建的NIC、公网IP和虚拟机,明明都是新分配的正确IP地址。

我的配置细节如下:

  • outputs.tf用来输出公网IP:
output "public_ip_address" {
  value = data.azurerm_public_ip.my_terraform_public_ip.ip_address
}
  • 公网IP的资源和数据块配置:
# Create public IPs
resource "azurerm_public_ip" "my_terraform_public_ip" {
  name                = "testpublicIP"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Dynamic"
}

data "azurerm_public_ip" "my_terraform_public_ip" {
  name                = azurerm_public_ip.my_terraform_public_ip.name
  resource_group_name = azurerm_public_ip.my_terraform_public_ip.resource_group_name
}
  • 虚拟机的provisioner部分:
provisioner "remote-exec" {
  inline = ["echo 'Wait until SSH is ready'"]
  connection {
    type        = "ssh"
    user        = "ubuntu"
    private_key =  file(local.private_key_path_Azure)
    host        = data.azurerm_public_ip.my_terraform_public_ip.ip_address
  }
}

provisioner "local-exec" {
  command = "ansible-playbook  -i ${data.azurerm_public_ip.my_terraform_public_ip.ip_address}, --private-key ${local.private_key_path_Azure} docker.yaml"
}

我实在搞不懂为什么provisioner会执着于旧IP,明明新资源的IP是对的,有没有人能指点一下问题出在哪?


问题原因分析

你这里的核心问题出在多余的data块使用上。Terraform的data块是在**计划阶段(plan)**就会读取资源状态,而不是等到资源实际创建/更新后的应用阶段(apply)。

当你销毁旧虚拟机后重新执行terraform apply,计划阶段时新的公网IP资源还未创建,data块会从Terraform本地状态文件里读取之前旧的公网IP记录,导致后续provisioner直接复用了这个旧值。而Azure门户里显示的是新创建的资源,所以IP是正确的,但Terraform的provisioner用的是计划阶段提前读取的旧数据。

解决方案

直接去掉多余的data块,直接引用公网IP资源的属性即可,不需要通过data间接获取:

  1. 删除这个冗余的data块:
data "azurerm_public_ip" "my_terraform_public_ip" {
  name                = azurerm_public_ip.my_terraform_public_ip.name
  resource_group_name = azurerm_public_ip.my_terraform_public_ip.resource_group_name
}
  1. 修改所有引用公网IP的地方,直接用azurerm_public_ip.my_terraform_public_ip.ip_address:
  • 调整outputs.tf:
output "public_ip_address" {
  value = azurerm_public_ip.my_terraform_public_ip.ip_address
}
  • 修改remote-exec的host配置:
host        = azurerm_public_ip.my_terraform_public_ip.ip_address
  • 修改local-exec的命令:
command = "ansible-playbook  -i ${azurerm_public_ip.my_terraform_public_ip.ip_address}, --private-key ${local.private_key_path_Azure} docker.yaml"

这样修改后,Terraform会在公网IP资源创建完成后,直接引用它的实时属性值,而不是在计划阶段读取旧状态,就能保证provisioner使用的是最新的IP地址了。

另外还有个小细节提醒:你的os_profile里设置的管理员用户名是testadmin,但remote-exec里用的是ubuntu,这里要确保用户名一致,否则可能会出现SSH连接失败的额外问题哦。


备注:内容来源于stack exchange,提问作者brokkosnarf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 13:34:33