错误:配置程序的主机不能为空

发布于 2025-01-10 15:09:41 字数 6354 浏览 0 评论 0原文

我正在处理 main.tf 文件,用于在 azure 中创建远程执行的虚拟机,并且我想在该文件中创建并下载 SSH 密钥 .pem 文件以访问 Linux VM。

主要的。 tf 文件

# Configure the Microsoft Azure Provider
terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "~>2.0"
    }
  }
}
provider "azurerm" {
  features {}
  subscription_id = var.subscription_id
  client_id       = var.client_id
  client_secret   = var.client_secret
  tenant_id =       var.tenant_id
 
}
# Create a resource group if it doesn't exist
resource "azurerm_resource_group" "myterraformgroup" {
    name     = var.resource_group
    location = var.resource_group_location

    tags = {
        environment = "Terraform Demo"
    }
}
# Create virtual network
resource "azurerm_virtual_network" "myterraformnetwork" {
    name                = "myVnet"
    address_space       = ["10.0.0.0/16"]
    location            = "eastus"
    resource_group_name = azurerm_resource_group.myterraformgroup.name

    tags = {
        environment = "Terraform Demo"
    }
}

# Create subnet
resource "azurerm_subnet" "myterraformsubnet" {
    name                 = "mySubnet"
    resource_group_name  = azurerm_resource_group.myterraformgroup.name
    virtual_network_name = azurerm_virtual_network.myterraformnetwork.name
    address_prefixes       = ["10.0.1.0/24"]
}

# Create public IPs
resource "azurerm_public_ip" "myterraformpublicip" {
    name                         = "myPublicIP"
    location                     = "eastus"
    resource_group_name          = azurerm_resource_group.myterraformgroup.name
    allocation_method            = "Dynamic"

    tags = {
        environment = "Terraform Demo"
    }
}

# Create Network Security Group and rule
resource "azurerm_network_security_group" "myterraformnsg" {
    name                = "myNetworkSecurityGroup"
    location            = "eastus"
    resource_group_name = azurerm_resource_group.myterraformgroup.name

    security_rule {
        name                       = "SSH"
        priority                   = 1001
        direction                  = "Inbound"
        access                     = "Allow"
        protocol                   = "Tcp"
        source_port_range          = "*"
        destination_port_range     = "22"
        source_address_prefix      = "*"
        destination_address_prefix = "*"
    }

    tags = {
        environment = "Terraform Demo"
    }
}

# Create network interface
resource "azurerm_network_interface" "myterraformnic" {
    name                      = "myNIC"
    location                  = "eastus"
    resource_group_name       = azurerm_resource_group.myterraformgroup.name

    ip_configuration {
        name                          = "myNicConfiguration"
        subnet_id                     = azurerm_subnet.myterraformsubnet.id
        private_ip_address_allocation = "Dynamic"
        public_ip_address_id          = azurerm_public_ip.myterraformpublicip.id
    }

    tags = {
        environment = "Terraform Demo"
    }
}

# Connect the security group to the network interface
resource "azurerm_network_interface_security_group_association" "example" {
    network_interface_id      = azurerm_network_interface.myterraformnic.id
    network_security_group_id = azurerm_network_security_group.myterraformnsg.id
}

# Generate random text for a unique storage account name
resource "random_id" "randomId" {
    keepers = {
        # Generate a new ID only when a new resource group is defined
        resource_group = azurerm_resource_group.myterraformgroup.name
    }

    byte_length = 8
}

# Create storage account for boot diagnostics
resource "azurerm_storage_account" "mystorageaccount" {
    name                        = "diag${random_id.randomId.hex}"
    resource_group_name         = azurerm_resource_group.myterraformgroup.name
    location                    = "eastus"
    account_tier                = "Standard"
    account_replication_type    = "LRS"

    tags = {
        environment = "Terraform Demo"
    }
}
# Create (and display) an SSH key
resource "tls_private_key" "example_ssh" {
  algorithm = "RSA"
  rsa_bits = 2048
    }
    output "tls_private_key" { 
    value = tls_private_key.example_ssh.private_key_pem 
    sensitive = true
}

