Azure Functions的存储注意事项

在 Azure 中创建函数应用实例时,必须提供对默认Azure 存储帐户的访问权限。 下图和表详细介绍了Azure Functions如何在默认存储帐户中使用服务:

请在本文顶部选择您的托管套餐,查看适用于您功能应用的存储指南。

Diagram 显示Azure Functions如何在Azure 存储帐户中使用不同的存储服务,包括 Blob 存储、文件共享、队列存储和表存储。

存储服务 函数用法
Azure Blob 存储 维护绑定状态和函数密钥1。
默认情况下,用于 Durable Functions 中的任务集线器。
可用于存储Linux 消耗计划远程生成或外部包 URL 部署中所用的函数应用代码。
Azure 文件存储2 文件共享,用于存储和运行消耗计划和高级计划中的函数应用代码。
维护 扩展捆绑包。
存储部署日志。
支持 PowerShell 中的托管依赖项。
Azure队列存储 默认情况下,用于 Durable Functions 中的任务集线器。 用于特定Azure Functions触发器中的失败和重试处理。 用于 Blob 存储触发器的对象跟踪。
Azure表存储 默认情况下,用于 Durable Functions 中的任务集线器。
  1. Blob 存储是功能密钥的默认存储,但你可以配置备用存储。
  2. 默认情况下,Azure 文件存储已设置,但在某些情况下,可以创建不带Azure 文件存储的应用。

重要注意事项

请考虑以下关于你功能应用所使用的存储账户的事实:

当你在Consumption Plan(Windows)或Premium套餐上托管函数应用时,你会将函数代码和配置文件存储在关联的存储账户中的Azure 文件存储中。 如果你删除这个存储账户,你就永久删除了该内容。 有关详细信息,请参阅 存储帐户已删除。

  • 存储账户保留重要数据,如函数代码、 访问密钥及其他重要的服务相关数据。 必须通过以下方式仔细管理对函数应用使用的存储帐户的访问:

    • 根据最低特权模型审核和限制应用和用户对存储帐户的访问。 存储帐户的权限可以来自分配角色中与数据操作相关的权限,或通过执行listKeys 操作的权限。

    • 监视存储帐户中的控制平面活动 (例如检索密钥) 和数据平面操作 (如写入 Blob)。 请考虑在除Azure 存储以外的位置维护存储日志。 有关详细信息,请参阅存储日志。

  • 如果使用 Durable Functions,则任务中心存储尤其安全敏感,因为对它的写入访问权限可用于更改应用程序行为,包括触发任意代码执行。 有关详细信息,请参阅 保护任务中心存储。

存储帐户要求

在Azure门户中的函数应用创建过程中创建的存储帐户适用于新的函数应用。 选择使用现有存储帐户时,提供的列表不包括某些不受支持的存储帐户。 以下限制适用于函数应用使用的存储帐户。 确保现有的存储账户满足以下要求:

  • 当函数应用托管在消耗计划中时,无法使用网络安全存储帐户。
  • 帐户类型必须支持 Blob、队列和表存储。 某些存储帐户不支持队列和表。 这些帐户包括仅限 blob 的存储帐户和 Azure Premium 存储。 若要了解存储帐户类型的详细信息,请参阅存储帐户概述。

  • 在Azure门户中创建函数应用时,只能选择与创建的函数应用位于同一区域中的现有存储帐户。 此要求是性能优化,而不是严格的限制。 若要了解详细信息,请参阅存储帐户位置。

  • 在启用了 可用性区域支持的 计划中创建函数应用时,仅支持 区域冗余存储帐户 。

使用部署自动化在具有网络保护的存储帐户中创建函数应用时,必须在 ARM 模板或 Bicep 文件中包含特定的网络配置。 如果未包括这些设置和资源,则自动部署可能会在验证中失败。 有关 ARM 模板和 Bicep 指南,请参阅 安全的部署。 有关使用网络配置存储帐户的概述,请参阅 如何使用具有 Azure Functions。

存储帐户指南

每个 Function App 都需要存储帐户才能运行。 删除该帐户时,函数应用将停止运行。 若要对存储相关问题进行故障排除,请参阅如何对存储相关问题进行故障排除。 以下注意事项适用于函数应用使用的存储帐户。

存储帐户位置

