如何使用 ARM 模板部署带有 Blob 触发器的 Azure Function App 以及代码?

问题描述 投票:0回答:1

我正在创建一个 ARM 模板,用于实现 Function App 从创建到代码部署的自动化部署。 Function App 在 Linux (Python) 上配置,当用户上传图像时,它会激活 Blob 触发器以进行图像处理。要使用 ARM 模板实现此目的,必要的步骤是:

  1. 建立存储帐户。
  2. 创建 App Insights 实例来存储日志。
  3. 开发功能应用程序。
  4. 在应用程序内定义特定功能。
  5. 配置 Blob 触发器,将该函数链接到存储帐户。
  6. 将位于指定 URI 的代码部署到 Azure 存储帐户。

我正在遵循 Stack Overflow 说明,并且我的具体场景与以下 stackoverflow 帖子(缩短了 URL)中提供的详细信息一致: https://shorturl.at/GJ247

我使用的代码参考了上面的帖子:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "functionAppName": {
            "defaultValue": "func",
            "type": "String",
            "metadata": {
                "description": "The name of the Azure Function app."
            }
        },
        "storageAccountName": {
            "defaultValue": "strgacc",
            "type": "String",
            "metadata": {
                "description": "The name of the storage account that you wish to use."
            }
        },
        "storageAccountType": {
            "defaultValue": "Standard_LRS",
            "allowedValues": [
                "Standard_LRS",
                "Standard_GRS",
                "Standard_RAGRS"
            ],
            "type": "String",
            "metadata": {
                "description": "Storage Account type"
            }
        },
        "blobContainerName": {
            "defaultValue": "myBlob",
            "type": "String",
            "metadata": {
                "description": "The name of the blob container that you wish to use."
            }
        },
        "location": {
            "defaultValue": "[resourceGroup().location]",
            "type": "String",
            "metadata": {
                "description": "Location for all resources."
            }
        },
        "appInsightsLocation": {
            "defaultValue": "[resourceGroup().location]",
            "type": "String",
            "metadata": {
                "description": "Location for Application Insights"
            }
        },
        "functionWorkerRuntime": {
            "defaultValue": "python",
            "allowedValues": [
                "dotnet",
                "node",
                "python",
                "java"
            ],
            "type": "String",
            "metadata": {
                "description": "The language worker runtime to load in the function app."
            }
        },
        "functionName": {
            "defaultValue": "blobfunc",
            "type": "String",
            "metadata": {
                "description": "The name of the function that you wish to create."
            }
        },
        "linuxFxVersion": {
            "defaultValue": "Python|3.10",
            "type": "String",
            "metadata": {
                "description": "Required for Linux app to represent runtime stack in the format of 'runtime|runtimeVersion'. For example: 'Python|3.10'"
            }
        }
    },
    "variables": {
        "hostingPlanName": "[parameters('functionAppName')]",
        "applicationInsightsName": "[parameters('functionAppName')]"
    },
    "resources": [
        {
            "type": "Microsoft.Web/serverfarms",
            "apiVersion": "2021-02-01",
            "name": "[variables('hostingPlanName')]",
            "location": "[parameters('location')]",
             "properties": {
              "reserved": true
            },
            "sku": {
                "name": "S1",
                "tier": "Standard"
            }       
        },
        {
            "type": "Microsoft.Insights/components",
            "apiVersion": "2020-02-02",
            "name": "[variables('applicationInsightsName')]",
            "location": "[parameters('appInsightsLocation')]",
            "tags": {
                "[format('hidden-link:{0}', resourceId('Microsoft.Web/sites', variables('applicationInsightsName')))]": "Resource"
            },
            "kind": "web",
            "properties": {
                "Application_Type": "web"
            }
        },
        {
            "type": "Microsoft.Web/sites",
            "apiVersion": "2022-03-01",
            "name": "[parameters('functionAppName')]",
            "location": "[parameters('location')]",
            "dependsOn": [
                "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
            ],
            "kind": "functionapp,linux",
            "properties": {
                "reserved": true,
                "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
                "siteConfig": {
                    "linuxFxVersion": "[parameters('linuxFxVersion')]",
                    "appSettings": [
                        {
                            "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
                            "value": "[reference(resourceId('Microsoft.Insights/components', parameters('functionAppName')), '2015-05-01').InstrumentationKey]"
                        },
                        {
                            "name": "AzureWebJobsStorage",
                            "value": "[format('DefaultEndpointsProtocol=https;AccountName={0};EndpointSuffix={1};AccountKey={2}', parameters('storageAccountName'), environment().suffixes.storage, listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01').keys[0].value)]"
                        },
                        {
                            "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
                            "value": "[format('DefaultEndpointsProtocol=https;AccountName={0};EndpointSuffix={1};AccountKey={2}', parameters('storageAccountName'), environment().suffixes.storage, listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01').keys[0].value)]"
                        },
                        {
                            "name": "WEBSITE_CONTENTSHARE",
                            "value": "[toLower(parameters('functionAppName'))]"
                        },
                        {
                            "name": "FUNCTIONS_EXTENSION_VERSION",
                            "value": "~4"
                        },
                        {
                            "name": "FUNCTIONS_WORKER_RUNTIME",
                            "value": "[parameters('functionWorkerRuntime')]"
                        },
                        {
                            "name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
                            "value": "true"
                        }
                    ]
                }
            }
        },
        {
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2021-08-01",
            "name": "[parameters('storageAccountName')]",
            "location": "[parameters('location')]",
            "sku": {
                "name": "Standard_LRS"
            },
            "kind": "StorageV2"
        },
        {
            "type": "Microsoft.Storage/storageAccounts/blobServices",
            "apiVersion": "2021-06-01",
            "name": "[format('{0}/{1}', parameters('storageAccountName'), 'default')]",
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
            ]
        },
        {
            "type": "Microsoft.Storage/storageAccounts/blobServices/containers",
            "apiVersion": "2019-06-01",
            "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), 'default', format('{0}default{1}', parameters('storageAccountName'), parameters('blobContainerName')))]",
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), 'default')]"
            ],
            "properties": {
                "publicAccess": "None"
            }
        },
        {
            "type": "Microsoft.Web/sites/functions",
            "apiVersion": "2018-02-01",
            "name": "[format('{0}/{1}', parameters('functionAppName'), format('{0}', parameters('functionName')))]",
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites', parameters('functionAppName'))]",
                "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), 'default', format('{0}default{1}', parameters('storageAccountName'), parameters('blobContainerName')))]"
            ],
            "properties": {
                "config": {
                    "bindings": [
                        {
                            "name": "Blob",
                            "type": "blobTrigger",
                            "direction": "in",
                            "path": "[format('default/{0}/{{name}}', parameters('blobContainerName'))]",
                            "connection": "AzureWebJobsStorage"
                        }
                    ],
                    "disabled": false
                }
            }
        }
    ]
}

我目前正在努力实施该解决方案,但我在部署页面上遇到了错误。有人可以指导我创建它吗?在 Function App 中创建函数时发生错误。这可能是因为里面没有代码,还是有其他潜在的问题?

{
    "status": "Failed",
    "error": {
        "code": "BadRequest",
        "message": "Encountered an error (InternalServerError) from host runtime.",
        "details": [
            {
                "message": "Encountered an error (InternalServerError) from host runtime."
            },
            {
                "code": "BadRequest"
            },
            {}
        ]
    }
}
---


  [1]: https://stackoverflow.com/questions/76812998/function-is-not-creating-inside-azure-function-app-using-arm-template
azure automation azure-functions azure-resource-manager
1个回答
0
投票

如果您需要使用代码和requirement.txt部署Azure功能,那么您将需要一些东西

  • 一个 FTP 服务器,您可以在其中保存代码文件和requirements.txt 文件
  • 一个 VM 将函数部署到 Azure 函数应用程序
  • 在 ARM 模板中部署脚本时只需一个脚本。

功能部署步骤

export FUNCTION_APP=${1}
[ -z $FUNCTION_APP ]  && $ECHO "Error...FunctionApp Name is missing." && exit 1

export RG_NAME=${3}
[ -z $RG_NAME ]  && $ECHO "Error...RG NAME is missing." && exit 1

export STORAGE_ACCOUNT=${4}
[ -z $STORAGE_ACCOUNT ]  && $ECHO "Error... STORAGE_ACCOUNT NAME is missing." && exit 1

export BLOB_COTAINER_NAME=${5}
[ -z $BLOB_COTAINER_NAME ]  && $ECHO "Error...BLOB_COTAINER_NAME is missing." && exit 1