# Create virtual machine
resource "azurerm_linux_virtual_machine" "myterraformvm" {
    name                  = "myVM"
    location              = "eastus"
    resource_group_name   = azurerm_resource_group.myterraformgroup.name
    network_interface_ids = [azurerm_network_interface.myterraformnic.id]
    size                  = "Standard_DS1_v2"

    os_disk {
        name              = "myOsDisk"
        caching           = "ReadWrite"
        storage_account_type = "Premium_LRS"
    }

    source_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "18.04-LTS"
        version   = "latest"
    }

    computer_name  = "myvm"
    admin_username = "azureuser"
    disable_password_authentication = true

    admin_ssh_key {
    username = "azureuser"
    public_key     = tls_private_key.example_ssh.public_key_openssh
    }

    boot_diagnostics {
        storage_account_uri = azurerm_storage_account.mystorageaccount.primary_blob_endpoint
    }

    tags = {
        environment = "Terraform Demo"
    }
}
resource "null_resource" "execute" {
connection {
    type        =   "ssh"
    agent       =   false
    user        =   "azureuser"
    host        =   azurerm_public_ip.myterraformpublicip.ip_address
    private_key =   tls_private_key.example_ssh.private_key_pem
}
provisioner "file" {
  source    =   "./config"
  destination   =   "~/"
}
provisioner "remote-exec" {
 inline     = [
   "chmod 755 ~/scripts/*",
   "sudo sh ~/scripts/foreman_prerequisite_config.sh",
   ]
}
depends_on = [azurerm_linux_virtual_machine.myterraformvm]
}

使用命令 terraform apply 时遇到以下错误,

