【问题标题】:Terraform - Import Azure VMs to state file using modulesTerraform - 使用模块将 Azure VM 导入状态文件
【发布时间】:2020-10-07 20:19:52
【问题描述】:

我正在使用以下以“# Script to create VM”开头的脚本创建 VM。正在从更高级别的目录调用该脚本,以便使用模块创建 VM,该调用类似于下面以“#Template..”开头的代码。问题是我们缺少之前运行期间创建的一些虚拟机的状态。我尝试导入虚拟机本身,但查看状态文件,它看起来与使用底部脚本创建的文件没有任何相似之处。任何帮助都会很棒。

#Template to call VM Script below
module <virtual_machine_name> {
    source = "./vm"
    virtual_machine_name = "<virtual_machine_name>"
    resource_group_name = "<resource_group_name>"
    availability_set_name = "<availability_set_name>"
    virtual_machine_size = "<virtual_machine_size>"
    subnet_name = "<subnet_name>"
    private_ip = "<private_ip>"

    optional:
    production = true (default is false)
    data_disk_name = ["<disk1>","<disk2>"]
    data_disk_size = ["50","100"] size is in GB
}

# Script to create VM
data azurerm_resource_group rgdata02 {
    name = "${var.resource_group_name}"
}
data azurerm_subnet sndata02 {
    name = "${var.subnet_name}"
  resource_group_name = "${var.core_resource_group_name}"
  virtual_network_name = "${var.virtual_network_name}"
}
data azurerm_availability_set availsetdata02 {
  name = "${var.availability_set_name}"
  resource_group_name = "${var.resource_group_name}"
}
data azurerm_backup_policy_vm bkpoldata02 {
  name                = "${var.backup_policy_name}"
  recovery_vault_name = "${var.recovery_services_vault_name}"
  resource_group_name = "${var.core_resource_group_name}"
}
data azurerm_log_analytics_workspace law02 { 
  name                = "${var.log_analytics_workspace_name}"
  resource_group_name = "${var.core_resource_group_name}"
}
#===================================================================
# Create NIC
#===================================================================
resource "azurerm_network_interface" "vmnic02" {
  name                = "nic${var.virtual_machine_name}"
  location            = "${data.azurerm_resource_group.rgdata02.location}"
  resource_group_name = "${var.resource_group_name}"

  ip_configuration {
    name                          = "ipcnfg${var.virtual_machine_name}"
    subnet_id                     = "${data.azurerm_subnet.sndata02.id}"
    private_ip_address_allocation = "Static"
    private_ip_address            = "${var.private_ip}"
  }
}
#===================================================================
# Create VM with Availability Set
#===================================================================
resource "azurerm_virtual_machine" "vm02" {
  count = var.avail_set != "" ? 1 : 0
  depends_on            = [azurerm_network_interface.vmnic02]
  name                  = "${var.virtual_machine_name}"
  location              = "${data.azurerm_resource_group.rgdata02.location}"
  resource_group_name   = "${var.resource_group_name}"
  network_interface_ids = [azurerm_network_interface.vmnic02.id]
  vm_size               = "${var.virtual_machine_size}"
  availability_set_id   = "${data.azurerm_availability_set.availsetdata02.id}"
  tags                  = var.tags

  # This means the OS Disk will be deleted when Terraform destroys the Virtual Machine
  # NOTE: This may not be optimal in all cases.
  delete_os_disk_on_termination = true

  os_profile {
    computer_name  = "${var.virtual_machine_name}"
    admin_username = "__VMUSER__"
    admin_password = "__VMPWD__"
  }

  os_profile_linux_config {
    disable_password_authentication = false
  }

  storage_image_reference {
    id = "${var.image_id}"
  }

  storage_os_disk {
    name              = "${var.virtual_machine_name}osdisk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Premium_LRS"
    os_type           = "Linux"     
  }

  boot_diagnostics {
    enabled = true
    storage_uri = "${var.boot_diagnostics_uri}"
  } 
}
#===================================================================
# Create VM without Availability Set
#===================================================================
resource "azurerm_virtual_machine" "vm03" {
  count = var.avail_set == "" ? 1 : 0
  depends_on            = [azurerm_network_interface.vmnic02]
  name                  = "${var.virtual_machine_name}"
  location              = "${data.azurerm_resource_group.rgdata02.location}"
  resource_group_name   = "${var.resource_group_name}"
  network_interface_ids = [azurerm_network_interface.vmnic02.id]
  vm_size               = "${var.virtual_machine_size}"
  # availability_set_id   = "${data.azurerm_availability_set.availsetdata02.id}"
  tags                  = var.tags

  # This means the OS Disk will be deleted when Terraform destroys the Virtual Machine
  # NOTE: This may not be optimal in all cases.
  delete_os_disk_on_termination = true

  os_profile {
    computer_name  = "${var.virtual_machine_name}"
    admin_username = "__VMUSER__"
    admin_password = "__VMPWD__"
  }

  os_profile_linux_config {
    disable_password_authentication = false
  }

  storage_image_reference {
    id = "${var.image_id}"
  }

  storage_os_disk {
    name              = "${var.virtual_machine_name}osdisk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Premium_LRS"
    os_type           = "Linux"     
  }

  boot_diagnostics {
    enabled = true
    storage_uri = "${var.boot_diagnostics_uri}"
  } 
}
#===================================================================
# Set Monitoring and Log Analytics Workspace
#===================================================================
resource "azurerm_virtual_machine_extension" "oms_mma02" {
  count = var.bootstrap ? 1 : 0
  name                       = "${var.virtual_machine_name}-OMSExtension"
  virtual_machine_id         = "${azurerm_virtual_machine.vm02.id}"
  publisher                  = "Microsoft.EnterpriseCloud.Monitoring"
  type                       = "OmsAgentForLinux"
  type_handler_version       = "1.8"
  auto_upgrade_minor_version = true

  settings = <<SETTINGS
    {
      "workspaceId" : "${data.azurerm_log_analytics_workspace.law02.workspace_id}"
    }
  SETTINGS

  protected_settings = <<PROTECTED_SETTINGS
    {
      "workspaceKey" : "${data.azurerm_log_analytics_workspace.law02.primary_shared_key}"
    }
  PROTECTED_SETTINGS
}
#===================================================================
# Associate VM to Backup Policy
#===================================================================
resource "azurerm_backup_protected_vm" "vm02" {
  count = var.bootstrap ? 1 : 0
  resource_group_name = "${var.core_resource_group_name}"
  recovery_vault_name = "${var.recovery_services_vault_name}"
  source_vm_id        = "${azurerm_virtual_machine.vm02.id}"
  backup_policy_id    = "${data.azurerm_backup_policy_vm.bkpoldata02.id}"}

