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

如何通过Terraform读取多JSON文件,用for_each部署Azure Shared App Gateway?

在Azure共享应用网关通过Terraform从多JSON文件部署多应用

目录结构规划

先把每个应用的独立配置放在单独JSON文件中,目录结构示例:

terraform/
├── apps/
│   ├── App1.json
│   ├── App2.json
│   └── App3.json
├── main.tf
└── variables.tf

示例应用配置JSON(App1.json)

每个文件包含对应应用的完整网关配置项:

{
  "name": "app1",
  "backend_address_pool": {
    "name": "app1-backend-pool",
    "backend_addresses": [
      {
        "fqdn": "app1-service.example.com"
      }
    ]
  },
  "http_settings": {
    "name": "app1-http-settings",
    "port": 80,
    "protocol": "Http",
    "cookie_based_affinity": "Disabled"
  },
  "probe": {
    "name": "app1-probe",
    "protocol": "Http",
    "path": "/health",
    "interval": 30,
    "timeout": 10
  },
  "listener": {
    "name": "app1-listener",
    "frontend_ip_configuration_name": "appgw-frontend-ip",
    "frontend_port_name": "appgw-frontend-port-80",
    "protocol": "Http",
    "host_name": "app1.example.com"
  },
  "request_routing_rule": {
    "name": "app1-routing-rule",
    "rule_type": "Basic"
  }
}

Terraform配置实现

1. 读取并解析所有应用JSON文件

通过fileset批量获取apps/目录下的JSON文件,再用jsondecode转成Terraform可识别的对象:

locals {
  app_configs = {
    for file in fileset(path.module, "apps/*.json") :
    replace(basename(file), ".json", "") => jsondecode(file("${path.module}/${file}"))
  }
}

这里用basename(file)提取文件名(去除路径),再去掉.json后缀,最终生成App1、App2作为遍历的key,方便后续关联资源。

2. 部署共享应用网关基础资源

先创建网关的共享核心资源(如果尚未存在):

resource "azurerm_resource_group" "appgw" {
  name     = "appgw-rg"
  location = "eastus"
}

resource "azurerm_public_ip" "appgw" {
  name                = "appgw-pip"
  location            = azurerm_resource_group.appgw.location
  resource_group_name = azurerm_resource_group.appgw.name
  allocation_method   = "Static"
  sku                 = "Standard"
}

resource "azurerm_application_gateway" "shared" {
  name                = "shared-appgw"
  resource_group_name = azurerm_resource_group.appgw.name
  location            = azurerm_resource_group.appgw.location
  sku {
    name     = "Standard_v2"
    tier     = "Standard_v2"
    capacity = 2
  }

  frontend_ip_configuration {
    name                 = "appgw-frontend-ip"
    public_ip_address_id = azurerm_public_ip.appgw.id
  }

  frontend_port {
    name = "appgw-frontend-port-80"
    port = 80
  }
}

3. 用for_each批量创建应用专属资源

遍历local.app_configs,自动生成每个应用对应的网关组件:

后端地址池

resource "azurerm_application_gateway_backend_address_pool" "app" {
  for_each               = local.app_configs
  name                   = each.value.backend_address_pool.name
  application_gateway_id = azurerm_application_gateway.shared.id
  backend_addresses      = each.value.backend_address_pool.backend_addresses
}

HTTP设置

resource "azurerm_application_gateway_http_settings" "app" {
  for_eeach                     = local.app_configs
  name                         = each.value.http_settings.name
  application_gateway_id        = azurerm_application_gateway.shared.id
  port                         = each.value.http_settings.port
  protocol                     = each.value.http_settings.protocol
  cookie_based_affinity        = each.value.http_settings.cookie_based_affinity
  pick_host_name_from_backend_address = true
}

健康探针

resource "azurerm_application_gateway_probe" "app" {
  for_eeach                = local.app_configs
  name                    = each.value.probe.name
  application_gateway_id   = azurerm_application_gateway.shared.id
  protocol                = each.value.probe.protocol
  path                    = each.value.probe.path
  interval                = each.value.probe.interval
  timeout                 = each.value.probe.timeout
  unhealthy_threshold     = 3
}

HTTP监听器

resource "azurerm_application_gateway_http_listener" "app" {
  for_each                     = local.app_configs
  name                          = each.value.listener.name
  application_gateway_id         = azurerm_application_gateway.shared.id
  frontend_ip_configuration_name = each.value.listener.frontend_ip_configuration_name
  frontend_port_name            = each.value.listener.frontend_port_name
  protocol                      = each.value.listener.protocol
  host_name                     = each.value.listener.host_name
}

请求路由规则

resource "azurerm_application_gateway_request_routing_rule" "app" {
  for_eeach                 = local.app_configs
  name                      = each.value.request_routing_rule.name
  application_gateway_id     = azurerm_application_gateway.shared.id
  rule_type                 = each.value.request_routing_rule.rule_type
  http_listener_name        = azurerm_application_gateway_http_listener.app[each.key].name
  backend_address_pool_name = azurerm_application_gateway_backend_address_pool.app[each.key].name
  backend_http_settings_name = azurerm_application_gateway_http_settings.app[each.key].name
  probe_name                = azurerm_application_gateway_probe.app[each.key].name
}

关键注意事项

  • 所有应用的网关资源名称(如监听器、后端池名称)必须唯一,避免冲突
  • 如需HTTPS,只需在JSON配置中新增SSL相关字段(如protocol: "Https"、ssl_certificate_name),并在Terraform中创建对应SSL证书资源
  • 可将共享资源名称(如前端IP配置名)提取为变量,避免硬编码在JSON文件中
  • 新增/删除apps/目录下的JSON文件时,Terraform会自动检测并同步创建/销毁对应资源

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 22:43:28