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

在Azure上用Terraform部署带托管标识的VM失败求助

问题

之前在AzureRM Provider块中配置client_id、subscription_id、client_secret和tenant_id时,可正常用Terraform部署Azure虚拟机。现为避免暴露client_secret,改用托管标识(Managed Identity),按官方指南操作后,执行时出现错误提示需运行az login,无法理解原因。

相关代码:

terraform {
  required_providers {
    azuread = {
      source = "hashicorp/azuread"
    }
  }
}

provider "azurerm" {
  features {}
  //client_id       = "XXXXXXXXXXXXXX"
  //client_secret   = "XXXXXXXXXXXXXX"
  //subscription_id = "XXXXXXXXXXXXXX"
  tenant_id       = "TENANT_ID"
  //use_msi         = true
}

provider "azuread" {
  use_msi   = true
  tenant_id = "TENANT_ID"
}

#Resource group definition
resource "azurerm_resource_group" "myVMachineRG" {
  name     = "testnew-resources"
  location = "westus2"
}

resource "azurerm_virtual_network" "myVNet" {
  name                = "testnew-network"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.myVMachineRG.location
  resource_group_name = azurerm_resource_group.myVMachineRG.name
}

resource "azurerm_subnet" "mySubnet" {
  name                 = "testnew-internal-subnet"
  resource_group_name  = azurerm_resource_group.myVMachineRG.name
  virtual_network_name = azurerm_virtual_network.myVNet.name
  #256 total IPs
  address_prefixes = ["10.0.2.0/24"]
}

resource "azurerm_network_interface" "myNIC" {
  name                = "testnew-nic"
  location            = azurerm_resource_group.myVMachineRG.location
  resource_group_name = azurerm_resource_group.myVMachineRG.name

  ip_configuration {
    name                          = "testconfiguration1"
    subnet_id                     = azurerm_subnet.mySubnet.id
    private_ip_address_allocation = "Dynamic"
  }
}

data "azurerm_subscription" "current" {}

data "azurerm_client_config" "example" {}

resource "azurerm_virtual_machine" "example" {
  name                  = "testnew-vm"
  location              = azurerm_resource_group.myVMachineRG.location
  resource_group_name   = azurerm_resource_group.myVMachineRG.name
  network_interface_ids = ["${azurerm_network_interface.myNIC.id}"]
  vm_size               = "Standard_F2"

  delete_os_disk_on_termination    = true
  delete_data_disks_on_termination = true

  storage_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "16.04-LTS"
    version   = "latest"
  }

  storage_os_disk {
    name              = "OSDISK"
    caching           = "Readwrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }

  os_profile {
    computer_name  = "XXXXXXXXXXXXXX"
    admin_username = "XXXXXXXXXXXXXX"
    admin_password = "XXXXXXXXXXXXXX"
  }

  os_profile_linux_config {
    disable_password_authentication = false
  }

  identity {
    type = "SystemAssigned"
  }
}

data "azurerm_role_definition" "contributor" {
  name = "Contributor"
}

resource "azurerm_role_assignment" "example" {
  scope                = data.azurerm_subscription.current.id
  role_definition_name = "Contributor"
  principal_id         = data.azurerm_client_config.example.object_id
}

错误信息:

Error: building AzureRM Client: obtain subscription() from Azure CLI: parsing json result from the Azure CLI: waiting for the Azure CLI: exit status 1: ERROR: Please run 'az login' to setup account.
│
│   with provider["registry.terraform.io/hashicorp/azurerm"],
│   on main.tf line 9, in provider "azurerm":
│    9: provider "azurerm" {
解决方案

1. 启用AzureRM Provider的托管标识支持

你的azurerm provider块注释掉了use_msi = true,这是核心问题。Terraform的AzureRM Provider默认会尝试从Azure CLI获取凭据,只有显式开启use_msi才会使用托管标识认证。修改后的provider块如下:

provider "azurerm" {
  features {}
  tenant_id       = "TENANT_ID"
  use_msi         = true
  # 若使用用户分配的托管标识,需额外指定client_id;系统分配的可省略
  # client_id = "USER_ASSIGNED_MSI_CLIENT_ID"
}

2. 显式指定订阅ID(可选但建议)

虽然托管标识可关联到特定订阅,但显式指定subscription_id能避免Terraform尝试从CLI获取订阅信息,减少混淆:

provider "azurerm" {
  features {}
  tenant_id       = "TENANT_ID"
  use_msi         = true
  subscription_id = "YOUR_SUBSCRIPTION_ID"
}

3. 修正角色分配的主体ID

当前角色分配的principal_id用的是data.azurerm_client_config.example.object_id,这是执行Terraform的身份(如本地CLI用户),而非VM的系统分配标识。若要给VM分配角色,应使用VM的标识ID:

resource "azurerm_role_assignment" "example" {
  scope                = data.azurerm_subscription.current.id
  role_definition_name = "Contributor"
  principal_id         = azurerm_virtual_machine.example.identity[0].principal_id
}

4. 确认托管标识的运行环境

托管标识仅适用于Azure内部资源(如Azure VM、Azure Function、Azure VMSS等)上运行Terraform的场景。若在本地机器执行Terraform,托管标识无法生效,必须使用Azure CLI登录或服务主体认证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 09:11:31