【问题讨论】:

  • 我看到的关键障碍是你提到的:I've tried importing the VM itself but ... it does not appear anything similar ... 所以你知道如何导入,恐怕你在这里的选择是有限的,你能不能把它们销毁,让 Terrafrom 重新创建它们?
  • 我不清楚你的状态是什么意思,你真正想要什么。你能给出一个真正的目的吗?
  • 感谢您的回复。真正的目的是能够将 VM 作为模块及其所有部分导入,而不是作为 VM。如果我查看状态文件,资源的格式是脚本中提到的每个资源的“module.win.module.name of VM”,但是当我导入 VM 时,它只是 VM 的名称,没有任何信息在创建脚本中。我知道我可以将 VM 作为模块导入,但它似乎不会导入创建脚本中列出的所有资源。我认为一切都始于删除原始状态文件以及这些虚拟机上的信息。
  • 我也不明白你想要什么。数据源仅引用一个现有资源。而Terraform import只是导入状态文件中已有的资源,不会改变文件中已有的资源配置。
  • 抱歉没有说得这么清楚。我按照link 文档中的说明进行操作,第三部分处理导入模块,这是我为创建 VM 所做的工作,如上面的代码所示。有关更多信息,当我运行 Terraform 计划时,我得到类似于以下内容的内容:2020-06-19T06:59:43.4014967Z module.windows.module.testwinvm30.azurerm_network_interface.vmnic: Refreshing state... 显示所有资源与 VM 关联的是模块的一部分。

标签: azure import virtual-machine state terraform


【解决方案1】:

据我了解,您并不清楚 Terraform Import。所以我会告诉你这是什么意思。

  1. 当您要导入已有资源时,您需要先在 Terraform 文件中配置资源,了解现有资源是如何配置的。并且所有的资源都会被导入到状态文件中。

  2. 目前的另一个警告是,一次只能将一个资源导入状态文件。

当您想将资源导入模块时,我假设文件夹结构如下:

testingimportfolder
    └── main.tf
    └── terraform.tfstate
    └── terraform.tfstate.backup
    └───module
          └── main.tf

testingimportfolder 文件夹中的 main.tf 文件设置模块块如下:

module "importlab" {
    source = "./module"
    ...
}

在你将所有资源导入到状态文件后,你可以看到terraform state list这个命令的输出是这样的:

module.importlab.azurerm_network_security_group.nsg
module.importlab.azurerm_resource_group.rg
module.importlab.azurerm_virtual_network.vnet

所有资源名称都应该像module.module_name.azurerm_xxxx.resource_name。如果你在模块内部使用模块,我假设文件夹结构是这样的:

importmodules
├── main.tf
├── modules
│   └── vm
│       ├── main.tf
│       └── module
│           └── main.tf

而文件importmodules/modules/vm/main.tf 是这样的:

module "azurevm" {
        source = "./module"
        ...
}

然后在你把所有资源导入到状态文件之后,你就可以看到terraform state list这个命令的输出是这样的:

module.vm.module.azurevm.azurerm_network_interface.example

是的,它只是喜欢你所拥有的。当您一一引用模块时,状态文件将存储您现有的资源。所以你需要仔细而清晰地规划你的代码和模块。否则你会把自己弄糊涂的。

【讨论】:

  • 感谢您的反馈,我确实尝试了使用单个嵌套目录的示例,如链接所示,效果很好。从您的评论看来,我需要通过添加嵌套目录来实现,并通过 modules 命令重定向到顶部目录。接下来我会尝试的。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2021-10-08
  • 2021-05-25
  • 2022-06-11
  • 2021-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
相关资源
最近更新 更多