为了获得最佳性能,函数应用应使用同一区域中的存储帐户,从而减少延迟。 Azure门户强制实施此最佳做法。 如果需要在与函数应用不同的区域中使用存储帐户,则必须在 Azure 管理门户以外创建函数应用。

存储帐户必须可供函数应用访问。 如果需要使用受保护的存储帐户,请考虑将存储帐户限制在虚拟网络中。

存储帐户连接设置

默认情况下,函数应用将 AzureWebJobsStorage 连接配置为存储在 AzureWebJobsStorage 应用程序设置中的连接字符串。 还可以 将 AzureWebJobsStorage 配置为在没有机密的情况下使用基于标识的连接 。

在消费计划(仅限 Windows)或弹性高级计划(Windows 或 Linux)中运行的函数应用可以使用 Azure 文件存储 存储用于启用动态扩展所需的镜像。 对于这些计划,请在WEBSITE_CONTENTAZUREFILECONNECTIONSTRING设置中设置存储帐户的连接字符串,并在WEBSITE_CONTENTSHARE设置中设置文件共享的名称。 此值通常与用于 AzureWebJobsStorage 的帐户相同。 还可以创建不使用 Azure 文件存储 的函数应用,但缩放可能受到限制。

注意

重新生成存储密钥时,必须更新存储帐户的连接字符串。 有关详细信息,请参阅 创建Azure存储帐户。

共享存储帐户

多个函数应用可以在没有任何问题的情况下共享同一存储帐户。 例如,在 Visual Studio 中,可以使用 Azurite 存储模拟器开发多个应用。 在这种情况下,仿真器的作用类似于单个存储帐户。 函数应用使用的同一存储帐户也可以存储应用程序数据。 但是在生产环境中,这种方法并不总是个好主意。

可能需要使用单独的存储帐户以避免主机 ID 冲突。

生命周期管理策略注意事项

不要将 生命周期管理策略 应用于函数应用使用的 Blob 存储帐户。 函数使用 Blob 存储来保存重要信息,例如 函数访问密钥。 策略可能会删除 Functions 主机所需的 Blob 数据对象,例如密钥。 如果必须使用策略,请排除 Functions 使用的容器,这些容器的前缀为 azure-webjobs 或 scm。

存储日志

由于函数代码和密钥可能保留在存储帐户中,因此针对存储帐户记录活动是监视未经授权的访问的好方法。 Azure Monitor资源日志可用于跟踪针对存储数据平面的事件。 有关如何配置和检查这些日志的详细信息,请参阅 Monitoring Azure 存储。

Azure Monitor 活动日志 显示控制平面事件,包括 listKeys 操作。 但是,还应为存储帐户配置资源日志,以跟踪密钥的后续使用或其他基于标识的数据平面操作。 至少启用 StorageWrite 日志类别,以便识别正常 Functions 操作之外的数据修改。

若要限制任何范围广泛的存储权限的潜在影响,请考虑对这些日志使用非存储的目的地,例如日志分析(Log Analytics)。 有关详细信息,请参阅 Monitoring Azure Blob 存储。

优化存储性能

若要最大程度地提高性能,请对每个函数应用使用单独的存储帐户。 当您使用 Durable Functions 或 Event Hubs 触发的函数时,由于这些函数会生成大量的存储事务,因此这种方法显得尤为重要。 当应用程序逻辑需要与Azure 存储进行交互时,无论是直接使用存储 SDK还是通过存储绑定,都应该使用专门的存储帐户。 例如,如果有事件中心触发的函数将一些数据写入 Blob 存储,请使用两个存储帐户:一个用于函数应用,另一个用于函数存储的 blob。

通过虚拟网络实现一致的路由

在同一计划中托管的多个函数应用还可以将同一存储帐户用于由 WEBSITE_CONTENTAZUREFILECONNECTIONSTRING 定义的Azure 文件存储内容共享。 在使用虚拟网络保护此存储帐户时,所有这些应用程序(包括插槽)应使用相同的vnetContentShareEnabled值(之前是WEBSITE_CONTENTOVERVNET)和相同的虚拟网络集成配置,以确保流量始终通过指定的虚拟网络进行路由。 使用同一Azure 文件存储存储帐户的应用之间的此设置不匹配可能会导致流量通过公用网络路由。 在此配置中,存储帐户网络规则阻止访问。

本指南 vnetContentShareEnabled 不适用于专用托管或消耗计划托管。

处理 Blob 文件

Functions 的一个关键方案是对 Blob 容器中的文件进行文件处理,例如图像处理或情绪分析。 要了解详细信息,请参阅处理文件上传。

在 Blob 容器上触发

有多种方法可以根据存储容器中 Blob 的更改来运行函数代码,如下图所示:

图示展示了在 Azure 的 Blob 存储 容器中添加或更新项目时触发函数的各种选项。

使用下表确定哪种函数触发器最适合满足在容器中处理新增或更新 Blob 对象的需求。

策略 Blob 触发器 (轮询机制) Blob 触发器(事件驱动) 队列触发器 事件网格触发器
延迟 高(最多 10 分钟) 低 中等 低
存储帐户限制 不支持仅限 Blob 的存储帐户¹,以及已启用分层命名空间 (HNS) 的存储帐户,例如 Azure Data Lake Storage Gen2 帐户 不支持通用 v1 帐户 None 不支持通用 v1 帐户
触发器类型 Blob 存储 Blob 存储 队列存储 事件网格
扩展版本 任意 存储 v5.x+ 任意 任意
处理现有 Blob 是 否 否 否
筛选器 Blob 名称模式 事件筛选器 不适用 事件筛选器
需要事件订阅 否 是 否 是
支持大规模² 否 是 是 是
适用于 入站访问限制 是 否 是 是3
说明 默认触发器行为,即依赖于轮询容器以检查更新。 有关详细信息,请查看 Blob 存储触发器参考中的示例。 从事件订阅中获取 Blob 存储事件。 需要 Source 的 EventGrid 参数值。 有关详细信息,请参阅 Tutorial:使用事件订阅触发 Azure Functions 在 blob 容器上。 将 Blob 添加到容器时,会手动将 Blob 名称字符串添加到存储队列中。 队列存储触发器将此值直接传递到相同函数上的 Blob 存储输入绑定。 除了来自存储容器的事件之外,还提供触发事件的灵活性。 需要同时让非存储事件触发函数时使用。 有关详细信息,请参阅 如何在 Azure Functions。
  1. 仅 Blob 帐户限制仅适用于基于轮询的 Blob 存储触发器。 Blob 存储输入和输出绑定支持仅 Blob 帐户。
  2. 大规模可以宽松地定义为包含 100,000 个以上的 Blob 的容器,或者定义为每秒进行 100 个以上 Blob 更新的存储帐户。
  3. 可以通过让事件订阅使用已知用户标识通过公共 IP 空间中的加密通道传递事件来解决入站访问限制。

存储数据加密

Azure 存储静态加密存储帐户中的所有数据。 有关详细信息,请参阅Azure 存储静态数据的加密。

默认情况下,数据使用Microsoft管理的密钥进行加密。 为了更好地控制加密密钥,可以提供客户管理的密钥来加密 Blob 和文件数据。 这些密钥必须存在于 Azure 密钥保管库 中,Functions 才能访问存储帐户。 若要了解详细信息,请参阅 使用客户管理的密钥加密应用程序静态数据。

区域内数据驻留

当所有客户数据必须保持在同一区域时,使用与功能应用关联且具有 区域内冗余功能的存储账户。 同时配合Azure Durable Functions使用区域内冗余存储账户。

当您将应用托管在内部负载均衡的 应用服务环境(ASE)中时,平台仅将其他由平台管理的客户数据存储在该区域内。 若要了解详细信息,请参阅 ASE 区域冗余。

主机 ID 注意事项

函数使用主机ID值在存储的产物中唯一标识特定函数应用。 默认情况下,运行时会自动从函数应用的名称生成该 ID,名称被截断为前 32 个字符。 运行时在关联的存储帐户中存储每个应用的关联和跟踪信息时,会使用该 ID。 当函数应用的名称超过32个字符且前32个字符相同时,这种截断可能导致主机ID值重复。 当两个拥有相同主机ID的功能应用使用同一个存储账户时,会发生主机ID冲突,因为存储的数据无法唯一关联到正确的功能应用。

注意

当生产槽位中的某个函数应用与暂存槽位中的同一函数应用共用同一个存储帐户时,它们之间也可能发生同样类型的主机 ID 冲突。

在 Functions 运行时 4.x 版本中,错误会被记录,主机停止,导致硬性失败。 有关详细信息,请参阅 HostID 截断可能导致冲突。

避免主机 ID 冲突