[0m[1mnull_resource.execute: Provisioning with 'file'...[0m[0m
[31m╷[0m[0m
[31m│[0m [0m[1m[31mError: [0m[0m[1mfile provisioner error[0m
[31m│[0m [0m
[31m│[0m [0m[0m  with null_resource.execute,
[31m│[0m [0m  on main.tf line 184, in resource "null_resource" "execute":
[31m│[0m [0m 184: provisioner "file" [4m{[0m[0m
[31m│[0m [0m
[31m│[0m [0mhost for provisioner cannot be empty

请帮助我解决此问题。提前致谢!

I am working on the main.tf file for creating a virtual machine in azure with remote execution and also I would like to create and download the SSH key .pem file in this file to access Linux VM.

main. tf file

# Configure the Microsoft Azure Provider
terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "~>2.0"
    }
  }
}
provider "azurerm" {
  features {}
  subscription_id = var.subscription_id
  client_id       = var.client_id
  client_secret   = var.client_secret
  tenant_id =       var.tenant_id
 
}
# Create a resource group if it doesn't exist
resource "azurerm_resource_group" "myterraformgroup" {
    name     = var.resource_group
    location = var.resource_group_location

    tags = {
        environment = "Terraform Demo"
    }
}
# Create virtual network
resource "azurerm_virtual_network" "myterraformnetwork" {
    name                = "myVnet"
    address_space       = ["10.0.0.0/16"]
    location            = "eastus"
    resource_group_name = azurerm_resource_group.myterraformgroup.name

    tags = {
        environment = "Terraform Demo"
    }
}

# Create subnet
resource "azurerm_subnet" "myterraformsubnet" {
    name                 = "mySubnet"
    resource_group_name  = azurerm_resource_group.myterraformgroup.name
    virtual_network_name = azurerm_virtual_network.myterraformnetwork.name
    address_prefixes       = ["10.0.1.0/24"]
}

# Create public IPs
resource "azurerm_public_ip" "myterraformpublicip" {
    name                         = "myPublicIP"
    location                     = "eastus"
    resource_group_name          = azurerm_resource_group.myterraformgroup.name
    allocation_method            = "Dynamic"

    tags = {
        environment = "Terraform Demo"
    }
}

# Create Network Security Group and rule
resource "azurerm_network_security_group" "myterraformnsg" {
    name                = "myNetworkSecurityGroup"
    location            = "eastus"
    resource_group_name = azurerm_resource_group.myterraformgroup.name

    security_rule {
        name                       = "SSH"
        priority                   = 1001
        direction                  = "Inbound"
        access                     = "Allow"
        protocol                   = "Tcp"
        source_port_range          = "*"
        destination_port_range     = "22"
        source_address_prefix      = "*"
        destination_address_prefix = "*"
    }

    tags = {
        environment = "Terraform Demo"
    }
}

# Create network interface
resource "azurerm_network_interface" "myterraformnic" {
    name                      = "myNIC"
    location                  = "eastus"
    resource_group_name       = azurerm_resource_group.myterraformgroup.name

    ip_configuration {
        name                          = "myNicConfiguration"
        subnet_id                     = azurerm_subnet.myterraformsubnet.id
        private_ip_address_allocation = "Dynamic"
        public_ip_address_id          = azurerm_public_ip.myterraformpublicip.id
    }

    tags = {
        environment = "Terraform Demo"
    }
}

# Connect the security group to the network interface
resource "azurerm_network_interface_security_group_association" "example" {
    network_interface_id      = azurerm_network_interface.myterraformnic.id
    network_security_group_id = azurerm_network_security_group.myterraformnsg.id
}

# Generate random text for a unique storage account name
resource "random_id" "randomId" {
    keepers = {
        # Generate a new ID only when a new resource group is defined
        resource_group = azurerm_resource_group.myterraformgroup.name
    }

    byte_length = 8
}

# Create storage account for boot diagnostics
resource "azurerm_storage_account" "mystorageaccount" {
    name                        = "diag${random_id.randomId.hex}"
    resource_group_name         = azurerm_resource_group.myterraformgroup.name
    location                    = "eastus"
    account_tier                = "Standard"
    account_replication_type    = "LRS"

    tags = {
        environment = "Terraform Demo"
    }
}
# Create (and display) an SSH key
resource "tls_private_key" "example_ssh" {
  algorithm = "RSA"
  rsa_bits = 2048
    }
    output "tls_private_key" { 
    value = tls_private_key.example_ssh.private_key_pem 
    sensitive = true
}

# Create virtual machine
resource "azurerm_linux_virtual_machine" "myterraformvm" {
    name                  = "myVM"
    location              = "eastus"
    resource_group_name   = azurerm_resource_group.myterraformgroup.name
    network_interface_ids = [azurerm_network_interface.myterraformnic.id]
    size                  = "Standard_DS1_v2"

    os_disk {
        name              = "myOsDisk"
        caching           = "ReadWrite"
        storage_account_type = "Premium_LRS"
    }

    source_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "18.04-LTS"
        version   = "latest"
    }

    computer_name  = "myvm"
    admin_username = "azureuser"
    disable_password_authentication = true

    admin_ssh_key {
    username = "azureuser"
    public_key     = tls_private_key.example_ssh.public_key_openssh
    }

    boot_diagnostics {
        storage_account_uri = azurerm_storage_account.mystorageaccount.primary_blob_endpoint
    }

    tags = {
        environment = "Terraform Demo"
    }
}
resource "null_resource" "execute" {
connection {
    type        =   "ssh"
    agent       =   false
    user        =   "azureuser"
    host        =   azurerm_public_ip.myterraformpublicip.ip_address
    private_key =   tls_private_key.example_ssh.private_key_pem
}
provisioner "file" {
  source    =   "./config"
  destination   =   "~/"
}
provisioner "remote-exec" {
 inline     = [
   "chmod 755 ~/scripts/*",
   "sudo sh ~/scripts/foreman_prerequisite_config.sh",
   ]
}
depends_on = [azurerm_linux_virtual_machine.myterraformvm]
}

Facing the below error when using command terraform apply

[0m[1mnull_resource.execute: Provisioning with 'file'...[0m[0m
[31m╷[0m[0m
[31m│[0m [0m[1m[31mError: [0m[0m[1mfile provisioner error[0m
[31m│[0m [0m
[31m│[0m [0m[0m  with null_resource.execute,
[31m│[0m [0m  on main.tf line 184, in resource "null_resource" "execute":
[31m│[0m [0m 184: provisioner "file" [4m{[0m[0m
[31m│[0m [0m
[31m│[0m [0mhost for provisioner cannot be empty

Please help me to resolve this issue. Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

甚是思念 2025-01-17 15:09:42

根据Azure提供商文档[1],当公共IP分配类型为动态时,您应该使用数据源来获取IP地址:

data "azurerm_public_ip" "myterraformpublicip" {
  name                = azurerm_public_ip.myterraformpublicip.name
  resource_group_name = azurerm_linux_virtual_machine.myterraformvm.resource_group_name
}

然后,在< null_resource 的 code>host 参数,您应该设置以下内容:

host = data.azurerm_public_ip.myterraformpublicip.ip_address

但是,这可能无法解决您遇到的问题,因为此版本的 Linux VM 的 Azure 提供程序似乎存在问题[2]:

在此版本中存在一个已知问题,即动态公共 IP 的 public_ip_address 和 public_ip_addresses 字段可能未完全填充。

问题的第二部分与生成 SSH 密钥有关,该密钥稍后可用于访问虚拟机。在您的问题中,您有以下代码:

resource "tls_private_key" "example_ssh" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

output "tls_private_key" { 
    value = tls_private_key.example_ssh.private_key_pem 
    sensitive = true
}

根据您在评论 [3] 中链接的答案,不需要 output 。这可用于在同一目录中创建私钥:

resource "tls_private_key" "example_ssh" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "local_file" "private_key_file" {
  content  = tls_private_key.example_ssh.private_key_pem
  filename = "${path.root}/private-key.pem"
}

然后,在 null_resource 中,您应该添加以下内容:

resource "null_resource" "execute" {
  connection {
    type        =   "ssh"
    agent       =   false
    user        =   "azureuser"
    host        =   data.azurerm_public_ip.myterraformpublicip.ip_address
    private_key =   "${path.root}/private-key.pem"
  }

  provisioner "file" {
    source      =  "./config"
    destination =  "~/"
  }

  provisioner "remote-exec" {
   inline     = [
     "chmod 755 ~/scripts/*",
     "sudo sh ~/scripts/foreman_prerequisite_config.sh",
   ]
  }
}
depends_on = [azurerm_linux_virtual_machine.myterraformvm]
}

请注意,您可能不应该使用 tls_private_key 资源对于生产环境[4]:

此资源生成的私钥将以未加密的方式存储在您的 Terraform 状态文件中。不建议将此资源用于生产部署。相反,在 Terraform 外部生成私钥文件并将其安全地分发到将运行 Terraform 的系统。


[1] https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/public_ip#example-usage-retrieve-the-dynamic-public-ip-of-a-new-vm

[2] <一href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_virtual_machine#:%7E:text=In%20this%20release%20there%27s%20a%20已知%20issue%20其中%20%20public_ip_address%20和%20public_ip_addresses%20fields%20may%20not%20be%20完全%20populated%20for%20Dynamic%20Public%20IP%27s" rel="nofollow noreferrer">https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_virtual_machine#:~:text=In%20this%20release%20there%27s%20a%20已知%20issue%20其中%20%20public_ip_address%20和%20public_ip_addresses%20fields%20may%20not%20be%20完全%20populated%20for%20Dynamic%20Public%20IP%27s。

[3] https://stackoverflow.com/a/67379867/8343484

[4] https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key

According to the Azure provider documentation [1], when the public IP allocation type is Dynamic, you should use the data source to get the IP address:

data "azurerm_public_ip" "myterraformpublicip" {
  name                = azurerm_public_ip.myterraformpublicip.name
  resource_group_name = azurerm_linux_virtual_machine.myterraformvm.resource_group_name
}

Then, in the host argument of the null_resource you should set the following:

host = data.azurerm_public_ip.myterraformpublicip.ip_address

However, this might not fix the issue you have as it seems there is a problem with this version of Azure provider for Linux VMs [2]:

In this release there's a known issue where the public_ip_address and public_ip_addresses fields may not be fully populated for Dynamic Public IP's.

The second part of the question was related to generating an SSH key which can be used later on to access a VM. In your question you have this code:

resource "tls_private_key" "example_ssh" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

output "tls_private_key" { 
    value = tls_private_key.example_ssh.private_key_pem 
    sensitive = true
}

The output is not needed based on the answer you linked in the comments [3]. This can be used to create a private key in the same directory:

resource "tls_private_key" "example_ssh" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "local_file" "private_key_file" {
  content  = tls_private_key.example_ssh.private_key_pem
  filename = "${path.root}/private-key.pem"
}

Then, in the null_resource, you should add the following:

resource "null_resource" "execute" {
  connection {
    type        =   "ssh"
    agent       =   false
    user        =   "azureuser"
    host        =   data.azurerm_public_ip.myterraformpublicip.ip_address
    private_key =   "${path.root}/private-key.pem"
  }

  provisioner "file" {
    source      =  "./config"
    destination =  "~/"
  }

  provisioner "remote-exec" {
   inline     = [
     "chmod 755 ~/scripts/*",
     "sudo sh ~/scripts/foreman_prerequisite_config.sh",
   ]
  }
}
depends_on = [azurerm_linux_virtual_machine.myterraformvm]
}

Note that you probably should not use the tls_private_key resource for production environments [4]:

The private key generated by this resource will be stored unencrypted in your Terraform state file. Use of this resource for production deployments is not recommended. Instead, generate a private key file outside of Terraform and distribute it securely to the system where Terraform will be run.


[1] https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/public_ip#example-usage-retrieve-the-dynamic-public-ip-of-a-new-vm

[2] https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_virtual_machine#:~:text=In%20this%20release%20there%27s%20a%20known%20issue%20where%20the%20public_ip_address%20and%20public_ip_addresses%20fields%20may%20not%20be%20fully%20populated%20for%20Dynamic%20Public%20IP%27s.

[3] https://stackoverflow.com/a/67379867/8343484

[4] https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文