首页 文章

使用Terraform与Azure VM Build SSH连接

提问于
浏览
2

我已经使用Terraform在Azure上成功创建了一个VM作为资源组的一部分 . 下一步是在新机器中ssh并运行一些命令 . 为此,我创建了一个配置器作为VM资源的一部分并设置了SSH连接:

resource "azurerm_virtual_machine" "helloterraformvm" {
    name = "terraformvm"
    location = "West US"
    resource_group_name = "${azurerm_resource_group.helloterraform.name}"
    network_interface_ids = ["${azurerm_network_interface.helloterraformnic.id}"]
    vm_size = "Standard_A0"

    storage_image_reference {
        publisher = "Canonical"
        offer = "UbuntuServer"
        sku = "14.04.2-LTS"
        version = "latest"
    }


    os_profile {
        computer_name = "hostname"
        user     = "some_user"
        password = "some_password"
    }

    os_profile_linux_config {
        disable_password_authentication = false
    }

    provisioner "remote-exec" {
        inline = [
          "sudo apt-get install docker.io -y"
        ]
        connection {
          type     = "ssh"
          user     = "some_user"
          password = "some_password"
        }
    }

}

如果我运行“terraform apply”,它似乎进入无限循环尝试ssh失败,反复重复此日志:

azurerm_virtual_machine.helloterraformvm (remote-exec): Connecting to remote host via SSH...
azurerm_virtual_machine.helloterraformvm (remote-exec):   Host:
azurerm_virtual_machine.helloterraformvm (remote-exec):   User: testadmin
azurerm_virtual_machine.helloterraformvm (remote-exec):   Password: true
azurerm_virtual_machine.helloterraformvm (remote-exec):   Private key: false
azurerm_virtual_machine.helloterraformvm (remote-exec):   SSH Agent: true

