使用幂等 ARM 模板将两个 Azure 应用服务部署到同一个应用服务计划

Deploy two Azure App Services to the same App Service Plan using idempotent ARM TEMPLATE

问题

如何在使用 VSTS 幂等持续集成/持续部署过程时将两个不同的 Azure 应用服务部署到同一个应用服务计划。

环境

下面的模板是用于将 Web 应用服务部署到应用服务计划的模板之一。

它显示了使用命名转换创建应用服务计划:

appname-Plan-q2dkkaaaaaaaa

这是使用以下方法创建的:

"hostingPlanName": "[concat(parameters('appName'),'-Plan-', uniqueString(resourceGroup().id))]",

示例

{
"parameters": {
    "appName": {
        "type": "string",
        "maxLength": 7,
        "metadata": {
            "description": "The name of the app that you wish to create."
        }
    },
    "appServicePlanSku": {
        "type": "string",
        "defaultValue": "Standard",
        "metadata": {
            "description": "The Service Plan SKU"
        }
    },
    "appServicePlanWorkerSize": {
        "type": "string",
        "defaultValue": "0",
        "metadata": {
            "description": "The App Service Plan Worker Size (?)"
        }
    },
    "appServicePlanSkuCode": {
        "type": "string",
        "defaultValue": "S1",
        "metadata": {
            "description": "The App Service Plan SKU Code"
        }
    },
    "appServicePlanNumWorkers": {
        "type": "string",
        "defaultValue": "2",
        "metadata": {
            "description": "The Number of App Service Workers."
        }

},
"variables": {
    "webAppName": "[concat(parameters('appName'),'-wa-', uniqueString(resourceGroup().id))]",
    "hostingPlanName": "[concat(parameters('appName'),'-Plan-', uniqueString(resourceGroup().id))]",
    "stageSlotName": "stageSlot",
    "devSlotName": "devSlot"
    }
},
"resources": [
    {
        "apiVersion": "2016-09-01",
        "name": "[variables('hostingPlanName')]",
        "type": "Microsoft.Web/serverfarms",
        "location": "[resourceGroup().location]",
        "properties": {
            "name": "[variables('hostingPlanName')]",
            "workerSizeId": "[parameters('appServicePlanWorkerSize')]",
            "numberOfWorkers": "[parameters('appServicePlanNumWorkers')]"
        },
        "sku": {
            "Tier": "[parameters('appServicePlanSku')]",
            "Name": "[parameters('appServicePlanSkuCode')]"
        },
        "dependsOn": []
    },
    {
        "apiVersion": "2015-08-01",
        "type": "Microsoft.Web/sites",
        "name": "[variables('webAppName')]",
        "location": "[resourceGroup().location]",
        "kind": "webapp",
        "tags": {
            "Environment": "production",
            "displayName": "WebAppService"
        },
        "dependsOn": [
            "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
        ],
        "properties": {
            "name": "[variables('webAppName')]",
            "serverFarmId": "[resourceId('Microsoft.Web/serverfarms',variables('hostingPlanName'))]"
        },
        "resources": [
            {
                "name": "slotConfigNames",
                "type": "config",
                "apiVersion": "2015-08-01",
                "dependsOn": [
                    "[resourceId('Microsoft.Web/sites', variables('webAppName'))]"
                ],
                "tags": {
                    "displayName": "slotConfigNames"
                },
                "properties": {
                    "appSettingNames": []
                }
            },
            {
                "apiVersion": "2015-08-01",
                "name": "[variables('stageSlotName')]",
                "type": "slots",
                "location": "[resourceGroup().location]",
                "dependsOn": [
                    "[resourceId('Microsoft.Web/sites', variables('webAppName'))]"],
                "properties": {},
                "resources": []
            },
            {
                "apiVersion": "2015-08-01",
                "name": "[variables('devSlotName')]",
                "type": "slots",
                "location": "[resourceGroup().location]",
                "dependsOn": [
                    "[resourceId('Microsoft.Web/sites', variables('webAppName'))]"],
                "properties": {},
                "resources": []
            }
        ]
    }
]
}

问题

我正在尝试执行两个 ARM 模板(类似于上面的示例)以将两个不同的 Web 应用程序部署到同一个服务计划。

很明显,这两个 Web 应用程序必须调用相同的中央资源,以确保它们都部署到相同的应用程序服务资源名称并执行任何更改。

考虑到上面的环境描述,我有什么选择才能让它工作?

热衷于遵循最佳实践。

我希望上面的描述足够详细。抱歉,如果遗漏了什么。谢谢。

ARM模板默认支持您的需求。基本上,如果 ARM 模板遇到存在的资源,如果属性不匹配,它将更新资源。否则它将使用您在 ARM 模板中设置的属性创建资源。

解决方案

我的解决方案是创建三个模板:

  • 用于创建应用服务计划的模板 1。此 ARM 模板存储在 BLOB 容器中,发布管道可通过 SAS URI 访问。
  • 用于创建网络应用程序 A 的模板 2。此模板使用 LINKED TEMPLATE 功能来调用和执行共享模板。
  • 用于创建网络应用程序 B 的模板 3。此模板使用 LINKED TEMPLATE 功能来调用和执行共享模板。

结果

  • 然后两个网络应用程序都发布到同一个服务器场,共享 实例。
  • 部署的幂等性得以保持。
  • 任何应用服务计划部署和任何修正的单一事实。
  • 所需服务器场数量节省的资金。

示例

共享服务计划 - 共享服务计划的 ARM 模板示例:

{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
    "planLabel": {
        "defaultValue": "shared-service-plan",
        "type": "string"
    }
},
"variables": {
    "servicePlanName": "[concat(parameters('planLabel'),'-Plan-', uniqueString(resourceGroup().id))]"
},
"resources": [
    {
        "comments": "Creates an App Service Plan on the Standard (S1) SKU.",
        "type": "Microsoft.Web/serverfarms",
        "sku": {
            "name": "S1",
            "tier": "Standard",
            "size": "S1",
            "family": "S",
            "capacity": 2
        },
        "kind": "app",
        "name": "[variables('servicePlanName')]",
        "apiVersion": "2016-09-01",
        "location": "[resourceGroup().location]",
        "properties": {
            "name": "[variables('servicePlanName')]"
        },
        "dependsOn": []
    }
],
"outputs": {
    "servicePlanResourceId": {
        "type": "string",
        "value": "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]"
    },
    "servicePlanName":{
        "type": "string",
        "value": "[variables('servicePlanName')]"
    },
    "resourceGroupName":{
        "type": "string",
        "value": "[resourceGroup().name]"
    }
}
}

Web 应用程序 A - 包含链接模板的 ARM 模板示例:

{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
    "servicePlanLabel": {
        "type": "string",
        "metadata": {
            "description": "The base name for the App Service Plan to be used in the linked template."
        },
        "defaultValue": "plan"
    },
    "appServicePlanResourceGroup": {
        "type": "string",
        "metadata": {
            "Description": "The name of the Resource Group the shared App Service Plan will be deployed to."
        },
        "defaultValue": "group"
    },
    "appServicePlanTemplateUri": {
        "type": "string",
        "metadata": {
            "description": "The URI to the App Service Plan linked template in BLOB"
        }
    }
},
"variables": {},
"resources": [
    {
        "apiVersion": "2017-05-10",
        "name": "appServicePlanTemplate",
        "type": "Microsoft.Resources/deployments",
        "resourceGroup": "[parameters('appServicePlanResourceGroup')]",
        "properties": {
            "mode": "Incremental",
            "templateLink": {
                "uri": "[parameters('appServicePlanTemplateUri')]",
                "contentVersion": "1.0.0.0"
            },
            "parameters": {
                "planLabel": {
                    "value": "[parameters('servicePlanLabel')]"
                }
            }
        }
    },
    {
        "apiVersion": "2015-08-01",
        "type": "Microsoft.Web/sites",
        "name": "[variables('webAppName')]",
        "location": "[resourceGroup().location]",
        "kind": "webapp",
        "tags": {
            "Environment": "production",
            "displayName": "App"
        },
        "dependsOn": [
            "[resourceId(parameters('appServicePlanResourceGroup'), 'Microsoft.Resources/deployments', 'appServicePlanTemplate')]"
        ],
        "properties": {}
    }
}
}

希望这对某人有用。

谢谢 斯科特

REF https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/azure-resource-manager/resource-group-linked-templates.md