你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

将消耗计划迁移到 Flex 消耗计划

本文提供了有关迁移 Azure Functions 中 消耗计划中 托管的现有函数应用的分步说明,以改用 弹性消耗计划

迁移现有无服务器应用时,函数可以轻松利用 Flex Consumption 计划的以下优势:

  • 增强性能:你的应用可获得更强的稳定性和随时就绪的实例,以减少冷启动影响。
  • 改进的控制:通过针对每个函数的缩放和并发性设置来微调您的函数。
  • 扩展的网络:虚拟网络集成和专用终结点允许在公共和专用网络中运行函数。

Flex 消耗计划是建议的无服务器托管选项,帮助你的函数继续运行。 有关详细信息,请参阅 Flex 消耗计划权益。 有关托管计划之间的详细比较,请参阅 Azure Functions 托管选项

注意事项

在开始迁移之前,请记住以下注意事项:

  • 由于这两个计划之间的重大配置和行为差异,无法将现有消耗计划应用 转移到 Flex Consumption 计划。 迁移过程改为创建与当前应用等效的新 Flex Consumption 计划应用。 此新应用在同一资源组中运行,其依赖项与当前应用相同。

  • 应优先考虑在 Linux 上的消耗计划中运行的应用的迁移。

  • 本文假定你大致了解 Functions 概念和体系结构,并熟悉要迁移的应用的功能。 此类概念包括触发器和绑定、身份验证和网络自定义。

  • 如果可能,本文面向特定的语言运行时堆栈。 请确保选择文章顶部的应用语言。

  • 本文介绍如何使用 Azure 门户Azure CLI 评估当前应用并部署新的 Flex Consumption 计划应用。 如果当前应用部署是使用基础结构即代码(IaC)定义的,则通常可以遵循相同的步骤。 可以直接在 ARM 模板或 Bicep 文件中执行相同的动作,同时考虑以下资源特定的注意事项:

先决条件

  • 访问包含一个或多个要迁移的函数应用的 Azure 订阅。 用于运行 Azure CLI 命令的帐户必须能够:

    • 创建和管理函数应用和应用服务托管计划。
    • 向托管标识分析角色。
    • 创建和管理存储帐户。
    • 创建和管理 Application Insights 资源。
    • 访问应用的所有依赖资源,例如 Azure Key Vault、Azure 服务总线或 Azure 事件中心。

    如分配到的角色是“所有者”或“参与者”,则一般可提供资源小组中足够的权限。

  • Azure CLI 版本 v2.74.0 或更高版本。 脚本在 Azure Cloud Shell 中使用 Azure CLI 进行测试。

  • 您可以使用以下命令安装 资源图 扩展: az extension add

    az extension add --name resource-graph
    
  • 该工具 jq 用于处理 JSON 输出。

评估现有应用

在迁移到 Flex Consumption 计划之前,应执行以下检查,以确保可以成功迁移函数应用:

确定要迁移的潜在应用

使用这些步骤可列出需要迁移的函数应用。 在此列表中,记下其名称、资源组、位置和运行时堆栈。 然后,可以针对决定迁移到 Flex Consumption 计划的每个应用重复本指南中的步骤。

函数应用信息维护的方式取决于你的应用是在 Linux 还是 Windows 上运行。

az graph query 使用此命令列出您的订阅中在“消耗计划”下运行的所有函数应用程序:

az graph query -q "resources | where subscriptionId == '$(az account show --query id -o tsv)' \
   | where type == 'microsoft.web/sites' | where ['kind'] == 'functionapp,linux' | where properties.sku == 'Dynamic' \
   | extend siteProperties=todynamic(properties.siteProperties.properties) | mv-expand siteProperties \
   | where siteProperties.name=='LinuxFxVersion' | project name, location, resourceGroup, stack=siteProperties.value" \
   --query data --output table

此命令为当前订阅中 Linux 上运行的所有消耗应用生成具有应用名称、位置、资源组和运行时堆栈的表。

如果尚未安装 资源图扩展,系统会提示您安装。

确认区域兼容性

确认目前支持的 Flex 消耗计划与要迁移的消耗计划处于同一区域。

az functionapp list-flexconsumption-locations使用此命令列出弹性消耗计划可用的所有区域:

az functionapp list-flexconsumption-locations --query "sort_by(@, &name)[].{Region:name}" -o table

此命令生成当前支持 Flex Consumption 计划的 Azure 区域的表。

确保列表中包括要迁移运行的消耗计划应用所在的区域。

小窍门

如果区域当前不受支持,但仍选择迁移函数应用,则应用必须在支持 Flex Consumption 计划的其他区域中运行。 但是,在其他连接服务的不同区域中运行应用可能会带来额外的延迟。 在完成迁移之前,请确保新区域能够满足应用程序的性能要求。

验证语言堆栈兼容性

Flex 消耗计划尚不支持所有函数语言堆栈。 此表指示当前支持哪些语言堆栈:

堆栈设置 堆栈名称 已支持
dotnet-isolated .NET(独立工作者模型) ✅ 是
node JavaScript/TypeScript ✅ 是
java 爪哇岛 ✅ 是
python Python ✅ 是
powershell PowerShell ✅ 是
dotnet .NET(进程内模型) ❌ 否
custom 自定义处理程序 ❌ 否

如果函数应用使用不受支持的运行时堆栈:

  • 对于使用运行时间 (dotnet)、正在运行中的 C# 应用,必须首先将应用迁移到隔离的 .NET。 有关详细信息,请参阅将 C# 应用从进程内模型迁移到独立的辅助角色模型

  • 当前无法迁移依赖于自定义处理程序的非本机语言应用以在 Flex Consumption 计划中运行。

