【问题标题】:SSH connection to Azure VM with Terraform使用 Terraform 与 A​​zure VM 建立 SSH 连接
【发布时间】:2017-12-13 07:33:39
【问题描述】:

我已使用 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 代替密码,但结果相同 - 无限循环连接尝试,没有明确的错误消息说明为什么它没有连接。

【问题讨论】:

  • 您可以使用这些凭据手动 ssh 进入该框吗?
  • 对,我的错,您没有“创建 NSG”步骤,因此无需为此创建规则。
  • @evilSnobu 是的,我可以使用用户/密码组合手动 ssh 进入机器。我已使用该信息更新了问题。
  • @zapatilla 我检查了你的问题,根据我的理解,你想在创建 VM 时使用 docker。对于 Azure VM,您不需要通过 ssh 访问它。您可以使用 Azure 自定义脚本扩展来执行此操作。 terraform 支持扩展。我测试了它,它对我来说很好用。你可以看看我的回答。

标签: linux azure terraform


【解决方案1】:

根据您的描述,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

更新:上面的例子只支持单个命令。如果你需要多个命令。就像在你的虚拟机上安装 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

【讨论】:

  • 嗨沃尔特 - MSFT。我设法使用 SSH 密钥使 Terraform 配置器工作。明天我将发布我的工作示例。您的替代方案有什么比 Terraform 供应商更好的选择?感谢您的帮助!
  • @zapatilla 对于 Azure VM,这是一个更好的选择。因为 Azure 在 Linux VM 上安装了一个代理。 Custom script extension 使用代理在您的虚拟机上执行脚本,您的虚拟机不需要 ssh。
  • @zapatilla 我认为这很容易满足您的需求。如果可能的话,你可以测试一下。
  • 我已经尝试了现在的命令,它似乎工作。这很棒,因为它不需要发送 SSH 密钥作为我最初的选择。但是,我需要运行的脚本不是单行脚本,也不应该将它们作为公共保存在 GH 上。我将尝试自动将脚本保存在 Azure 存储上,看看效果如何。再次感谢您的建议!
  • 还有一些我不确定我喜欢的东西 - 扩展不输出我在 VM 上运行的命令的标准输出,而其他解决方案可以。此外,这需要更长的时间,这对我来说很重要。我认为这是一个不错的选择,但我将使用另一个。
【解决方案2】:

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

  • 将主机名提供给connection
  • 正确配置 SSH 密钥 - 它们需要不加密。
  • connection 元素从provisioner 元素中取出。

这是完整的工作 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"
    }
}

【讨论】:

    猜你喜欢
    • 2021-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多