请采用以下策略以避免主机ID碰撞:

  • 使用不同的存储账户,这样每个相冲突的主机都会写入不同的账户。
  • 将其中一个函数应用重命名,使其名称少于 32 个字符,这将更改该应用计算得出的主机 ID,并消除冲突。
  • 为一个或多个发生冲突的应用设置显式主机 ID。 若要了解详细信息,请参阅 “替代主机 ID”。

重要

更改与现有函数应用关联的存储帐户或更改应用的主机 ID 可能会影响现有函数的行为。 例如,Blob 存储触发器会通过在存储中某个特定的主机 ID 路径下写入回执,来跟踪各个 Blob 是否已被处理。 当主机 ID 发生更改或你指向新的存储帐户时,以前处理的 Blob 可能会被重新处理。

覆盖主机 ID

你可以在应用设置里用该 AzureFunctionsWebHost__hostid 设置为函数应用设置一个显式的主机ID。 有关详细信息,请参阅 AzureFunctionsWebHost__hostid。

当槽位之间发生冲突时,必须为每个槽位(包括生产槽位)设置特定的主机 ID。 还必须将这些设置标记为部署设置,以免它们进行交换。 若要了解如何创建应用设置,请参阅使用应用程序设置。

在没有Azure 文件存储的情况下创建应用

Azure 文件存储服务提供支持大规模方案的共享文件系统。 函数应用在弹性高级计划中运行或在消耗计划中于 Windows 上运行时,默认情况下会在存储帐户中创建 Azure 文件存储 共享。 函数可以使用此共享来实现日志流等功能,并将其用作共享的应用内容存储位置。 部署地点取决于部署技术和应用配置。 例如,使用外部包 URL 的应用会从配置的 URL 运行包,而不是从 Azure 文件存储 共享中运行。

使用 Azure 文件存储 需要一个 连接字符串,你可以在应用设置中存储为 WEBSITE_CONTENTAZUREFILECONNECTIONSTRING。 Azure 文件存储目前不支持基于标识的连接。 如果你的场景要求应用设置中不存储任何秘密,你必须移除应用对 Azure 文件存储 的依赖。 可以通过创建应用而不创建默认Azure 文件存储依赖项来避免此依赖项。

要在没有Azure 文件存储共享的情况下运行您的应用,您必须满足以下要求:

还应注意以下注意事项:

  • 你的应用不能依赖共享的可写文件系统。
  • 不支持门户编辑。
  • 在客户端(例如Azure门户)中,日志流式处理默认使用文件系统日志。 你应该改为依赖 Application Insights 日志。

如果上述要求符合你的情境,你可以继续创建函数应用而不用Azure 文件存储。 使用以下方法之一创建不含 WEBSITE_CONTENTAZUREFILECONNECTIONSTRING 应用和 WEBSITE_CONTENTSHARE 应用设置的应用程序:

  • Bicep/ARM 模板:从 ARM 模板或 Bicep 文件中移除两个应用设置,然后使用修改后的模板部署应用。
  • Azure 门户:在 Azure 门户中创建应用时,在存储选项卡中清空添加 Azure 文件存储 连接。

Azure 文件存储用于为 Functions 启用动态横向扩展。 如果在弹性高级计划和Windows上运行的消耗计划中没有Azure 文件存储,则缩放可能会受到限制。

专用套餐应用没有本节描述的默认Azure 文件存储内容共享依赖。

装载文件共享

此功能仅在运行于Linux上时可用。

你可以将 Azure 文件存储 共享挂载到 Linux 函数应用中,利用它们访问现有文件、机器学习模型或函数中的大型二进制文件。 有关在存储装载、绑定和外部数据库之间进行选择的概念性指南,请参阅 为 Azure Functions选择文件访问策略。

请使用以下命令将已有的共享挂载到你的 Linux 函数应用中。

az webapp 配置存储账户添加

在此命令中,share-name是现有Azure 文件存储共享的名称。 custom-id 可以是在装载到函数应用时唯一定义共享的任何字符串。 此外,mount-path 是在函数应用中用于访问共享的路径。 mount-path 必须采用 /dir-name 格式,不能以 /home 开头。

有关完整示例,请参阅 创建Python函数应用并装载Azure 文件存储共享。

Consumption 套餐不支持存储挂载。

重要

2028 年 9 月 30 日之后,在消耗计划中托管 Linux 上的函数应用的选项将停用。 消耗计划中Windows上运行的应用不受此更改的影响。