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

Terraform部署AKS添加NSG安全规则首次执行报404异常求助

解决Terraform部署AKS时NSG规则创建的竞态条件问题

我之前也碰到过一模一样的情况——AKS自动生成的MC资源组和NSG总是跟不上Terraform的节奏,第一次terraform apply必报404,第二次又能成功。你加的sleep其实只是“赌运气”,根本解决不了本质的竞态问题,因为AKS创建NSG的时机和helm部署ingress的时间没有强关联,就算睡60秒,也可能刚好NSG还没创建完成。

问题根源

你现在用external数据源去查询NSG,但这个查询的时机完全没和AKS的创建进度绑定。哪怕你让它依赖helm_release.ingress,helm部署完成不代表AKS的底层网络资源(比如NSG)已经就绪。AKS创建MC资源组和NSG是在集群初始化的后期阶段,很可能helm都部署完了,NSG还在后台创建中,这时候external数据源查不到NSG,自然就报错了。

最可靠的解决方案:直接从AKS资源获取NSG信息

Terraform的azurerm_kubernetes_cluster资源本身就暴露了节点池的NSG ID,完全不需要用外部脚本去查。我们可以通过这个ID提取NSG的名称和所属资源组,同时让NSG规则直接依赖AKS资源,确保Terraform等待AKS完全创建完成后再去创建规则。

修改你的配置如下:

# 你的AKS集群定义保持不变
resource "azurerm_kubernetes_cluster" "aks" {
  name                = "terraform-aks"
  location            = "westeurope"
  resource_group_name = "terraform-aks-rg"
  dns_prefix          = "terraform-aks"

  default_node_pool {
    name       = "agentpool"
    node_count = 3
    vm_size    = "Standard_D2s_v3"
  }

  identity {
    type = "SystemAssigned"
  }

  tags = {
    Environment = "Production"
  }
}

# 从AKS资源中提取NSG的名称和资源组
locals {
  # 获取节点池的NSG ID
  node_nsg_id             = azurerm_kubernetes_cluster.aks.default_node_pool[0].node_network_security_group_id
  # 从ID中拆分出NSG名称(Azure资源ID的第9段,索引从0开始是第8位)
  node_nsg_name           = element(split("/", local.node_nsg_id), 8)
  # 拆分出NSG所属的资源组(ID的第5段,索引4)
  node_nsg_resource_group = element(split("/", local.node_nsg_id), 4)
}

# 创建NSG规则,直接使用上面的local变量,自动依赖AKS集群
resource "azurerm_network_security_rule" "https" {
  name                        = "myRule"
  priority                    = 100
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "443"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  resource_group_name         = local.node_nsg_resource_group
  network_security_group_name = local.node_nsg_name
}

为什么这个方案能解决问题?

  • Terraform的资源依赖是基于变量引用的:因为azurerm_network_security_rule引用了azurerm_kubernetes_cluster的属性,Terraform会自动等待AKS集群完全创建完成(包括MC资源组和NSG)之后,才会执行NSG规则的创建操作,从根本上避免了竞态条件。
  • 不需要依赖外部脚本和sleep,完全利用Terraform自身的资源依赖机制,比手动加延迟可靠得多。

如果你一定要保留外部查询的方式(不推荐)

如果因为某些原因必须用external数据源查询NSG,那至少要把external数据源的依赖改成直接依赖azurerm_kubernetes_cluster.aks,而不是helm release:

data "external" "aks_nsg" {
  program = ["bash", "./get-aks-nsg.sh"]

  # 确保AKS集群完全创建后再执行查询
  depends_on = [azurerm_kubernetes_cluster.aks]
}

# 然后你的NSG规则依赖这个external数据源
resource "azurerm_network_security_rule" "https" {
  # ... 其他配置 ...
  network_security_group_name = data.external.aks_nsg.result.output
  resource_group_name         = "MC_terraform-aks-rg_terraform-aks_westeurope"

  depends_on = [data.external.aks_nsg]
}

同时,把你的查询脚本改得更精确,避免匹配到其他NSG:

#!/bin/bash
# 精确匹配AKS节点池的NSG,名称通常是aks-agentpool-xxxx-nsg
OUTPUT=$(az network nsg list --resource-group MC_terraform-aks-rg_terraform-aks_westeurope --query "[?contains(name, 'aks-agentpool')].name" -o tsv | head -n 1)
jq -n --arg output "$OUTPUT" '{"output":$output}'

但还是那句话,这种方式不如直接用AKS资源的属性可靠,因为外部查询还是可能因为Azure API的延迟出现问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:16:28