验证堆栈版本兼容性

迁移到 Flex Consumption 计划之前,必须确保在新计划中运行时,应用运行时堆栈版本在区域中受支持。

使用此 az functionapp list-flexconsumption-runtimes 命令验证 Flex 消耗计划在指定的区域是否支持你所使用的编程语言堆栈版本:

az functionapp list-flexconsumption-runtimes --location <REGION> --runtime <LANGUAGE_STACK> --query '[].{version:version}' -o tsv

在此示例中,请将 <REGION> 当前区域替换为 <LANGUAGE_STACK> 以下值之一:

语言堆栈 价值
C#(独立辅助角色模型) dotnet-isolated
爪哇岛 java
JavaScript node
PowerShell powershell
Python python
TypeScript node

此命令会显示你所在区域 Flex 消耗计划支持的指定语言堆栈的所有版本。

如果函数应用使用不受支持的语言堆栈版本,必须先 将应用代码升级到受支持的版本 ,然后再迁移到 Flex Consumption 计划。

验证部署槽位使用情况

消耗计划应用可以定义部署槽位。 有关详细信息,请参阅 Azure Functions 部署槽。 但是,Flex 消耗计划目前暂不支持部署槽。 在迁移之前,必须确定应用是否具有部署槽位。 因此,需要定义一个策略规定在使用 Flex 消耗计划时,在没有部署槽的情况下如何管理你的应用。

az functionapp deployment slot list使用此命令列出函数应用中定义的任何部署槽位:

az functionapp deployment slot list --name <APP_NAME> --resource-group <RESOURCE_GROUP> --output table

在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为应用名称。 如果命令返回的是条目,则表明应用已启用部署槽。

如果函数应用当前正在使用部署槽位,则当前无法在 Flex Consumption 计划中重现此功能。 在迁移之前,应...

  • 将任何新代码或功能从部署槽迁移到主(生产)槽。
  • 请考虑重新架构应用程序以使用单独的函数应用。 这样,您可以将函数代码进行开发、测试和部署至第二个非生产应用,而无需使用部署槽。

验证证书的使用

