Terraform - Azure 上的静态 IP 地址

时间:2021-03-17 17:38:37

标签: azure ansible terraform terraform-provider-azure

我们需要为通过 terraform 部署在 Azure 中的 vm 配置静态私有 ip。原因是我们需要通过 ansible 管道在 Ansible 中使用这些。

我在这里找到的一个解决方案是先创建一个具有“动态”地址的 nic,然后在 Terraform 的下一步中将其转换为“静态”IP。

# Create network interfaces with Private IP's
resource "azurerm_network_interface" "nic" {
  for_each = { for vm in var.vms : vm.hostname => vm }
  name                = "${each.value.hostname}-NIC"
  location            = var.network_location
  resource_group_name = var.vm_resource_group
  ip_configuration {
    name                          = "monitoringConfg"
    subnet_id                     = data.azurerm_subnet.vm_subnet.id
    private_ip_address_allocation = "dynamic"
  }
  tags = each.value.extra_tag
}

#Convert Dynamic Private IP's to Static
resource "azurerm_network_interface" "staticnic" {
  for_each = { for vm in var.vms : vm.hostname => vm }
  name                = "${each.value.hostname}-NIC"
  location            = var.network_location
  resource_group_name = var.vm_resource_group
  ip_configuration {
    name                          = "monitoringConfg"
    subnet_id                     = data.azurerm_subnet.vm_subnet.id
    private_ip_address_allocation = "static"
    private_ip_address            = azurerm_network_interface.nic[each.key].private_ip_address    
  }
  tags = each.value.extra_tag

但是当我运行这个时,我收到以下错误:

ID 为“/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/xxxxxxxxxxxxxxxxxx/providers/Microsoft.Network/networkInterfaces/xxxxxxxxxxxxxxxxxxx-NIC”的资源已经存在 - 将通过 Terraform 进行管理资源需要进口到国家。有关详细信息,请参阅“azurerm_network_interface”的资源文档。 在 ../../modules/main.tf 第 58 行,在资源“azurerm_network_interface”“staticnic”中: 58:资源“azurerm_network_interface”“静态”{

有没有人知道我做错了什么或有更好的方法来处理这个问题?

亲切的问候, RB

2 个答案:

答案 0 :(得分:2)

在网络接口连接到正在运行的虚拟机(或其他资源)之前,Azure 不会分配动态 IP 地址,请参阅 this。所以我认为我们不能在创建VM之前将动态IP转换为静态IP,因为IP地址暂时不存在。

相反,我们可以通过在该子网范围内分配一些 IP 地址,将一些静态 IP 地址直接关联到 Azure VM。阅读private IP分配方法。

<块引用>

Azure 保留每个子网地址范围中的前四个地址。 地址不能分配给资源。例如,如果 子网的地址范围是 10.0.0.0/16,地址 10.0.0.0-10.0.0.3 和 10.0.255.255 不可用。

例如,您可以参考此模板为虚拟机配置静态私有 ip:

variable "vmlist" {
  type = map(object({
    hostname = string
    IP_address = string
  }))
  default = {
    vm1 ={
    hostname = "vma"
    IP_address = "10.0.2.4"
    },
    vm2 = {
    hostname = "vmb"
    IP_address = "10.0.2.5"
    }
  }
}

#...

resource "azurerm_network_interface" "staticnic" {
  for_each = var.vmlist
  name                = "${each.value.hostname}-nic"
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name

  ip_configuration {
    name                          = "testconfiguration1"
    subnet_id                     = azurerm_subnet.internal.id
    private_ip_address_allocation = "Static"
    private_ip_address            = each.value.IP_address
  }
}

 #...

resource "azurerm_virtual_machine" "main" {
  for_each = var.vmlist
  name                  = each.value.hostname
  location              = azurerm_resource_group.main.location
  resource_group_name   = azurerm_resource_group.main.name
  network_interface_ids = [azurerm_network_interface.staticnic[each.key].id]
  vm_size               = "Standard_DS1_v2"

  # Uncomment this line to delete the OS disk automatically when deleting the VM
  # delete_os_disk_on_termination = true

  # Uncomment this line to delete the data disks automatically when deleting the VM
  # delete_data_disks_on_termination = true

  storage_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2016-Datacenter"
    version   = "latest"
  }

  storage_os_disk {
    name              = "${each.value.hostname}-osdisk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }
  os_profile {
    computer_name  = each.value.hostname
    admin_username = "testadmin"
    admin_password = "Password1234!"
  }

   os_profile_windows_config {
    provision_vm_agent = "true"
  }

}

我正在使用

Terraform v0.14.7
+ provider registry.terraform.io/hashicorp/azurerm v2.52.0

enter image description here

更新

如果您想让 Azure 分配动态 IP,然后将其转换为静态 IP,您可以在创建资源后使用 local-exec Provisioner 调用本地可执行文件。

resource "null_resource" "example" {

  for_each = var.vmlist
    provisioner "local-exec" {

   command = <<EOT

      $Nic = Get-AzNetworkInterface -ResourceGroupName ${azurerm_resource_group.main.name} -Name ${azurerm_network_interface.nic[each.key].name}
      $Nic.IpConfigurations[0].PrivateIpAllocationMethod = "Static"
      Set-AzNetworkInterface -NetworkInterface $Nic
   EOT
   
   interpreter = ["PowerShell", "-Command"]
  
  }
}

答案 1 :(得分:0)

为了便于阅读,我们做了这些。

首先,我使用此处列出的步骤在 azure 中创建了一个服务原则Creating a Service Principal

变量.TF

命令输出被添加到 variables.TF 中

variable APP_ID {
  default = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
}
variable SP_PASSWORD {
  default = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
variable TENANT_ID {
  default = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

此服务主体变量将用于在 Windows 工作代理上运行 az network 命令之前进行 az 登录

Main.TF

resource "azurerm_network_interface" "nic" {
  for_each = { for vm in var.vms : vm.hostname => vm }
  name                = "${each.value.hostname}-NIC"
  location            = var.network_location
  resource_group_name = var.vm_resource_group
  ip_configuration {
    name                          = var.nic_ip_config
    subnet_id                     = data.azurerm_subnet.vm_subnet.id
    private_ip_address_allocation = "dynamic"
  }
  tags = each.value.extra_tag
}

转换上面动态ip的tp static

# Convert All Private IP's from Dynamic to Static using powershell
resource "null_resource" "StaticIPsPrivateVMs" {
  for_each = { for vm in var.vms : vm.hostname => vm }
    provisioner "local-exec" {
      command = <<EOT
      az login --service-principal --username ${var.APP_ID} --password ${var.SP_PASSWORD} --tenant ${var.TENANT_ID}
      az network nic ip-config update -g ${var.vm_resource_group} --nic-name ${azurerm_network_interface.nic[each.key].name} --name ${var.nic_ip_config} --set privateIpAllocationMethod="Static"
      EOT
    interpreter = ["powershell", "-Command"]
  }
  depends_on = [
    azurerm_virtual_machine.vm
  ]
}

#AZ logout
resource "null_resource" "AzLogout" {
    provisioner "local-exec" {
      command = <<EOT
      az logout
      EOT
    interpreter = ["powershell", "-Command"]
  }
  depends_on = [
    null_resource.StaticIPsPrivateVMs
  ]
}

Azure-pipelines.yml

我在 validatedeploy 阶段的顶部添加了 vmImage: 'windows-latest' 这样我们就不会结束使用 linux 代理会抛出 powershell not found 错误:

  - stage: validate
    jobs:
    - job: validate
      pool:
        vmImage: 'windows-latest'
      continueOnError: false
      steps:
- stage: deploy
    jobs:
    - deployment: deploy
      pool:
        vmImage: 'windows-latest'
      continueOnError: false
相关问题