【发布时间】:2019-07-08 09:28:38
【问题描述】:
如何通过资源类型和标识符识别 ARM 模板中是否存在 azure 资源
【问题讨论】:
-
ARM 模板本质上是声明性的(所以理论上这不是必需的) - 你的情况是什么,可能有另一种方法来做你在想的事情......
标签: azure azure-resource-manager arm-template
如何通过资源类型和标识符识别 ARM 模板中是否存在 azure 资源
【问题讨论】:
标签: azure azure-resource-manager arm-template
实际上是有可能的。您可以使用资源组标签来标记当前部署的版本,如果设置了标签则跳过部署。所有这些都可以通过链接模板来实现。
请注意,我们不检查资源本身是否存在,但我们仍然允许编写可能包含一次性初始化模板的 ARM 模板。如果资源组被删除并且资源丢失(假设您再次创建了资源组),最后一个将恢复资源。您可以扩展它以支持每个资源标签,这在某些情况下会更有用。
开始部署的模板可能如下所示:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"DeploymentTemplateLink": {
"type": "string"
},
"DeploymentVersion": {
"defaultValue": 1,
"type": "int"
}
},
"variables": {
"rgWithDefaultVersion": {
"tags": {
"Version": "0"
}
}
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-05-10",
"name": "DeploymentTemplate",
"condition": "[less(int(union(variables('rgWithDefaultVersion'), resourceGroup()).tags['Version']), parameters('DeploymentVersion'))]",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[parameters('DeploymentTemplateLink')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"DeploymentVersion": {
"value": "[parameters('DeploymentVersion')]"
}
}
}
}
]
}
链接模板的条件查看标签并仅在当前版本(存储在标签中)小于请求的版本时返回 true。您实际上不必维护版本控制:只需不设置 DeploymentVersion 参数,它只会在第一次部署。如果您决定重新部署,您始终可以选择增加版本,这将导致链接模板的部署(也称为“主部署”)。
主要部署模板在你身上,但它应该包含一个 tags 资源以维护逻辑。
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"DeploymentVersion": {
"defaultValue": 1,
"type": "int"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Resources/tags",
"name": "default",
"apiVersion": "2019-10-01",
"dependsOn": [],
"properties": {
"tags": {
"Version": "[string(parameters('DeploymentVersion'))]"
}
}
}
]
}
Remark 给那些不了解 union() 和 rgWithDefaultVersion 东西的人。如果引用的对象不包含属性,ARM 模板部署将失败。在我们的例子中,我们有两个这样的属性:'tags' 和 'Version'。 'Tags' 仅当特定资源组具有或曾经具有标签时才会存在。 'Version' 只有在我们已经编写过一次之后(在主部署中)才会存在。因此,在我们访问它们之前,我们使用适当的默认值对返回的对象执行 union() 操作,以确保我们可以安全地访问所提到的属性。
【讨论】:
union 的诀窍太棒了
merge,而不是replace)当有多个受状态影响的资源保留为RG标签时,在并行运行ARM模板步骤而不是运行ARM模板步骤时,维护标签而不丢失一些标签就成了一个问题。序列。
在 arm 模板中无法做到这一点。您可以使用一些外部源(如powershell)来确定并传入具有适当值的参数,或者您可以使用标签来解决这个问题(有一个代表资源存在\不存在的标签)。
【讨论】:
资源管理器提供以下函数来获取资源值:Resource functions for Azure Resource Manager templates
您可以用一块 powershell\whatever 包装您的模板,这将确定资源是否存在,并根据该参数传入参数值,并在模板中使用条件语句来决定根据输入(但输入必须来自其他地方)
【讨论】:
您可能会发现 https://docs.microsoft.com/en-us/azure/developer/terraform/overview 这对于解决您的问题很有用。
Hashicorp Terraform 是一种用于配置和管理云基础设施的开源工具。它将基础设施编入描述云资源拓扑的配置文件中。这些资源包括虚拟机、存储帐户和网络接口。 Terraform CLI 提供了一种将配置文件部署到 Azure 并对其进行版本控制的简单机制。
但这将要求您远离 ARM 模板。
【讨论】:
我最近需要一个解决方案来基本上对 SQL 服务器进行增量更新。既然你不能这样做;模板将因 NameAlreadyExists 错误而失败。 所以我需要检查资源不存在,如果不存在才创建。
添加“条件”检查 azure 资源 id 是否存在;如果有,请不要创建。
{
...
"condition": "[empty(resourceId('[resourceGroup().id]', 'Microsoft.SQL/servers', parameters('serverName')))]",
...
}
您可以对任何资源类型执行此操作。
【讨论】:
resourceId 函数实际上并不检查资源是否存在,它只是返回给定资源组、类型和名称的 ID。有关更多信息,请参阅文档 - docs.microsoft.com/en-us/azure/azure-resource-manager/…