你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
在本教程中,你将部署一个 Python 应用,该应用在装载的 Azure 文件共享上使用 ffmpeg 二进制文件来处理 Azure Functions 中的映像。 将映像上传到容器时,该函数会触发,从装载调用 ffmpeg 以转换映像,并将结果保存回存储。 通过将大型二进制文件(如 ffmpeg)托管在挂载的共享存储中,而不是在部署包中,可以保持部署的小巧并加快冷启动速度。
在本教程中,你将了解:
- 使用 Azure Developer CLI 部署装载有 Azure 文件存储共享的 Flex 消耗函数应用
- 上传示例映像以触发基于 Blob 的处理
- 验证函数是否从装载中调用了 ffmpeg 并保存转换后的映像
注释
本文的代码示例可在 带有 Azure 文件挂载示例的 Azure Functions Flex Consumption GitHub 存储库中找到。
先决条件
- 拥有有效订阅的 Azure 帐户。 免费创建帐户。
- Azure 开发人员 CLI (azd) 版本 1.9.0 或更高版本
- Git
本教程中的 CLI 示例使用 Bash 语法,并在 Azure Cloud Shell (Bash) 和 Linux/macOS 终端中进行测试。
初始化示例项目
本教程的示例代码位于 Azure Functions Flex Consumption 与 Azure 文件操作系统装载示例 GitHub 存储库中。 该 ffmpeg-image-processing 文件夹包含函数应用代码、预配所需 Azure 资源的 Bicep 模板,以及上传 ffmpeg 二进制文件的部署后脚本。
打开终端,转到要克隆存储库的目录。
克隆存储库:
git clone https://github.com/Azure-Samples/Azure-Functions-Flex-Consumption-with-Azure-Files-OS-Mount-Samples.git转到项目文件夹:
cd Azure-Functions-Flex-Consumption-with-Azure-Files-OS-Mount-Samples/ffmpeg-image-processingazd初始化环境。 出现提示时,输入环境名称,例如ffmpeg-processing:azd init
查看代码
使基于 OS 装载的处理工作的三个关键部分是创建装载的基础结构、上传二进制文件的脚本以及调用它的函数代码。
该 mounts.bicep 模块在函数应用上配置 Azure 文件共享 SMB 挂载。 该值 mountPath 确定文件在运行时出现的本地路径。 将存储帐户访问密钥作为参数传递,平台通过 Key Vault 引用在运行时解析它:
@description('Function app name')
param functionAppName string
@description('Storage account name')
param storageAccountName string
@description('Storage account access key or app setting reference for Azure Files SMB mount')
param accessKey string
@description('Array of mount configurations')
param mounts array
// Function app reference
resource functionApp 'Microsoft.Web/sites@2023-12-01' existing = {
name: functionAppName
}
// Azure Files OS mount configuration
// Deploys azureStorageAccounts site config with all mounts in one shot
resource mountConfig 'Microsoft.Web/sites/config@2023-12-01' = {
parent: functionApp
name: 'azurestorageaccounts'
properties: reduce(mounts, {}, (cur, mount) => union(cur, {
'${mount.name}': {
type: 'AzureFiles'
shareName: mount.shareName
mountPath: mount.mountPath
accountName: storageAccountName
accessKey: accessKey
}
}))
}
output mountPaths array = [for mount in mounts: mount.mountPath]
由于 Azure 文件存储 SMB 装载尚不支持托管标识身份验证,因此需要存储帐户密钥。 最佳做法是将此密钥存储在 Azure Key Vault 中,并在应用设置中使用 Key Vault 引用 。 装载配置使用 @AppSettingRef()引用应用设置,因此密钥永远不会显示在 Bicep 模板中。 该 keyvault.bicep 模块创建保管库、存储密钥并授予 RBAC 角色:
@description('Key Vault name')
param name string
@description('Location')
param location string
@description('Tags')
param tags object = {}
@description('Storage account name')
param storageAccountName string
@description('Principal ID of the function app identity (receives Key Vault Secrets User role)')
param functionAppPrincipalId string
@description('Principal ID of the deploying user (receives Key Vault Secrets Officer role)')
param deployerPrincipalId string = ''
// Storage account reference
resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' existing = {
name: storageAccountName
}
// Key Vault with RBAC authorization
resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = {
name: name
location: location
tags: tags
properties: {
sku: {
family: 'A'
name: 'standard'
}
tenantId: tenant().tenantId
enableRbacAuthorization: true
enabledForTemplateDeployment: true
enableSoftDelete: true
softDeleteRetentionInDays: 7
}
}
// Store storage account key as a secret (Azure Files mounts require shared key)
resource storageKeySecret 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = {
parent: keyVault
name: 'storageAccountKey'
properties: {
value: storage.listKeys().keys[0].value
contentType: 'Storage account access key for Azure Files SMB mount'
}
}
// Built-in Key Vault RBAC role IDs
var roles = {
KeyVaultSecretsOfficer: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')
KeyVaultSecretsUser: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')
}
// Grant the function app identity read access to secrets
resource functionAppSecretsUser 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(keyVault.id, functionAppPrincipalId, roles.KeyVaultSecretsUser)
scope: keyVault
properties: {
roleDefinitionId: roles.KeyVaultSecretsUser
principalId: functionAppPrincipalId
principalType: 'ServicePrincipal'
}
}
// Grant the deployer manage access to secrets
resource deployerSecretsOfficer 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (!empty(deployerPrincipalId)) {
name: guid(keyVault.id, deployerPrincipalId, roles.KeyVaultSecretsOfficer)
scope: keyVault
properties: {
roleDefinitionId: roles.KeyVaultSecretsOfficer
principalId: deployerPrincipalId
principalType: 'User'
}
}
output name string = keyVault.name
output uri string = keyVault.properties.vaultUri
output storageKeySecretUri string = storageKeySecret.properties.secretUri
main.bicep 文件调用装载和密钥保管库模块:
// Key Vault for secure storage of Azure Files access key
module keyVault './app/keyvault.bicep' = {
name: 'keyVault'
scope: rg
params: {
name: !empty(keyVaultName) ? keyVaultName : '${abbrs.keyVaultVaults}${resourceToken}'
location: location
tags: tags
storageAccountName: storage.outputs.name
functionAppPrincipalId: processorIdentity.outputs.principalId
deployerPrincipalId: principalId
}
}
// Azure Files mount configuration (access key resolved via Key Vault reference)
module azureFilesMount './app/mounts.bicep' = {
name: 'azureFilesMount'
scope: rg
params: {
functionAppName: functionApp.outputs.name
storageAccountName: storage.outputs.name
accessKey: '@AppSettingRef(MOUNT_SECRET_REFERENCE)'
mounts: [
{
name: 'tools'
shareName: 'tools'
mountPath: '/mounts/tools/'
}
]
}
dependsOn: [
functionAppRoleAssignments
]
}
使用 Azure 开发人员 CLI 进行部署
此示例是 Azure 开发人员 CLI (azd) 模板。 单个 azd up 命令预配基础结构、部署函数代码、将 ffmpeg 二进制文件上传到 Azure 文件存储,并为 Blob 触发器创建事件网格订阅。
登录到Azure。 部署后脚本使用 Azure CLI 命令,因此需要使用这两种工具进行身份验证:
azd auth login az login配置和部署所有内容:
azd up出现提示时,选择要使用的 Azure 订阅和位置。 命令如下:
- 创建资源组、存储帐户、Key Vault、Flex Consumption 函数应用、Application Insights 实例和托管标识。
- 部署 Python 函数代码。
- 将 ffmpeg 二进制文件下载并上传到 Azure 文件共享。
- 创建事件网格订阅,以便 Blob 上传触发函数。
- 执行健康检查。
注释
由于 Azure 文件存储 SMB 装载尚不支持托管标识身份验证,因此需要存储帐户密钥。 最佳做法是,部署将此密钥存储在 Azure Key Vault 中,并使用 Key Vault 引用 ,以便密钥永远不会在应用设置中公开。 此方法提供对密钥轮换的集中式机密管理、审核和支持。
部署需要几分钟时间。 完成后,会看到已创建资源的摘要。
将资源名称另存为剩余步骤的 shell 变量:
RESOURCE_GROUP=$(azd env get-value AZURE_RESOURCE_GROUP) STORAGE_ACCOUNT=$(azd env get-value AZURE_STORAGE_ACCOUNT_NAME) FUNCTION_APP_NAME=$(azd env get-value AZURE_FUNCTION_APP_NAME) INPUT_CONTAINER=$(azd env get-value AZURE_STORAGE_INPUT_CONTAINER) OUTPUT_CONTAINER=$(azd env get-value AZURE_STORAGE_OUTPUT_CONTAINER)
处理图像
将存储库中包含的示例映像上传到输入容器。 部署期间创建的事件网格订阅会在上传 Blob 时自动触发函数。
az storage blob upload \ --container-name $INPUT_CONTAINER \ --name sample_image.png \ --file sample_image.png \ --account-name $STORAGE_ACCOUNT \ --auth-mode login小窍门
如果触发器未立即触发,请等待 10-15 秒,然后在 Azure 门户中检查函数的执行日志。
通过列出输出容器中的 blob 来验证函数处理图像:
az storage blob list \ --container-name $OUTPUT_CONTAINER \ --account-name $STORAGE_ACCOUNT \ --auth-mode login \ -o table应该在输出容器中看到
sample_image.jpg元素。下载转换后的映像:
az storage blob download \ --container-name $OUTPUT_CONTAINER \ --name sample_image.png \ --file ./output_image.png \ --account-name $STORAGE_ACCOUNT \ --auth-mode login
注释
第一次执行可能稍微慢一些(冷启动)。 后续调用速度更快,因为函数容器保持活跃,并且 ffmpeg 被缓存。 若要尽量减少冷启动,请考虑启用 始终就绪的实例。
清理资源
若要避免持续收费,请删除本教程创建的所有资源:
azd down --purge
警告
此命令删除资源组及其中的所有资源,包括函数应用、存储帐户和 Application Insights 实例。