传输层安全性(TLS)证书(以前称为安全套接字层(SSL)证书,用于帮助保护 Internet 连接。 弹性消耗计划目前不支持 TLS/SSL 证书(包括托管证书、自带证书(BYOC)或公钥证书)。

使用az webapp config ssl list命令列出您函数应用程序中可用的任何 TLS/SSL 证书:

az webapp config ssl list --resource-group <RESOURCE_GROUP>  

在此示例中,请将 <RESOURCE_GROUP> 替换为您的资源组名称。 如果此命令生成输出,则应用可能会使用证书。

如果应用当前依赖于 TSL/SSL 证书,在将证书支持添加到 Flex Consumption 计划之前,不应继续迁移。

验证 Blob 存储触发器

目前,Flex 消耗计划针对 Azure Blob 存储仅支持基于事件的触发器,这些触发器使用 EventGridSource 设置进行定义。 Flex 消耗不支持使用窗器轮询和使用 LogsAndContainerScanSource 设置的 Blob 存储触发器。 由于容器轮询是默认设置,因此必须确定任何 Blob 存储触发器是否使用默认 LogsAndContainerScan 源设置。 有关详细信息,请参阅 Blob 容器触发器

使用此 [az functionapp function list] 命令可确定应用是否具有任何不使用事件网格作为源的 Blob 存储触发器:

az functionapp function list  --name <APP_NAME> --resource-group <RESOURCE_GROUP> \
  --query "[?config.bindings[0].type=='blobTrigger' && config.bindings[0].source!='EventGrid'].{Function:name,TriggerType:config.bindings[0].type,Source:config.bindings[0].source}" \
  --output table

在此示例中,将 <RESOURCE_GROUP> 替换为您的资源组名称,将 <APP_NAME> 替换为您的应用名称。 如果命令返回的是行,则表示你的函数应用中至少有一个使用容器轮询的触发器。

如果您的应用程序有任何没有事件网格源的 Blob 存储触发器,您必须在迁移到 Flex Consumption 计划之前将其更改为事件网格源。

将现有 Blob 存储触发器更改为事件网格源的基本步骤包括:

  1. 在事件订阅使用的函数应用中生成终结点 URL

  2. 在 Blob 存储容器上创建事件订阅

  3. 在 Blob 存储触发器定义中将 source 属性添加或更新为 EventGrid

有关详细信息,请参阅教程:使用事件订阅在 Blob 容器上触发 Azure Functions

考虑依赖服务

由于 Azure Functions 是计算服务,因此必须考虑迁移对应用上游和下游的数据和服务的影响。

数据保护策略

以下是在迁移期间保护上游和下游数据的一些策略:

按触发器类型进行的缓解

应计划缓解策略来保护应用中可能具有的特定函数触发器的数据:

触发器 数据风险 策略
Azure Blob 存储服务 在新应用中为基于事件的触发器创建单独的容器。
运行新应用后,将客户端切换为使用新容器。
允许在停止旧应用之前完全处理原始容器。
Azure Cosmos DB 为新应用专门创建专用租约容器。
将此新的租用容器设置为新应用中的 leaseCollectionName 配置。
需要函数是幂等或必须能够处理副本更改源处理的结果。
StartFromBeginning 配置在新应用中设置为 false 以避免重新处理整个数据流。
Azure 事件网格 中等 在新应用中重新创建相同的事件订阅。
要求 函数具有幂等性,或者你必须能够处理由于重复事件处理而产生的结果。
Azure 事件中心 中等 创建新的 使用者组 供新应用使用。 有关详细信息,请参阅 事件网格触发器的迁移策略
Azure 服务总线 创建新主题或队列供新应用使用。
将发送者和客户端更新为使用新主题或队列。
原始主题为空后,关闭旧应用。
Azure 存储队列 创建新队列供新应用使用。
将发送者和客户端更新为使用新队列。
原始队列为空后,关闭旧应用。
HTTP 请记住,在迁移后将客户端和其他应用或服务切换为面向新的 HTTP 终结点。
计时器 在直接转换期间,确保偏移两个应用之间的计时器计划,避免两个应用同时执行任务。
在新应用成功运行后,禁用旧应用中的计时器触发器

预迁移任务

在继续进行迁移之前,必须收集消耗计划应用相关的关键信息及其使用的资源,帮助顺利过渡到使用 Flex 消耗计划运行。

在迁移应用以在 Flex Consumption 计划中运行之前,应先完成这些任务:

收集应用设置

如果计划从应用设置使用相同的触发器和绑定源和其他设置,则需要首先记下现有消耗计划应用中的当前应用设置。

使用此命令 az functionapp config appsettings list 可返回一个 app_settings 对象,该对象包含现有应用设置作为 JSON:

app_settings=$(az functionapp config appsettings list --name `<APP_NAME>` --resource-group `<RESOURCE_GROUP>`)
echo $app_settings

在此示例中,将 <RESOURCE_GROUP> 替换为您的资源组名称,将 <APP_NAME> 替换为您的应用名称。

谨慎

应用设置经常包含密钥和其他共享机密。 始终安全地存储应用程序设置,理想情况下是加密的。 为了提高安全性,应在新的 Flex Consumption 计划应用中将 Microsoft Entra ID 身份验证与托管标识配合使用,而不是共享机密。

收集应用配置

应用设置中未找到其他应用配置。 还应从现有应用捕获这些配置,以便确保在新应用中正确重新创建这些配置。

查看这些设置。 如果当前应用中存在其中任意项,则必须决定是否必须在新的 Flex 消耗计划应用中重新创建相应项:

配置 设置 注释
CORS 设置 cors 确定任何现有的跨域资源共享(CORS)设置,这些设置可能是您的客户端所需的。
自定义域 如果应用当前使用的是域而非 *.azurewebsites.net,则需要将此自定义域映射替换为指向新应用的映射。
HTTP 版本 http20Enabled 确定应用是否需要 HTTP 2.0。
仅 HTTPS httpsOnly 确定访问应用是否需要 TSL/SSL。
传入的客户端证书 clientCertEnabled
clientCertMode
clientCertExclusionPaths
设置使用证书进行身份验证的客户端请求的要求。
横向扩展上限 WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT 设置横向扩展实例的上限。 默认值为 200。 此值在应用设置中找到,但在 Flex Consumption 计划应用中,它会改为添加为网站设置(maximumInstanceCount)。
最低入站 TLS 版本 minTlsVersion 设置应用所需的最低 TLS 版本。
最低入站 TLS 密码 minTlsCipherSuite 为应用设置最低 TLS 密码要求。
装载的 Azure 文件共享 azureStorageAccounts 确定应用中是否存在任何显式装载的文件共享(仅限 Linux)。
SCM 基础身份验证发布凭据 scm.allow 确定 scm 发布站点是否已启用。 虽然出于安全性考虑不建议这样做,但某些 发布方法需要这样做。

使用此脚本获取现有应用的相关应用程序配置:

# Set the app and resource group names
appName=<APP_NAME>
rgName=<RESOURCE_GROUP>

echo "Getting commonly used site settings..."
az functionapp config show --name $appName --resource-group $rgName \
    --query "{http20Enabled:http20Enabled, httpsOnly:httpsOnly, minTlsVersion:minTlsVersion, \
    minTlsCipherSuite:minTlsCipherSuite, clientCertEnabled:clientCertEnabled, \
    clientCertMode:clientCertMode, clientCertExclusionPaths:clientCertExclusionPaths}"

echo "Checking for SCM basic publishing credentials policies..."
az resource show --resource-group $rgName --name scm --namespace Microsoft.Web \
    --resource-type basicPublishingCredentialsPolicies --parent sites/$appName --query properties

echo "Checking for the maximum scale-out limit configuration..."
az functionapp config appsettings list --name $appName --resource-group $rgName \
    --query "[?name=='WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT'].value" -o tsv

echo "Checking for any file share mount configurations..."
az webapp config storage-account list --name $appName --resource-group $rgName

echo "Checking for any custom domains..."
az functionapp config hostname list --webapp-name $appName --resource-group $rgName --query "[?contains(name, 'azurewebsites.net')==\`false\`]" --output table

echo "Checking for any CORS settings..."
az functionapp cors show --name $appName --resource-group $rgName 

在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为应用名称。 如果任何网站设置或检查返回非 null 值,请记下这些值。

识别托管标识和基于角色的访问权限

在迁移之前,应记录应用是依赖于系统分配的托管标识还是任何用户分配的托管标识。 还必须确定授予给这些标识的基于角色的访问控制 (RBAC) 权限。 必须在新应用中重新创建系统分配的托管标识和任何角色分配。 你应该能够在新应用中重复使用用户分配的托管标识。

此脚本检查系统分配的托管标识和与应用关联的任何用户分配的托管标识:

appName=<APP_NAME>
rgName=<RESOURCE_GROUP>

echo "Checking for a system-assigned managed identity..."
systemUserId=$(az functionapp identity show --name $appName --resource-group $rgName --query "principalId" -o tsv) 

if [[ -n "$systemUserId" ]]; then
echo "System-assigned identity principal ID: $systemUserId"
echo "Checking for role assignments..."
az role assignment list --assignee $systemUserId --all
else
  echo "No system-assigned identity found."
fi

echo "Checking for user-assigned managed identities..."
userIdentities=$(az functionapp identity show --name $appName --resource-group $rgName --query 'userAssignedIdentities' -o json)
if [[ "$userIdentities" != "{}" && "$userIdentities" != "null" ]]; then
  echo "$userIdentities" | jq -c 'to_entries[]' | while read -r identity; do
    echo "User-assigned identity name: $(echo "$identity" | jq -r '.key' | sed 's|.*/userAssignedIdentities/||')"
	echo "Checking for role assignments..."
    az role assignment list --assignee $(echo "$identity" | jq -r '.value.principalId') --all --output json
    echo
  done
else
  echo "No user-assigned identities found."
fi

在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为应用名称。 记下所有标识及其角色分配。

标识内置身份验证设置

迁移到 Flex Consumption 之前,应收集有关任何内置身份验证配置的信息。 如果想要让应用使用相同的客户端身份验证行为,则必须在新应用中重新创建它们。 有关详细信息,请参阅 Azure Functions 中的身份验证和授权

请特别注意重定向 URI、允许的外部重定向和令牌设置,以确保经过身份验证的用户顺利过渡。

az webapp auth show使用此命令来确定函数应用中是否配置了内置身份验证

az webapp auth show --name <APP_NAME> --resource-group <RESOURCE_GROUP>

在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为应用名称。 查看输出以确定身份验证是否已启用,以及配置了哪些标识提供者。

应在迁移后的新应用中重新创建这些设置,以便客户端可以使用首选提供程序来维护访问权限。

入站访问限制

可以在消耗计划中设置应用的 入站访问限制 。 你可能希望在新应用中维护这些限制。 对于定义的每个限制,请确保记录以下属性:

  • IP 地址或 CIDR 范围
  • 优先级值
  • 操作类型(允许/拒绝)
  • 规则的名称

此命令 az functionapp config access-restriction show 返回任何基于 IP 的现有访问限制的列表:

az functionapp config access-restriction show --name <APP_NAME> --resource-group <RESOURCE_GROUP>

在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为应用名称。

在 Flex Consumption 计划中运行时,可以重新创建这些基于 IP 的入站限制。 可以通过实施其他网络限制(例如虚拟网络集成和入站专用终结点)进一步保护应用。 有关详细信息,请参阅虚拟网络集成

获取代码部署包

若要重新部署应用,必须具有项目的源文件或部署包。 理想情况下,项目文件保留在源代码管理中,以便你可以轻松地将函数代码重新部署到新应用。 如果你有源代码文件,则可以跳过本部分。

如果不再有权访问项目源文件,可以从 Azure 中的现有消耗计划应用下载当前部署包。 部署包的位置取决于是在 Linux 还是 Windows 上运行。

Linux 上的消费计划应用将在以下位置之一存储部署 zip 包文件:

  • 在默认的主机存储帐户 AzureWebJobsStorage 中,一个名为 scm-releases 的 Azure Blob 存储容器。 此容器是 Linux 上的消耗计划应用的默认部署源。

  • 如果应用具有 WEBSITE_RUN_FROM_PACKAGE URL 设置,则包位于由你维护的外部可访问位置。 外部包应托管在具有受限访问权限的 Blob 存储容器中。 有关详细信息,请参阅 外部包 URL

小窍门

如果存储帐户仅限于托管身份访问,您可能需要通过将其添加到 Storage Blob Data Reader 角色来授予 Azure 帐户对存储容器的读取访问权限。

使用以下步骤从当前应用下载部署包:

  1. 使用此命令 az functionapp config appsettings list 获取 WEBSITE_RUN_FROM_PACKAGE 应用设置(如果存在):

    az functionapp config appsettings list --name <APP_NAME> --resource-group <RESOURCE_GROUP> \
        --query "[?name=='WEBSITE_RUN_FROM_PACKAGE'].value" -o tsv
    

    在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为应用名称。 如果此命令返回 URL,则可以从该远程位置下载部署包文件,并跳到下一部分。

  2. 如果 WEBSITE_RUN_FROM_PACKAGE 的值是 1 或无值,请使用此脚本获取现有应用程序的部署包:

    appName=<APP_NAME>
    rgName=<RESOURCE_GROUP>
    
    echo "Getting the storage account connection string from app settings..."
    storageConnection=$(az functionapp config appsettings list --name $appName --resource-group $rgName \
             --query "[?name=='AzureWebJobsStorage'].value" -o tsv)
    
    echo "Getting the package name..."
    packageName=$(az storage blob list --connection-string $storageConnection --container-name scm-releases \
    --query "[0].name" -o tsv)
    
    echo "Download the package? $packageName? (Y to proceed, any other key to exit)"
    read -r answer
    if [[ "$answer" == "Y" || "$answer" == "y" ]]; then
       echo "Proceeding with download..."
       az storage blob download --connection-string $storageConnection --container-name scm-releases \
    --name $packageName --file $packageName
    else
       echo "Exiting script."
       exit 0
    fi
    

    同样,请将 <RESOURCE_GROUP><APP_NAME> 替换为您的资源组名称和应用名称。 包 .zip 文件将下载到您执行命令的目录中。

部署包使用 squashfs 格式进行压缩。 若要查看包内的内容,必须使用可解压缩此格式的工具。

捕获性能基准(可选)

如果计划根据迁移到 Flex Consumption 计划来验证应用中的性能改进,则应(可选)捕获当前计划的性能基准。 然后,你可以将它们与在 Flex Consumption 计划中运行的应用的相同基准进行比较以进行比较。

小窍门

始终比较类似条件下的性能,例如一天、一周中的时间和客户端负载。 尽可能一切运行两个基准。

下面是一些用于结构化性能测试的基准:

建议的基准 注释
冷启动 测量从第一个请求到空闲时间段后的第一个响应的时间。
吞吐量 使用 负载测试工具 测量每秒最大请求数,以确定应用如何处理并发请求。
延迟 在各种负载条件下,跟踪P50P95P99的响应时间。 可以在 Application Insights 中监视这些指标。

可以使用此 Kusto 查询查看 Application Insights 中建议的延迟响应时间:

requests
| where timestamp > ago(1d)
| summarize percentiles(duration, 50, 95, 99) by bin(timestamp, 1h)
| render timechart

迁移步骤

函数从消耗计划应用到 Flex 消耗计划应用的实际迁移,主要分为以下几步:

步骤 1:计划的最终评审

在继续迁移过程之前,请花点时间执行以下最后的准备步骤:

  • 查看所有收集的信息:浏览前面评估和预迁移部分中记录的所有备注、配置详细信息和应用程序设置。 如果有任何内容不清楚,请再次运行 Azure CLI 命令,或从门户获取信息。

  • 定义迁移计划:根据你的发现,为迁移创建一个清单,其中突出显示了:

    • 需要特别注意的任何设置
    • 在迁移过程中可能影响的触发器和绑定或其他依赖项
    • 迁移后验证的测试策略
    • 如果出现意外问题,则回滚计划
  • 停机时间规划:考虑何时停止原始函数应用以避免数据丢失和重复处理事件,以及这如何影响用户或下游系统。 在某些情况下,可能需要在停止整个应用之前 禁用特定函数

仔细的最终评审有助于确保迁移过程更顺利,并最大程度地降低忽略重要配置的风险。

步骤 2:在 Flex Consumption 计划中创建应用

可通过多种方式在 Flex Consumption 计划中创建函数应用以及其他所需的 Azure 资源:

创建选项 参考文章
Azure CLI 创建 Flex 消耗应用
Azure 门户 在 Azure 门户中创建函数应用
基础结构即代码 ARM 模板
azd
肱二头肌
Terraform
Visual Studio Code Visual Studio Code 部署
Visual Studio Visual Studio 部署

小窍门

如果可能,应使用 Microsoft Entra ID 进行身份验证,而不是包含共享密钥的连接字符串。 使用托管标识是一种最佳做法,通过消除直接在应用程序设置中存储共享机密的需要,从而提高安全性。 如果原始应用使用了连接字符串,则 Flex Consumption 计划旨在支持托管标识。 其中大多数链接介绍了如何在函数应用中启用托管标识。

步骤 3:在新应用中设置迁移的应用配置

在部署代码之前,必须使用原始函数应用中的相关 Flex Consumption 计划应用设置来配置新应用。

重要

在 Flex Consumption 计划中运行时,并非所有消耗计划应用设置都受支持。 有关详细信息,请参阅 Flex 消耗计划弃用

运行执行以下任务的此脚本:

  1. 从旧应用获取应用设置,忽略在 Flex Consumption 计划中不适用或新应用中已存在的设置。
  2. 将收集的设置本地写入临时文件。
  3. 将文件中的设置应用到新应用。
  4. 删除临时文件。
sourceAppName=<SOURCE_APP_NAME>
destAppName=<DESTINATION_APP_NAME>
rgName=<RESOURCE_GROUP>

echo "Getting app settings from the old app..."
app_settings=$(az functionapp config appsettings list --name $sourceAppName --resource-group $rgName)

# Filter out settings that don't apply to Flex Consumption apps or that will already have been created
filtered_settings=$(echo "$app_settings" | jq 'map(select(
  (.name | ascii_downcase) != "website_use_placeholder_dotnetisolated" and
  (.name | ascii_downcase | startswith("azurewebjobsstorage") | not) and
  (.name | ascii_downcase) != "website_mount_enabled" and
  (.name | ascii_downcase) != "enable_oryx_build" and
  (.name | ascii_downcase) != "functions_extension_version" and
  (.name | ascii_downcase) != "functions_worker_runtime" and
  (.name | ascii_downcase) != "functions_worker_runtime_version" and
  (.name | ascii_downcase) != "functions_max_http_concurrency" and
  (.name | ascii_downcase) != "functions_worker_process_count" and
  (.name | ascii_downcase) != "functions_worker_dynamic_concurrency_enabled" and
  (.name | ascii_downcase) != "scm_do_build_during_deployment" and
  (.name | ascii_downcase) != "website_contentazurefileconnectionstring" and
  (.name | ascii_downcase) != "website_contentovervnet" and
  (.name | ascii_downcase) != "website_contentshare" and
  (.name | ascii_downcase) != "website_dns_server" and
  (.name | ascii_downcase) != "website_max_dynamic_application_scale_out" and
  (.name | ascii_downcase) != "website_node_default_version" and
  (.name | ascii_downcase) != "website_run_from_package" and
  (.name | ascii_downcase) != "website_skip_contentshare_validation" and
  (.name | ascii_downcase) != "website_vnet_route_all" and
  (.name | ascii_downcase) != "applicationinsights_connection_string"
))')

