Azure for AWS engineers: 您的 AWS 直觉如何迁移(以及何时失效)
您已了解如何在 AWS 中组织账户、分配权限和引导状态。本文将介绍如何在 Azure 中完成相同的工作 — 概念如何清晰映射,以及您的 AWS 肌肉记忆在哪些方面会积极误导您。
如果您精通 AWS 却正面临 Azure,好消息是大约 80% 的直觉可以直接迁移:Azure 也有用于组织事物的层次结构、基于角色的访问授权方式、用于无密钥 CI 的 OIDC 机制,以及“冷启动您的状态后端”的引导流程。坏消息是另外 20% — 它们集中在几个关键点,这些地方如果沿用 AWS 的做法,会产生令人困惑的拒绝,而非显而易见的错误。本文是翻译层:您在 AWS 中完成的相同工作,在 Azure 中如何完成,并指出其中的陷阱。
如果您只读一段,简而言之:AWS 基本上只有一个权限平面 (IAM),而 Azure 有三个互不相干的权限平面;AWS accounts 是 Azure subscriptions,但账单完全在别处管理;Azure 还增加了一个强制性容器(resource group),而 AWS 没有真正等效的容器。 下文将详细阐述这些内容。
最大的转变:一个权限平面变为三个
在 AWS 中,IAM 实际上就是全部。一个服务管理您的身份是谁、他们可以对资源做什么,以及——通过 Organizations——如何创建和分组 accounts。权限以您可能甚至没有注意到的方式融合在一起,直到它们消失才察觉。
Azure 有意将这个单一平面划分为三个独立的平面,具有三套角色系统、三种授权机制,并且几乎没有自动渗透。在一个平面中拥有完全权限,在其他平面中什么也得不到。这是需要理解的最重要一点,因为几乎所有的“我是管理员,为什么被拒绝了?”的困惑都源于此。
一个能帮助您的规则是:当 Azure 拒绝了“应该”起作用的操作时,首先要问“我正在与哪个平面对话?”——然后检查该平面的角色。 大多数神秘的拒绝(无法读取 subscription、无法列出 management groups、无法查看账单)并不是平面内部缺少权限——而是您完全与错误的平面对话。
平面 1 — Entra ID directory roles (identity)
此平面管理目录对象:users、groups、service principals / app registrations、Conditional Access、MFA policy、licenses。它不管理您部署的资源。
- 这里的角色包括 Global Administrator、User Administrator、Application Administrator 等。它们在 Entra ID 中分配和评估,并通过 Microsoft Graph API 公开。
- Global Administrator 是目录之神,而不是资源之神。 这让所有人感到困惑:一个 Global Admin 可以愉快地管理组织中的每个 user 和 app,但仍可能在尝试仅仅读取一个 subscription 时遇到授权失败。最接近的 AWS 类比是“管理 IAM Identity Center 和目录本身的人”——但这种类比并不完美,正是因为 AWS 将目录管理与资源授权融合在一起,而 Azure 拒绝这样做。
平面 2 — Azure RBAC (resources)
这是您将主要使用的平面,也是 azurerm Terraform provider 所驱动的平面。它管理您部署的所有内容:VMs、virtual networks、storage、AKS 等。
- 授权是一个三元组:(主体, 角色定义, 范围),其中范围是
root → management group → subscription → resource group → resource链中的一个节点,并且它向下继承。内置角色有 Owner、Contributor、Reader,以及您编写的任何自定义角色定义。 - 这是 AWS 大脑的陷阱:没有附加到身份的策略。 在 AWS 中,您将策略附加到 user 或 role,权限随身份而动。在 Azure 中,角色在特定范围是唯一的模型。最接近的 AWS 心智模型是“附加到 Organizations OU 的 IAM policy”——授权存在于树节点上,而不是主体上。
- 平面 1 和平面 2 之间唯一受认可的桥梁是一个刻意的“紧急访问”操作:Global Administrator 可以切换“Access management for Azure resources”(
elevateAccess操作)来授予自己User Access Administrator 在 root scope 的权限。这个操作是显眼的、可逆的,并且不是默认设置——您在引导期间使用它一次,将自己分配为 tenant root 的 Owner,然后此权限会继承到每个 subscription 中。
平面 3 — 账单/商务(资金)
此平面管理 billing accounts、billing profiles、invoice sections、payment methods — 以及关键的subscription creation。
- 它有自己的角色集(Billing account owner、Billing profile owner、Azure subscription creator 等),在 billing account 内部授予并存储在账单系统中。这些角色不会显示在
az role assignment list或 Entra 角色刀片中。它们是完全独立的世界。 - 您可以从两个方向遇到此问题。即使拥有最大的身份 + 资源权限(Global Admin + User Access Administrator at root + Owner at the root management group),您仍然会从
az billing account list得到一个空列表,并且无法创建 subscription。反之,一个 billing owner 只需点击一下即可授予账单权限。 - 最隐蔽的部分是:账单通过看似 ARM 的 REST URL (
Microsoft.Billing/...) 提供服务,因此它看起来像资源平面——但授权是根据 billing roles 进行评估的。同一个门,不同的守卫。
一个 AWS 永远不会让您思考的具体后果是:您是否可以以编程方式创建 subscriptions 完全取决于您的 billing agreement type。 传统的即用即付/web-direct accounts 只能通过最初的注册身份在门户中手动创建 subscriptions——这种所有权甚至无法授予。现代的 Customer Agreement 支持 subscription-creation API(自服务 accounts 有零售上限——总共只有少数 subscriptions,并且每天有速率限制),而 enterprise/partner agreements 则取消了这些上限。在 AWS 中,CreateAccount 在 management account 中可以直接工作;在 Azure 中,“我可以用代码创建这个 account 吗?”是一个您必须首先回答的 billing-plane 问题。这就是为什么许多 Azure 资产将 subscriptions 视为导入到 Terraform 中,而不是由 Terraform 创建的。
这些平面在实践中如何交织
大多数任务只涉及一个平面,少数任务会涉及多个平面——这也是划分平面的全部意义所在:
- 创建 user、group 或 app registration → 仅限 Entra。
- 部署 VM / VNet / storage account → 仅限资源 (Azure RBAC)。
- 创建 subscription → 账单创建它,它归属于一个 Entra tenant,并成为一个 Azure RBAC 范围。一个操作涉及三个平面。
- 将目录审计日志导出到 Log Analytics workspace → Entra(源)加上资源(目标)。
- Terraform
azurermvsazuread→ 资源 API vs Graph API — 不同的端点,不同的 token 受众。
最后一点具有真正的操作影响:一次登录会针对每个受众生成单独的 tokens(一个用于资源管理器,一个用于 Graph,一个用于 Key Vault)。为某个平面 API 生成的 token 在另一个平面中是无效的。如果您的工具只获取其中一个,那么您的 Terraform 将神秘地出现 401 错误。
“Entra ID”、“tenant”和“directory”(大体上)是同一事物
从不同角度看,三个词指代一个对象,再加上一个改名以迷惑您:
- Entra ID 是产品——身份服务。直到 2023 年,它被称为 Azure Active Directory (Azure AD / AAD),旧名称无处不在:
azureadTerraform provider、AADSTS…错误代码、文档中的“AAD auth”。它们是同一回事。 - tenant 是您组织专用的 Entra ID 实例——容器和信任/隔离边界,由 GUID 和主域标识。Users、groups、apps、Conditional Access 和 licenses 都存在于每个 tenant 中,并且不会跨 tenant。
- directory 是 tenant 的内容——身份对象的数据库。一个 tenant 等于一个 directory,所以人们会互换使用这些词;门户的“Switch directory”按钮实际上是切换 tenants。
接下来的规则是 AWS 类比变得松散的地方:
- 一个 subscription 归属于且仅归属于一个 tenant。 该 tenant 是其身份验证领域并提供其 RBAC 主体。(Subscriptions 可以在 tenants 之间转移;账单是独立的关联。)
- 一个组织可以拥有多个 tenants。 一种常见模式是具有一个锁定生产 tenant 加上一个完全隔离的沙盒 tenant——独立的身份世界,在一个 tenant 中的操作不会影响另一个。AWS 没有“同一公司下第二个完全独立的身份宇宙”这种一流概念。
- Users 有一个 home tenant,并可以在其他 tenant 中作为 guest (B2B) 存在。 guest 在 guest tenant 中获得一个本地对象 ID,同时保留其home身份。AWS 没有“来自另一个组织目录的 guest user”这种一流概念。
最松散的 AWS 类比:一个 tenant 大致相当于“一个融合了其 Identity Center 目录的 AWS Organization”——除了 subscriptions 仅为身份目的附加到 tenant,而支付则附加到 billing account,并且跨组织 guests 是一个原生概念。
资源组:AWS 所没有的容器
resource group (RG) 是 subscription 内部的一个强制性容器——每个资源都精确地存在于一个 RG 中。这是 AWS 没有等效部分的功能(AWS 的“resource groups”只是保存的标签查询;忽略名称冲突)。
一个 RG 同时具备四种功能:
- RBAC 范围——在一个 RG 上授予 Reader 权限,您就将访问权限精确地限定在了该工作负载。
- 策略范围——在 RG 级别附加治理规则。
- 生命周期单元——删除 RG,其中的所有内容都会随之删除。
- 成本边界——一个自然的开销明细项。
惯用模式是每个工作负载(通常是每个区域)一个 RG,因此一个 RG 成为“此应用程序在此区域的文件夹”。RG 有一个 location,但这只说明其元数据存储在哪里——其资源可以位于其他区域,因此不要过分强调 RG 的 location。
资源 ID 承载上下文,因此名称不必
每个 Azure 资源都有一个完整的 Resource ID,例如 /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.App/containerApps/<name>。Subscription 和 RG 随每个日志记录、审计事件和 API 调用一起传输——与 ARN 的 account 和 region 在 AWS 中所做的工作相同。
命名上的结果与您的 AWS 习惯相反。在 AWS 中,名称通常是您获得的唯一上下文,因此您将所有内容都塞入其中。在 Azure 中,名称应省略范围已编码的信息:qa subscription 中 rg-quest 内名为 aks-quest 的 cluster 已经完全明确,并且相同的 RG/资源名称可以在 dev/qa/prod subscriptions 中安全地重复。只有全局唯一的资源类型(storage accounts、container registries、Key Vaults)才将 org/env/region 重新加入名称中——而这些类型具有严格的长度和字符限制,这就是为什么您会看到 stcwtfstateplatformcus 这样的压缩名称。
(顺便说一句,那个 cus 后缀并非杜撰——它是 Microsoft 自己的 Central US 地理代码,来自 Azure 用于构建 private-endpoint DNS zones 的同一官方表格。eus/eus2 是 East US 和 East US 2。尽早学习地理代码表会带来回报。)
AWS → Azure 快速映射
第一个月请将此表放在身边:
- Organization → 一个 Entra tenant 加上 management groups。身份 (tenant) 和结构 (management groups) 在 Azure 中是独立的事物,而不是一个整体。
- Account → subscription。归属于一个 tenant 以用于身份;通过单独的 billing account 计费。
- SCP(防护机制) → 作用于 management group 范围的 Azure Policy——具有比 deny-only 更丰富的效果(audit、deny、modify、deployIfNotExists)。
- IAM role/policy → RBAC role assignment——(主体、角色、范围)。请记住:没有附加到身份的策略。
- Root-account 超级权限 → 三方拆分:Global Admin(身份)+ elevateAccess(资源)+ billing owner(资金)。没有哪个单一主体一开始就拥有全部三项权限。
- Organizations
CreateAccount→ subscription aliases API + 账单范围——并且仅适用于允许此操作的 billing agreement types。 - IRSA (IAM Roles for Service Accounts) → workload identity federation——相同的 OIDC 理念。
- 基于标签的分组 → resource group——结构化的和强制性的,而不是标签查询。
- 日志中的 ARN → Resource ID(
_ResourceId列)——范围上下文是结构化的,而非名称编码。
Terraform 状态引导,译文
这是一个您的 AWS 运行手册几乎可行,却在第一步就失效的地方。
您熟悉的 AWS 引导流程:在 management account 中冷启动一个状态后端(本地状态,然后将后端迁移到自身),将每个 OU 的后端状态保存在该根后端中,并使用自己的后端创建成员 accounts。使其清晰的不变量是:您始终可以从 root account 进行引导,因为它始终存在并且可以拥有一个 S3 存储桶。
Azure 在创建时就打破了这个不变量。始终存在的对象是tenant——但 tenant 不能拥有资源。存储账户存在于 subscriptions 中,而 subscriptions 诞生于 billing plane。因此,Azure 的“root account”是您指定为 root 的任何 subscription,您必须有意识地指定一个。实际上,大多数 tenants 在注册时都会获得一个 subscription,因此这种并行性大部分成立:AWS 为您提供一个 management account,Azure 为您提供第一个 subscription。
当 subscriptions 已经存在时(常见情况)的翻译流程:
- 一次且仅一次冷启动: 使用本地状态将状态后端部署到您指定的root subscription 中,然后
init -migrate-state到自身。 - 每个 subscription 的后端,状态存储在根后端中: 每个额外的 subscription 的后端组件将其自身的状态绑定到根后端,因此启动它们是一个正常的 apply——不再需要冷启动。
- 每个 subscription 中的所有其他内容都使用该 subscription 自己的后端。
从零开始(使用代码创建 subscriptions),顺序是强制的——root subscription 在前,root 后端在后——因为后端是一个存储账户,而存储账户需要一个 subscription 才能存在。请注意一个鸡生蛋蛋生鸡的问题:azurerm provider 本身需要一个 subscription 上下文,因此在零 subscriptions 的情况下,您通过命令式调用(CLI 或 azapi provider)创建第一个 subscription,然后将其导入 Terraform。
这就是 Azure 真正比 AWS 肌肉记忆更简单的地方:后端在根中加上资源在成员中,不需要 AWS 集线器-辐条信任机制——没有后端 role_arn、没有 provider assume_role、没有双向信任策略。租户根管理组的 Owner 权限继承到每个 subscription 中,因此一个 token 可以在整个租户范围内工作;provider 通过简单地设置 subscription_id 来在 subscriptions 之间“跳跃”;后端只是由 Storage Blob Data Contributor 授权的数据平面 blob 访问。跨 subscription 是一个参数,而不是信任协商。(您稍后将通过自定义角色、PIM 和专用 CI 身份来收紧此操作——但即便如此,它也只是在范围内的角色分配,而非信任策略握手。)如果您想深入研究任一方的代码化,HashiCorp Terraform Authoring & Operations Pro 考试正是围绕这些状态和 provider 模式构建的。
您的 AWS 直觉会积极误导您的四个方面
如果您忘记了其他所有内容,请记住以下几点:
- “管理员”并非全局。 Global Administrator 仅限于身份;在有人授予其资源角色之前,它无法读取 subscription。没有单一的“root”主体。
- 权限附加到范围,而非身份。 不要再在 user 上查找策略——而是在 management group、subscription、resource group 或 resource 上查找角色分配。
- 账单是一个与资源分离的宇宙。 “我可以部署任何东西”并不能说明“我可以创建 subscription”。不同的平面,不同的角色,对
az role assignment list不可见。 - resource group 是承重结构。 它不是一个标签——它是一个 RBAC 范围、一个策略范围和一个删除边界。请有目的地设计您的 RG 布局。
哪些认证深入探讨每个方面
云治理——层次结构、身份、防护机制和状态——是两种云上架构和管理考试的核心,因此备考它们也是让上述概念扎根的最快方法。如果您已经持有 AWS 凭证,那么同一行的 Azure 凭证是您的自然下一步。
在 AWS 方面(您要从其知识体系翻译):
- AWS Certified Cloud Practitioner (CLF-C02) — accounts、IAM 和 Organizations 的基础。
- AWS Certified Solutions Architect – Associate (SAA-C03) — IAM、多账户结构和核心架构。
- AWS Certified Solutions Architect – Professional (SAP-C02) — 大规模多账户 Organizations、SCPs 和跨账户访问。
- AWS Certified Security – Specialty (SCS-C03) — IAM 深度、SCPs 和密钥管理。
在 Azure 方面(您要翻译到的知识体系):
- Microsoft Certified: Azure Fundamentals (AZ-900) — tenants、subscriptions、resource groups 和 RBAC 基础。
- Microsoft Certified: Azure Administrator Associate (AZ-104) — 日常管理平面:RBAC、resource groups、subscriptions 和 Entra 基础。
- Microsoft Certified: Azure Solutions Architect Expert (AZ-305) — management groups、治理和 landing-zone 设计。
- Microsoft Certified: Azure Security Engineer Associate (AZ-500) — Entra ID、RBAC、Azure Policy、Conditional Access 和 Key Vault。
如果您今天已获得 AWS 认证,一条实用的路径是:从 AZ-900 开始映射词汇,然后跳到 AZ-104(它存在于您最常用的资源平面中),再根据您的工作倾向于架构还是安全,添加 AZ-305 或 AZ-500。
总结
Azure 并不比 AWS 难——它只是以不同的方式进行分解。AWS 将身份、资源和账单权限合并到一个平面中,并为您提供一个可以做所有事情的 management account。Azure 有意将这三个关注点分开,这在第一天会让人觉得不便,但到第三个月就会觉得边界清晰。将概念翻译一次——一个平面变为三个,accounts 变为在别处计费的 subscriptions,策略附加到范围而非身份,并且 resource group 是真实结构——剩下的就是词汇问题。通过上面的认证进行练习,那些曾经感觉是武断拒绝的部分将开始被理解为连贯、有意的设计。