Azure Batch用户分配托管身份创建池遇权限及网关超时问题
问题:Azure Batch池用户分配托管身份创建失败(权限及网关超时)
我们正将Python解决方案从服务主体(SPN)迁移至托管身份(MI)认证,已完成代码适配,但创建带用户分配托管身份的Azure Batch池时,先遇到权限错误,添加Managed Identity Operator角色后又出现网关超时错误。
原代码
import os from azure.identity import DefaultAzureCredential, ManagedIdentityCredential from azure.mgmt.batch import BatchManagementClient from azure.mgmt.batch.models import ( Pool, CloudServiceConfiguration, PoolIdentityType, FixedScaleSettings, ContainerRegistry, ContainerConfiguration, PoolAllocationMode, ComputeNodeIdentityReference, VirtualMachineConfiguration, BatchPoolIdentity, UserAssignedIdentities, DeploymentConfiguration, ScaleSettings, NetworkConfiguration ) app_name = 'BatchTest' #The name of the Batch Application to load onto the pool. app_version = 0.0.1 #The version of the Batch Application to load. If omitted the default version will be loaded. registry_name = 'sampleregistry.azurecr.io' image_name = 'test-image' image_version = 'latest' sku_to_use = 'batch.node.ubuntu 20.04' # Marketplace image sku image_ref_to_use = {'additional_properties': {}, 'publisher': 'microsoft-azure-batch', 'offer': 'ubuntu-server-container', 'sku': '20-04-lts', 'version': 'latest', 'virtual_machine_image_id': None} client_id = "xxx-xxx-xx-xx-xx" subscription_id = "yyyy-yyy-yyy-yyy-yyy" resource_group_name = "TestRG" user_assigned_identity_name = "testUMI" resource_id = f"/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{user_assigned_identity_name}" pool_vm_size = "STANDARD_DS4_V2" pool_vm_count = 4 pool_vm_maxcount = 1 if app_version is None: version_str = " with the Default {} Version".format(app_name) else: version_str = "with {} Version {}".format(app_name, app_version) # 错误:镜像名称拼接重复了registry的域名 image_name = registry_name + image_name + image_version # 错误:未导入batchmodels就使用 application_references = [batchmodels.ApplicationPackageReference(application_id = app_name, version = app_version)] network_config = None # Authenticate using DefaultAzureCredential credentials = ManagedIdentityCredential(client_id = f"{client_id}") batch_client = BatchManagementClient(credential=credentials,subscription_id=f"{subscription_id}") # Define the container registry (with username and password if needed) container_registry = ContainerRegistry( registry_server=f"{registry_name}", user_name=None, password=None, identity_reference = ComputeNodeIdentityReference(resource_id = resource_id)) # Define the container configuration # 错误:镜像地址重复了registry域名(registry_name已经包含.azurecr.io,又加了一次) container_config = ContainerConfiguration( type="dockerCompatible", container_registries=[container_registry], container_image_names=[f"{registry_name}.azurecr.io/{image_name}:{image_version}"]) vm_config = VirtualMachineConfiguration( image_reference=image_ref_to_use, node_agent_sku_id=sku_to_use, container_configuration=container_config) # 错误:user_assigned_identities格式错误,max_tasks_per_node未定义 pool = Pool( identity=BatchPoolIdentity( type=PoolIdentityType.USER_ASSIGNED, user_assigned_identities={f"{resource_id}:UserAssignedIdentities()"} ), display_name='managedidentitytest', vm_size=pool_vm_size, deployment_configuration=DeploymentConfiguration( virtual_machine_configuration=vm_config, ), scale_settings=ScaleSettings( fixed_scale=FixedScaleSettings( target_dedicated_nodes=pool_vm_count, target_low_priority_nodes=0) ), task_slots_per_node=max_tasks_per_node ) # 错误:pool_id未定义 batch_client.pool.create( resource_group_name="TestRG", account_name="Teststsystemdev", pool_name=pool_id, parameters=pool )
遇到的错误
1. 权限错误
Code: LinkedAuthorizationFailed Message: The client "xxx-xxx-xx-xx-xx" with object id "xxx-xxx-xx-xx-xx" has permission to perform action 'Microsoft.Batch/batchAccounts/pools/write' on scope '/subscriptions/yyyy-yyy-yyy-yyy-yyy/resourceGroups/TestRG/providers/Microsoft.Batch/batchAccounts/Teststsystemdev/pools/ForecastCluster'; however, it does not have permission to perform action(s) 'Microsoft.ManagedIdentity/userAssignedIdentities/assign/action' on the linked scope(s) '/subscriptions/yyyy-yyy-yyy-yyy-yyy/resourcegroups/ProdRG/providers/microsoft.managedidentity/userassignedidentities/testUMI' (respectively) or the linked scope(s) are invalid.
2. 网关超时错误
Encountered unexpected exception of type <class 'azure.core.exceptions.HttpResponseError'> when trying to create a pool. Exception details: (GatewayTimeout) The gateway did not receive a response from 'Microsoft.Batch' within the specified time period. Code: GatewayTimeout Message: The gateway did not receive a response from 'Microsoft.Batch' within the specified time period.
解决方案
1. 修复代码中的关键错误
(1)修正用户分配身份的格式
BatchPoolIdentity的user_assigned_identities参数是字典类型,键为用户分配MI的资源ID,值为空对象或UserAssignedIdentities实例,原代码的字符串拼接格式完全错误:
# 错误写法 user_assigned_identities={f"{resource_id}:UserAssignedIdentities()"} # 正确写法 user_assigned_identities={resource_id: {}}
(2)修正镜像地址拼接错误
原代码中registry_name已经包含.azurecr.io,无需重复添加,同时镜像名称拼接逻辑错误:
# 错误写法 image_name = registry_name + image_name + image_version container_image_names=[f"{registry_name}.azurecr.io/{image_name}:{image_version}"] # 正确写法 full_image_name = f"{registry_name}/{image_name}:{image_version}"
(3)补全未定义的变量
添加max_tasks_per_node和pool_id的定义:
max_tasks_per_node = 1 # 根据需求调整 pool_id = "ForecastCluster" # 对应错误信息中的池名称
(4)修正应用包引用的导入问题
原代码中使用batchmodels但未导入,直接使用azure.mgmt.batch.models中的类:
from azure.mgmt.batch.models import ApplicationPackageReference # ... application_references = [ApplicationPackageReference(application_id=app_name, version=app_version)]
2. 修正权限配置
之前的LinkedAuthorizationFailed错误是因为执行代码的托管身份(即ManagedIdentityCredential对应的MI)没有权限分配目标用户托管身份,需:
- 在用户分配MI的资源范围上,给执行代码的MI分配
Managed Identity Operator角色(或自定义角色包含Microsoft.ManagedIdentity/userAssignedIdentities/assign/action权限) - 确保用户分配MI拥有Azure容器注册表(ACR)的
ACR Pull角色,用于拉取容器镜像
3. 解决网关超时问题
网关超时通常是Batch服务处理请求超时导致,可尝试:
- 先减少目标节点数(比如
target_dedicated_nodes=1),测试基础配置是否能成功创建 - 增加客户端请求超时时间,创建
BatchManagementClient时配置超时:from azure.core.pipeline.transport import RequestsTransport transport = RequestsTransport(timeout=120) # 设置120秒超时 batch_client = BatchManagementClient( credential=credentials, subscription_id=subscription_id, transport=transport ) - 确保Batch账户、用户分配MI、ACR处于同一Azure区域,减少跨区域延迟
- 检查容器镜像大小,过大的镜像会延长节点初始化时间,导致超时
修正后的完整代码
import os from azure.identity import ManagedIdentityCredential from azure.mgmt.batch import BatchManagementClient from azure.mgmt.batch.models import ( Pool, PoolIdentityType, FixedScaleSettings, ContainerRegistry, ContainerConfiguration, ComputeNodeIdentityReference, VirtualMachineConfiguration, BatchPoolIdentity, DeploymentConfiguration, ScaleSettings, ApplicationPackageReference ) # 配置参数 app_name = 'BatchTest' app_version = '0.0.1' registry_name = 'sampleregistry.azurecr.io' image_name = 'test-image' image_version = 'latest' sku_to_use = 'batch.node.ubuntu 20.04' image_ref_to_use = { 'publisher': 'microsoft-azure-batch', 'offer': 'ubuntu-server-container', 'sku': '20-04-lts', 'version': 'latest' } client_id = "xxx-xxx-xx-xx-xx" subscription_id = "yyyy-yyy-yyy-yyy-yyy" resource_group_name = "TestRG" user_assigned_identity_name = "testUMI" resource_id = f"/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{user_assigned_identity_name}" pool_vm_size = "STANDARD_DS4_V2" pool_vm_count = 1 # 先测试1个节点 max_tasks_per_node = 1 pool_id = "ForecastCluster" batch_account_name = "Teststsystemdev" # 认证 credentials = ManagedIdentityCredential(client_id=client_id) batch_client = BatchManagementClient(credential=credentials, subscription_id=subscription_id) # 容器注册表配置(使用用户分配身份认证) container_registry = ContainerRegistry( registry_server=registry_name, identity_reference=ComputeNodeIdentityReference(resource_id=resource_id) ) # 容器配置 full_image_name = f"{registry_name}/{image_name}:{image_version}" container_config = ContainerConfiguration( type="dockerCompatible", container_registries=[container_registry], container_image_names=[full_image_name] ) # VM配置 vm_config = VirtualMachineConfiguration( image_reference=image_ref_to_use, node_agent_sku_id=sku_to_use, container_configuration=container_config ) # 池配置(修正用户分配身份格式) pool = Pool( identity=BatchPoolIdentity( type=PoolIdentityType.USER_ASSIGNED, user_assigned_identities={resource_id: {}} ), display_name='managedidentitytest', vm_size=pool_vm_size, deployment_configuration=DeploymentConfiguration( virtual_machine_configuration=vm_config ), scale_settings=ScaleSettings( fixed_scale=FixedScaleSettings( target_dedicated_nodes=pool_vm_count, target_low_priority_nodes=0 ) ), task_slots_per_node=max_tasks_per_node ) # 创建池 batch_client.pool.create( resource_group_name=resource_group_name, account_name=batch_account_name, pool_name=pool_id, parameters=pool )
内容的提问来源于stack exchange,提问作者RSK
相关产品推荐
相关产品推荐