echo "Settings to migrate..."
echo "$filtered_settings"

echo "Writing settings to a local a local file (app_settings_filtered.json)..."
echo "$filtered_settings" > app_settings_filtered.json

echo "Applying settings to the new app..."
output=$(az functionapp config appsettings set --name $destAppName --resource-group $rgName --settings @app_settings_filtered.json)

echo "Deleting the temporary settings file..."
rm -rf app_settings_filtered.json  

echo "Current app settings in the new app..."
az functionapp config appsettings list --name $destAppName --resource-group $rgName 

在此示例中,将<RESOURCE_GROUP>替换为您的资源组名称,将<SOURCE_APP_NAME>替换为旧应用名称,将<DEST_APP_NAME>替换为新应用名称。 此脚本假定这两个应用位于同一资源组中。

步骤 4:应用其他应用配置

查找 在预迁移期间收集 的旧应用中的其他应用配置列表,并在新应用中设置这些配置。

在此脚本中,为原始应用中的任何配置集设置值,并使用注释禁用任何未设置的配置 (null):

appName=<APP_NAME>
rgName=<RESOURCE_GROUP>
http20Setting=<YOUR_HTTP_20_SETTING>
minTlsVersion=<YOUR_TLS_VERSION>
minTlsCipher=<YOUR_TLS_CIPHER>
httpsOnly=<YOUR_HTTPS_ONLY_SETTING>
certEnabled=<CLIENT_CERT_ENABLED>
certMode=<YOUR_CLIENT_CERT_MODE>
certExPaths=<CERT_EXCLUSION_PATHS>
scmAllowBasicAuth=<ALLOW_SCM_BASIC_AUTH>

# Apply HTTP version and minimum TLS settings
az functionapp config set --name $appName --resource-group $rgName --http20-enabled $http20Setting  
az functionapp config set --name $appName --resource-group $rgName --min-tls-version $minTlsVersion

# Apply the HTTPS-only setting
az functionapp update --name $appName --resource-group $rgName --set HttpsOnly=$httpsOnly

# Apply incoming client cert settings
az functionapp update --name $appName --resource-group $rgName --set clientCertEnabled=$certEnabled
az functionapp update --name $appName --resource-group $rgName --set clientCertMode=$certMode
az functionapp update --name $appName --resource-group $rgName --set clientCertExclusionPaths=$certExPaths

# Apply the TLS cipher suite setting
az functionapp update --name $appName --resource-group $rgName --set minTlsCipherSuite=$minTlsCipher

# Apply the allow scm basic auth configuration
az resource update --resource-group $rgName --name scm --namespace Microsoft.Web --resource-type basicPublishingCredentialsPolicies \
	--parent sites/$appName --set properties.allow=$scmAllowBasicAuth

在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为函数应用名称。 此外,替换掉要在新应用中重新创建的现有设置任何变量定义的占位符,并使用注释禁用任何 null 设置。

步骤 5:配置缩放和并发设置

Flex Consumption 计划实现每个函数缩放,其中应用中的每个函数都可以根据其工作负荷独立缩放。 缩放也更严格地与并发设置相关,这些设置用于根据当前的并发执行做出缩放决策。 有关详细信息,请参阅 Flex Consumption 计划文章中的 按函数缩放并发性

如果想让您的新应用像原始应用一样扩展,请首先考虑并发设置。 设置更高的并发值可能会导致创建更少的实例来处理相同的负载。

如果在原始应用中设置了自定义横向扩展限制,也可以将其应用到新应用。 否则,可以跳到下一部分。

默认的最大实例计数为 100,并且必须设置为 40 或更高的值。

使用此命令 az functionapp scale config set 设置最大扩展规模。

az functionapp scale config set --name <APP_NAME> --resource-group <RESOURCE_GROUP> \
    --maximum-instance-count <MAX_SCALE_SETTING>

在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为函数应用名称。 将 <MAX_SCALE_SETTING> 替换为所设置的最大缩放值。

步骤 6:配置存储装载

如果原始应用在 Linux 上运行并具有一个或多个显式连接的存储共享,则可能需要在新应用中重新连接相同的存储共享。

az webapp config storage-account add使用此命令重新连接新应用中的每个存储共享。

az webapp config storage-account add --name <APP_NAME> --resource-group <RESOURCE_GROUP> \
  --custom-id <MOUNT_NAME> --storage-type AzureFiles --account-name <STORAGE_ACCOUNT> \
  --share-name <STORAGE_SHARE_NAME> --access-key <ACCESS_KEY> --mount-path <MOUNT_PATH>

在此示例中,根据预迁移期间记录的详细信息进行这些替换:

占位符 DESCRIPTION
<APP_NAME> 函数应用的名称。
<RESOURCE_GROUP> 资源组的名称。
<STORAGE_ACCOUNT> 要连接的存储帐户的名称。
<ACCESS_KEY> 用于访问存储帐户的密钥,仅在使用基于密钥的访问时才需要。
<STORAGE_SHARE_NAME> 存储帐户中的 Azure 共享文件夹的名称。
<MOUNT_NAME> 应用中连接共享所使用的名称。
<MOUNT_PATH> 应用中连接共享所使用的路径。

对重新连接的每个文件共享重复此步骤。

步骤 7:配置任何自定义域和 CORS 访问

如果原始应用定义了任何绑定的自定义域或任何 CORS 设置,请在新应用中重新创建它们。 有关自定义域的详细信息,请参阅 在 Azure 应用服务中设置现有自定义域

  1. az functionapp config hostname add使用此命令将任何自定义域映射重新绑定到应用:

    az functionapp config hostname add --name <APP_NAME> --resource-group <RESOURCE_GROUP> \
        --hostname <CUSTOM_DOMAIN>
    

    在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为函数应用名称。 将 <CUSTOM_DOMAIN> 替换为你的自定义域名。

  2. 使用此az functionapp cors add命令用来替换所有的 CORS 设置:

    az functionapp cors add --name <APP_NAME> --resource-group <RESOURCE_GROUP> \
        --allowed-origins <ALLOWED_ORIGIN_1> <ALLOWED_ORIGIN_2> <ALLOWED_ORIGIN_N>
    

    在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为函数应用名称。 将 <ALLOWED_ORIGIN_*> 替换为允许的来源。

步骤 8:配置托管标识并分配角色

在新应用中配置托管标识的方式取决于托管标识的类型:

托管标识类型 创建标识 角色分配
用户分配 可选 可以继续在新应用中使用相同的用户分配的托管标识。 必须将这些标识重新分配给 Flex Consumption 应用,并验证它们是否仍然在远程服务中具有正确的角色分配。 如果选择为新应用创建新标识,则必须分配与现有标识相同的角色。
系统分配 是的 由于每个函数应用都有自己的系统分配托管标识,因此必须在新应用中启用系统分配的托管标识,并重新分配与原始应用中相同的角色。

正确重新创建角色分配是确保函数应用在迁移后对 Azure 资源具有相同访问权限的关键。

小窍门

如果原始应用使用连接字符串或其他共享机密进行身份验证,则通过切换到将 Microsoft Entra ID 身份验证与托管标识配合使用来提高应用的安全性是一个很好的机会。 有关详细信息,请参阅 教程:创建使用标识而不是机密连接到 Azure 服务的函数应用

  • 系统分配
  • 用户分配
  1. az functionapp identity assign使用此命令在新应用中启用系统分配的托管标识:

    az functionapp identity assign --name <APP_NAME> --resource-group <RESOURCE_GROUP>
    

    在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为函数应用名称。

  2. 使用此脚本获取系统分配的标识的主体 ID,然后将其添加到所需的角色:

    # Get the principal ID of the system identity
    principalId=$(az functionapp identity show --name <APP_NAME> --resource-group <RESOURCE_GROUP> \
        --query principalId -o tsv)
    
    # Assign a role in a specific resource (scope) to the system identity
    az role assignment create --assignee $principalId --role "<ROLE_NAME>" --scope "<RESOURCE_ID>"
    

    在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为函数应用名称。 将<ROLE_NAME><RESOURCE_ID>替换为从原始应用中捕获的角色名称和特定资源。

  3. 针对新应用所需的每个角色重复上述命令。

步骤 9:配置内置身份验证

如果原始应用使用了内置客户端身份验证,则应在新应用中重新创建它。 如果计划重复使用相同的客户端注册,请确保在身份验证提供程序中设置新应用的经过身份验证的终结点。

根据之前收集的信息,使用 az webapp auth update 命令重新创建应用所需的每个内置身份验证注册。

步骤 10:配置网络访问限制

如果原始应用有任何基于 IP 的入站访问限制,则可以重新创建要保留在新应用中的任何相同入站访问规则。

小窍门

Flex Consumption 计划 完全支持虚拟网络集成。 因此,还可以选择在迁移后使用入站专用终结点。 有关详细信息,请参阅专用终结点

az functionapp config access-restriction add对要在新应用中复制的每个 IP 访问限制使用此命令:

az functionapp config access-restriction add --name <APP_NAME> --resource-group <RESOURCE_GROUP> \
  --rule-name <RULE_NAME> --action Deny --ip-address <IP_ADDRESS> --priority <PRIORITY>

在此示例中,将这些占位符替换为原始应用中的值:

占位符 价值
<APP_NAME> 函数应用名称。
<RESOURCE_GROUP> 您的资源组。
<RULE_NAME> IP 规则的易记名称。
<Priority> 排除项的优先级。
<IP_Address> 要排除的 IP 地址。

针对原始应用中记录的每个 IP 限制运行此命令。

步骤 11:启用监视

在开始使用 Flex 消耗计划运行新应用之前,确保已启用 Application Insights。 配置 Application Insights 有助于排查在代码部署和启动期间可能发生的任何问题。

实施涵盖应用指标、日志和成本的综合监视策略。 通过使用此类策略,可以验证迁移的成功,及时识别任何问题,并优化新应用的性能和成本。

如果计划将此新应用与当前应用进行比较,请确保方案还会收集所需的比较基准。 有关详细信息,请参阅 “配置监视”。

步骤 12:将应用程序代码部署到新的"灵活消费"应用程序

根据原始应用的设置完全配置新的 Flex Consumption 计划应用后,是时候将代码部署到 Azure 中的新应用资源了。

谨慎

成功部署后,新应用中的触发器会立即开始处理连接服务中的数据。 若要最大程度地减少重复数据并在启动新应用并关闭原始应用时防止数据丢失,应查看 按触发器类型在缓解中定义的策略。

Functions 提供了多种方式来部署代码,无论是从代码项目还是作为现成的部署包进行部署。

小窍门

如果项目代码保留在源代码存储库中,则现在是配置持续部署管道的最佳时机。 通过持续部署,可以根据连接的存储库中的更改自动部署应用程序更新。

应更新现有部署工作流,将源代码部署到新应用:

还可以为新应用创建新的持续部署工作流。 有关详细信息,请参阅 Azure Functions 的持续部署

迁移后的任务

成功迁移后,应执行以下后续任务:

验证基本功能

  1. 验证新应用是否在 Flex Consumption 计划中运行:

    使用此命令 az functionapp show 来查看有关托管计划的详细信息。

    az functionapp show --name <APP_NAME> --resource-group <RESOURCE_GROUP> --query "serverFarmId"
    

    在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为函数应用名称。

  2. 使用 HTTP 客户端在新应用上至少调用一个 HTTP 触发器终结点,以确保它按预期响应。

记录性能基准

运行新应用后,可以运行从原始应用收集的相同性能基准,例如:

建议的基准 注释
冷启动 测量从第一个请求到空闲时间段后的第一个响应的时间。
吞吐量 使用 负载测试工具 测量每秒最大请求数,以确定应用如何处理并发请求。
延迟 在各种负载条件下,跟踪P50P95P99的响应时间。 可以在 Application Insights 中监视这些指标。

可以使用此 Kusto 查询查看 Application Insights 中建议的延迟响应时间:

requests
| where timestamp > ago(1d)
| summarize percentiles(duration, 50, 95, 99) by bin(timestamp, 1h)
| render timechart

注释

弹性消耗计划指标不同于消耗计划指标。 在迁移前后比较性能时,请记住,必须使用不同的指标来跟踪类似的性能特征。 有关详细信息,请参阅 “配置监视”。

创建自定义仪表板

使用 Azure Monitor 指标和 Application Insights,可以在 Azure 门户中创建仪表板 ,以便显示平台指标和运行时日志和分析中的图表。

请考虑在 Azure 门户中设置有关关键指标的仪表板和警报。 有关详细信息,请参阅 在 Azure 中监视应用

优化计划设置

迁移的实际性能改进和成本影响可能会因特定于应用的工作负载和配置而异。 弹性消耗计划提供了多个设置,你可以调整这些设置来优化应用的性能。 你可能想要进行调整,以更紧密地匹配原始应用的行为,或平衡成本与性能。 有关详细信息,请参阅 Flex Consumption 文章中的 微调应用

删除原始应用(可选)

全面测试新的 Flex Consumption 函数应用并验证一切是否按预期工作后,可能需要清理资源以避免不必要的成本。 尽管原始应用中的触发器可能已禁用,但可能需要几天甚至几周才能完全删除原始应用。 此延迟取决于应用程序的使用模式,可确保正确测试所有方案(包括不常见方案)。 只有在对迁移结果感到满意后,才应继续删除原始函数应用。

重要

此操作将删除原始函数应用程序。 如果其他应用正在使用它,消耗计划将保持不变。 在继续作之前,请确保已成功将所有功能迁移到新的 Flex Consumption 应用,验证未将流量定向到原始应用,并备份可能需要引用的任何相关日志、配置或数据。

az functionapp delete使用命令删除原始函数应用:

az functionapp delete --name <ORIGINAL_APP_NAME> --resource-group <RESOURCE_GROUP>

在此示例中,将 <RESOURCE_GROUP> 替换为资源组名称,将 <APP_NAME> 替换为函数应用名称。

故障排除和恢复策略

尽管经过精心规划,但可能会出现迁移问题。 下面介绍如何在迁移期间处理潜在问题:

問题 解决方案
冷启动性能问题 • 查看并发设置
• 检查缺少的依赖项
缺少绑定 • 验证扩展捆绑包
• 更新绑定配置
权限错误 • 检查标识分配和角色权限
网络连接问题 • 验证访问限制和网络设置
缺少 Application Insights • 重新创建 Application Insights 连接
应用无法启动 请参阅 常规故障排除步骤
触发器不处理事件 请参阅 常规故障排除步骤

如果在迁移生产应用的过程中遇到问题,则可能需要在进行故障排查时将迁移回滚到原始应用

常规故障排除步骤

对于新应用无法启动或函数触发器未处理事件的情况,请使用以下步骤:

  1. Azure 门户中的新应用页中,选择“ 诊断”并在 应用页面的左窗格中解决问题。 依次选择“可用性和性能”、“函数应用关闭或报告错误”检测器。 有关详细信息,请参阅 Azure Functions 诊断概述

  2. 在应用页中,选择“ 监视>Application Insights>查看 Application Insights 数据 ”,然后选择“ 调查>失败 ”并检查是否存在任何故障事件。

  3. 选择监视>日志并运行此 Kusto 查询以检查这些表是否存在错误:

    traces
        | where severityLevel == 3
        | where cloud_RoleName == "<APP_NAME>"
        | where timestamp > ago(1d)
        | project timestamp, message, operation_Name, customDimensions
        | order by timestamp desc
    

    在这些查询中,将 <APP_NAME> 替换为新应用的名称。 这些查询用于检查过去一天中出现的错误(where timestamp > ago(1d))。

  4. 返回应用页,选择“设置环境变量”>,并验证是否已正确传输所有关键应用程序设置。 查找任何可能错误迁移的弃用的设置、任何拼写错误或错误的连接字符串。 验证 默认主机存储连接

  5. 选择“设置标识”>,然后仔细检查预期标识是否存在,以及它们是否已分配给正确的角色。

  6. 在代码中,验证所有绑定配置是否正确,特别注意连接字符串名称、存储队列和容器名称,以及事件中心触发器中的使用者组设置。

关键生产应用的回滚步骤

如果无法成功进行故障排除,则在继续进行故障排除时,可能需要还原为使用原始应用。

  1. 如果原始应用已停止,请重启它:

    az functionapp start使用此命令重启原始函数应用:

    az functionapp delete --name <ORIGINAL_APP_NAME> --resource-group <RESOURCE_GROUP>
    
  2. 如果创建新的队列/主题/容器,请确保将客户端重定向回原始资源。

  3. 如果修改了 DNS 或自定义域,请将这些更改还原为指向原始应用。

提供反馈

如果使用本文遇到迁移问题或想要提供有关本指南的其他反馈,请使用以下方法之一获取帮助或提供反馈: