Automatización de la implementación de recursos para una aplicación de función en Azure Functions

Puede usar un archivo de Bicep o una plantilla de Azure Resource Manager para automatizar el proceso de implementación de una aplicación de funciones en recursos de Azure nuevos o existentes. Esta automatización proporciona una excelente manera de poder integrar las implementaciones de recursos con el código fuente en DevOps, restaurar una aplicación de funciones y los recursos relacionados desde una copia de seguridad o implementar una topología de aplicación varias veces.

En este artículo se muestra cómo automatizar la creación de recursos y la implementación para Azure Functions. En función de los desencadenadores y enlaces usados por las funciones, es posible que tenga que implementar otros recursos, que están fuera del ámbito de este artículo.

El código de plantilla específico depende de cómo se hospede la aplicación de funciones, tanto si va a implementar código como a una aplicación de funciones contenedorizada, y al sistema operativo que usa la aplicación. En este artículo se admiten las siguientes opciones de hospedaje:

Opción de hospedaje Tipo de implementación Para obtener más información, consulte...
Azure Functions Consumption plan (Plan de consumo de Azure Functions) Solo código Plan de consumo
Plan Elastic Premium de Azure Functions Código | Contenedor Plan Premium
Plan dedicado de Azure Functions (App Service) Código | Contenedor Plan dedicado
Azure Container Apps Solo el contenedor Container Apps que hospeda Azure Functions
Azure Arc Código | Contenedor App Service, Functions y Logic Apps en Azure Arc (versión preliminar)

Recursos necesarios

Normalmente, una implementación hospedada en Azure Functions consta de estos recursos:

Resource Requisito Referencia de sintaxis y propiedades
Una cuenta de almacenamiento. Obligatorio Microsoft.Storage/storageAccounts
Un componente de Application Insights Recomendado Microsoft.Insights/components
Un Plan de hospedaje Obligatorio1 Microsoft.Web/serverfarms
Una aplicación de funciones Obligatorio Microsoft.Web/sites

Normalmente, una implementación de Azure Functions para un plan de consumo consta de estos recursos:

Resource Requisito Referencia de sintaxis y propiedades
Una cuenta de almacenamiento. Obligatorio Microsoft.Storage/storageAccounts
Un componente de Application Insights Recomendado Microsoft.Insights/components
Una aplicación de funciones Obligatorio Microsoft.Web/sites

Normalmente, una implementación hospedada en Azure Container Apps consta de estos recursos:

Resource Requisito Referencia de sintaxis y propiedades
Una cuenta de almacenamiento. Obligatorio Microsoft.Storage/storageAccounts
Un componente de Application Insights Recomendado Microsoft.Insights/components
Un entorno administrado Obligatorio Microsoft.App/managedEnvironments
Una aplicación de funciones Obligatorio Microsoft.Web/sites

Normalmente, una implementación hospedada en Azure Arc consta de estos recursos:

Resource Requisito Referencia de sintaxis y propiedades
Una cuenta de almacenamiento. Obligatorio Microsoft.Storage/storageAccounts
Un componente de Application Insights Recomendado Microsoft.Insights/components
Un Entorno de Kubernetes de App Service Obligatorio Microsoft.ExtendedLocation/customLocations
Una aplicación de funciones Obligatorio Microsoft.Web/sites

1No es necesario un plan de hospedaje explícito al elegir hospedar la aplicación de funciones en un Plan de consumo.

Al implementar varios recursos en un único archivo de Bicep o una plantilla de ARM, es importante el orden en que se crean los recursos. Este requisito es el resultado de las dependencias entre los recursos. Para estas dependencias, asegúrese de usar el elemento dependsOn para definir la dependencia en el recurso dependiente. Para obtener más información, consulte Definición del orden de implementación de recursos en plantillas de ARM o Dependencias de recursos en Bicep.

En este artículo se supone que tiene conocimientos básicos sobre la creación de archivos de Bicep o la creación de plantillas de Azure Resource Manager, y se muestran ejemplos como secciones individuales para recursos específicos. Para obtener un amplio conjunto de ejemplos completos de plantillas de ARM y archivos de Bicep, consulte estos ejemplos de implementación de aplicaciones de funciones.

Requisitos previos

En este artículo se supone que ya ha creado un entorno administrado en Azure Container Apps. Necesita tanto el nombre como el identificador del entorno administrado para crear una aplicación de funciones hospedada en Container Apps.

En este artículo se supone que ya ha creado una ubicación personalizada habilitada para App Service en un clúster de Kubernetes habilitado para Azure Arc. Necesita tanto el identificador de ubicación personalizada como el identificador de entorno de Kubernetes para crear una aplicación de funciones hospedada en una ubicación personalizada de Azure Arc.

Crear cuenta de almacenamiento

Todas las aplicaciones de funciones requieren una cuenta de almacenamiento de Azure. Se necesita una cuenta de uso general que admita blobs, tablas, colas y archivos. Para más información, vea Requisitos de la cuenta de almacenamiento de Azure Functions.

Importante

La cuenta de almacenamiento se usa para almacenar datos importantes de la aplicación, a veces incluido el propio código de la aplicación. Debe limitar el acceso desde otras aplicaciones y usuarios a la cuenta de almacenamiento.

En esta sección de ejemplo se crea una cuenta de almacenamiento estándar de uso general v2:

"resources": [
  {
    "type": "Microsoft.Storage/storageAccounts",
    "apiVersion": "2022-05-01",
    "name": "[parameters('storageAccountName')]",
    "location": "[parameters('location')]",
    "kind": "StorageV2",
    "sku": {
      "name": "[parameters('storageAccountType')]"
    },
    "properties": {
      "supportsHttpsTrafficOnly": true,
      "defaultToOAuthAuthentication": true
    }
  }
]

Para obtener más contexto, consulte el archivo azuredeploy.json completo en el repositorio de plantillas.

Debe establecer la cadena de conexión de esta cuenta de almacenamiento como la configuración de la aplicación AzureWebJobsStorage, que Functions requiere. Las plantillas de este artículo crean este valor de cadena de conexión en función de la cuenta de almacenamiento creada, que es un procedimiento recomendado. Para obtener más información, consulte Configuración de la aplicación.

Habilitación de los registros de almacenamiento

Dado que la cuenta de almacenamiento se usa para datos importantes de la aplicación de funciones, debe supervisar la modificación de ese contenido. Para supervisar la cuenta de almacenamiento, debe configurar los registros de recursos de Azure Monitor para Azure Storage. En esta sección ejemplo, se usa un área de trabajo de Log Analytics denominada myLogAnalytics como destino para estos registros.

"resources": [
  {
    "type": "Microsoft.Insights/diagnosticSettings",
    "apiVersion": "2021-05-01-preview",
    "scope": "[format('Microsoft.Storage/storageAccounts/{0}/blobServices/default', parameters('storageAccountName'))]",
    "name": "[parameters('storageDataPlaneLogsName')]",
    "properties": {
        "workspaceId": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('myLogAnalytics'))]",
        "logs": [
          {
            "category": "StorageWrite",
            "enabled": true
          }
        ],
        "metrics": [
          {
            "category": "Transaction",
            "enabled": true
          }
        ]
    }
  }
]

Esta misma área de trabajo se puede usar para el recurso de Application Insights definido más adelante. Para obtener más información, incluido cómo trabajar con estos registros, consulte Supervisión de Azure Storage.

Creación de recursos de Application Insights

Para la supervisión de las ejecuciones de la aplicación de funciones, se recomienda Application Insights. En esta sección de ejemplo, el recurso de Application Insights se define con el tipo Microsoft.Insights/components y el tipo web:

{
  "type": "Microsoft.Insights/components",
  "apiVersion": "2020-02-02",
  "name": "[variables('applicationInsightsName')]",
  "location": "[parameters('appInsightsLocation')]",
  "tags": {
    "[format('hidden-link:{0}', resourceId('Microsoft.Web/sites', parameters('functionAppName')))]": "Resource"
  },
  "properties": {
    "Application_Type": "web"
  },
  "kind": "web"
},

Para obtener más contexto, consulte el archivo azuredeploy.json completo en el repositorio de plantillas.

La conexión a la aplicación de funciones debe proporcionarse mediante la configuración de la aplicación APPLICATIONINSIGHTS_CONNECTION_STRING. Para obtener más información, consulte Configuración de la aplicación.

Los ejemplos de este artículo obtienen el valor de cadena de conexión de la instancia creada. En su lugar, es posible que las versiones anteriores usen APPINSIGHTS_INSTRUMENTATIONKEY para establecer la clave de instrumentación, que ya no se recomienda.

Creación de plan de hospedaje

Las aplicaciones hospedadas en un plan premium o un plan dedicado (App Service) de Azure Functions deben tener definido explícitamente el plan de hospedaje.

El plan Prémium ofrece la misma escala que el plan de consumo, pero incluye funcionalidades adicionales y recursos dedicados. Para obtener más información, consulte Plan Premium de Azure Functions.

Un plan Premium es un tipo especial de recurso serverfarm. Puede especificarlo mediante EP1, EP2 o EP3 para el valor de la propiedad Name en la propiedad sku. La manera en que defina el plan de hospedaje de Functions depende de si la aplicación de funciones se ejecuta en Windows o en Linux. En esta sección de ejemplo se crea un plan EP1:

"resources": [
  {
    "type": "Microsoft.Web/serverfarms",
    "apiVersion": "2022-03-01",
    "name": "[parameters('hostingPlanName')]",
    "location": "[parameters('location')]",
    "sku": {
      "name": "EP1",
      "tier": "ElasticPremium",
      "family": "EP"
    },
    "kind": "elastic",
    "properties": {
      "maximumElasticWorkerCount": 20
    }
  }
]

Para obtener más contexto, consulte el archivo azuredeploy.json completo en el repositorio de plantillas.

Para obtener más información sobre el objeto sku, consulte SkuDefinition o revise las plantillas de ejemplo.

En el plan dedicado (App Service), la aplicación de funciones se ejecuta en máquinas virtuales dedicadas en las SKU de los niveles Básico, Estándar y Premium en planes de App Service, de un modo similar a las aplicaciones web. Para obtener más información, consulte Plan dedicado.

Para ver un archivo de Bicep o una plantilla de Azure Resource Manager de ejemplo, consulte Aplicación de funciones en el plan de Azure App Service

En Functions, el plan Dedicado es simplemente un plan de App Service normal, que se define mediante un recurso serverfarm. Debe proporcionar al menos el valor name. Para obtener una lista de nombres de plan admitidos, consulte el valor --sku en az appservice plan create para obtener la lista actual de valores admitidos para un plan dedicado.

La forma en que defina el plan de hospedaje depende de si la aplicación de funciones se ejecuta en Windows o en Linux:

"resources": [
  {
    "type": "Microsoft.Web/serverfarms",
    "apiVersion": "2022-03-01",
    "name": "[parameters('hostingPlanName')]",
    "location": "[parameters('location')]",
    "sku": {
      "tier": "Standard",
      "name": "S1",
      "size": "S1",
      "family": "S",
      "capacity": 1
    }
  }
]

Para obtener más contexto, consulte el archivo azuredeploy.json completo en el repositorio de plantillas.

Creación de plan de hospedaje

No es necesario definir explícitamente un recurso de plan de hospedaje de consumo. Al omitir esta definición de recurso, se crea o selecciona automáticamente un plan por región al crear el propio recurso de la aplicación de funciones.

Puede definir explícitamente un plan de consumo como un tipo especial de recurso serverfarm, que se especifica mediante el valor Dynamic de las propiedades computeMode y sku. En esta sección de ejemplo se muestra cómo definir explícitamente un plan de consumo. La forma en que defina un plan de hospedaje depende de si la aplicación de funciones se ejecuta en Windows o en Linux.

"resources": [
  {
    "type": "Microsoft.Web/serverfarms",
    "apiVersion": "2022-03-01",
    "name": "[parameters('hostingPlanName')]",
    "location": "[parameters('location')]",
    "sku": {
      "name": "Y1",
      "tier": "Dynamic",
      "size": "Y1",
      "family": "Y",
      "capacity": 0
    },
    "properties": {
      "computeMode": "Dynamic"
    }
  }
]

Para obtener más contexto, consulte el archivo azuredeploy.json completo en el repositorio de plantillas.

Entorno de Kubernetes

Azure Functions se puede implementar en Kubernetes habilitado para Azure Arc como un proyecto de código o una aplicación de funciones contenedorizada.

Para crear la aplicación y planear los recursos, ya debe haber creado un entorno de Kubernetes de App Service para un clúster de Kubernetes habilitado para Azure Arc. En los ejemplos de este artículo se supone que tiene el identificador de recurso de la ubicación personalizada (customLocationId) y el entorno de Kubernetes de App Service (kubeEnvironmentId) en el que se va a implementar, que se establecen en este ejemplo:

"parameters": {
  "kubeEnvironmentId" : {
    "type": "string"
  },
  "customLocationId" : {
    "type": "string"
  }
}

Tanto los sitios como los planes deben hacer referencia a la ubicación personalizada mediante un campo extendedLocation. Como se muestra en este ejemplo truncado, extendedLocation se encuentra fuera de properties, como un elemento del mismo nivel que kind y location:

{
  "type": "Microsoft.Web/serverfarms",
  ...
  {
    "extendedLocation": {
      "name": "[parameters('customLocationId')]"
    },
  }
}

El recurso del plan debe usar el valor de Kubernetes (K1) para SKU, el campo kind debe ser linux,kubernetes y la propiedad reserved debe ser true, ya que es una implementación de Linux. También debe establecer extendedLocation y kubeEnvironmentProfile.id en el identificador de ubicación personalizada y el identificador de entorno de Kubernetes, respectivamente, que podría tener un aspecto similar a esta sección de ejemplo:

"resources": [
  {
    "type": "Microsoft.Web/serverfarms",
    "apiVersion": "2022-03-01",
    "name": "[parameters('hostingPlanName')]",
    "location": "[parameters('location')]",
    "kind": "linux,kubernetes",
    "sku": {
      "name": "K1",
      "tier": "Kubernetes"
    },
    "extendedLocation": {
      "name": "[parameters('customLocationId')]"
    },
    "properties": {
      "kubeEnvironmentProfile": {
        "id": "[parameters('kubeEnvironmentId')]"
      },
      "reserved": true
    }
  }
]

Crear la aplicación de función

El recurso de la aplicación de funciones se define mediante un recurso de tipo Microsoft.Web/sites y kind que incluye functionapp, como mínimo.

La forma en que se define un recurso de aplicación de funciones depende de si se hospeda en Linux o en Windows:

Para obtener una lista de la configuración de la aplicación necesaria al ejecutarse en Windows, consulte Configuración de la aplicación. Para ver un archivo de Bicep o una plantilla de Azure Resource Manager de ejemplo, consulte la plantilla Aplicación de funciones hospedada en Windows en un plan de consumo.

Para obtener una lista de la configuración de la aplicación necesaria al ejecutarse en Windows, consulte Configuración de la aplicación.

Nota:

Se elige definir de manera opcional el plan de con, deberá establecer la propiedad serverFarmId en la aplicación de forma que apunte al identificador de recurso del plan. Asegúrese de que la aplicación de funciones dispone del valor dependsOn, que también hace referencia al plan. Si no ha definido explícitamente un plan, se crea uno automáticamente.

Establezca la propiedad serverFarmId en la aplicación para que apunte al identificador de recurso del plan. Asegúrese de que la aplicación de funciones dispone del valor dependsOn, que también hace referencia al plan.

"resources": [
  {
    "type": "Microsoft.Web/sites",
    "apiVersion": "2022-03-01",
    "name": "[parameters('functionAppName')]",
    "location": "[parameters('location')]",
    "kind": "functionapp",
    "dependsOn": [
      "[resourceId('Microsoft.Insights/components', parameters('applicationInsightsName'))]",
      "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]",
      "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
    ],
    "properties": {
      "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]",
      "siteConfig": {
        "appSettings": [
          {
            "name": "APPLICATIONINSIGHTS_CONNECTION_STRING",
            "value": "[reference(resourceId('Microsoft.Insights/components', parameters('applicationInsightsName')), '2020-02-02').ConnectionString]"
          },
          {
            "name": "AzureWebJobsStorage",
            "value": "[format('DefaultEndpointsProtocol=https;AccountName={0};EndpointSuffix={1};AccountKey={2}', parameters('storageAccountName'), environment().suffixes.storage, listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2021-09-01').keys[0].value)]"
          },
          {
            "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
            "value": "[format('DefaultEndpointsProtocol=https;AccountName={0};EndpointSuffix={1};AccountKey={2}', parameters('storageAccountName'), environment().suffixes.storage, listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2021-09-01').keys[0].value)]"
          },
          {
            "name": "WEBSITE_CONTENTSHARE",
            "value": "[toLower(parameters('functionAppName'))]"
          },
          {
            "name": "FUNCTIONS_EXTENSION_VERSION",
            "value": "~4"
          },
          {
            "name": "FUNCTIONS_WORKER_RUNTIME",
            "value": "node"
          },
          {
            "name": "WEBSITE_NODE_DEFAULT_VERSION",
            "value": "~14"
          }
        ]
      }
    }
  }
]

Para ver un ejemplo completo de un extremo a otro, consulte esta plantilla azuredeploy.json.

"resources": [
  {
    "type": "Microsoft.Web/sites",
    "apiVersion": "2022-03-01",
    "name": "[parameters('functionAppName')]",
    "location": "[parameters('location')]",
    "kind": "functionapp",
    "dependsOn": [
      "[resourceId('Microsoft.Insights/components', parameters('applicationInsightsName'))]",
      "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]",
      "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
    ],
    "properties": {
      "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]",
      "siteConfig": {
        "alwaysOn": true,
        "appSettings": [
          {
            "name": "APPLICATIONINSIGHTS_CONNECTION_STRING",
            "value": "[reference(resourceId('Microsoft.Insights/components', parameters('applicationInsightsName')), '2020-02-02').ConnectionString]"
          },
          {
            "name": "AzureWebJobsStorage",
            "value": "[format('DefaultEndpointsProtocol=https;AccountName={0};EndpointSuffix={1};AccountKey={2}', parameters('storageAccountName'), environment().suffixes.storage, listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2021-09-01').keys[0].value)]"
          },
          {
            "name": "FUNCTIONS_EXTENSION_VERSION",
            "value": "~4"
          },
          {
            "name": "FUNCTIONS_WORKER_RUNTIME",
            "value": "node"
          },
          {
            "name": "WEBSITE_NODE_DEFAULT_VERSION",
            "value": "~14"
          }
        ]
      }
    }
  }
]

Para ver un ejemplo completo de un extremo a otro, consulte esta plantilla azuredeploy.json.

Orígenes de la implementación

El archivo de Bicep o la plantilla de ARM también pueden definir de manera opcional una implementación para el código de función, que podría incluir estos métodos:

Orígenes de la implementación

El archivo de Bicep o la plantilla de ARM también pueden definir de manera opcional una implementación para el código de función mediante un paquete de implementación zip.

Para implementar la aplicación de forma correcta mediante Azure Resource Manager, es importante comprender cómo se implementan los recursos en Azure. En la mayoría de los ejemplos, las configuraciones de nivel superior se aplican mediante siteConfig. Es importante establecer estas configuraciones en un nivel superior porque transmiten información al motor de implementación y en tiempo de ejecución de Functions. Se requiere información de nivel superior antes de aplicar el recurso secundario sourcecontrols/web. Aunque es posible configurar estas opciones en el recurso de nivel secundario config/appSettings, en algunos casos la aplicación de funciones debe implementarse antesconfig/appSettings de aplicarse.

Paquete de implementación zip

La implementación zip es una manera recomendada de implementar el código de la aplicación de funciones. De manera predeterminada, las funciones que usan la implementación zip se ejecutan en el propio paquete de implementación. Para obtener más información, incluidos los requisitos de un paquete de implementación, consulte Implementación zip para Azure Functions. Al usar la automatización de la implementación de recursos, puede hacer referencia al paquete de implementación .zip en la plantilla de ARM o Bicep.

Para usar la implementación zip en la plantilla, establezca el valor WEBSITE_RUN_FROM_PACKAGE de la aplicación en 1 e incluya la definición de recursos /zipDeploy.

En el caso de un plan de consumo en Linux, establezca el URI del paquete de implementación directamente en el valor WEBSITE_RUN_FROM_PACKAGE, como se muestra en esta plantilla de ejemplo.

En este ejemplo se agrega un origen de implementación zip a una aplicación existente:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "functionAppName": {
      "type": "string",
      "metadata": {
        "description": "The name of the Azure Function app."
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "The location into which the resources should be deployed."
      }
    },
    "packageUri": {
      "type": "string",
      "metadata": {
        "description": "The zip content url."
      }
    }
  },
  "resources": [
    {
      "name": "[concat(parameters('functionAppName'), '/ZipDeploy')]",
      "type": "Microsoft.Web/sites/extensions",
      "apiVersion": "2021-02-01",
      "location": "[parameters('location')]",
      "properties": {
        "packageUri": "[parameters('packageUri')]"
      }
    }
  ]
}

Tenga en cuenta lo siguiente al incluir recursos de implementación zip en la plantilla:

  • packageUri debe ser una ubicación a la que puede acceder Functions. Considere la posibilidad de usar Azure Blob Storage con una firma de acceso compartido (SAS). Una vez expirada la SAS, Functions ya no puede acceder al recurso compartido para las implementaciones. Cuando vuelva a generar la SAS, recuerde actualizar el valor WEBSITE_RUN_FROM_PACKAGE con el nuevo valor de URI.

  • Al establecer WEBSITE_RUN_FROM_PACKAGE en un URI, deberá sincronizar manualmente los desencadenadores.

  • Asegúrese de establecer siempre toda la configuración de la aplicación necesaria en la colección appSettings al agregar o actualizar la configuración. La actualización quita la configuración existente no establecida explícitamente. Para obtener más información, consulte Configuración de la aplicación.

  • Functions no admite Web Deploy (msdeploy) para implementaciones de paquetes. En su lugar, debe usar la implementación zip en las canalizaciones de implementación y la automatización. Para más información, consulte Implementación de archivos ZIP en Azure Functions.

Compilaciones remotas

El proceso de implementación supone que el archivo .zip que usa o una implementación zip contiene una aplicación lista para ejecutarse. Esto significa que, de manera predeterminada, no se ejecutan personalizaciones.

Sin embargo, hay escenarios que requieren que recompile la aplicación de forma remota, como cuando necesite extraer paquetes específicos de Linux en aplicaciones de Python o Node.js desarrolladas en un equipo Windows. En este caso, puede configurar Functions para realizar una compilación remota en el código después de la implementación del archivo zip.

La forma en que solicita una compilación remota depende del sistema operativo en el que se va a implementar:

Cuando se implementa una aplicación en Windows, se ejecutan comandos específicos del lenguaje (como dotnet restore para aplicaciones de C# o npm install para aplicaciones de Node.js).

Para habilitar los mismos procesos de compilación que obtiene con la integración continua, agregue SCM_DO_BUILD_DURING_DEPLOYMENT=true a la configuración de la aplicación en el código de implementación y quite WEBSITE_RUN_FROM_PACKAGE completamente.

Contenedores de Linux

Si va a implementar una aplicación de funciones contenedorizada en un plan Premium o Dedicado de Azure Functions, debe hacer lo siguiente:

Para obtener más información, consulte Configuración de la aplicación.

"resources": [
  {
    "type": "Microsoft.Web/sites",
    "apiVersion": "2022-03-01",
    "name": "[parameters('functionAppName')]",
    "location": "[parameters('location')]",
    "kind": "functionapp",
    "dependsOn": [
      "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]",
      "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
    ],
    "properties": {
      "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]",
      "siteConfig": {
        "appSettings": [
          {
            "name": "AzureWebJobsStorage",
            "value": "[format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}', parameters('storageAccountName'), listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2021-09-01').keys[0].value)]"
          },
          {
            "name": "FUNCTIONS_WORKER_RUNTIME",
            "value": "node"
          },
          {
            "name": "WEBSITE_NODE_DEFAULT_VERSION",
            "value": "~14"
          },
          {
            "name": "FUNCTIONS_EXTENSION_VERSION",
            "value": "~4"
          },
          {
            "name": "DOCKER_REGISTRY_SERVER_URL",
            "value": "[parameters('dockerRegistryUrl')]"
          },
          {
            "name": "DOCKER_REGISTRY_SERVER_USERNAME",
            "value": "[parameters('dockerRegistryUsername')]"
          },
          {
            "name": "DOCKER_REGISTRY_SERVER_PASSWORD",
            "value": "[parameters('dockerRegistryPassword')]"
          },
          {
            "name": "WEBSITES_ENABLE_APP_SERVICE_STORAGE",
            "value": "false"
          }
        ],
        "linuxFxVersion": "DOCKER|myacr.azurecr.io/myimage:mytag"
      }
    }
  }
]

Al implementar funciones contenedorizadas en Azure Container Apps, la plantilla debe:

  • Establezca el campo kind en un valor de functionapp,linux,container,azurecontainerapps.
  • Establezca la propiedad de sitio managedEnvironmentId en el URI completo del entorno de Container Apps.
  • Agregue un vínculo de recurso en la colección dependsOn del sitio al crear un recurso Microsoft.App/managedEnvironments al mismo tiempo que el sitio.

La definición de una aplicación de funciones contenedorizada implementada desde un registro de contenedor privado en un entorno de Container Apps existente podría tener un aspecto similar al de este ejemplo:

"resources": [
  {
    "type": "Microsoft.Web/sites",
    "apiVersion": "2022-03-01",
    "name": "[parameters('functionAppName')]",
    "kind": "functionapp,linux,container,azurecontainerapps",
    "location": "[parameters('location')]",
    "dependsOn": [
      "[resourceId('Microsoft.Insights/components', parameters('applicationInsightsName'))]",
      "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
    ],
    "properties": {
      "serverFarmId": "[parameters('hostingPlanName')]",
      "siteConfig": {
        "linuxFxVersion": "DOCKER|myacr.azurecr.io/myimage:mytag",
        "appSettings": [
          {
            "name": "FUNCTIONS_EXTENSION_VERSION",
            "value": "~4"
          },
          {
            "name": "AzureWebJobsStorage",
            "value": "[format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}', parameters('storageAccountName'), listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2021-09-01').keys[0].value)]"
          },
          {
            "name": "APPLICATIONINSIGHTS_CONNECTION_STRING",
            "value": "[reference(resourceId('Microsoft.Insights/components', parameters('applicationInsightsName')), '2020-02-02').ConnectionString]"
          }
        ],
      },
      "managedEnvironmentId": "[parameters('managedEnvironmentId')]"
    }
  }
]

Al implementar funciones en Azure Arc, el valor establecido para el campo kind del recurso de la aplicación de funciones depende del tipo de implementación:

Tipo de implementación Valor de campo kind
Implementación solo de código functionapp,linux,kubernetes
Implementación de contenedores functionapp,linux,kubernetes,container

También debe establecer customLocationId como hizo para el recurso del plan de hospedaje.

La definición de una aplicación de funciones contenedorizada, con una imagen de inicio rápido de .NET 6, podría tener este aspecto:

"resources": [
  {
    "type": "Microsoft.Web/sites",
    "apiVersion": "2022-03-01",
    "name": "[parameters('functionAppName')]",
    "kind": "kubernetes,functionapp,linux,container",
    "location": "[parameters('location')]",
    "extendedLocation": {
      "name": "[parameters('customLocationId')]"
    },
    "dependsOn": [
      "[resourceId('Microsoft.Insights/components', parameters('applicationInsightsName'))]",
      "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]",
      "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
    ],
    "properties": {
      "serverFarmId": "[parameters('hostingPlanName')]",
      "siteConfig": {
        "linuxFxVersion": "DOCKER|mcr.microsoft.com/azure-functions/4-dotnet-isolated6.0-appservice-quickstart",
        "appSettings": [
          {
            "name": "FUNCTIONS_EXTENSION_VERSION",
            "value": "~4"
          },
          {
            "name": "AzureWebJobsStorage",
            "value": "[format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}', parameters('storageAccountName'), listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2021-09-01').keys[0].value)]"
          },
          {
            "name": "APPLICATIONINSIGHTS_CONNECTION_STRING",
            "value": "[reference(resourceId('Microsoft.Insights/components', parameters('applicationInsightsName')), '2020-02-02').ConnectionString]"
          }
        ],
        "alwaysOn": true
      }
    }
  }
]

Configuración de aplicaciones

Functions proporciona las siguientes opciones para configurar la aplicación de funciones en Azure:

Configuración PropiedadMicrosoft.Web/sites
Configuración del sitio siteConfig
Configuración de aplicación Colección siteConfig.appSettings

Es necesaria la siguiente configuración del sitio en la propiedad siteConfig:

Esta configuración de la aplicación es necesaria (o recomendada) para un sistema operativo específico y una opción de hospedaje:

Esta configuración de la aplicación es necesaria para las implementaciones de contenedores:

Esta configuración solo es necesaria al implementar desde un registro de contenedor privado:

Tenga en cuenta estas consideraciones al trabajar con la configuración del sitio y la aplicación mediante archivos de Bicep o plantillas de ARM:

  • Hay consideraciones importantes para cuando se debe establecer WEBSITE_CONTENTSHARE en una implementación automatizada. Para obtener instrucciones detalladas, consulta la referencia WEBSITE_CONTENTSHARE.
  • En el caso de las implementaciones de contenedores, también se establece WEBSITES_ENABLE_APP_SERVICE_STORAGE en false, ya que el contenido de la aplicación se proporciona en el propio contenedor.
  • Siempre debe definir la configuración de la aplicación como una colección siteConfig/appSettings del recurso Microsoft.Web/sites que se va a crear, como se hace en los ejemplos de este artículo. Esto garantiza que la configuración que la aplicación de funciones necesita ejecutar esté disponible en el inicio.

  • Al agregar o actualizar la configuración de la aplicación mediante plantillas, asegúrese de incluir toda la configuración existente con la actualización. Debe hacerlo porque las llamadas API de REST de actualización subyacente reemplazan todo el recurso /config/appsettings. Si quita la configuración existente, la aplicación de funciones no se ejecutará. Para actualizar mediante programación la configuración de la aplicación individual, puede usar la CLI de Azure, Azure PowerShell o Azure Portal para realizar estos cambios. Para más información, consulte Trabajar con la configuración de la aplicación.

Implementaciones de ranuras

Functions le permite implementar diferentes versiones del código en puntos de conexión únicos en la aplicación de funciones. Esto facilita el desarrollo, validación e implementación de actualizaciones de funciones sin afectar a las funciones que se ejecutan en producción. Las ranuras de implementación son una característica de Azure App Service. El número de ranuras disponibles depende del plan de hospedaje. Para obtener más información, consulte Funciones de ranuras de implementación de Azure Functions.

Un recurso de ranura se define de la misma manera que un recurso de aplicación de funciones (Microsoft.Web/sites), pero en su lugar se usa el identificador de recursos Microsoft.Web/sites/slots. Para obtener un ejemplo de implementación (en Bicep y plantillas de ARM) que crea una ranura de producción y un espacio de ensayo en un plan Premium, consulte Aplicación de funciones de Azure con una ranura de implementación.

Para obtener información sobre cómo realizar el intercambio mediante plantillas, consulte Automatización con plantillas de Resource Manager.

Tenga en cuenta las siguientes consideraciones al trabajar con implementaciones de ranuras:

  • No establezca explícitamente el valor WEBSITE_CONTENTSHARE en la definición de la ranura de implementación. Esta configuración se genera automáticamente cuando se crea la aplicación en la ranura de implementación.

  • Al intercambiar ranuras, algunas opciones de configuración de la aplicación se consideran "persistentes", ya que permanecen con la ranura y no con el código que se va a intercambiar. Puede definir esta configuración de ranura incluyendo "slotSetting":true en la definición del valor de configuración de la aplicación específica de la plantilla. Para obtener más información, consulte Administración de la configuración.

Implementaciones protegidas

Puede crear la aplicación de funciones en una implementación en la que se haya protegido uno o varios de los recursos mediante la integración con redes virtuales. La integración con una red virtual para la aplicación de funciones se define mediante un recurso Microsoft.Web/sites/networkConfig. Esta integración depende de la aplicación de funciones a la que se hace referencia y de los recursos de red virtual. La aplicación de funciones también puede depender de otros recursos de red privados, como puntos de conexión privados y rutas. Para obtener más información, vea las opciones de red de Azure Functions.

Al crear una implementación que usa una cuenta de almacenamiento protegida, debes establecer explícitamente la configuración WEBSITE_CONTENTSHARE y crear el recurso compartido de archivos denominado en esta configuración. Asegúrate de crear un recurso Microsoft.Storage/storageAccounts/fileServices/shares con el valor de WEBSITE_CONTENTSHARE, como se muestra en este ejemplo (plantilla de ARM|archivo Bicep). También deberá establecer la propiedad del sitio vnetContentShareEnabled en true.

Nota:

Cuando esta configuración no forme parte de una implantación que utiliza una cuenta de almacenamiento protegida, aparece este error al validar la implementación: Could not access storage account using provided connection string.

Estos proyectos proporcionan ejemplos de plantillas de ARM y Bicep sobre cómo implementar las aplicaciones de funciones en una red virtual, incluidas las restricciones de acceso de red:

Escenario restringido Descripción
Creación de una aplicación de funciones con integración de red virtual La aplicación de funciones se crea en una red virtual con acceso total a los recursos de esa red. El acceso entrante y saliente a la aplicación de funciones no está restringido. Para obtener más información, consulte Integración de la red virtual.
Creación de una aplicación de funciones que tenga acceso a una cuenta de almacenamiento protegida La aplicación de funciones creada usa una cuenta de almacenamiento protegida, a la que Functions accede mediante puntos de conexión privados. Para obtener más información, consulte Restricción de la cuenta de almacenamiento a una red virtual.
Creación de una aplicación de funciones y una cuenta de almacenamiento que usan puntos de conexión privados Solo se puede acceder a la aplicación de funciones creada mediante puntos de conexión privados y se usan puntos de conexión privados para acceder a los recursos de almacenamiento. Para obtener más información, consulte Puntos de conexión privados.

Configuración de red restringida

También es posible que tenga que usar esta configuración cuando la aplicación de funciones tenga restricciones de red:

Configuración valor Descripción
WEBSITE_CONTENTOVERVNET 1 Configuración de la aplicación que permite que la aplicación de funciones se escale cuando la cuenta de almacenamiento esté restringida a una red virtual. Para obtener más información, consulte Restricción de la cuenta de almacenamiento a una red virtual.
vnetrouteallenabled 1 Valor del sitio que obliga a todo el tráfico de la aplicación de funciones a usar la red virtual. Para obtener más información, consulte Integración de la red virtual regional. Este valor de sitio reemplaza la configuración de la aplicación WEBSITE_VNET_ROUTE_ALL.

Consideraciones para las restricciones de red

Al restringir el acceso a la cuenta de almacenamiento a través de los puntos de conexión privados, no podrá acceder a la cuenta de almacenamiento a través del portal ni de ningún dispositivo fuera de la red virtual. Puede conceder acceso a la dirección IP protegida o a la red virtual en la cuenta de almacenamiento mediante Administración de la regla de acceso de red predeterminada.

Creación de la plantilla

Los expertos con plantillas de ARM o Bicep pueden codificar manualmente sus implementaciones mediante un editor de texto sencillo. Para el resto de nosotros, hay varias maneras de facilitar el proceso de desarrollo:

  • Visual Studio Code: hay extensiones disponibles para ayudarle a trabajar con archivos de Bicep y plantillasde ARM. Puede usar estas herramientas para asegurarse de que el código es correcto y proporcionan alguna validación básica.

  • Azure Portal: al crear la aplicación de funciones y los recursos relacionados en el portal, la pantalla de Revisión y creación final tiene un vínculo Descargar una plantilla para la automatización.

    Descargue el vínculo de plantilla del proceso de creación de Azure Functions en Azure Portal.

    Este vínculo muestra la plantilla de ARM generada en función de las opciones que eligió en el portal. Aunque esta plantilla puede ser un poco compleja al crear una aplicación de funciones con muchos recursos nuevos, puede proporcionar una buena referencia para el aspecto de la plantilla de ARM.

Validación de la plantilla

Al crear manualmente el archivo de plantilla de implementación, es importante validar la plantilla antes de la implementación. Todos los métodos de implementación validan la sintaxis de la plantilla y generan un mensaje de error validation failed como se muestra en el siguiente ejemplo con formato JSON:

{"error":{"code":"InvalidTemplate","message":"Deployment template validation failed: 'The resource 'Microsoft.Web/sites/func-xyz' is not defined in the template. Please see https://aka.ms/arm-template for usage details.'.","additionalInfo":[{"type":"TemplateViolation","info":{"lineNumber":0,"linePosition":0,"path":""}}]}}

Los métodos siguientes se pueden usar para validar la plantilla antes de la implementación:

La siguiente tarea de implementación del grupo de recursos de Azure v2 con deploymentMode: 'Validation' indica a Azure Pipelines que valide la plantilla.

- task: AzureResourceManagerTemplateDeployment@3
  inputs:
    deploymentScope: 'Resource Group'
    subscriptionId: # Required subscription ID
    action: 'Create Or Update Resource Group'
    resourceGroupName: # Required resource group name
    location: # Required when action == Create Or Update Resource Group
    templateLocation: 'Linked artifact'
    csmFile: # Required when  TemplateLocation == Linked Artifact
    csmParametersFile: # Optional
    deploymentMode: 'Validation'

También puede crear un grupo de recursos de prueba para buscar errores de comprobación e implementación.

Implementación de la plantilla

Puede usar cualquiera de los siguientes métodos para implementar el archivo de Bicep y la plantilla:

Botón Implementación en Azure

Nota

Este método no admite actualmente la implementación de archivos de Bicep.

Reemplace <url-encoded-path-to-azuredeploy-json> por una versión codificada de la URL de la ruta de acceso sin formato del archivo azuredeploy.json en GitHub.

Este es un ejemplo donde se usa Markdown:

[![Deploy to Azure](https://azuredeploy.net/deploybutton.png)](https://portal.azure.com/#create/Microsoft.Template/uri/<url-encoded-path-to-azuredeploy-json>)

Este es un ejemplo donde se usa HTML:

<a href="https://portal.azure.com/#create/Microsoft.Template/uri/<url-encoded-path-to-azuredeploy-json>" target="_blank"><img src="https://azuredeploy.net/deploybutton.png"></a>

Implementación mediante PowerShell

Los siguientes comandos de PowerShell crean un grupo de recursos e implementan un archivo de Bicep o una plantilla de ARM que crea una aplicación de funciones con los recursos necesarios. Para la ejecución local, es preciso tener instalado Azure PowerShell. Ejecute Connect-AzAccount para iniciar sesión.

# Register Resource Providers if they're not already registered
Register-AzResourceProvider -ProviderNamespace "microsoft.web"
Register-AzResourceProvider -ProviderNamespace "microsoft.storage"

# Create a resource group for the function app
New-AzResourceGroup -Name "MyResourceGroup" -Location 'West Europe'

# Deploy the template
New-AzResourceGroupDeployment -ResourceGroupName "MyResourceGroup" -TemplateFile azuredeploy.json  -Verbose

Para probar esta implementación, puede usar una plantilla como esta, que crea una aplicación de funciones en Windows en un plan de consumo.

Pasos siguientes

Aprenda a desarrollar y configurar Azure Functions.