You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform部署Azure虚拟机时自定义主机名不生效问题求助

Azure Terraform部署自定义镜像VM时主机名不生效的解决方法

问题描述

使用自定义Rocky Linux镜像通过Terraform部署Azure虚拟机,已在azurerm_linux_virtual_machine的computer_name字段设置自定义主机名(如test-vm),但部署后VM主机名仍固定为镜像中的rockylinuximage01,无法生效。

相关代码

var.tf

variable "vm_template" {
  type = map(any)
  default = {
    vm1 = {
      source_image_id = "/subscriptions/00000/resourceGroups/image/providers/Microsoft.Compute/images/new-image-rocky8"
      vm_name         = "test-vm"
      hostname        = "test-vm"
      os_publisher    = "resf"
      os_offer        = "rockylinux-x86_64"
      os_sku          = "8-base"
      os_version      = "8.9.20231119"
      osdisk_type     = "StandardSSD_LRS"
      osdisk_size     = "32"
      vm_type         = "Standard_D2s_v5"
      nic             = "nic01"
      os_disk         = "osdisk01"
    }
  }
}

vm.tf

data "azurerm_key_vault" "kv" {
  name                = var.kv_name
  resource_group_name = var.kv_rg
}

data "azurerm_key_vault_secret" "password" {
  name         = var.kv_secret_name
  key_vault_id = data.azurerm_key_vault.kv.id
}

data "azurerm_resource_group" "system_rg_name" {
  name = var.system_rg
}

data "azurerm_subnet" "network_subnet" {
  name                 = var.network_subnet
  virtual_network_name = var.network_vnet
  resource_group_name  = var.network_rg
}

resource "azurerm_network_interface" "nic" {
  for_each                      = var.vm_template
  name                          = "${each.value.vm_name}-${each.value.nic}"
  location                      = var.location
  resource_group_name           = data.azurerm_resource_group.system_rg_name.name
  enable_accelerated_networking = true
  ip_configuration {
    name                          = "internal"
    subnet_id                     = data.azurerm_subnet.network_subnet.id
    private_ip_address_allocation = var.private-ip-type
    private_ip_address            = each.value.private_ip
  }
}

resource "azurerm_linux_virtual_machine" "vm" {
  for_each = var.vm_template
  name                = each.value.vm_name
  location            = var.location
  resource_group_name = data.azurerm_resource_group.system_rg_name.name
  source_image_id     = each.value.source_image_id
  zone                = each.value.zone
  #### VM Instance Type
  size = each.value.vm_type

  network_interface_ids = [
    azurerm_network_interface.nic[each.key].id,
  ]

  identity {
    type = "SystemAssigned"
  }

  os_disk {
    name                 = "${each.value.vm_name}-${each.value.os_disk}"
    caching              = "ReadWrite" # ReadOnly, ReadWrite
    storage_account_type = each.value.osdisk_type
    disk_size_gb         = each.value.osdisk_size
  }

  plan {
    name      = each.value.os_sku
    publisher = each.value.os_publisher
    product   = each.value.os_offer
  }

  computer_name  = each.value.hostname
  admin_username = var.adminid
  admin_password = data.azurerm_key_vault_secret.password.value
 
  disable_password_authentication = false

  lifecycle {
    ignore_changes = [
      admin_password,
    ]
  }
}

解决方案

核心原因

Azure Linux VM的computer_name参数需要依赖cloud-init读取Azure实例元数据服务的配置来生效。如果自定义镜像未正确配置cloud-init,或镜像中硬编码了主机名,就会导致Terraform设置的主机名无法覆盖镜像原有值。

具体修复步骤

1. 修复自定义镜像的cloud-init配置

在制作自定义镜像的源VM上执行以下操作:

  • 安装cloud-init及Azure相关依赖:
    sudo dnf install -y cloud-init cloud-utils-growpart
    
  • 配置Azure为cloud-init的数据源:
    创建/编辑/etc/cloud/cloud.cfg.d/90-azure.cfg,写入以下内容:
    datasource_list: [ Azure ]
    datasource:
        Azure:
            metadata_urls: [ 'http://169.254.169.254/metadata/instance?api-version=2021-02-01' ]
            wait_for_metadata_service: True
    
  • 清理旧主机名残留:
    sudo rm -f /etc/hostname
    sudo sed -i '/rockylinuximage01/d' /etc/hosts
    
  • 重置cloud-init状态,准备制作镜像:
    sudo cloud-init clean --logs --seed
    sudo poweroff
    
  • 基于该关机状态的VM重新生成自定义镜像。

2. Terraform代码兜底优化(可选)

如果暂时无法重新制作镜像,可以在azurerm_linux_virtual_machine资源中添加custom_data,强制cloud-init启动时设置主机名:

resource "azurerm_linux_virtual_machine" "vm" {
  # 原有配置...

  computer_name  = each.value.hostname
  # 添加以下custom_data配置
  custom_data = base64encode(<<-EOF
    #cloud-config
    hostname: ${each.value.hostname}
    preserve_hostname: false
  EOF
  )

  # 原有配置...
}

验证方法

部署完成后,登录VM执行hostname命令,确认输出为Terraform中设置的test-vm。


内容的提问来源于stack exchange,提问作者gotothesky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:35:17