Hospede una aplicación de Durable Functions con el back-end de MSSQL en Azure Container Apps (.NET aislado)

Azure Container Apps es la única opción de hospedaje que admite el escalado automático controlado por eventos (escala a cero) para Durable Functions cuando se usa el proveedor de almacenamiento Microsoft SQL (MSSQL). Si utiliza un backend de almacenamiento diferente, debe establecer el recuento mínimo de réplicas a un valor mayor que cero.

Sugerencia

En el caso de los nuevos proyectos, considere la posibilidad de usar el Durable Task Scheduler, que es el backend administrado por Azure recomendado para flujos de trabajo duraderos. En esta guía se describe específicamente el back-end de MSSQL.

Para más información sobre la ejecución de Azure Functions en Container Apps, consulte Azure Container Apps para hospedar Azure Functions.

En este artículo aprenderá a:

  • Cree una imagen de Docker a partir de un proyecto local de Durable Functions.
  • Cree una aplicación de contenedor de Azure y recursos relacionados.
  • Implemente la imagen en Azure Container App y configure la autenticación.

Prerrequisitos

Creación de un proyecto local de Durable Functions

En esta guía se da por supuesto que tiene un proyecto de Durable Functions aislado en funcionamiento .NET configurado con el back-end de MSSQL. Si aún no tiene uno, siga el inicio rápido de MSSQL para crear y probar uno localmente y, a continuación, vuelva aquí.

Antes de continuar, compruebe que:

  • El proyecto tiene como destino .NET 8.0 con el modelo de trabajo aislado
  • El proveedor de almacenamiento MSSQL está configurado en host.json
  • La aplicación se ejecuta correctamente con func start

Cree un Dockerfile en la raíz del proyecto que describa el entorno mínimo necesario para ejecutar la aplicación de funciones en un contenedor.

  1. En el directorio raíz del proyecto, cree un archivo denominado Dockerfile.

  2. Copie o pegue el siguiente contenido en el Archivo Dockerfile.

    FROM mcr.microsoft.com/dotnet/sdk:8.0 AS installer-env
    
    COPY . /src/dotnet-function-app
    RUN cd /src/dotnet-function-app && \
    mkdir -p /home/site/wwwroot && \
    dotnet publish *.csproj --output /home/site/wwwroot
    
    # To enable ssh & remote debugging on app service change the base image to the one below
    # FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated8.0-appservice
    FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated8.0
    ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
        AzureFunctionsJobHost__Logging__Console__IsEnabled=true
    
    COPY --from=installer-env ["/home/site/wwwroot", "/home/site/wwwroot"]
    
  3. Guarde el archivo.

  4. Agregue un archivo .dockerignore con el siguiente contenido:

    local.settings.json
    
  5. Guarde el archivo .dockerignore .

Compilación de la imagen del contenedor

Compile la imagen de Docker. Busque la lista completa de imágenes base admitidas para Azure Functions en La base de Azure Functions por Microsoft | Docker Hub

  1. Inicie el demonio de Docker.

  2. Inicie sesión en Docker con el docker login comando .

  3. Cuando se le solicite, inicie sesión con su nombre de usuario y contraseña. Un mensaje "Login Succeeded" confirma que ha iniciado sesión.

  4. Vaya al directorio raíz del proyecto.

  5. Ejecute el siguiente comando para compilar la imagen, reemplazando <DOCKER_ID> por el identificador de la cuenta de Docker Hub:

    dockerId=<DOCKER_ID>
    imageName=<IMAGE_NAME>
    imageVersion=v1.0.0
    
    docker build --tag $dockerId/$imageName:$imageVersion .
    

    Nota:

    Si está utilizando un Mac de la serie M, use --platform linux/amd64 en su lugar.

  6. Inserte la imagen en Docker:

    docker push $dockerId/$imageName:$imageVersion
    

    En función de la velocidad de red, la inserción de la imagen inicial puede tardar unos minutos. Mientras espera, continúe con la sección siguiente.

Creación de recursos de Azure para Durable Functions en Container Apps

Cree los recursos de Azure necesarios para ejecutar Durable Functions en una aplicación contenedora.

  • Grupo de recursos de Azure: Grupo de recursos que contiene todos los recursos creados.
  • Entorno de Azure Container App: Entorno que hospeda la aplicación contenedora.
  • Aplicación contenedora de Azure: La imagen que contiene la aplicación Durable Functions se implementa en esta aplicación.
  • Cuenta de Azure Storage: Requerido por la aplicación de funciones para almacenar datos relacionados con la aplicación, como el código de la aplicación.

Configuración inicial

  1. En un nuevo terminal, inicie sesión en la suscripción de Azure:

    az login  
    
    az account set -s <subscription_name>
    
  2. Ejecute los comandos necesarios para configurar la extensión de la CLI de Azure Container Apps:

    az upgrade
    
    az extension add --name containerapp --upgrade
    
    az provider register --namespace Microsoft.App
    
    az provider register --namespace Microsoft.OperationalInsights
    

Un perfil de carga de trabajo determina la cantidad de recursos de proceso y memoria disponibles para las aplicaciones de contenedor implementadas en un entorno. Cree un perfil de carga de trabajo de consumo para la compatibilidad de escalado a cero y pago por uso.

  1. Establezca las variables de entorno.

    location=<REGION>
    resourceGroup=<RESOURCE_GROUP_NAME>
    storage=<STORAGE_NAME>
    containerAppEnv=<CONTAINER_APP_ENVIRONMNET_NAME>
    functionApp=<APP_NAME>
    vnet=<VNET_NAME>
    
  2. Cree un grupo de recursos.

    az group create --name $resourceGroup --location $location
    
  3. Cree el entorno de la aplicación contenedora.

    az containerapp env create \
      --enable-workload-profiles \
      --resource-group $resourceGroup \
      --name $containerAppEnv \
      --location $location \
    
  4. Cree una aplicación de contenedor basada en la imagen de Durable Functions.

    az containerapp create --resource-group $resourceGroup \
    --name $functionApp \
    --environment $containerAppEnv \
    --image $dockerId/$imageName:$imageVersion \
    --ingress external \
    --kind functionapp \
    --query properties.outputs.fqdn
    
  5. Anote la dirección URL de la aplicación, que debe tener un aspecto similar a https://<APP_NAME>.<ENVIRONMENT_IDENTIFIER>.<REGION>.azurecontainerapps.io.

Creación de bases de datos

  1. Cree una cuenta de Azure Storage que la aplicación de funciones necesita.

    az storage account create --name $storage --location $location --resource-group $resourceGroup --sku Standard_LRS
    
  2. En Azure Portal, cree una base de datos de Azure SQL para conservar la información de estado. Durante la creación:

Configuración de la autenticación basada en identidades

Las identidades administradas hacen que la aplicación sea más segura mediante la eliminación de secretos de la aplicación, como las credenciales de las cadenas de conexión. Aunque puede elegir entre la identidad administrada asignada por el sistema y la asignada por el usuario, se recomienda la identidad administrada asignada por el usuario, ya que no está vinculada al ciclo de vida de la aplicación.

En esta sección, configurará la identidad administrada asignada por el usuario para Azure Storage.

  1. Establezca las variables de entorno.

    subscription=<SUBSCRIPTION_ID>
    identity=<IDENTITY_NAME>
    
  2. Cree un recurso de identidad administrada.

    echo "Creating $identity"
    az identity create -g $resourceGroup -n $identity --location "$location"
    
  3. Asigne la identidad de usuario a la aplicación contenedora.

    echo "Assigning $identity to app"
    az containerapp identity assign --resource-group $resourceGroup --name $functionApp --user-assigned $identity
    
  4. Establezca el ámbito de los permisos de control de acceso basado en rol (RBAC).

    scope="/subscriptions/$subscription/resourceGroups/$resourceGroup/providers/Microsoft.Storage/storageAccounts/$storage"
    
  5. Obtenga la identidad del clientId del usuario.

    # Get the identity's ClientId 
    clientId=$(az identity show --name $identity --resource-group $resourceGroup --query 'clientId' --output tsv)
    
  6. Asigne el rol Propietario de datos de Storage Blob para acceder a la cuenta de almacenamiento.

    echo "Assign Storage Blob Data Owner role to identity"
    az role assignment create --assignee "$clientId" --role "Storage Blob Data Owner" --scope "$scope"
    

Configuración de la aplicación

Nota:

No se admite la autenticación en la base de datos MSSQL mediante identidad administrada al hospedar una aplicación de Durable Functions en Azure Container Apps. Por ahora, esta guía se autentica mediante cadenas de conexión.

  1. En el recurso de base de datos SQL de Azure Portal, vaya a Configuración>Cadenas de conexión para buscar la cadena de conexión.

    Captura de pantalla de la cadena de conexión de la base de datos de Azure SQL en el portal de Azure.

    La cadena de conexión debe tener un formato similar al siguiente:

    dbserver=<SQL_SERVER_NAME>
    sqlDB=<SQL_DB_NAME>
    username=<DB_USER_LOGIN>
    password=<DB_USER_PASSWORD>
    
    connStr="Server=tcp:$dbserver.database.windows.net,1433;Initial Catalog=$sqlDB;Persist Security Info=False;User ID=$username;Password=$password;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
    

    Si olvida la contraseña del paso de creación de la base de datos anterior, puede restablecerla en el recurso de SQL Server.

    Captura de pantalla del botón restablecer contraseña en la página de recursos del servidor de Azure SQL.

  2. Almacene la cadena de conexión de la base de datos SQL como un secreto denominado sqldbconnection en la aplicación contenedora.

    az containerapp secret set \
    --resource-group $resourceGroup \
    --name $functionApp \
    --secrets sqldbconnection=$connStr
    
  3. Agregue la siguiente configuración a la aplicación:

    az containerapp update \
    -n $functionApp \
    -g $resourceGroup \
    --set-env-vars SQLDB_Connection=secretref:sqldbconnection \
    AzureWebJobsStorage__accountName=$storage \
    AzureWebJobsStorage__clientId=$clientId \
    AzureWebJobsStorage__credential=managedidentity \
    FUNCTIONS_WORKER_RUNTIME=dotnet-isolated
    

Prueba de la aplicación de Durable Functions implementada

  1. Use una herramienta de prueba HTTP para enviar una POST solicitud al punto de conexión del desencadenador HTTP, que debe ser similar a:

    https://<APP NAME>.<ENVIRONMENT_IDENTIFIER>.<REGION>.azurecontainerapps.io/api/DurableFunctionsOrchestrationCSharp1_HttpStart
    

    La respuesta es el resultado inicial de la función HTTP que le permite saber que la orquestación de Durable Functions se inició correctamente. Aunque la respuesta incluye algunas direcciones URL útiles, aún no muestra el resultado final de la orquestación.

  2. Copie o pegue el valor de dirección URL de statusQueryGetUri en la barra de direcciones del explorador y ejecútelo. Como alternativa, puede seguir usando la herramienta de prueba HTTP para emitir la GET solicitud.

    La solicitud consultará la instancia de orquestación sobre el estado. Debería ver que la instancia finalizó y las salidas o los resultados de la aplicación de Durable Functions.

    {
        "name":"HelloCities",
        "instanceId":"7f99f9474a6641438e5c7169b7ecb3f2",
        "runtimeStatus":"Completed",
        "input":null,
        "customStatus":null,
        "output":"Hello, Tokyo! Hello, London! Hello, Seattle!",
        "createdTime":"2023-01-31T18:48:49Z",
        "lastUpdatedTime":"2023-01-31T18:48:56Z"
    }
    

Pasos siguientes