You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Bicep部署Azure Function FlexConsumption时遇404错误

解决Bicep部署弹性消费计划Azure Function时的404日志缺失问题

问题概述

使用Bicep模板部署包含代码的Azure Function(弹性消费计划)时,出现404部署错误。排查发现,Bicep部署会清除所有现有部署日志,包括当前新代码的部署日志,导致ARM部署引擎查询部署状态时返回404。日志消失前可见提示:

你查找的日志未找到。在消费计划中,实例会被回收,日志不会持久化。如需持久化请启用Application Insights。

核心原因

  1. 弹性消费计划(FlexConsumption)的Function实例会自动弹性伸缩,闲置时会被回收,默认部署日志不会持久化到本地存储
  2. Bicep部署过程中,旧日志被清除,而新部署日志尚未写入Application Insights时,ARM引擎查询状态就会触发404错误
  3. 代码部署(OneDeploy扩展)可能在Function App身份权限、存储配置未完全就绪时执行,导致部署失败且日志丢失

解决方案

  1. 确保日志持久化配置:完善Application Insights关联,添加强制日志发送的应用设置
  2. 添加权限依赖:为Function App的系统分配身份授予存储Blob读取权限,确保代码包可被访问
  3. 调整部署顺序:明确资源依赖关系,确保关键资源(App Insights、存储权限)就绪后再执行代码部署
  4. 优化部署参数:确保SAS令牌生成逻辑正确,避免权限不足或过期问题

修正后的Bicep代码

param location string = 'northeurope'
param name string = '<func-name>'
param storageAccountName string = '<my-storage>'
param artifactBlobName string = '<blob-name-in-storage>'
param subnetId string = '<subnet-id>'

// 弹性消费计划
resource appServicePlan 'Microsoft.Web/serverfarms@2024-04-01' = {
  name: 'sp-${name}'
  location: location
  sku: {
    name: 'FC1'
    tier: 'FlexConsumption'
    capacity: 2
  }
  kind: 'functionapp,linux'
  properties: {
    reserved: true
  }
}

// Log Analytics工作区
resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = {
  name: 'workspace-${name}'
  location: location
  properties: any({
    retentionInDays: 30
    features: {
      searchVersion: 1
    }
    sku: {
      name: 'PerGB2018'
    }
  })
}

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

// 引用现有存储账户
resource functionsStorageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' existing = {
  name: storageAccountName
}

// 存储Blob数据读取角色定义(内置角色)
var storageBlobDataReaderRoleId = '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1'

// 为Function App系统身份授予存储Blob读取权限
resource functionStorageRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(functionsStorageAccount.id, functionApp.id, storageBlobDataReaderRoleId)
  scope: functionsStorageAccount
  properties: {
    roleDefinitionId: storageBlobDataReaderRoleId
    principalId: functionApp.identity.principalId
    principalType: 'ServicePrincipal'
  }
}

// Function App资源
resource functionApp 'Microsoft.Web/sites@2024-04-01' = {
  name: name
  location: location
  kind: 'functionapp,linux'
  identity: { type: 'SystemAssigned' }
  properties: {
    httpsOnly: true
    publicNetworkAccess: 'Enabled'
    reserved: true
    vnetRouteAllEnabled: true
    serverFarmId: appServicePlan.id
    siteConfig: {
      appSettings: [
        {
          name: 'AzureWebJobsStorage__accountName'
          value: storageAccountName
        }
        {
          name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: applicationInsights.properties.ConnectionString
        }
        {
          name: 'FUNCTIONS_WORKER_RUNTIME'
          value: 'node'
        }
        {
          name: 'FUNCTIONS_EXTENSION_VERSION'
          value: '~4'
        }
        // 强制日志发送到App Insights
        {
          name: 'DIAGNOSTICS_APPLICATIONINSIGHTS_ENABLED'
          value: 'true'
        }
      ]
    }

    functionAppConfig: {
      scaleAndConcurrency: {
        maximumInstanceCount: 100
        instanceMemoryMB: 2048
        alwaysReady: []
      }
      runtime: { name: 'node', version: '20' }
      deployment: {
        storage: {
          type: 'blobContainer'
          value: 'https://${storageAccountName}.blob.${environment().suffixes.storage}/${name}'
          authentication: {
            type: 'SystemAssignedIdentity'
          }
        }
      }
    }
    virtualNetworkSubnetId: subnetId
  }
}

param deployTime string = utcNow('u')

// 生成SAS令牌(有效1小时)
var serviceSasToken = functionsStorageAccount.listServiceSas(functionsStorageAccount.apiVersion, {
  signedResource: 'b'
  signedPermission: 'rl'
  canonicalizedResource: '/blob/${storageAccountName}/artifacts/${artifactBlobName}'
  signedExpiry: dateTimeAdd(deployTime, 'PT1H')
}).serviceSasToken

var artifactUrl = 'https://${storageAccountName}.blob.${environment().suffixes.storage}/artifacts/${artifactBlobName}?${serviceSasToken}'

// OneDeploy代码部署,依赖权限分配完成
resource functionOneDeploy 'Microsoft.Web/sites/extensions@2024-04-01' = {
  parent: functionApp
  name: 'onedeploy'
  dependsOn: [
    functionStorageRoleAssignment
  ]
  properties: {
    packageUri: artifactUrl
    remoteBuild: false
  }
}

关键修正点

  • 添加了存储Blob数据读取角色分配,确保Function App身份有权限访问代码包所在的存储Blob
  • 完善了应用设置,添加了FUNCTIONS_WORKER_RUNTIME、FUNCTIONS_EXTENSION_VERSION以及强制日志发送到App Insights的配置
  • 为OneDeploy扩展添加dependsOn依赖,确保权限配置完成后再执行代码部署
  • 修正了日志持久化相关配置,避免部署日志提前丢失

内容的提问来源于stack exchange,提问作者y. bs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:23:18