你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

基于 Terraform 的 SCVMM VM 管理

本文介绍如何使用 Terraform 模板以编程方式对 SCVMM 托管的本地虚拟机执行生命周期操作。

Hashicorp Terraform 是一种开源 IaC(基础结构即代码)工具,用于配置和部署云基础结构。 Terraform 可通过 AzAPI Terraform 提供程序管理基于 SCVMM 的虚拟基础结构。 可在此处访问已启用 Azure Arc 的 SCVMM 的一整套 Terraform 模板。

本文介绍了以下场景:

  • 从 Azure 新建 SCVMM 托管的本地虚拟机
  • 启用 SCVMM 托管的本地虚拟机,以在 Azure 中进行管理
  • 删除 SCVMM 托管的本地虚拟机的基于 Azure 的管理功能

最佳做法

  • 使用版本控制:使 Terraform 配置文件接受版本控制(例如在 Git 中),以跟踪其在不同时间发生的更改。
  • 状态管理:定期备份 Terraform 状态文件以避免数据丢失。

先决条件

在创建新虚拟机之前,请确保满足以下先决条件:

  • 具有 Arc SCVMM VM 参与者角色或具有在虚拟机上执行生命周期作所需的权限的自定义 RBAC 角色的 Azure 订阅和资源组。
  • 已启用 Arc 的 SCVMM 服务器,其 Azure Arc 资源网桥处于“正在运行”状态。
  • 安装了 Terraform 的工作站计算机。
  • 已启用 Azure 的云资源,你在其中拥有 Arc SCVMM 私有云资源用户角色。
  • 已启用 Azure 的虚拟机模板资源,你在其中拥有 Arc SCVMM 私有云资源用户角色。
  • 已启用 Azure 的虚拟机网络资源,你在其中拥有 Arc SCVMM 私有云资源用户角色。

步骤 1:在 variables.tf 文件中定义 VM 变量

下面是包含占位符的示例 variables.tf 文件。

variable "subscription_id" {
  description = "The subscription ID for the Azure account."
  type        = string
}

variable "resource_group_name" {
  description = "The name of the resource group."
  type        = string
}

variable "location" {
  description = "The location/region where the resources will be created."
  type        = string
}

variable "machine_name" {
  description = "The name of the machine."
  type        = string
}

variable "inventory_item_id" {
  description = "The ID of the Inventory Item for the VM."
  type        = string
}

variable "vm_username" {
  description = "The admin username for the VM."
  type        = string
}

variable "vm_password" {
  description = "The admin password for the VM."
  type        = string
}

variable "cloud_id" {
    description = "The ID of the cloud."
    type        = string
}

variable "template_id" {
  description = "The ID of the template."
  type        = string
}

variable "virtual_network_id" {
  description = "The ID of the virtual network."
  type        = string
}

variable "availability_set_name" {
  description = "The name of the availability set."
  type        = string
  
}

variable "vmmserver_id" {
  description = "The ID of the SCVMM server."
  type        = string
}

variable "custom_location_id" {
  description = "The ID of the custom location."
  type        = string
}

步骤 2:在 tfvars 文件中定义元数据和凭据

下面是包含占位符的示例 createscvmmVM.tfvars 文件。

subscription_id      = "your-subscription-id"
resource_group_name  = "your-resource-group"
location             = "eastus"
machine_name         = "vm-name"
vm_username          = "Administrator"
vm_password          = "your_vm_password"
vmmserver_id         = "/subscriptions/your-subscription-id/resourceGroups/your-resource-group/providers/Microsoft.SCVMM/vmmServers/your-vmmserver-name"
availability_set_name = "/subscriptions/your-subscription-id/resourceGroups/your-resource-group/providers/Microsoft.SCVMM/AvailabilitySets/your-availabilityset-name" #this parameter is optional
cloud_id             = "/subscriptions/your-subscription-id/resourceGroups/your-resource-group/providers/Microsoft.SCVMM/Clouds/your-vmmcloud-name"
template_id          = "/subscriptions/your-subscription-id/resourceGroups/your-resource-group/providers/Microsoft.SCVMM/VirtualMachineTemplates/your-template-name"
virtual_network_id   = "/subscriptions/your-subscription-id/resourceGroups/your-resource-group/providers/Microsoft.SCVMM/VirtualNetworks/your-vmnetwork-name"
custom_location_id   = "/subscriptions/your-subscription-id/resourcegroups/your-resource-group/providers/Microsoft.extendedlocation/customlocations/your-customlocation-name"

步骤 3:在 main.tf 文件中定义 VM 配置

下面是包含占位符的示例 main.tf 文件。

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = ">= 3.0"
    }
    azapi = {
      source  = "azure/azapi"
      version = ">= 1.0.0"
    }
  }
}

# Configure the AzureRM provider with the subscription ID
provider "azurerm" {
  features {}
  subscription_id = var.subscription_id
}

# Configure the AzAPI provider with the subscription ID
provider "azapi" {
  subscription_id = var.subscription_id
}

# Retrieve the resource group details
data "azurerm_resource_group" "example" {
  name = var.resource_group_name
}

# Create a Hybrid machine resource in Azure
resource "azapi_resource" "test_machine02" {
  schema_validation_enabled = false
  parent_id = data.azurerm_resource_group.example.id
  type = "Microsoft.HybridCompute/machines@2024-07-10"
  name = var.machine_name
  location = var.location
  body = {
      kind = "SCVMM"
      identity = {
        type = "SystemAssigned"
      }
  }
}

# Create a Virtual Machine instance using the Hybrid machine and Inventory Item ID
resource "azapi_resource" "test_inventory_vm001" {
  schema_validation_enabled = false
  type = "Microsoft.SCVMM/VirtualMachineInstances@2024-06-01"
  name = "default"
  parent_id = azapi_resource.test_machine01.id
  body = {
    properties = {
      infrastructureProfile = {
        templateId   = var.template_id
        cloudId      = var.cloud_id
        vmName       = var.machine_name
      }
    # Availability sets, OS profile and hardware profile are optional
      availabilitySets = [
      {
      name = var.availability_set_name
      }
      ]
    # Override VM template to customize VM creation 
      osProfile = {
        computerName    = "myVM"
        adminPassword   = var.vm_password
        domainName      = "cdmlab"
        domainUsername  = "cdmlabuser"
        domainPassword  = "your_domain_password"
        workgroup       = "myWorkgroup"
        runOnceCommands = "echo Hello; echo World"
      }
      hardwareProfile = {
        cpuCount = 4
        memoryMB = 3072
        limitCpuForMigration = "true"
      }
      networkProfile = {
        networkInterfaces = [
          {
            name            = "nic1"
            macAddress      = "00:0A:95:9D:68:16"
            virtualNetworkId = var.virtual_network_id
            ipv4AddressType = "Dynamic"
          }
        ]
      }
      storageProfile = {
        disks = [
          {
            name       = "disk1"
            diskId     = "disk-unique-id-1"
            diskSizeGB = 30
            bus        = 0
            lun        = 0
            busType    = "SCSI"
            vhdType    = "Dynamic"
          }
        ]
      }
    }
    extendedLocation = {
      type = "CustomLocation"
      name = var.custom_location_id
    }
  }
  depends_on = [azapi_resource.test_machine01]
}

# Install Arc agent on the VM
resource "azapi_resource" "guestAgent" {
  type      = "Microsoft.SCVMM/virtualMachineInstances/guestAgents@2024-06-01"
  parent_id = azapi_resource.test_inventory_vm001.id
  name      = "default"
  body = {
    properties = {
      credentials = {
        username = var.vm_username
        password = var.vm_password
      }
      provisioningAction = "install"
    }
  }
  schema_validation_enabled = false
  ignore_missing_property   = false
  depends_on = [azapi_resource.test_inventory_vm001]
}

步骤 4:运行 Terraform 命令

在运行 Terraform 命令期间,使用 -var-file 标志传递 .tfvars 文件

  • 初始化 Terraform(如果尚未初始化):terraform init
  • 验证配置:terraform validate -var-file="createscvmmVM.tfvars"
  • 规划更改:terraform plan -var-file="createscvmmVM.tfvars"
  • 应用更改:terraform apply -var-file="createscvmmVM.tfvars"

输入 yes 确认提示,以应用更改。

后续步骤