copy_Binary()
{
  [ -f /tmp/.copy_Binary ] && return 0
  
  $ECHO "Installing the Azure CLI..." >> $LOG
  curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
  [ $? -ne 0 ] && $ECHO "Failed to install Azure-CLI into the VM." >> $LOG && exit 1
  
  $ECHO "Configuring the Azure CLI..." >> $LOG
  az login --service-principal -u fcabaecd-984c-4ed0-9d05-69429e34de44 -p mkx8Q~upcFFlzMMBm_bTS7ewJxx9gT6taK-~Qb5R --tenant 31472f81-8fe4-49ec-8bc3-fa1c295640d7 --allow-no-subscriptions  >> $LOG 2>&1
  [ $? -ne 0 ] && $ECHO "Failed to login to azure  " >> $LOG && exit 1
  
  $ECHO "Setting the Customer Subscription..." >> $LOG
  az account set --subscription $SUBSCRIPTION_ID >> $LOG 2>&1
  [ $? -ne 0 ] && $ECHO "Failed to set subscription" >> $LOG && exit 1

  $ECHO "Setting the Customer Resource Group..." >> $LOG
  az configure --defaults group=$RG_NAME >> $LOG 2>&1
  [ $? -ne 0 ] && $ECHO "Failed to set resource group" >> $LOG && exit 1
  
  $ECHO "Update the config..." >> $LOG
  $ECHO "[core]" >> /root/.azure/config
  $ECHO "output = table" >> /root/.azure/config
  
  apt install unzip >> $LOG
  
  cd /home/ubuntu
  mkdir Azure_CFT
  cd Azure_CFT
  pwd >> $LOG
  $ECHO "Downloading Azure Function Core Tool Binary" >> $LOG
  wget "https://github.com/Azure/azure-functions-core-tools/releases/download/4.0.5390/Azure.Functions.Cli.linux-x64.4.0.5390.zip" >> $LOG
  [ $? -ne 0 ] && $ECHO "Failed to download the Azure Function Core Tools zip file." >> $LOG && exit 1
  
  $ECHO "Unzipping the Azure Function Core Tools Binary" >> $LOG
  unzip -d azure-functions-cli Azure.Functions.Cli.linux-x64.*.zip >> $LOG
  [ $? -ne 0 ] && $ECHO "Failed to Unzip the Azure Function Core Tools zip file." >> $LOG && exit 1
  
  cd azure-functions-cli 
  chmod +x func
  chmod +x gozip
  ./func >> $LOG

  export PATH=`pwd`:$PATH
  func
  
  
  $ECHO "Listing the functions in the $FUNCTION_APP" >> $LOG
  func azure functionapp list-functions $FUNCTION_APP >> $LOG
  [ $? -ne 0 ] && $ECHO "Failed to List the functions in FunctionApp" >> $LOG && exit 1
  
  cd /home/ubuntu
  mkdir NewFunction
  cd NewFunction
  $ECHO "Creating the new function project" >> $LOG
  func init FunctionProjFolder --worker-runtime python --model V2 >> $LOG
  
  $ECHO "Downloading the function_app.py file and requirements.txt files" >> $LOG
  FTP_UNAME=username
  FTP_PASS=password
  FTP_URL=ftp_url
  wget "ftp://${FTP_UNAME}:${FTP_PASS}@${FTP_URL}/function_app.py" >> $LOG 2>&1
  [ $? -ne 0 ] && $ECHO "Failed to Download the Function App Python file." >> $LOG && exit 1
  
  wget "ftp://${FTP_UNAME}:${FTP_PASS}@${FTP_URL}/requirements.txt" >> $LOG 2>&1
  [ $? -ne 0 ] && $ECHO "Failed to download the Requirements file." >> $LOG && exit 1
  
  

  
  $ECHO "Copying the updated function_app.py and requirements.txt in the FunctionProjFolder" >> $LOG
  cp function_app.py requirements.txt FunctionProjFolder/ >> $LOG
    
  cd FunctionProjFolder
  $ECHO "Publishing the function in the $FUNCTION_APP" >> $LOG
  #printf "${BLOB_COTAINER_NAME}/{name}\nAzureWebJobsStorage" | func new --language Python --template "Blob trigger" --name "myAzureFunction" >> $LOG
  func azure functionapp publish $FUNCTION_APP >> $LOG
  
}

#
# Main
#

$ECHO "STEP: EXECUTION STARTED" >> $LOG
$ECHO "Parameters Passed..." >> $LOG
$ECHO "SUBSCRIPTION_ID= ${SUBSCRIPTION_ID}" >> $LOG
$ECHO "RG_NAME= ${RG_NAME}" >> $LOG
$ECHO "FUNCTION_APP= ${FUNCTION_APP}" >> $LOG
$ECHO "STORAGE_ACCOUNT= ${STORAGE_ACCOUNT}" >> $LOG
copy_Binary

$ECHO "STEP: COMPLETED SUCCESSFULLY" >> $LOG

创建 ARM 模板时,创建一个脚本文件,将其保存在脚本文件夹中,并将上述用于部署函数的所有命令粘贴到 Function App。

注意:- 在 mainTemplate.json 文件中定义 VM 的 ARM 模板。如果您不需要虚拟机,则可以在功能部署后删除虚拟机。

您的 zip 文件应遵循以下结构。

  Azuretemplate.zip
    
    scripts(folder)/script.sh
    createUiDefinition.json
    mainTemplate.json
    viewDefinition.json

创建 zip 文件并尝试部署它。

© www.soinside.com 2019 - 2024. All rights reserved.