Поделиться через


Краткое руководство: Создание и развертывание ресурсов Функций Azure с помощью Bicep

В этой статье описано, как с помощью Bicep создать приложение функции в плане потребления Flex в Azure, а также его необходимые ресурсы Azure. Приложение-функция предоставляет бессерверный контекст выполнения для выполнения кода функции. Приложение использует Microsoft Entra ID с управляемыми удостоверениями для подключения к другим ресурсам Azure.

Выполнение этого краткого руководства предполагает небольшую дополнительную плату в несколько центов США в учетной записи Azure.

Bicep — это предметно-ориентированный язык (DSL), который использует декларативный синтаксис для развертывания ресурсов Azure. Он обеспечивает краткий синтаксис, надежную безопасность типов и поддержку повторного использования кода. Bicep предлагает лучшие возможности для разработки решений Azure типа "инфраструктура как код".

После создания функционального приложения вы можете развернуть код проекта Функций Azure в этом приложении. Последний шаг развертывания кода выходит за рамки этого быстрого руководства.

Предварительные условия

Учетная запись Azure

Для начала работы вам потребуется учетная запись Azure с активной подпиской. Создайте учетную запись бесплатно .

Проверка BICEP-файла

Файл Bicep, используемый в этом кратком руководстве, состоит из шаблона быстрого запуска Azure.

/* This Bicep file creates a function app running in a Flex Consumption plan 
that connects to Azure Storage by using managed identities with Microsoft Entra ID. */

//********************************************
// Parameters
//********************************************

@description('Primary region for all Azure resources.')
@minLength(1)
param location string = resourceGroup().location 

@description('Language runtime used by the function app.')
@allowed(['dotnet-isolated','python','java', 'node', 'powerShell'])
param functionAppRuntime string = 'dotnet-isolated' //Defaults to .NET isolated worker

@description('Target language version used by the function app.')
@allowed(['3.10','3.11', '7.4', '8.0', '9.0', '10', '11', '17', '20'])
param functionAppRuntimeVersion string = '8.0' //Defaults to .NET 8.

@description('The maximum scale-out instance count limit for the app.')
@minValue(40)
@maxValue(1000)
param maximumInstanceCount int = 100

@description('The memory size of instances used by the app.')
@allowed([2048,4096])
param instanceMemoryMB int = 2048

@description('A unique token used for resource name generation.')
@minLength(3)
param resourceToken string = toLower(uniqueString(subscription().id, location))

@description('A globally unigue name for your deployed function app.')
param appName string = 'func-${resourceToken}'

//********************************************
// Variables
//********************************************

// Generates a unique container name for deployments.
var deploymentStorageContainerName = 'app-package-${take(appName, 32)}-${take(resourceToken, 7)}'

// Key access to the storage account is disabled by default 
var storageAccountAllowSharedKeyAccess = false

// Define the IDs of the roles we need to assign to our managed identities.
var storageBlobDataOwnerRoleId  = 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b'
var storageBlobDataContributorRoleId = 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'
var storageQueueDataContributorId = '974c5e8b-45b9-4653-ba55-5f855dd0fb88'
var storageTableDataContributorId = '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3'
var monitoringMetricsPublisherId = '3913510d-42f4-4e42-8a64-420c390055eb'

//********************************************
// Azure resources required by your function app.
//********************************************

resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
  name: 'log-${resourceToken}'
  location: location
  properties: any({
    retentionInDays: 30
    features: {
      searchVersion: 1
    }
    sku: {
      name: 'PerGB2018'
    }
  })
}

resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: 'appi-${resourceToken}'
  location: location
  kind: 'web'
  properties: {
    Application_Type: 'web'
    WorkspaceResourceId: logAnalytics.id
    DisableLocalAuth: true
  }
}

resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = {
  name: 'st${resourceToken}'
  location: location
  kind: 'StorageV2'
  sku: { name: 'Standard_LRS' }
  properties: {
    accessTier: 'Hot'
    allowBlobPublicAccess: false
    allowSharedKeyAccess: storageAccountAllowSharedKeyAccess
    dnsEndpointType: 'Standard'
    minimumTlsVersion: 'TLS1_2'
    networkAcls: {
      bypass: 'AzureServices'
      defaultAction: 'Allow'
    }
    publicNetworkAccess: 'Enabled'
  }
  resource blobServices 'blobServices' = {
    name: 'default'
    properties: {
      deleteRetentionPolicy: {}
    }
    resource deploymentContainer 'containers' = {
      name: deploymentStorageContainerName
      properties: {
        publicAccess: 'None'
      }
    }
  }
}

resource userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
  name: 'uai-data-owner-${resourceToken}'
  location: location
}

resource roleAssignmentBlobDataOwner 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(subscription().id, storage.id, userAssignedIdentity.id, 'Storage Blob Data Owner')
  scope: storage
  properties: {
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', storageBlobDataOwnerRoleId)
    principalId: userAssignedIdentity.properties.principalId
    principalType: 'ServicePrincipal'
  }
}

resource roleAssignmentBlob 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(subscription().id, storage.id, userAssignedIdentity.id, 'Storage Blob Data Contributor')
  scope: storage
  properties: {
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', storageBlobDataContributorRoleId)
    principalId: userAssignedIdentity.properties.principalId
    principalType: 'ServicePrincipal'
  }
}

resource roleAssignmentQueueStorage 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(subscription().id, storage.id, userAssignedIdentity.id, 'Storage Queue Data Contributor')
  scope: storage
  properties: {
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', storageQueueDataContributorId)
    principalId: userAssignedIdentity.properties.principalId
    principalType: 'ServicePrincipal'
  }
}

resource roleAssignmentTableStorage 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(subscription().id, storage.id, userAssignedIdentity.id, 'Storage Table Data Contributor')
  scope: storage
  properties: {
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', storageTableDataContributorId)
    principalId: userAssignedIdentity.properties.principalId
    principalType: 'ServicePrincipal'
  }
}

resource roleAssignmentAppInsights 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(subscription().id, applicationInsights.id, userAssignedIdentity.id, 'Monitoring Metrics Publisher')
  scope: applicationInsights
  properties: {
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', monitoringMetricsPublisherId)
    principalId: userAssignedIdentity.properties.principalId
    principalType: 'ServicePrincipal'
  }
}

//********************************************
// Function app and Flex Consumption plan definitions
//********************************************

resource appServicePlan 'Microsoft.Web/serverfarms@2024-04-01' = {
  name: 'plan-${resourceToken}'
  location: location
  kind: 'functionapp'
  sku: {
    tier: 'FlexConsumption'
    name: 'FC1'
  }
  properties: {
    reserved: true
  }
}

resource functionApp 'Microsoft.Web/sites@2024-04-01' = {
  name: appName
  location: location
  kind: 'functionapp,linux'
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '${userAssignedIdentity.id}':{}
      }
    }
  properties: {
    serverFarmId: appServicePlan.id
    httpsOnly: true
    siteConfig: {
      minTlsVersion: '1.2'
    }
    functionAppConfig: {
      deployment: {
        storage: {
          type: 'blobContainer'
          value: '${storage.properties.primaryEndpoints.blob}${deploymentStorageContainerName}'
          authentication: {
            type: 'UserAssignedIdentity'
            userAssignedIdentityResourceId: userAssignedIdentity.id
          }
        }
      }
      scaleAndConcurrency: {
        maximumInstanceCount: maximumInstanceCount
        instanceMemoryMB: instanceMemoryMB
      }
      runtime: { 
        name: functionAppRuntime
        version: functionAppRuntimeVersion
      }
    }
  }
  resource configAppSettings 'config' = {
    name: 'appsettings'
    properties: {
        AzureWebJobsStorage__accountName: storage.name
        AzureWebJobsStorage__credential : 'managedidentity'
        AzureWebJobsStorage__clientId: userAssignedIdentity.properties.clientId
        APPLICATIONINSIGHTS_INSTRUMENTATIONKEY: applicationInsights.properties.InstrumentationKey
        APPLICATIONINSIGHTS_AUTHENTICATION_STRING: 'ClientId=${userAssignedIdentity.properties.clientId};Authorization=AAD'
      }
  }
}

Этот файл развертывания создает эти ресурсы Azure, необходимые приложению-функции, которое безопасно подключается к службам Azure:

  • Microsoft.Web/sites: создает функциональное приложение.
  • Microsoft.Web/serverfarms: создает бессерверный план Flex Consumption для размещения вашего приложения.
  • Microsoft.Storage/storageAccounts: создает учетную запись хранения Azure, необходимую функциями.
  • Microsoft.Insights/components: создает экземпляр Application Insights для мониторинга приложения.
  • Microsoft.OperationalInsights/workspaces: создает рабочую область, необходимую Application Insights.
  • Microsoft.ManagedIdentity/userAssignedIdentities: создает управляемое удостоверение, назначаемое пользователем, которое используется приложением для проверки подлинности с другими службами Azure с помощью Microsoft Entra.
  • Microsoft.Authorization/roleAssignments: создает назначения ролей для управляемого удостоверения, назначаемого пользователем, которые предоставляют приложению минимальные привилегии при подключении к другим службам Azure.

Рекомендации по развертыванию:

  • Учетная запись хранения используется для хранения важных данных приложения, включая пакет развертывания кода приложения. Это развертывание создает учетную запись хранения, доступ к которой осуществляется с помощью аутентификации Microsoft Entra ID и управляемых идентификаций. Доступ предоставляется на основе принципа минимальных прав.
  • Файл Bicep по умолчанию создает приложение C#, использующее .NET 8 в изолированном процессе. Для других языков используйте параметры functionAppRuntime и functionAppRuntimeVersion, чтобы указать конкретный язык и версию, на которой нужно запустить приложение. Убедитесь, что вы выбрали язык программирования в верхней части статьи.

Разверните Bicep-файл

  1. Сохраните файл Bicep с именем main.bicep на локальном компьютере.

  2. Разверните файл Bicep с помощью Azure CLI или Azure PowerShell.

    az group create --name exampleRG --location <SUPPORTED_REGION>
    az deployment group create --resource-group exampleRG --template-file main.bicep --parameters functionAppRuntime=dotnet-isolated functionAppRuntimeVersion=8.0
    
    az group create --name exampleRG --location <SUPPORTED_REGION>
    az deployment group create --resource-group exampleRG --template-file main.bicep --parameters functionAppRuntime=java functionAppRuntimeVersion=17
    
    az group create --name exampleRG --location <SUPPORTED_REGION>
    az deployment group create --resource-group exampleRG --template-file main.bicep --parameters functionAppRuntime=node functionAppRuntimeVersion=20
    
    az group create --name exampleRG --location <SUPPORTED_REGION>
    az deployment group create --resource-group exampleRG --template-file main.bicep --parameters functionAppRuntime=python functionAppRuntimeVersion=3.11
    
    az group create --name exampleRG --location <SUPPORTED_REGION>
    az deployment group create --resource-group exampleRG --template-file main.bicep --parameters functionAppRuntime=powerShell functionAppRuntimeVersion=7.4
    

    В этом примере замените <SUPPORTED_REGION> на регион, который поддерживает план потребления Flex.

    После завершения развертывания должно отобразиться сообщение о том, что развертывание успешно выполнено.

Проверка развертывания

Используйте Azure CLI или Azure PowerShell для проверки развертывания.

az resource list --resource-group exampleRG

Посетите страницу приветствия функционального приложения

  1. Используйте выходные данные предыдущего шага проверки, чтобы получить уникальное имя, созданное для приложения-функции.

  2. Откройте браузер и введите следующий URL-адрес: <https://< appName.azurewebsites.net>. Обязательно замените <\appName> уникальным именем, созданным для приложения-функции.

    При посещении URL-адреса вы увидите следующую страницу:

    Страница приветствия функционального приложения

Очистка ресурсов

Теперь, когда вы развернули приложение-функцию и связанные ресурсы в Azure, можно перейти к следующему шагу публикации кода проекта в приложении. В противном случае используйте эти команды для удаления ресурсов, если они больше не нужны.

az group delete --name exampleRG

Вы также можете удалить ресурсы с помощью портала Azure.

Следующие шаги

Теперь вы можете развернуть проект кода в ресурсах функционального приложения, которые вы создали в Azure.

Вы можете создавать, проверять и развертывать проект кода в новом приложении-функции из следующих локальных сред: