(400) 通过 ARM 部署 Function App 时的错误请求

(400) Bad Request when deploying a Function App via ARM

希望有人能告诉我这个 ARM 模板部署有什么问题。

使用问题底部的模板,我可以部署一个功能应用程序 - 带有应用程序服务计划和存储帐户 - 但我收到以下错误。

STATUS              BadRequest
PROVISIONING STATE  Failed
TIMESTAMP           4/19/2017, 1:33:00 PM
DURATION            1 second
TYPE                Microsoft.Web/sites/config
RESOURCE ID         /subscriptions/blah-blah-blah/resourceGroups/blah/providers/Microsoft.Web/sites/functionname/config/appsettings
STATUSMESSAGE       {
                        "Code": "BadRequest",
                        "Message": "There was a conflict. The remote server returned an error: (400) Bad Request.",
                        "Target": null,
                        "Details": [
                        {
                            "Message": "There was a conflict. The remote server returned an error: (400) Bad Request."
                        },
                        {
                            "Code": "BadRequest"
                        },
                        {
                            "ErrorEntity": {
                                "ExtendedCode": "01020",
                                "MessageTemplate": "There was a conflict. {0}",
                                "Parameters": [
                                    "The remote server returned an error: (400) Bad Request."
                                ],
                                "Code": "BadRequest",
                                "Message": "There was a conflict. The remote server returned an error: (400) Bad Request."
                            }
                        }],
                        "Innererror": null
                    }
RESOURCE            functionname/appsettings

如果我从模板的函数应用程序部分删除此 AppSetting 属性,则部署工作正常。

"WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('Storage_Account_Name'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name')),'2015-05-01-preview').key1)]",

但是当我转到已部署的功能应用程序时,我收到了这个错误弹出窗口。

Error:

'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING' application setting is missing from your app. This setting contains a connection string for an Azure Storage account that is used to host your functions content. Your app will be completely broken without this setting. You may need to delete and recreate this function app if you no longer have access to the value of that application setting.

我还注意到,如果我在成功部署后尝试在门户中手动添加该应用程序设置,我会遇到与初始部署相同的错误。

因此,我不知道是不是我将其放入模板中的方式不正确,或者函数应用程序的 Azure 部署中的某些内容是否已损坏。

我哪里错了?

模板

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "App_Service_Plan_Name": {
            "defaultValue": "aspname",
            "type": "String"
        },
        "Functions_App_Name": {
            "defaultValue": "funcname",
            "type": "String"
        },
        "Storage_Account_Name": {
            "defaultValue": "storagename",
            "type": "String"
        }
    },
    "variables": {},
    "resources": [
        {
            "comments": "Deployed from template",
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[parameters('Storage_Account_Name')]",
            "apiVersion": "2016-01-01",
            "sku": {
                "name": "Standard_LRS"
            },
            "location": "[resourceGroup().location]",
            "kind": "Storage"
        },
        {
            "comments": "Deployed from template",
            "type": "Microsoft.Web/serverfarms",
            "sku": {
                "name": "Y1",
                "tier": "Dynamic",
                "size": "Y1",
                "family": "Y",
                "capacity": 0
            },
            "kind": "functionapp",
            "name": "[parameters('App_Service_Plan_Name')]",
            "apiVersion": "2015-08-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "name": "[parameters('App_Service_Plan_Name')]",
                "numberOfWorkers": 0
            },
            "dependsOn": []
        },
        {
            "comments": "Deployed from template",
            "type": "Microsoft.Web/sites",
            "kind": "functionapp",
            "name": "[parameters('Functions_App_Name')]",
            "apiVersion": "2015-08-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "name": "[parameters('Functions_App_Name')]",
                "hostNames": [
                    "[concat(parameters('Functions_App_Name'),'.azurewebsites.net')]"
                ],
                "enabledHostNames": [
                    "[concat(parameters('Functions_App_Name'),'.azurewebsites.net')]",
                    "[concat(parameters('Functions_App_Name'),'.scm.azurewebsites.net')]"
                ],
                "hostNameSslStates": [
                    {
                        "name": "[concat(parameters('Functions_App_Name'),'.azurewebsites.net')]",
                        "sslState": 0,
                        "thumbprint": null,
                        "ipBasedSslState": 0
                    },
                    {
                        "name": "[concat(parameters('Functions_App_Name'),'.scm.azurewebsites.net')]",
                        "sslState": 0,
                        "thumbprint": null,
                        "ipBasedSslState": 0
                    }
                ],
                "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('App_Service_Plan_Name'))]"
            },
            "dependsOn": [
                "[resourceId('Microsoft.Web/serverfarms', parameters('App_Service_Plan_Name'))]",
                "[resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name'))]"
            ],
            "resources": [
                {
                    "apiVersion": "2015-08-01",
                    "name": "appsettings",
                    "type": "config",
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/Sites', parameters('Functions_App_Name'))]",
                        "[resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name'))]"
                    ],
                    "properties": {
                        "FUNCTIONS_EXTENSION_VERSION": "~1",
                        "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('Storage_Account_Name'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name')),'2015-05-01-preview').key1)]",
                        "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('Storage_Account_Name'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name')),'2015-05-01-preview').key1)]",
                        "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('Storage_Account_Name'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name')),'2015-05-01-preview').key1)]",
                        "WEBSITE_CONTENTSHARE": "[concat(parameters('Functions_App_Name'),'_files')]",
                        "WEBSITE_NODE_DEFAULT_VERSION": "6.5.0"
                    }
                },
                {
                    "apiVersion": "2015-08-01",
                    "name": "web",
                    "type": "config",
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/Sites', parameters('Functions_App_Name'))]",
                        "[resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name'))]"
                    ],
                    "properties": {
                        "cors": {
                            "allowedOrigins": [
                                "[concat('https://',parameters('Storage_Account_Name'),'.blob.core.windows.net')]"
                            ]
                        }
                    }
                }
            ]
        }
    ]
}

所以通常情况下,在花了一天左右的时间试图找出问题所在,然后才崩溃并求助于 SO,一旦我这样做,我就会发现问题所在。

问题不在于 WEBSITE_CONTENTAZUREFILECONNECTIONSTRING,而在于 WEBSITE_CONTENTSHARE。这里面有一个下划线,存储帐户文件共享的命名约定中不允许使用下划线。

所以,请记住,当我看到类似 存在冲突... 的错误时,请考虑 ...使用命名约定[=24] =],而不是 ...使用现有资源

我还必须将 3 个 Azure URL 添加到 CORS AllowedOrigins 部分

"https://functions.azure.com",
"https://functions-staging.azure.com",
"https://functions-next.azure.com"

不确定它是否与问题直接相关,但我建议您使您的模板更类似于 Portal 默认使用的模板。要查看此内容:

  • 开始在 Azure 门户中创建新函数应用程序
  • 输入任意应用程序名称和资源组
  • 点击底部的'Automation options' link

您将获得它使用的完全严格。它看起来像这样:

{
  "parameters": {
    "name": {
      "type": "string"
    },
    "storageName": {
      "type": "string"
    },
    "location": {
      "type": "string"
    },
    "subscriptionId": {
      "type": "string"
    }
  },
  "resources": [
    {
      "apiVersion": "2016-03-01",
      "name": "[parameters('name')]",
      "type": "Microsoft.Web/sites",
      "properties": {
        "name": "[parameters('name')]",
        "siteConfig": {
          "appSettings": [
            {
              "name": "AzureWebJobsDashboard",
              "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2015-05-01-preview').key1)]"
            },
            {
              "name": "AzureWebJobsStorage",
              "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2015-05-01-preview').key1)]"
            },
            {
              "name": "FUNCTIONS_EXTENSION_VERSION",
              "value": "~1"
            },
            {
              "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
              "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2015-05-01-preview').key1)]"
            },
            {
              "name": "WEBSITE_CONTENTSHARE",
              "value": "[concat(toLower(parameters('name')), 'a66e')]"
            },
            {
              "name": "WEBSITE_NODE_DEFAULT_VERSION",
              "value": "6.5.0"
            }
          ]
        },
        "clientAffinityEnabled": false
      },
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageName'))]"
      ],
      "location": "[parameters('location')]",
      "kind": "functionapp"
    },
    {
      "apiVersion": "2015-05-01-preview",
      "type": "Microsoft.Storage/storageAccounts",
      "name": "[parameters('storageName')]",
      "location": "[parameters('location')]",
      "properties": {
        "accountType": "Standard_LRS"
      }
    }
  ],
  "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0"
}

