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

VSTS发布定义中ARM模板部署:仅创建不存在的Azure资源

解决ARM模板部署时跳过已存在资源&保留手动应用设置的问题

针对你遇到的这两个头疼的问题——部署时不想更新已存在的Function App,又怕手动添加的应用设置被覆盖,我给你整理了具体的解决方案:

一、仅在资源不存在时创建Function App

ARM模板默认的Incremental部署模式不会删除现有资源,但会更新模板中定义的资源属性。如果想要完全跳过已存在的资源(不做任何更新操作),可以在模板里给Function App资源添加condition判断,检查该资源是否已经存在于资源组中:

  1. 先在模板的parameters部分定义Function App的名称参数:
  2. 在Function App的资源块里,添加condition属性,用resourceId函数尝试获取资源ID,如果返回空则说明资源不存在,才执行创建逻辑:
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "functionAppName": {
      "type": "string",
      "metadata": {
        "description": "Name of your Azure Function App"
      }
    },
    // 其他必要参数比如存储账户、宿主计划名称等...
  },
  "resources": [
    {
      "type": "Microsoft.Web/sites",
      "apiVersion": "2022-03-01",
      "name": "[parameters('functionAppName')]",
      // 核心判断:资源不存在才创建
      "condition": "[empty(resourceId('Microsoft.Web/sites', parameters('functionAppName')))]",
      "location": "[resourceGroup().location]",
      "properties": {
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]",
        "siteConfig": {
          "appSettings": []
        }
        // 其他基础配置...
      },
      "dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]"
      ]
    }
  ]
}

这样部署时,如果资源组里已经有同名的Function App,这个资源块会直接被跳过,不会做任何修改。另外提一句:你现在用的New-AzureRMResourceGroupDeployment已经被弃用了,建议换成Az模块的New-AzResourceGroupDeployment命令,后续兼容性更好。

二、保留手动添加的应用设置

默认情况下,ARM模板里定义的appSettings会完全覆盖现有配置,导致你手动加的密钥丢失。要解决这个问题,我们可以用ARM的list函数获取现有应用设置,再和模板里的配置合并:

在Function App的嵌套config/appsettings资源块里,修改properties为合并后的结果:

{
  "type": "Microsoft.Web/sites/config",
  "apiVersion": "2022-03-01",
  "name": "[concat(parameters('functionAppName'), '/appsettings')]",
  "dependsOn": [
    "[resourceId('Microsoft.Web/sites', parameters('functionAppName'))]"
  ],
  "properties": "[union(list(concat(resourceId('Microsoft.Web/sites', parameters('functionAppName')), '/config/appsettings'), '2022-03-01').properties, variables('defaultAppSettings'))]"
}

这里的逻辑是:

  • list(...):获取Function App当前已有的所有应用设置
  • variables('defaultAppSettings'):你在模板里定义的默认配置(比如必须的连接字符串、环境变量)
  • union():合并两个对象,重复的键会用模板里的值覆盖现有值,手动添加的非重复键则会被保留

不过要注意,第一次部署时资源还不存在,list函数会报错,所以可以结合前面的condition用if函数做判断:

"properties": "[if(empty(resourceId('Microsoft.Web/sites', parameters('functionAppName'))), variables('defaultAppSettings'), union(list(concat(resourceId('Microsoft.Web/sites', parameters('functionAppName')), '/config/appsettings'), '2022-03-01').properties, variables('defaultAppSettings')))]"

这样第一次部署时直接用模板里的默认设置,后续部署就会合并现有配置和模板配置,手动加的密钥再也不会丢了。

额外小提示

在Azure DevOps(原VSTS)的发布管道里,ARM模板部署任务默认用的就是Incremental模式,千万别改成Complete模式,否则会删除模板里没定义的资源,那麻烦就大了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:03:44