我确定我做错了什么,但我不知道它是什么:(

编辑:

我已经尝试在没有配置器的情况下设置这台机器,我可以使用给定的用户名/密码来SSH连接到它 . 但是我需要在Azure门户中查找主机名,因为我不知道如何从Terraform中检索它 . 令人怀疑日志中的“Host:”行是空的,所以我想知道它是否与此有关?

更新:

我尝试过不同的东西,比如在连接中指明主机名

host = "${azurerm_public_ip.helloterraformip.id}"

host = "${azurerm_public_ip.helloterraformips.ip_address}"

如文档中所示,但没有成功 .

我也尝试过使用ssh-keys代替密码,但结果相同 - 无限循环的连接尝试,没有明确的错误消息,因为它没有连接 .

2 回答

  • 1

    我已成功完成这项工作 . 我改变了几件事:

    • connection 的主机名 .

    • 正确配置SSH密钥 - 它们需要未加密 .

    • provisioner 元素中取出 connection 元素 .

    这是完整的Terraform文件,替换SSH密钥等数据:

    # Configure Azure provider
    provider "azurerm" {
      subscription_id = "${var.azure_subscription_id}"
      client_id       = "${var.azure_client_id}"
      client_secret   = "${var.azure_client_secret}"
      tenant_id       = "${var.azure_tenant_id}"
    }
    
    # create a resource group if it doesn't exist
    resource "azurerm_resource_group" "rg" {
        name = "sometestrg"
        location = "ukwest"
    }
    
    # create virtual network
    resource "azurerm_virtual_network" "vnet" {
        name = "tfvnet"
        address_space = ["10.0.0.0/16"]
        location = "ukwest"
        resource_group_name = "${azurerm_resource_group.rg.name}"
    }
    
    # create subnet
    resource "azurerm_subnet" "subnet" {
        name = "tfsub"
        resource_group_name = "${azurerm_resource_group.rg.name}"
        virtual_network_name = "${azurerm_virtual_network.vnet.name}"
        address_prefix = "10.0.2.0/24"
        #network_security_group_id = "${azurerm_network_security_group.nsg.id}"
    }
    
    # create public IPs
    resource "azurerm_public_ip" "ip" {
        name = "tfip"
        location = "ukwest"
        resource_group_name = "${azurerm_resource_group.rg.name}"
        public_ip_address_allocation = "dynamic"
        domain_name_label = "sometestdn"
    
        tags {
            environment = "staging"
        }
    }
    
    # create network interface
    resource "azurerm_network_interface" "ni" {
        name = "tfni"
        location = "ukwest"
        resource_group_name = "${azurerm_resource_group.rg.name}"
    
        ip_configuration {
            name = "ipconfiguration"
            subnet_id = "${azurerm_subnet.subnet.id}"
            private_ip_address_allocation = "static"
            private_ip_address = "10.0.2.5"
            public_ip_address_id = "${azurerm_public_ip.ip.id}"
        }
    }
    
    # create storage account
    resource "azurerm_storage_account" "storage" {
        name = "someteststorage"
        resource_group_name = "${azurerm_resource_group.rg.name}"
        location = "ukwest"
        account_type = "Standard_LRS"
    
        tags {
            environment = "staging"
        }
    }
    
    # create storage container
    resource "azurerm_storage_container" "storagecont" {
        name = "vhd"
        resource_group_name = "${azurerm_resource_group.rg.name}"
        storage_account_name = "${azurerm_storage_account.storage.name}"
        container_access_type = "private"
        depends_on = ["azurerm_storage_account.storage"]
    }
    
    
    
    # create virtual machine
    resource "azurerm_virtual_machine" "vm" {
        name = "sometestvm"
        location = "ukwest"
        resource_group_name = "${azurerm_resource_group.rg.name}"
        network_interface_ids = ["${azurerm_network_interface.ni.id}"]
        vm_size = "Standard_A0"
    
        storage_image_reference {
            publisher = "Canonical"
            offer = "UbuntuServer"
            sku = "16.04-LTS"
            version = "latest"
        }
    
        storage_os_disk {
            name = "myosdisk"
            vhd_uri = "${azurerm_storage_account.storage.primary_blob_endpoint}${azurerm_storage_container.storagecont.name}/myosdisk.vhd"
            caching = "ReadWrite"
            create_option = "FromImage"
        }
    
        os_profile {
            computer_name = "testhost"
            admin_username = "testuser"
            admin_password = "Password123"
        }
    
        os_profile_linux_config {
          disable_password_authentication = false
          ssh_keys = [{
            path     = "/home/testuser/.ssh/authorized_keys"
            key_data = "ssh-rsa xxx email@something.com"
          }]
        }
    
        connection {
            host = "sometestdn.ukwest.cloudapp.azure.com"
            user = "testuser"
            type = "ssh"
            private_key = "${file("~/.ssh/id_rsa_unencrypted")}"
            timeout = "1m"
            agent = true
        }
    
        provisioner "remote-exec" {
            inline = [
              "sudo apt-get update",
              "sudo apt-get install docker.io -y",
              "git clone https://github.com/somepublicrepo.git",
              "cd Docker-sample",
              "sudo docker build -t mywebapp .",
              "sudo docker run -d -p 5000:5000 mywebapp"
            ]
        }
    
        tags {
            environment = "staging"
        }
    }
    
  • 4

    根据您的描述,Azure Custom Script Extension是您的选择 .

    自定义脚本扩展在Azure虚拟机上下载并执行脚本 . 此扩展对于部署后配置,软件安装或任何其他配置/管理任务非常有用 .

    删除 provisioner "remote-exec" 而不是下面的:

    resource "azurerm_virtual_machine_extension" "helloterraformvm" {
      name                 = "hostname"
      location             = "West US"
      resource_group_name  = "${azurerm_resource_group.helloterraformvm.name}"
      virtual_machine_name = "${azurerm_virtual_machine.helloterraformvm.name}"
      publisher            = "Microsoft.OSTCExtensions"
      type                 = "CustomScriptForLinux"
      type_handler_version = "1.2"
    
      settings = <<SETTINGS
        {
            "commandToExecute": "apt-get install docker.io -y"
        }
    SETTINGS
    }
    

    注意:命令由root用户执行,请勿使用 sudo .

    更多信息请参考此链接:azurerm_virtual_machine_extension .

    有关可能的扩展名列表,您可以使用Azure CLI命令 az vm extension image list -o table

    更新:以上示例仅支持单个命令 . 如果需要多个命令 . 就像你的VM上的安装docker一样,你需要

    apt-get update 
    apt-get install docker.io -y
    

    将其另存为名为script.sh的文件,并将其保存到Azure存储帐户或GitHub(该文件应该是公共的) . 修改如下的terraform文件:

    settings = <<SETTINGS
        {
            "fileUris": ["https://gist.githubusercontent.com/Walter-Shui/dedb53f71da126a179544c91d267cdce/raw/bb3e4d90e3291530570eca6f4ff7981fdcab695c/script.sh"],
            "commandToExecute": "sh script.sh"
        }
    SETTINGS
    

相关问题