Azure 自动化中的上下文切换
上下文切换是指一个进程中的上下文更改另一个进程中的上下文。 Azure 上下文是一组定义 Azure PowerShell cmdlet 目标的信息。 上下文包括下列属性:
属性 | 说明 |
---|---|
名称 | 上下文名称。 |
帐户 | 对 Azure 通信进行身份验证时所用的用户名或服务主体。 |
环境 | 表示 Azure 全球或国家/地区 Azure 云之一,例如 Azure 中国。 还可以指定混合云平台,如 Azure Stack。 |
订阅 | 表示包含要管理的资源的 Azure 订阅。 |
租户 | 表示单个组织的 Microsoft Entra ID 的专用受信任实例。 |
凭据 | Azure 用来验证你的身份并确保你有权访问 Azure 中的资源的信息。 |
当可以访问多个订阅的帐户登录时,可以将这些订阅中的任何一个添加到用户的上下文中。 若要保证正确的订阅,必须在连接时声明。 例如,使用 Add-AzAccount -Credential $Cred -subscription 'aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e'
。 但是,当管理一个订阅的 runbook 与管理同一自动化帐户的另一个订阅中的资源的其他 runbook 在同一沙盒进程中运行时,可能会出现问题。 一个 runbook 对上下文所做的更改可能会影响使用默认上下文的其他 runbook。 当上下文包含信息(例如要使用的凭据和目标订阅)时,cmdlet 可能会将错误的订阅设为目标,从而导致 not found
或权限错误。 此问题称为上下文切换。
管理 Azure 上下文
若要避免 runbook 针对错误订阅中的资源运行,请查看以下建议:
- 通过在每个 runbook 的开头使用以下命令,禁止在自动化 runbook 中保存沙盒上下文:
Disable-AzContextAutosave -Scope Process
。 - Azure PowerShell cmdlet 支持
-DefaultProfile
参数。 此参数已添加到所有 Az 和 Azure 资源管理器 (AzureRM) cmdlet 以支持在同一进程中运行多个脚本,从而允许你为每个 cmdlet 指定要使用的上下文。 在创建和每次更改上下文对象时将其保存在 runbook 中。 然后在每次使用 Az 或 AzureRM cmdlet 进行的调用中引用它。 例如,$AzureContext = Set-AzContext -SubscriptionId $subID
。 - 将上下文对象传递到 PowerShell cmdlet,例如
Get-AzVM -ResourceGroupName "myGroup" -DefaultProfile $AzureContext
。
下面是一个 PowerShell runbook 代码片段,它使用系统分配的托管标识,这些标识遵循避免上下文切换的建议。
# Ensures you do not inherit an AzContext in your runbook
Disable-AzContextAutosave -Scope Process
# Connect to Azure with system-assigned managed identity
$AzureContext = (Connect-AzAccount -Identity -Environment AzureChinaCloud).context
# set and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext
# Pass context object - even though the context had just been set
# This is the step that guarantees the context will not be switched.
Get-AzVM -ResourceGroupName "resourceGroupName" -DefaultProfile $AzureContext | Select Name
可能出现的症状
如果不遵循这些建议,可能不会遇到问题,但机会确实存在。 这种情况的根本问题是时机;这取决于每个 runbook 在另一个 runbook 切换其上下文时正在做什么。 下面是一些可能的错误消息。 但是,这些错误消息可能是由非上下文切换条件导致的。
The subscription named <subscription name> cannot be found.
Get-AzVM : The client '<clientid>' with object id '<objectid>' does not have authorization to perform action 'Microsoft.Compute/virtualMachines/read' over scope '/subscriptions/<subcriptionIdOfSubscriptionWichDoesntContainTheVM>/resourceGroups/REsourceGroupName/providers/Microsoft.Compute/virtualMachines/VMName '.
ErrorCode: AuthorizationFailed
StatusCode: 403
ReasonPhrase: Forbidden Operation
ID : <AGuidRepresentingTheOperation> At line:51 char:7 + $vm = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $UNBV... +
Get-AzureRmResource : Resource group "SomeResourceGroupName" could not be found.
... resources = Get-AzResource -ResourceGroupName $group.ResourceGro ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzResource], CloudException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.GetAzureResourceCmdlet