Hızlı Başlangıç: Bicep kullanarak Azure İşlevleri kaynakları oluşturma ve dağıtma

Bu makalede, Gerekli Azure kaynaklarıyla birlikte Azure'daki Flex Consumption planında işlev uygulaması oluşturmak için Bicep'i kullanacaksınız. İşlev uygulaması, işlev kodu yürütmeleriniz için sunucusuz yürütme bağlamı sağlar. Uygulama, diğer Azure kaynaklarına bağlanmak için yönetilen kimliklerle Microsoft Entra Id kullanır.

Bu hızlı başlangıcı tamamladığınızda Azure hesabınıza birkaç sentlik (ABD doları cinsinden) veya daha düşük bir ücret yansıtılır.

Bicep, Azure kaynaklarını dağıtmak için bildirim temelli söz dizimi kullanan, etki alanına özgü bir dildir (DSL). Kısa sözdizimi, güvenilir tür güvenliği ve kod yeniden kullanımı için destek sağlar. Bicep, Azure'daki kod olarak altyapı çözümleriniz için en iyi yazma deneyimini sunar.

İşlev uygulamasını oluşturduktan sonra Azure İşlevleri proje kodunuzu bu uygulamaya dağıtabilirsiniz. Son kod dağıtım adımı bu hızlı başlangıç makalesinin kapsamı dışındadır.

Önkoşullar

Azure hesabı

Başlamadan önce etkin aboneliği olan bir Azure hesabınız olmalıdır. Ücretsiz hesap oluşturun.

Bicep dosyasını gözden geçir

Bu hızlı başlangıçta kullanılan Bicep dosyası bir Azure Hızlı Başlangıç Şablonu'ndan alınmıştı.

/* 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 unique 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
        APPINSIGHTS_INSTRUMENTATIONKEY: applicationInsights.properties.InstrumentationKey
        APPLICATIONINSIGHTS_AUTHENTICATION_STRING: 'ClientId=${userAssignedIdentity.properties.clientId};Authorization=AAD'
      }
  }
}

Bu dağıtım dosyası, Azure hizmetlerine güvenli bir şekilde bağlanan bir işlev uygulaması tarafından gereken şu Azure kaynaklarını oluşturur:

Dağıtımla ilgili dikkat edilmesi gerekenler:

  • Depolama hesabı, uygulama kodu dağıtım paketi de dahil olmak üzere önemli uygulama verilerini depolamak için kullanılır. Bu dağıtım, Microsoft Entra ID kimlik doğrulaması ve yönetilen kimlikler kullanılarak erişilen bir depolama hesabı oluşturur. Kimlik erişimi, asgari izinler esas alınarak verilir.
  • Bicep dosyası varsayılan olarak yalıtılmış bir işlemde .NET 8 kullanan bir C# uygulaması oluşturur. Başka diller için, uygulamanızı çalıştırılacağı belirli dili ve sürümü belirtmek üzere functionAppRuntime ve functionAppRuntimeVersion parametrelerini kullanın. Makalenin üst kısmında programlama dilinizi seçtiğinizden emin olun.

Bicep dosyasını dağıt

  1. Bicep dosyasını main.bicep olarak yerel bilgisayarınıza kaydedin.

  2. Azure CLI veya Azure PowerShell kullanarak Bicep dosyasını dağıtın.

    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
    

    Bu örnekte yerine <SUPPORTED_REGION> bir bölge yazın.

    Dağıtım tamamlandığında, dağıtımın başarılı olduğunu belirten bir ileti görmeniz gerekir.

Dağıtımı doğrulayın

Dağıtımı doğrulamak için Azure CLI veya Azure PowerShell kullanın.

az resource list --resource-group exampleRG

İşlev uygulaması karşılama sayfasını ziyaret edin

  1. İşlev uygulamanız için oluşturulan benzersiz adı almak için önceki doğrulama adımının çıktısını kullanın.

  2. Bir tarayıcı açın ve şu URL'yi girin: <https://< appName.azurewebsites.net>. <\appName> değerini işlev uygulamanız için oluşturulan benzersiz adla değiştirdiğinizden emin olun.

    URL'yi ziyaret ettiğinizde aşağıdakine benzer bir sayfa görmeniz gerekir:

    İşlev uygulaması karşılama sayfası

Kaynakları temizleme

Artık bir işlev uygulamasını ve ilgili kaynakları Azure'a dağıttığınız için, proje kodunu uygulamanızda yayımlamanın sonraki adımına devam edebilirsiniz. Aksi takdirde, artık ihtiyacınız kalmadığında kaynakları silmek için bu komutları kullanın.

az group delete --name exampleRG

Azure portalını kullanarak da kaynakları kaldırabilirsiniz.

Sonraki adımlar

Artık Azure'da oluşturduğunuz işlev uygulaması kaynaklarına bir kod projesi dağıtabilirsiniz.

Bu yerel ortamlardan yeni işlev uygulamanıza bir kod projesi oluşturabilir, doğrulayabilir ve dağıtabilirsiniz: