Search code examples
azureubuntuipprovisioningterraform

Terraform provision private VM on Azure


I'm new to Terraform. I have a subnet with two Ubuntu VMs. One is VM A, which has a public IP, and the other is VM B, with a private IP and no public IP. Is there a Terraform way of provisioning files and running commands on B without first having to SSH into VM A and then into VM B?

From what I've found, the file provisioners in Terraform require a connection block like so:

      # Example Azure VM provisioner block
      provisioner "remote-exec" {
        inline = [
          "rsync -Pav user@A:~/install.sh ~",
          "rsync -Pav user@A:~/file.txt ~",
          "sudo ~/install.sh"
        ]
        connection {
          type     = "ssh"
          user     = "${var.ssh_user_username}"
          host     = "<something to put here>"
          private_key = "${file("~/.ssh/azure_key_rsa")}"
          timeout  = "1m"
          agent = false
        }
      }

But since I can't connect to the private IP directly in Terraform, I'm not sure what to put for the host field to make this provisioner successful.


Solution

  • According to my knowledge, you could not do it with terraform directly. You could use Custom Script extension to execute your install.sh, the script is executed by Azure, you don't need ssh to the VM.

    The Custom Script Extension configuration specifies things like script location and the command to be run. This configuration can be stored in configuration files, specified on the command line, or in an Azure Resource Manager template. Sensitive data can be stored in a protected configuration, which is encrypted and only decrypted inside the virtual machine. According to your scenario, it seems that what you need.

    Terraform also supports CustomScript, you could refer to this example.

    resource "azurerm_virtual_machine_extension" "test" {
      name                 = "hostname"
      location             = "West US"
      resource_group_name  = "${azurerm_resource_group.test.name}"
      virtual_machine_name = "${azurerm_virtual_machine.test.name}"
      publisher            = "Microsoft.OSTCExtensions"
      type                 = "CustomScriptForLinux"
      type_handler_version = "1.2"
    
      settings = <<SETTINGS
        {
            "commandToExecute": "hostname"
        }
    SETTINGS