Attach NIC to a running VM in Azure using Terraform

1.9k views Asked by At

I have written a terraform script to deploy a VM in Azure. I want to Attach/detach multiple NIC to that VM at different times. Since the VM starts running after deployment I get error when I try to add another NIC Id to network_interface_ids inside azurerm_virtual_machine resource block. Terraform can't yet change the state of VM in Azure, I think. How can I achieve this as I don't see any VM-NIC association resource in terraform?

I'm a beginner with cloud and terraform, so this may be a basic question but I can't find a solution anywhere. Any help is appreciated.

My current code looks like this:

resource "azurerm_network_interface" "nic1" {
  name = "nic1"
  resource_group_name = data.azurerm_resource_group.rg.name
  location = data.azurerm_resource_group.rg.location
  enable_accelerated_networking = true
  ip_configuration {
    name = "nic1-config1"
    # public_ip_address_id = azurerm_public_ip.public_ip.id
    private_ip_address_allocation = "dynamic"
    subnet_id = data.azurerm_subnet.subnet.id
    primary = true

  }
  ip_configuration {
    name = "nic1-config2"
    public_ip_address_id = azurerm_public_ip.public_ip.id
    private_ip_address_allocation = "dynamic"
    subnet_id = data.azurerm_subnet.subnet.id
  }
  tags =  var.TAGS
}



 resource "azurerm_network_interface" "nic2" {
  name = "nic2"
  resource_group_name = data.azurerm_resource_group.rg.name
  location = data.azurerm_resource_group.rg.location
  enable_accelerated_networking = true
  ip_configuration {
    name = "nic2-config1"
    # public_ip_address_id = azurerm_public_ip.public_ip.id
    private_ip_address_allocation = "dynamic"
    subnet_id = data.azurerm_subnet.subnet.id
    primary = true

  }
  ip_configuration {
    name = "nic2-config2"
    # public_ip_address_id = azurerm_public_ip.public_ip.id
    private_ip_address_allocation = "dynamic"
    subnet_id = data.azurerm_subnet.subnet.id
  }
  tags =  var.TAGS
}


resource "azurerm_virtual_machine" "vm" {
  name = "vm"
  resource_group_name = data.azurerm_resource_group.rg.name
  location = data.azurerm_resource_group.rg.location
  network_interface_ids = [azurerm_network_interface.nic1.id]
  vm_size = "Standard_D4S_v3"
  delete_os_disk_on_termination = true
  delete_data_disks_on_termination = true
  storage_os_disk {
    name = "os-disk"
    create_option = "FromImage"
    caching = "ReadWrite"
    managed_disk_type = "Premium_LRS"
    disk_size_gb = 32
  }

  primary_network_interface_id = azurerm_network_interface.nic.id
  
  storage_image_reference {
    id = lookup(var.VMI,data.azurerm_resource_group.rg.location)
  }


  os_profile {
    admin_username = "test"
    computer_name = "test"
    admin_password = "test"
  }
  os_profile_linux_config {
    disable_password_authentication = true


    ssh_keys {
      path = "/home/user/.ssh/authorized_keys"
      key_data = "..."
    }
  }
  tags =  var.TAGS
  
}

I successfully deployed the above infrastructure.

Now I want to attach nic2 to this VM so I made the following change

resource "azurerm_virtual_machine" "vm" {
....
  network_interface_ids = [azurerm_network_interface.nic1.id, azurerm_network_interface.nic2.id]
...
}

https://azure.microsoft.com/en-us/blog/introducing-the-new-dv3-and-ev3-vm-sizes says I can attach upto two NICs to Standard_D4s_v3.

I get this error, which clearly says shut down the VM then try to attach.

Error: compute.VirtualMachinesClient#CreateOrUpdate Code="AddingOrDeletingNetworkInterfacesOnARunningVirtualMachineNotSupported" Message="Virtual machine vm with a single network interface must be stop-deallocated before it can be updated to have multiple network interfaces and vice-versa."

I want to know whether there is a way I can hot attach an NIC to VM in azure or not?

I was looking at this https://github.com/Azure/azure-powershell/issues/4565

1

There are 1 answers

0
Charles Xu On BEST ANSWER

The VM must be in the stopped(deallocated) status when you attach another NIC to the existing VM. It's designed. And Terraform does not have a separate resource for the association between VM and the NIC.

So according to what I know, you need first to stop the VM anyway and then add the second nic id to the VM as change you made:

resource "azurerm_virtual_machine" "vm" {
....
  network_interface_ids = [azurerm_network_interface.nic1.id, azurerm_network_interface.nic2.id]
...
}

When the VM is in the stopped status, then apply the Terraform code. For stopping the VM via Terraform, you can execute the CLI command with the null_resource with local-exec provisioner:

resource "null_resource" "example2" {
  provisioner "local-exec" {
    command = "az vm stop --resource-group groupName --name vmName"
    interpreter = ["/bin/bash", "-c"]
  }
}