使用Azure DevOps部署Azure App Service的权限问题解决咨询
问题:Azure DevOps流水线部署Docker镜像至Azure App Service失败(权限+IP限制相关)
问题背景
- 基础NodeJS Express应用打包为Docker镜像,通过Azure DevOps构建流水线发布至Azure Container Registry(ACR),此环节运行正常。
- 执行任务让Azure App Service使用新发布的镜像时出现权限问题:流水线执行成功,但App Service显示应用状态不健康。
流水线部署任务配置
inputs: azureSubscription: ${{ variables.service_connection }} appName: ${{ variables.app_name }} imageName: ${{ variables.container_registry }}/${{ variables.image_name }}:${{ parameters.stack }}
App Service错误日志
2024-07-17T13:13:53.610Z ERROR - DockerApiException: Docker API responded with status code=NotFound, response={"message":"manifest for mycontainerrepository.azurecr.io/myimagename:my_tag not found: manifest unknown: manifest tagged by \"my_tag\" is not found"} 2024-07-17T13:13:53.784Z ERROR - DockerApiException: Docker API responded with status code=InternalServerError, response={"message":"Head \"https://mycontainerrepository.azurecr.io/v2/myimagename/manifests/my_tag\": unauthorized: authentication required, visit https://aka.ms/acr/authorization for more information."} 2024-07-17T13:13:53.788Z WARN - Image pull failed. Defaulting to local copy if present. 2024-07-17T13:13:53.792Z ERROR - Image pull failed: Verify docker image configuration and credentials (if using private repository)/home/LogFiles/2024_07_17_lw1sdlwk00013M_msi_docker.log (https://myimagename.scm.azurewebsites.net/api/vfs/LogFiles/2024_07_17_lw1sdlwk00013M_msi_docker.log)
已完成的排查与临时修复
- 确认服务连接的服务主体已拥有ACR的
AcrPull权限,以及目标App Service的Website Contributor角色,权限配置无误。 - 临时修复方案:断开部署中心的Azure Pipeline,手动配置App Service通过托管标识对接ACR(托管标识已获
AcrPull权限),此方法可正常拉取镜像。
IP限制相关测试发现
- 关闭ACR的入站IP限制后,镜像可正常拉取;重新开启后,仅在下次部署前保持正常。
- 将构建代理IP加入ACR白名单后,问题仍存在;外部请求触发应用启动时,使用的是旧代码版本。
当前服务计划Bicep定义
resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = { name: appServicePlanName location: location kind: 'app,linux' properties: { reserved: true } tags: { costcenter: costcenter } sku: { name: 'S1' } }
解决方案建议
1. 配置App Service通过托管标识拉取ACR镜像
在流水线中添加AzureCLI任务,自动完成托管标识启用、权限分配和镜像配置,替代服务主体的认证方式,避免权限传递问题:
# 启用App Service系统托管标识 az webapp identity assign --name ${{ variables.app_name }} --resource-group ${{ variables.resource_group }} # 获取托管标识ID MANAGED_IDENTITY_ID=$(az webapp identity show --name ${{ variables.app_name }} --resource-group ${{ variables.resource_group }} --query principalId -o tsv) # 为托管标识分配ACR的AcrPull权限 az role assignment create --assignee $MANAGED_IDENTITY_ID --role AcrPull --scope /subscriptions/${{ variables.subscription_id }}/resourceGroups/${{ variables.resource_group }}/providers/Microsoft.ContainerRegistry/registries/${{ variables.container_registry_name }} # 配置App Service使用托管标识拉取指定镜像 az webapp config container set --name ${{ variables.app_name }} --resource-group ${{ variables.resource_group }} --docker-custom-image-name ${{ variables.container_registry }}/${{ variables.image_name }}:${{ parameters.stack }} --docker-registry-server-url https://${{ variables.container_registry }}.azurecr.io --enable-managed-identity true
2. 调整ACR入站IP限制规则
App Service拉取镜像使用的是自身出站IP而非构建代理IP,需将App Service的所有出站IP加入ACR白名单:
# 获取App Service出站IP列表 az webapp show --name ${{ variables.app_name }} --resource-group ${{ variables.resource_group }} --query outboundIpAddresses -o tsv
将上述命令返回的IP全部添加到ACR的入站IP允许列表中。
3. 强制App Service重启拉取新镜像
在部署任务后添加AzureCLI任务,重启App Service以避免使用本地缓存的旧镜像:
az webapp restart --name ${{ variables.app_name }} --resource-group ${{ variables.resource_group }}
内容的提问来源于stack exchange,提问作者Johan Carlsson
相关产品推荐
相关产品推荐

