在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
相关产品推荐
相关产品推荐

