【问题标题】:Can not deploy ARM template of Azure App Service with Linux that has mounted storage无法使用已装载存储的 Linux 部署 Azure 应用服务的 ARM 模板
【发布时间】:2021-11-08 23:53:54
【问题描述】:

我们正在尝试部署 Azure Linux 应用服务,该服务也已挂载存储。这是我们的 ARM 模板

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "Environment": {
            "type": "String",
            "allowedValues": [
                "dev",
                "stg",
                "prd"
            ]
        },
        "Region": {
            "type": "string",
            "allowedValues": [
                "eu",
                "we"
            ]
        },
        "MagentoMediaFileShareName": {
            "type": "string"
        },
        "StorageAccountName": {
            "type": "string"
        },
        "StorageAccountAccessKey": {
            "type": "securestring"
        },
        "MagentoMediaMountPath": {
            "type": "string",
            "defaultValue": "/var/www/html/pub/external_media"
        }
    },
    "variables": {
        "Location": "[resourceGroup().location]",
        "ResourcePrefix": "[format('ariva-{0}-{1}-magento', parameters('Environment'), parameters('Region'))]",
        "WebSiteName": "[concat(variables('ResourcePrefix'), '-web')]",
        "ServicePlanId": "[format('/subscriptions/{0}/resourceGroups/ariva-{1}-{2}/providers/Microsoft.Web/serverfarms/ariva-{1}-{2}-asp', subscription().subscriptionId,  parameters('Environment'), parameters('Region'))]"
    },
    "resources": [
        {
            "type": "Microsoft.Web/sites",
            "apiVersion": "2020-12-01",
            "name": "[variables('WebSiteName')]",
            "location": "[variables('Location')]",
            "kind": "app,linux,container",
            "properties": {
                "enabled": true,
                "hostNameSslStates": [
                    {
                        "name": "[concat(variables('WebSiteName'), '.azurewebsites.net')]",
                        "sslState": "Disabled",
                        "hostType": "Standard"
                    },
                    {
                        "name": "[concat(variables('WebSiteName'), '.scm.azurewebsites.net')]",
                        "sslState": "Disabled",
                        "hostType": "Repository"
                    }
                ],
                "serverFarmId": "[variables('ServicePlanId')]",
                "reserved": true,
                "isXenon": false,
                "hyperV": false,
                "siteConfig": {
                    "numberOfWorkers": 1,
                    "linuxFxVersion": "DOCKER|mcr.microsoft.com/appsvc/staticsite:latest",
                    "acrUseManagedIdentityCreds": false,
                    "alwaysOn": false,
                    "http20Enabled": false,
                    "functionAppScaleLimit": 0,
                    "minimumElasticInstanceCount": 1
                },
                "scmSiteAlsoStopped": false,
                "clientAffinityEnabled": false,
                "clientCertEnabled": false,
                "clientCertMode": "Required",
                "hostNamesDisabled": false,
                "customDomainVerificationId": "1071794BD68C78EC0A4569F03C034F6E1B21BD4E6D35725D99523AC00AE12AA1",
                "containerSize": 0,
                "dailyMemoryTimeQuota": 0,
                "keyVaultReferenceIdentity": "SystemAssigned",
                "httpsOnly": false,
                "redundancyMode": "None",
                "storageAccountRequired": false
            }
        },
        {
            "type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies",
            "apiVersion": "2020-12-01",
            "name": "[concat(variables('WebSiteName'), '/ftp')]",
            "location": "[variables('Location')]",
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites', variables('WebSiteName'))]"
            ],
            "properties": {
                "allow": true
            }
        },
        {
            "type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies",
            "apiVersion": "2020-12-01",
            "name": "[concat(variables('WebSiteName'), '/scm')]",
            "location": "[variables('Location')]",
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites', variables('WebSiteName'))]"
            ],
            "properties": {
                "allow": true
            }
        },
        {
            "type": "Microsoft.Web/sites/config",
            "apiVersion": "2020-12-01",
            "name": "[concat(variables('WebSiteName'), '/web')]",
            "location": "[variables('Location')]",
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites', variables('WebSiteName'))]"
            ],
            "properties": {
                "numberOfWorkers": 1,
                "defaultDocuments": [
                    "Default.htm",
                    "Default.html",
                    "Default.asp",
                    "index.htm",
                    "index.html",
                    "iisstart.htm",
                    "default.aspx",
                    "index.php",
                    "hostingstart.html"
                ],
                "netFrameworkVersion": "v4.0",
                "linuxFxVersion": "DOCKER|mcr.microsoft.com/appsvc/staticsite:latest",
                "requestTracingEnabled": false,
                "remoteDebuggingEnabled": false,
                "remoteDebuggingVersion": "VS2019",
                "httpLoggingEnabled": false,
                "acrUseManagedIdentityCreds": false,
                "logsDirectorySizeLimit": 35,
                "detailedErrorLoggingEnabled": false,
                "publishingUsername": "[concat('$', variables('WebSiteName'))]",
                "azureStorageAccounts": {
                    "magento-media": {
                        "type": "AzureFiles",
                        "accountName": "[parameters('StorageAccountName')]",
                        "shareName": "[parameters('MagentoMediaFileShareName')]",
                        "mountPath": "[parameters('MagentoMediaMountPath')]",
                        "accessKey": "[parameters('StorageAccountAccessKey')]"
                    }
                },
                "scmType": "None",
                "use32BitWorkerProcess": true,
                "webSocketsEnabled": true,
                "alwaysOn": true,
                "managedPipelineMode": "Integrated",
                "virtualApplications": [
                    {
                        "virtualPath": "/",
                        "physicalPath": "site\\wwwroot",
                        "preloadEnabled": false
                    }
                ],
                "loadBalancing": "LeastRequests",
                "experiments": {
                    "rampUpRules": []
                },
                "autoHealEnabled": false,
                "vnetRouteAllEnabled": false,
                "vnetPrivatePortsCount": 0,
                "localMySqlEnabled": false,
                "ipSecurityRestrictions": [
                    {
                        "ipAddress": "Any",
                        "action": "Allow",
                        "priority": 1,
                        "name": "Allow all",
                        "description": "Allow all access"
                    }
                ],
                "scmIpSecurityRestrictions": [
                    {
                        "ipAddress": "Any",
                        "action": "Allow",
                        "priority": 1,
                        "name": "Allow all",
                        "description": "Allow all access"
                    }
                ],
                "scmIpSecurityRestrictionsUseMain": false,
                "http20Enabled": true,
                "minTlsVersion": "1.2",
                "scmMinTlsVersion": "1.0",
                "ftpsState": "AllAllowed",
                "preWarmedInstanceCount": 0,
                "functionAppScaleLimit": 0,
                //"healthCheckPath": "/health_check.php",
                "functionsRuntimeScaleMonitoringEnabled": false,
                "minimumElasticInstanceCount": 1
            }
        },
        {
            "type": "Microsoft.Web/sites/hostNameBindings",
            "apiVersion": "2020-12-01",
            "name": "[concat(variables('WebSiteName'), '/', variables('WebSiteName'), '.azurewebsites.net')]",
            "location": "[variables('Location')]",
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites', variables('WebSiteName'))]"
            ],
            "properties": {
                "siteName": "[variables('WebSiteName')]",
                "hostNameType": "Verified"
            }
        }
    ]
}

