Compartilhar via


Tutorial: Processar imagens usando FFmpeg em um compartilhamento de Arquivos do Azure montado

Neste tutorial, você implantará um aplicativo Python que usa um binário ffmpeg em um compartilhamento de Arquivos do Azure montado para processar imagens no Azure Functions. Quando você carrega uma imagem no contêiner, a função dispara, chama o ffmpeg da unidade montada para converter a imagem e salva o resultado de volta no armazenamento. Ao hospedar arquivos binários grandes, como o ffmpeg, em um compartilhamento montado em vez de incluí-los no pacote de implantação, você mantém as implantações compactas e garante que as inicializações a frio sejam rápidas.

Neste tutorial, você:

  • Implantar um aplicativo de função Consumo Flexível com um compartilhamento do Azure Files montado usando a CLI do Azure Developer
  • Carregar uma imagem de exemplo para iniciar o processamento baseado em blob
  • Verifique se a função chamou o ffmpeg a partir do diretório de montagem e salvou a imagem convertida

Observação

Os exemplos de código deste artigo estão disponíveis no repositório do GitHub Azure Functions Flex Consumption com Exemplos de Montagem do Sistema Operacional Azure Files.

Pré-requisitos

Os exemplos da CLI neste tutorial usam a sintaxe bash e são testados nos terminais do Azure Cloud Shell (Bash) e linux/macOS.

Inicializar o projeto de exemplo

O código de exemplo deste tutorial está no repositório do GitHub Azure Functions Flex Consumption with Azure Files OS Mount Samples. A ffmpeg-image-processing pasta contém o código do aplicativo de funções, um modelo Bicep que provisiona os recursos necessários do Azure e um script pós-implantação que carrega o binário de ffmpeg.

  1. Abra um terminal e vá para o diretório onde você deseja clonar o repositório.

  2. Por favor, clone o repositório:

    git clone https://github.com/Azure-Samples/Azure-Functions-Flex-Consumption-with-Azure-Files-OS-Mount-Samples.git
    
  3. Vá para a pasta do projeto:

    cd Azure-Functions-Flex-Consumption-with-Azure-Files-OS-Mount-Samples/ffmpeg-image-processing
    
  4. Inicialize o ambiente azd. Quando solicitado, insira um nome de ambiente como ffmpeg-processing:

    azd init
    

Examine o código

As três partes principais que fazem com que o processamento baseado em montagem do sistema operacional funcione são a infraestrutura que cria a montagem, o script que carrega o binário e o código de função que o chama.

O módulo mounts.bicep configura uma montagem SMB de Arquivos do Azure no aplicativo de funções. O mountPath valor determina o caminho local em que os arquivos aparecem em runtime. Você passa a chave de acesso da conta de armazenamento como um parâmetro e a plataforma a resolve em runtime por meio de uma referência do 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]

Como as montagens SMB dos Arquivos do Azure ainda não dão suporte à autenticação de identidade gerenciada, você precisa de uma chave de conta de armazenamento. Como prática recomendada, armazene essa chave no Azure Key Vault e use uma referência do Key Vault em uma configuração de aplicativo. A configuração de montagem faz referência à configuração do aplicativo usando @AppSettingRef(), portanto, a chave nunca aparece em seus modelos Bicep. O keyvault.bicep módulo cria o cofre, armazena a chave e concede funções 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

O arquivo main.bicep invoca a montagem e os módulos do Key Vault:


// 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
  ]
}

Implantar usando a CLI do Desenvolvedor do Azure

Este exemplo é um modelo da CLI do Desenvolvedor do Azure (azd). Um único comando azd up provisiona a infraestrutura, implanta o código da função, carrega o binário ffmpeg nos Arquivos do Azure e cria a assinatura na Grade de Eventos para gatilhos de blob.

  1. Inicie sessão no Azure. O script pós-implantação usa comandos da CLI do Azure, portanto, você precisa se autenticar usando ambas as ferramentas:

    azd auth login
    az login
    
  2. Provisionar e implantar tudo:

    azd up
    

    Quando solicitado, selecione a assinatura e o local do Azure a serem usados. Em seguida, o comando:

    • Cria um grupo de recursos, conta de armazenamento, Key Vault, aplicativo de funções Flex Consumption, instância do Application Insights e identidade gerenciada.
    • Implanta o código da função Python.
    • Baixa e carrega o binário ffmpeg para o compartilhamento de Arquivos do Azure.
    • Cria uma assinatura da Grade de Eventos para que os uploads de blob ativem sua função.
    • Executa uma verificação de saúde.

    Observação

    Como as montagens SMB dos Arquivos do Azure ainda não dão suporte à autenticação de identidade gerenciada, uma chave de conta de armazenamento é necessária. Como prática recomendada, a implantação armazena essa chave no Azure Key Vault e usa uma referência do Key Vault para que a chave nunca seja exposta nas configurações do aplicativo. Essa abordagem fornece gerenciamento centralizado de segredos, auditoria e suporte para rotação de chaves.

    A implantação leva alguns minutos. Quando ele for concluído, você verá um resumo dos recursos criados.

  3. Salve nomes de recursos como variáveis de shell para as etapas restantes:

    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)
    

Processar uma imagem

  1. Carregue a imagem de exemplo incluída no repositório para o contêiner de entrada. A assinatura da Grade de Eventos criada durante a implantação dispara automaticamente sua função quando um blob é carregado.

    az storage blob upload \
      --container-name $INPUT_CONTAINER \
      --name sample_image.png \
      --file sample_image.png \
      --account-name $STORAGE_ACCOUNT \
      --auth-mode login
    

    Dica

    Se o gatilho não for acionado imediatamente, aguarde de 10 a 15 segundos e verifique os logs de execução da função no portal do Azure.

  2. Verifique se a função processou a imagem listando os blobs no contêiner de saída:

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

    Você deve ver sample_image.jpg no contêiner de saída.

  3. Baixe a imagem convertida:

    az storage blob download \
      --container-name $OUTPUT_CONTAINER \
      --name sample_image.png \
      --file ./output_image.png \
      --account-name $STORAGE_ACCOUNT \
      --auth-mode login
    

Observação

A primeira execução pode ser um pouco mais lenta (início frio). As invocações subsequentes são mais rápidas porque o contêiner de função permanece quente e o ffmpeg é armazenado em cache. Para reduzir a inicialização a frio, considere habilitar instâncias sempre prontas.

Limpar os recursos

Para evitar encargos contínuos, exclua todos os recursos criados por este tutorial:

azd down --purge

Aviso

Esse comando exclui o grupo de recursos e todos os recursos nele, incluindo o aplicativo de funções, a conta de armazenamento e a instância do Application Insights.