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

Terraform部署Azure ACI时挂载Azure文件共享失败求助

问题:Azure容器实例(ACI)挂载Azure文件共享失败

问题详情

使用Terraform部署ACI时,尝试挂载4个Azure文件共享但持续失败,报错重复多次"Failed to mount Azure File Volume",最终因超时导致部署失败。

所用Terraform代码

存储账户及文件共享配置

resource "azurerm_storage_account" "file_share_storage_account" {
    name                     = "st${var.lztri}${substr(var.st_file_share.name, 0, 3)}${var.env}${var.loc}${var.stage}01"
    resource_group_name      = azurerm_resource_group.storage_rg.name
    location                 = var.location

    account_replication_type = var.st_file_share.account_replication_type
    account_kind             = var.st_file_share.account_kind
    access_tier              = var.st_file_share.access_tier

    enable_https_traffic_only       = var.st_file_share.enable_https_traffic_only
    min_tls_version                  = var.st_file_share.min_tls_version

    is_hns_enabled                  = var.st_file_share.is_hns_enabled  // must be true for ADLS Gen2
    account_tier                    = var.st_file_share.account_tier    // must be Standard for HNS enabled

  public_network_access_enabled   = true
  default_to_oauth_authentication = true

  dynamic "network_rules" {
    for_each = local.st_net_rules
    content {
      default_action             = network_rules.value.default_action
      bypass                     = network_rules.value.bypass
      ip_rules                   = network_rules.value.ip_rules
      virtual_network_subnet_ids = network_rules.value.virtual_network_subnet_ids
    }
  }

  tags = merge(local.mandatory_tags, {  })
  lifecycle { ignore_changes = [tags] }
}

resource "azurerm_role_assignment" "st_role_assignment" {
  for_each           = toset(["Storage Blob Data Contributor"])
  scope              = azurerm_storage_account.file_share_storage_account.id
  role_definition_name = each.key
  principal_id       =  data.azurerm_client_config.client_config.object_id
}

resource "azurerm_storage_share" "file_share" {
  for_each             = { for each in var.shares_config : each.share_name => each }
  name                 = each.value.share_name
  quota                = each.value.quota_gb
  storage_account_name = azurerm_storage_account.file_share_storage_account.name
}

容器组配置

resource "azurerm_container_group" "containergroup" {
  name                = "ci-${var.lztri}-sonarqube-${var.env}-${var.loc}${var.stage != "" ? "-" : ""}${var.stage}-01"
  location            = var.location
  resource_group_name = azurerm_resource_group.sonarqube_rg.name
  ip_address_type     = var.ci_sonarqube_ip_address_type
  os_type             = var.ci_sonarqube_os_type
 
  container {
    name   = var.ci_sonarqube_container_name
    image  = var.ci_sonarqube_image_name
    cpu    = var.ci_sonarqube_cpu_core_number
    memory = var.ci_sonarqube_memory_size

    ports {
        port     = var.ci_sonarqube_ports
        protocol = var.ci_sonarqube_protocol
      }

    dynamic "volume" {
      for_each = var.shares_config
      content {
        name                 = volume.value.share_name
        mount_path           = "/opt/sonarqube/${volume.value.share_name}"
        share_name           = volume.value.share_name
        storage_account_name = azurerm_storage_account.file_share_storage_account.name
        storage_account_key  = azurerm_storage_account.file_share_storage_account.primary_access_key
      }
    }
  }

  timeouts {
    create = "2h"
    delete = "15m"
  }
}

错误信息

polling after ContainerGroupsCreateOrUpdate: Code="Failed" Message="The async operation failed." AdditionalInfo=[{"error":{"message":"Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Failed to mount Azure File Volume.;Subscription deployment didn't reach a successful provisioning state after '00:30:00'."}

排查及修复方案

1. 关闭默认OAuth认证

存储账户启用了default_to_oauth_authentication = true,但ACI挂载文件共享目前仅支持存储账户密钥认证,默认OAuth会导致认证失败。修改存储账户配置:

resource "azurerm_storage_account" "file_share_storage_account" {
    # ... 其他配置 ...
    default_to_oauth_authentication = false  # 改为false
    # ... 其他配置 ...
}

2. 移除无效的RBAC角色分配

添加的Storage Blob Data Contributor权限针对Blob存储,与文件共享无关,且ACI挂载文件共享不需要RBAC权限(依赖存储账户密钥),直接删除该角色分配:

# 删除以下角色分配块
# resource "azurerm_role_assignment" "st_role_assignment" {
#   for_each           = toset(["Storage Blob Data Contributor"])
#   scope              = azurerm_storage_account.file_share_storage_account.id
#   role_definition_name = each.key
#   principal_id       =  data.azurerm_client_config.client_config.object_id
# }

3. 验证存储账户网络规则

确保存储账户的网络规则允许ACI访问:

  • 若ACI使用公网IP:检查network_rules的default_action是否为Allow,或ip_rules包含ACI的出站公网IP
  • 若ACI部署在VNet内:确保virtual_network_subnet_ids包含ACI所在子网ID

4. 添加资源依赖确保同步

添加depends_on到容器组,确保所有文件共享创建完成后再部署ACI,避免密钥或共享未就绪:

resource "azurerm_container_group" "containergroup" {
  # ... 其他配置 ...
  depends_on = [azurerm_storage_share.file_share]
  # ... 其他配置 ...
}

5. 检查容器挂载路径权限

Sonarqube容器默认使用sonarqube用户运行,确保挂载路径/opt/sonarqube/${volume.value.share_name}对该用户有读写权限。可通过自定义启动脚本或修改容器镜像权限解决,或选择容器内已存在且有权限的路径。

内容的提问来源于stack exchange,提问作者pieter-jan goeman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 19:18:13