如果我们执行这个确切的模板,我们将收到以下错误

{
    "status": "Failed",
    "error": {
        "code": "BadRequest",
        "message": "Required parameter AccessKey is missing.",
        "details": [
            {
                "message": "Required parameter AccessKey is missing."
            },
            {
                "code": "BadRequest"
            },
            {}
        ]
    }
}

如果我们通过门户手动挂载存储并尝试更改配置或添加部署槽,我们会收到相同的错误。

一旦我删除了挂载的存储配置,一切正常。

我们需要在我们的 DevOps 管道中使用它,在部署之前和之后手动卸载-重新安装存储是不可接受的。这将导致重大问题和停机时间。我们可以做些什么来克服这个问题?

更新 1

我尝试手动创建一个完全独立的网络应用程序和存储帐户。例如,当我连接存储挂载并尝试启用运行状况检查时,我得到了同样的错误。我认为 Azure 中存在错误。

更新 2

这是部署依赖存储帐户的模板

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "Environment": {
            "type": "String",
            "allowedValues": [
                "dev",
                "stg",
                "prd"
            ]
        },
        "Region": {
            "type": "string",
            "allowedValues": [
                "eu",
                "we"
            ]
        }
    },
    "variables": {
        "Location": "[resourceGroup().location]",
        "StorageAccountName": "[format('ariva{0}{1}magentostorage', parameters('Environment'), parameters('Region'))]",
        "MagentoMediaFileShareName": "magento-media"
    },
    "resources": [
        {
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2021-04-01",
            "name": "[variables('StorageAccountName')]",
            "location": "[variables('Location')]",
            "sku": {
                "name": "Standard_LRS",
                "tier": "Standard"
            },
            "kind": "StorageV2",
            "properties": {
                "allowCrossTenantReplication": true,
                "minimumTlsVersion": "TLS1_2",
                "allowBlobPublicAccess": true,
                "allowSharedKeyAccess": true,
                "networkAcls": {
                    "resourceAccessRules": [],
                    "bypass": "AzureServices",
                    "virtualNetworkRules": [],
                    "ipRules": [],
                    "defaultAction": "Allow"
                },
                "supportsHttpsTrafficOnly": true,
                "encryption": {
                    "services": {
                        "file": {
                            "keyType": "Account",
                            "enabled": true
                        },
                        "blob": {
                            "keyType": "Account",
                            "enabled": true
                        }
                    },
                    "keySource": "Microsoft.Storage"
                },
                "accessTier": "Hot"
            }
        },
        {
            "type": "Microsoft.Storage/storageAccounts/blobServices",
            "apiVersion": "2021-04-01",
            "name": "[concat(variables('StorageAccountName'), '/default')]",
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName'))]"
            ],
            "sku": {
                "name": "Standard_LRS",
                "tier": "Standard"
            },
            "properties": {
                "changeFeed": {
                    "enabled": false
                },
                "restorePolicy": {
                    "enabled": false
                },
                "containerDeleteRetentionPolicy": {
                    "enabled": true,
                    "days": 7
                },
                "cors": {
                    "corsRules": []
                },
                "deleteRetentionPolicy": {
                    "enabled": true,
                    "days": 7
                },
                "isVersioningEnabled": false
            }
        },
        {
            "type": "Microsoft.Storage/storageAccounts/fileServices",
            "apiVersion": "2021-04-01",
            "name": "[concat(variables('StorageAccountName'), '/default')]",
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName'))]"
            ],
            "sku": {
                "name": "Standard_LRS",
                "tier": "Standard"
            },
            "properties": {
                "shareDeleteRetentionPolicy": {
                    "enabled": true,
                    "days": 7
                }
            }
        },
        {
            "type": "Microsoft.Storage/storageAccounts/queueServices",
            "apiVersion": "2021-04-01",
            "name": "[concat(variables('StorageAccountName'), '/default')]",
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName'))]"
            ],
            "properties": {
                "cors": {
                    "corsRules": []
                }
            }
        },
        {
            "type": "Microsoft.Storage/storageAccounts/tableServices",
            "apiVersion": "2021-04-01",
            "name": "[concat(variables('StorageAccountName'), '/default')]",
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName'))]"
            ],
            "properties": {
                "cors": {
                    "corsRules": []
                }
            }
        },
        {
            "type": "Microsoft.Storage/storageAccounts/fileServices/shares",
            "apiVersion": "2021-04-01",
            "name": "[concat(variables('StorageAccountName'), '/default/', variables('MagentoMediaFileShareName'))]",
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts/fileServices', variables('StorageAccountName'), 'default')]",
                "[resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName'))]"
            ],
            "properties": {
                "accessTier": "TransactionOptimized",
                "shareQuota": 5120,
                "enabledProtocols": "SMB"
            }
        }
    ],
    "outputs": {
        "MagentoMediaFileShareName": {
            "type": "string",
            "value": "[variables('MagentoMediaFileShareName')]"
        },
        "StorageAccountName": {
            "type": "string",
            "value": "[variables('StorageAccountName')]"
        },
        "StorageAccountAccessKey": {
            "type": "securestring",
            "value": "[listKeys(variables('StorageAccountName'), '2019-04-01').keys[0].value]"
        }
    }
}

更新 3 - 临时解决方法

我们找到了临时解决方法。我们没有通过 ARM 模板部署文件挂载,而是从 ARM 模板中删除了该位,之后,我们在 DevOps 管道中使用以下构建步骤通过 azure CLI 挂载存储

 - task: AzureCLI@2
   displayName: 'Attach media volume'
   inputs:
     azureSubscription: '${{ parameters.azureSubscription }}'
     scriptType: pscore
     scriptLocation: inlineScript
     inlineScript: |
       az webapp config storage-account add `
         --resource-group ${{ parameters.resourceGroup }} `
         --name "$(WebSiteName)" `
         --access-key "$(StorageAccountAccessKey)" `
         --custom-id magento-media `
         --storage-type AzureFiles `
         --share-name "$(MagentoMediaFileShareName)" `
         --account-name "$(StorageAccountName)" `
         --mount-path "/var/www/html/pub/external_media"

这当然不能解决问题。

  1. 这样做,ARM 模板将实质上移除挂载,然后由脚本部署,导致停机
  2. 挂载完成后,我们仍然无法通过门户更改任何 WebApp 属性,我们将收到缺少 AccessKey 的错误

【问题讨论】:

  • 如何配置存储帐户的安全性?也只是为了确认,当 //"healthCheckPath": "/health_check.php", 被评论时,您的模板会部署,但如果不是,您会收到错误消息?
  • @RyanHill-MSFT 我们正在另一个 ARM 模板中部署存储。我们没有任何特定的安全设置。我已经使用我们使用的存储 ARM 模板更新了帖子。然后,我们输出 AccessKey 并将其作为此部署的输入参数提供。至于健康检查,它还没有配置。当我们使用它时,它不会改变行为,无论有没有健康检查,我们仍然会收到 AccessKey 失败。我提到健康检查的原因是,当您通过 GUI 挂载存储并尝试添加健康检查时,会引发相同的错误。
  • 在 Azure 门户中,您设置的存储帐户是否具有访问密钥?我没有遇到你在mounting the storage account to the app service 时遇到的同样问题。
  • 您的设置应该类似于i.imgur.com/Qbwl5cb.png
  • 非常感谢瑞恩。根据以下建议更改 ARM 模板后,就存储安装而言一切正常))

标签: azure azure-web-app-service azure-storage azure-resource-manager azure-storage-files


【解决方案1】:

azureStorageAccounts 不是Microsoft.Web sites/config 2020-12-01 的一部分,但它在Microsoft.Web sites 2020-12-01 SiteConfig 属性下。这可能是没有找到、没有上传 accessKey 的原因。我会把azureStorageAccounts移到siteConfig下面

【讨论】:

  • 谢谢瑞恩。你其实是对的。这部分回答了我的问题。问题是当您将 WebApp 导出为 ARM 模板时,它会提供不同的 API 版本 2021-01-15,这在 Microsoft 文档中不可用。可用的版本是 2020-12-01,我只是用它替换了导出模板中的值。这显然不起作用,因为架构不同。我们该如何解决这种情况?
  • 您可以使用ARM template tool test kit。如果我没记错的话,ARMBicep VS Code Extensions 中使用的 linter 就是利用了这个。
  • 确实如此。 Linter 确实帮了一点忙。但我看到的主要问题是,当您导出 WebApp ARM 模板时,它不能开箱即用。此外,它引用的 API 版本至少没有记录,甚至可能不存在,并且 linter 抱怨该版本
  • 我会看看我能找到与 API 版本相关的文档更新的内容。
  • 这真是太棒了!感谢更新。我希望 json 架构也将被发布,以便 VS Code 扩展识别它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-28
  • 2020-10-12
  • 1970-01-01
  • 2020-08-23
  • 1970-01-01
  • 2019-02-11
相关资源
最近更新 更多