通过


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

教程:在装载的 Azure 文件共享上使用 FFmpeg 处理映像

在本教程中,你将部署一个 Python 应用,该应用在装载的 Azure 文件共享上使用 ffmpeg 二进制文件来处理 Azure Functions 中的映像。 将映像上传到容器时,该函数会触发,从装载调用 ffmpeg 以转换映像,并将结果保存回存储。 通过将大型二进制文件(如 ffmpeg)托管在挂载的共享存储中,而不是在部署包中,可以保持部署的小巧并加快冷启动速度。

在本教程中,你将了解:

  • 使用 Azure Developer CLI 部署装载有 Azure 文件存储共享的 Flex 消耗函数应用
  • 上传示例映像以触发基于 Blob 的处理
  • 验证函数是否从装载中调用了 ffmpeg 并保存转换后的映像

注释

本文的代码示例可在 带有 Azure 文件挂载示例的 Azure Functions Flex Consumption GitHub 存储库中找到。

先决条件

本教程中的 CLI 示例使用 Bash 语法,并在 Azure Cloud Shell (Bash) 和 Linux/macOS 终端中进行测试。

初始化示例项目

本教程的示例代码位于 Azure Functions Flex Consumption 与 Azure 文件操作系统装载示例 GitHub 存储库中。 该 ffmpeg-image-processing 文件夹包含函数应用代码、预配所需 Azure 资源的 Bicep 模板,以及上传 ffmpeg 二进制文件的部署后脚本。

  1. 打开终端,转到要克隆存储库的目录。

  2. 克隆存储库:

    git clone https://github.com/Azure-Samples/Azure-Functions-Flex-Consumption-with-Azure-Files-OS-Mount-Samples.git
    
  3. 转到项目文件夹:

    cd Azure-Functions-Flex-Consumption-with-Azure-Files-OS-Mount-Samples/ffmpeg-image-processing
    
  4. azd初始化环境。 出现提示时,输入环境名称,例如 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 触发器创建事件网格订阅。

  1. 登录到Azure。 部署后脚本使用 Azure CLI 命令,因此需要使用这两种工具进行身份验证:

    azd auth login
    az login
    
  2. 配置和部署所有内容:

    azd up
    

    出现提示时,选择要使用的 Azure 订阅和位置。 命令如下:

    • 创建资源组、存储帐户、Key Vault、Flex Consumption 函数应用、Application Insights 实例和托管标识。
    • 部署 Python 函数代码。
    • 将 ffmpeg 二进制文件下载并上传到 Azure 文件共享。
    • 创建事件网格订阅,以便 Blob 上传触发函数。
    • 执行健康检查。

    注释

    由于 Azure 文件存储 SMB 装载尚不支持托管标识身份验证,因此需要存储帐户密钥。 最佳做法是,部署将此密钥存储在 Azure Key Vault 中,并使用 Key Vault 引用 ,以便密钥永远不会在应用设置中公开。 此方法提供对密钥轮换的集中式机密管理、审核和支持。

    部署需要几分钟时间。 完成后,会看到已创建资源的摘要。

  3. 将资源名称另存为剩余步骤的 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)
    

处理图像

  1. 将存储库中包含的示例映像上传到输入容器。 部署期间创建的事件网格订阅会在上传 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 门户中检查函数的执行日志。

  2. 通过列出输出容器中的 blob 来验证函数处理图像:

    az storage blob list \
      --container-name $OUTPUT_CONTAINER \
      --account-name $STORAGE_ACCOUNT \
      --auth-mode login \
      -o table
    

    应该在输出容器中看到 sample_image.jpg 元素。

  3. 下载转换后的映像:

    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 实例。