Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
In questa esercitazione si implementa un'app Python di Azure Functions che usa Durable Functions per orchestrare l'analisi parallela dei file di testo. L'app per le funzioni monta una condivisione di File di Azure, analizza più file di testo in parallelo (fan-out), aggrega i risultati (fan-in) e li restituisce al chiamante. Questo approccio illustra un vantaggio fondamentale dei montaggi di archiviazione: l'accesso condiviso ai file tra più istanze di funzione senza sovraccarico di rete per richiesta.
In questa esercitazione, farai:
- Usare la CLI per sviluppatori di Azure per distribuire un'app Durable Functions in un piano di consumo flessibile con una condivisione di Azure Files montata
- Attivare un'orchestrazione per elaborare i file di testo di esempio in parallelo
- Verificare i risultati dell'analisi aggregata
Annotazioni
Gli esempi di codice per questo articolo sono disponibili nel repository GitHub Azure Functions Flex Consumption with Azure Files OS Mount Samples.
Prerequisiti
- Un account Azure con una sottoscrizione attiva. Creare un account gratuito.
- CLI per sviluppatori di Azure (azd) versione 1.9.0 o successiva
- Git
Gli esempi dell'interfaccia della riga di comando di questa esercitazione usano la sintassi Bash e sono stati testati nei terminali Azure Cloud Shell (Bash) e Linux/macOS.
Inizializzare il progetto di esempio
È possibile trovare il codice di esempio per questa esercitazione nel repository GitHub Azure Functions Flex Consumption with Azure Files OS Mount Samples. La durable-text-analysis cartella contiene il codice dell'app per le funzioni, un modello Bicep che effettua il provisioning delle risorse di Azure necessarie e uno script di post-distribuzione che carica i file di testo di esempio.
Aprire un terminale e passare alla directory in cui si vuole clonare il repository.
Clonare il repository:
git clone https://github.com/Azure-Samples/Azure-Functions-Flex-Consumption-with-Azure-Files-OS-Mount-Samples.gitPassare alla cartella del progetto:
cd Azure-Functions-Flex-Consumption-with-Azure-Files-OS-Mount-Samples/durable-text-analysisInizializzare l'ambiente
azd. Quando richiesto, immettere un nome di ambiente,durable-textad esempio :azd init
Esaminare il codice
I tre elementi chiave che fanno funzionare questo esempio sono l'infrastruttura che crea il montaggio, lo script che carica i file di esempio e il codice della funzione che orchestra l'analisi.
Il modulo mounts.bicep configura un mount SMB di Azure Files nell'applicazione funzione. Il mountPath valore determina il percorso locale in cui vengono visualizzati i file in fase di esecuzione. La chiave di accesso dell'account di archiviazione viene passata come parametro e la piattaforma la risolve in fase di esecuzione tramite un riferimento a 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]
Poiché i montaggi SMB di Azure Files non supportano ancora l'autenticazione tramite identità gestita, è necessaria una chiave dell'account di archiviazione. Come procedura consigliata, archiviare questa chiave in Azure Key Vault e usare un riferimento a Key Vault in un'impostazione dell'app. La configurazione di montaggio fa riferimento all'impostazione dell'app usando @AppSettingRef(), in modo che la chiave non venga mai visualizzata nei modelli Bicep. Il keyvault.bicep modulo crea il vault, archivia la chiave e concede i ruoli di controllo degli accessi in base al ruolo (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
Il main.bicep file richiama i moduli mount e 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: 'data'
shareName: 'data'
mountPath: '/mounts/data/'
}
]
}
dependsOn: [
functionAppRoleAssignments
]
Eseguire la distribuzione usando l'interfaccia della riga di comando per sviluppatori di Azure
Questo esempio è un modello dell'interfaccia della riga di comando per sviluppatori di Azure (azd). Un singolo azd up comando effettua il provisioning dell'infrastruttura, distribuisce il codice della funzione e carica i file di testo di esempio nella condivisione file di Azure.
Accedere ad Azure. Lo script post-distribuzione usa i comandi dell'interfaccia della riga di comando di Azure, quindi è necessario eseguire l'autenticazione usando entrambi gli strumenti:
azd auth login az loginEffettuare il provisioning e distribuire tutti gli elementi seguenti:
azd upQuando richiesto, selezionare la sottoscrizione di Azure e il percorso da usare. Il comando quindi:
- Crea un gruppo di risorse, un account di archiviazione, Key Vault, un'app per le funzioni Flex Consumption con una configurazione di Durable Functions, un'istanza di Application Insights e un'identità gestita
- Distribuisce il codice della funzione Python
- Carica file di testo di esempio nella condivisione file di Azure
- Esegue un controllo di salute
Annotazioni
Poiché i montaggi SMB di Azure Files non supportano ancora l'autenticazione tramite identità gestita, è necessario utilizzare una chiave dell'account di archiviazione. Come procedura consigliata, la distribuzione archivia questa chiave in Azure Key Vault e usa un riferimento a Key Vault in modo che la chiave non venga mai esposta nelle impostazioni dell'app. Questo approccio offre la gestione centralizzata dei segreti, il controllo e il supporto per la rotazione delle chiavi.
La distribuzione richiede alcuni minuti. Al termine, viene visualizzato un riepilogo delle risorse create.
Salvare i nomi delle risorse come variabili della shell per i passaggi rimanenti:
RESOURCE_GROUP=$(azd env get-value AZURE_RESOURCE_GROUP) FUNCTION_APP_NAME=$(azd env get-value AZURE_FUNCTION_APP_NAME) FUNCTION_APP_URL=$(azd env get-value AZURE_FUNCTION_APP_URL)
Attivare l'orchestrazione
Ottenere la chiave host della funzione:
HOST_KEY=$(az functionapp keys list \ --resource-group $RESOURCE_GROUP \ --name $FUNCTION_APP_NAME \ --query "functionKeys.default" \ -o tsv)Avviare l'orchestrazione:
curl -s -X POST "${FUNCTION_APP_URL}/api/start-analysis?code=${HOST_KEY}" | jq .La risposta include un ID istanza e gli URI di interrogazione dello stato.
{ "id": "abc123def456", "statusQueryGetUri": "https://...", "sendEventPostUri": "https://...", "terminatePostUri": "https://..." }
Verificare i risultati
Controllare lo stato dell'orchestrazione. Usare l'
statusQueryGetUridalla risposta precedente o costruire manualmente l'URL:INSTANCE_ID="<instance-id-from-trigger-response>" curl -s "${FUNCTION_APP_URL}/api/orchestrators/TextAnalysisOrchestrator/${INSTANCE_ID}?code=${HOST_KEY}" | jq .Mentre l'orchestrazione è in esecuzione,
runtimeStatusèRunning. Al termine, la risposta sarà simile alla seguente:{ "name": "TextAnalysisOrchestrator", "instanceId": "abc123def456", "runtimeStatus": "Completed", "output": { "results": [ { "file": "sample1.txt", "word_count": 15, "char_count": 98, "sentiment": "positive" }, { "file": "sample2.txt", "word_count": 18, "char_count": 120, "sentiment": "positive" }, { "file": "sample3.txt", "word_count": 12, "char_count": 85, "sentiment": "neutral" } ], "total_words": 45, "total_chars": 303, "analysis_duration_seconds": 2.34 } }
Suggerimento
L'app per le funzioni accede a tutti e tre i file in parallelo tramite il montaggio di archiviazione. L'app non richiede chiamate di rete per richiesta. La funzione li legge direttamente dalla condivisione montata usando l'I/O del file standard. Questo approccio illustra la potenza dei montaggi di archiviazione combinati con Durable Functions.
Pulire le risorse
Per evitare addebiti in corso, eliminare tutte le risorse create da questa esercitazione:
azd down --purge
Avviso
Questo comando elimina il gruppo di risorse e tutte le risorse in esso contenute, tra cui l'app per le funzioni, l'account di archiviazione e l'istanza di Application Insights.