由于这些应用程序设置,我的 Azure 部署(尤其是 Function App)也失败了。这是我的 ARM 脚本的摘录。

"siteConfig": {
   "appsettings": [
   {
     "name": "AzureWebJobsDashboard",
     "value": "[Concat('DefaultEndpointsProtocol=https;AccountName=',variables('StorageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
   },
 ]

该值用于以下设置:AzureWebJobsDashboard、AzureWebJobsStorage,WEBSITE_CONTENTAZUREFILECONNECTIONSTRING。 取决于我的存储帐户也在ARM脚本中设置。

我正在通过 Visual Studio 团队服务开始部署。在这里我弄错了。我直接从 Azure 收到错误消息。

  • 资源:Azure-Function-Dev
  • 类型:微软。Web/sites
  • 状态:BadRequest

    { "error":{ "code": "InternalServerError", "message": "There was an unexpected InternalServerError. Please try again later. x-ms-correlation-request-id: 44444-4444..." } }

如果再次重新部署 Function App - 没有任何更改 - 部署始终有效。奇怪的行为。

然后我使用我的参数将我的值设置为固定值。从那时起,部署运行没有问题。这可能不是一个技术上干净的解决方案,但可以分析错误

"siteConfig": {
      "appsettings": [
        {
          "name": "AzureWebJobsStorage",
          "value": "[parameters('AzureWebJobsStorage')]"
        }, ]

TLDR;

检查存储帐户名称是否正确且仅使用小写字母。

更长的版本

github 问题 - https://github.com/Azure/azure-cli/issues/14518#issuecomment-665255337

在我的场景中,我正在设置一个新的资源组、新的应用服务计划和新的功能 - 但是使用现有的存储帐户和 运行 进入这个问题 There was a conflict. The remote server returned an error: (400) Bad Request.

我的问题是我的参数文件在存储帐户名称中有大小写问题。 myownstorageaccountTest 而不是 myownstorageaccounttest

ARM 模板部署试图创建一个新的存储帐户,名称为 myownstorageaccountTest,而这个 myownstorageaccounttest 已经存在。存储帐户名称在整个 Azure 中必须是唯一的。

存储帐户名称要求: 该名称在 Azure 中的所有现有存储帐户名称中必须是唯一的。长度必须为 3 到 24 个字符,并且只能包含小写字母和数字。

TL;DR: 函数应用程序名称不得超过 59 个字符

因为这些名称构成了一个主机名,所以我通常会附加随机数字来填写最大限制,我相信记录为 60 个字符。

在 Function App 创建向导中,输入 61 个字符的名称会正确拒绝表单中的名称: “必须小于 60”的错误消息与“59 或更少”相同,但准确输入 60(我在其他地方看到过)允许该过程继续: 继续创建 Function App 最终失败并出现此错误:

{
  "code": "DeploymentFailed",
  "message": "At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.",
  "details": [
    {
      "message": "There was a conflict. The remote server returned an error: (400) Bad Request."
    }
  ]
}

使用 59 个字符的名称 创建 OK。

这感觉像是表单中的栅栏错误,它接受的名称输入比下游进程接受的名称大一个字符。