Azure Local 部署之 CI/CD 完整文档

一、为什么 Azure Local 需要 CI/CD?

Azure Local(前身 Azure Stack HCI)是超融合基础设施,部署流程涉及数十个 phase、上百个 step

  • Azure 云端准备(Landing Zones / RP / RBAC / Mgmt Infra / IAM)
  • On-Prem 就绪(AD / 网络验证 / 网络配置)
  • 集群部署(硬件 → OS → OS 配置 → Arc → Cluster → Post-Deploy)
  • 运维基础(监控 / BCDR / 安全治理 / 许可)
  • 测试与验证

手工部署 :每个 phase 数小时 → 全流程 20-24 小时 → 容易出错、难复盘、难审计。CI/CD 自动化:每次部署完整审计链(PR + CI run + Approval + Artifact)→ 多环境并行 → 多实例可重复。


二、两种视角对比(Microsoft 官方 vs AzureLocal.Cloud)

|----------------|---------------------------------------------|------------------------------------------------------------------------------------------------------|
| 维度 | Microsoft 官方 | AzureLocal.Cloud 社区 |
| CI/CD 关注重点 | 部署阶段的自动化(portal 走完 → 自动化 release pipeline) | 全生命周期 CI/CD 基础设施(SP / 仓库 / Runner / Pipeline / 环境) |
| 部署入口 | Azure Portal 部署向导 + Template Spec | Azure Portal + ARM Template + Bicep + Terraform |
| 流水线工具 | 推荐 Azure Pipelines(First-party) | GitHub Actions / GitLab CI / Azure DevOps 三选一 |
| IaC 风格 | ARM / Bicep(First-party) | Bicep / Terraform(任选) |
| Runner 模型 | 云托管为主(自托管较少强调) | 强制自托管 Runner(部署到目标订阅,VPN 到 on-prem) |
| 代码仓库 | 官方 Sample 仓库 + QuickStart Templates | 从 AzureLocal Cloud 模板 fork |
| 环境隔离 | portal 提供 Cluster 类型(Standard / Rack Aware) | azr-prod-us / azr-dev-us / azr-staging / azr-prod-eu |
| 审计 | Azure Activity Log + Deployment History | 完整 Git PR / CI Run / Approval 链 |

核心差异 :MS 官方文档是怎么部署一次 的指南;AzureLocal.Cloud 是怎么批量标准化部署的体系。


三、CI/CD 整体架构

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                        CI/CD 流水线架构                          │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐       │
│  │ 源代码仓库    │    │  CI/CD 平台  │    │  Runner      │       │
│  │ (Templates)  │───>│ (GitHub/ADO/ │───>│ (Self-hosted)│       │
│  │  - ARM       │    │  GitLab)     │    │  在目标订阅   │       │
│  │  - Bicep     │    └──────────────┘    │VPN 到 on-prem│       │
│  │  - Terraform │           │            └──────────────┘       │
│  │  - Scripts   │           │                     │             │
│  └──────────────┘           ▼                     ▼             │
│                     ┌──────────────────────────────┐            │
│                     │  目标 Azure 订阅 + on-prem    │            │
│                     │  - Landing Zones             │            │
│                     │  - Azure Local 集群           │            │
│                     │  - 监控 / BCDR / 安全         │            │
│                     └──────────────────────────────┘            │
└─────────────────────────────────────────────────────────────────┘

四、Phase 01: CI/CD Setup(6 个 Task 详解)

来源:Phase 01 - CI/CD Setup(2604 Preview)

Task 01: Bootstrap(Service Principal)

目的:创建 CI/CD 服务主体,让流水线以"非交互式"身份认证到 Azure。

核心操作

复制代码
# 1. 创建 Entra ID App Registration
az ad app create --display-name "azlocal-cicd-sp" \
  --query appId -o tsv

# 2. 创建 Client Secret
az ad app credential reset --id <APP_ID> \
  --append --years 1

# 3. 创建 Service Principal
az ad sp create --id <APP_ID>

# 4. 初始角色(按需逐步加,不要一上来给 Owner)
az role assignment create \
  --assignee <SP_OBJECT_ID> \
  --role "Contributor" \
  --scope /subscriptions/<SUB_ID>

关键原则

  • 不要一上来给 Owner ------ 后续按 Part 2 的 RBAC 设计逐步加
  • Secret 必须用 CI/CD 平台的 Encrypted Secrets 存储
  • 推荐使用 OIDC (GitHub Actions)或 Workload Identity Federation(Azure DevOps)替代静态密钥

Task 02: Create Source Control Project

目的:从模板 fork 一份部署仓库。

命名规范

复制代码
<org-name>-azurelocal

|--------------|--------------------|------------------|
| 组件 | 格式 | 示例 |
| Organization | 小写 + 连字符 | iic |
| Workload | 基础设施类型 | azurelocal |
| 全名 | <org>-azurelocal | iic-azurelocal |

推荐平台

  • Azure DevOps(MS 官方 First-party,最深集成)
  • GitHub(社区最广,OIDC 支持好)
  • GitLab(自带 Container Registry)

模板仓库


Task 03: Configure Project Settings

分支保护(Branch Protection):

  • ✅ Main 分支保护
  • 禁止 Force Push
  • 禁止删除
  • ✅ Pull Request 才能合入

代码审查(Code Review):

  • ✅ 合入前需要审批
  • ✅ 所有 Discussions 必须 resolved
  • ✅ CI 流水线必须跑通才能合入

安全扫描(Security):

  • Secret detection(防密钥泄露)
  • SAST scanning(静态代码扫描)
  • Dependency scanning(依赖漏洞扫描)

Task 04: Create Environments

每个部署目标创建独立环境,示例命名:

|---------------|-------------------|----------|
| 环境 | 说明 | 用途 |
| azr-prod-us | Production US 区域 | 主要生产部署 |
| azr-dev-us | Development US 区域 | 开发测试 |
| azr-prod-eu | Production EU 区域 | 欧洲部署(可选) |
| azr-staging | Staging 环境 | 生产前验证 |

为什么用独立环境

  • 不同环境用不同 RBAC 角色
  • 不同环境用不同变量(生产凭据 vs 测试凭据)
  • 审批流可以按环境设置(prod 需要更多审批人)
  • 部署历史按环境隔离

Task 05: Configure Environment Variables

典型变量

|-------------------------|------------------------|----------|
| 变量 | 用途 | 加密 |
| AZURE_SUBSCRIPTION_ID | 目标订阅 | 否 |
| AZURE_TENANT_ID | Entra ID 租户 | 否 |
| ARM_CLIENT_ID | SP 的 App ID | 否 |
| ARM_CLIENT_SECRET | SP 客户端密钥 | 必须加密 |
| ARM_TENANT_ID | SP 所在租户 | 否 |
| LOCATION | 部署区域(如 eastus) | 否 |
| RESOURCE_GROUP_PREFIX | RG 命名前缀 | 否 |
| DOMAIN_FQDN | AD 域名(如 contoso.com) | 否 |
| LCM_USERNAME | LCM 部署用户名 | 否 |
| LCM_PASSWORD | LCM 密码 | 必须加密 |

⚠️ 强制规则 :所有 secrets 必须用平台 encrypted secrets 存储,禁止明文写在 YAML 里


Task 06: Deploy Runners(关键)

azurelocal-toolkit 仓库的 Terraform 模块:

复制代码
azurelocal-toolkit/terraform/modules/cicd-runner

Runner 部署位置:推荐部署在可访问的Azure Local网络的管理订阅(管理网段)

为什么必须用自托管 Runner

  • 流水线要访问 on-prem 网络(VPN / ExpressRoute)
  • 流水线要部署到 on-prem Azure Local 集群
  • 云托管 Runner 无法满足这两点

Runner 部署示例(Terraform):

复制代码
module "cicd_runner" {
  source  = "AzureLocal/azurelocal-toolkit//terraform/modules/cicd-runner"
  # latest通常会固定版本,如version="1.0.0"
  version = "latest" 
  
  name                = "azlocal-runner"
  resource_group_name = "rg-cicd-runners"
  location            = var.location
  subnet_id           = var.runner_subnet_id
  
  # Runner 注册用的 token
  runner_registration_token = var.runner_registration_token
  
  vm_size = "Standard_D4s_v5"
  
  tags = {
    Environment = "shared"
    ManagedBy   = "terraform"
    Purpose     = "cicd-runner"
  }
}

验证

  • Runner 在源代码平台显示 Online
  • 跑一个 Smoke Test Pipeline 验证能连到目标订阅

五、Phase 02: CI/CD Pipelines(流水线平台选择)

5.1 GitHub Actions(社区最广)

参考:GitHub Actions Guide

优点

  • ✅ OIDC 支持最好(无密钥认证到 Azure)
  • ✅ GitHub Environments 原生支持
  • ✅ 社区 Action 丰富
  • ✅ GitHub Advanced Security(secret scanning / SAST)开箱即用

OIDC 认证示例

复制代码
# .github/workflows/azure-local-deploy.yml
name: Deploy Azure Local

on:
  workflow_dispatch:
    inputs:
      environment:
        type: choice
        options: [azr-dev-us, azr-staging, azr-prod-us]
      cluster_name:
        type: string
        required: true

permissions:
  id-token: write   # OIDC 需要
  contents: read

jobs:
  deploy:
    runs-on: [self-hosted, azure-local]   # 自托管 runner
    environment: ${{ github.event.inputs.environment }}
    steps:
      - uses: actions/checkout@v4
      
      - name: Azure Login (OIDC)
        uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      
      - name: Deploy Landing Zones
        uses: azure/CLI@v1
        with:
          inlineScript: |
            cd terraform/landing-zones
            terraform init
            terraform apply -auto-approve
      
      - name: Deploy Azure Local Cluster
        uses: azure/CLI@v1
        with:
          inlineScript: |
            az deployment sub create \
              --location eastus \
              --template-file arm/azure-local.bicep \
              --parameters @parameters/${{ github.event.inputs.environment }}.json \
              --parameters clusterName=${{ github.event.inputs.cluster_name }}

OIDC 在 Entra ID 端的配置(一次性):

复制代码
# 1. 创建 Entra ID App Registration(同 Task 01)
# 2. 在 App 上添加 Federated Credential
az ad app federated-credential create \
  --id <APP_ID> \
  --parameters '{
    "name": "github-actions-azlocal",
    "issuer": "https://token.actions.githubusercontent.com",
    "subject": "repo:YOUR_ORG/iic-azurelocal:environment:azr-prod-us",
    "audiences": ["api://AzureADTokenExchange"]
  }'

5.2 GitLab CI/CD(自带 Container Registry)

参考:GitLab CI/CD Guide

优点

  • ✅ 自带 Container Registry
  • ✅ 自带 Terraform Module Registry
  • ✅ Self-hosted Runner 集成好
  • ✅ 内置 Secret Management

示例 .gitlab-ci.yml

复制代码
stages:
  - validate
  - plan
  - deploy

variables:
  TF_VERSION: "1.7.0"

validate:terraform:
  stage: validate
  tags: [azure-local-runner]
  script:
    - cd terraform/landing-zones
    - terraform init
    - terraform validate
    - terraform fmt -check

plan:terraform:
  stage: plan
  tags: [azure-local-runner]
  script:
    - cd terraform/landing-zones
    - terraform init
    - terraform plan -out=tfplan
  artifacts:
    paths:
      - terraform/landing-zones/tfplan
    expire_in: 1 day

deploy:azure-local:
  stage: deploy
  tags: [azure-local-runner]
  environment:
    name: $CI_ENVIRONMENT_NAME
  script:
    - az login --service-principal \
        -u $AZURE_CLIENT_ID \
        -p $AZURE_CLIENT_SECRET \
        --tenant $AZURE_TENANT_ID
    - az deployment sub create \
        --location eastus \
        --template-file arm/azure-local.bicep \
        --parameters @parameters/${CI_ENVIRONMENT_NAME}.json
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual

5.3 Azure DevOps Pipelines(MS 官方 First-party)

参考:Azure DevOps Pipelines Guide

优点

  • ✅ 与 Azure Arc / Resource Graph 集成最深
  • ✅ Service Connection 一键创建
  • ✅ Environments 审批流最完善
  • ✅ Azure Deployment Stack 集成

示例 azure-pipelines.yml

复制代码
trigger:
  branches:
    include: [main]
  paths:
    exclude: [README.md]

variables:
  - group: azr-prod-us-variables   # 变量组(从 Library 引用)

stages:
  - stage: Validate
    jobs:
      - job: ValidateBicep
        pool:
          name: 'azlocal-runners'   # 自托管 agent pool
        steps:
          - checkout: self
          - task: AzureCLI@2
            inputs:
              azureSubscription: 'azlocal-prod-serviceconnection'
              scriptType: 'bash'
              scriptLocation: 'inlineScript'
              inlineScript: |
                az bicep build --file arm/azure-local.bicep

  - stage: DeployLandingZones
    dependsOn: Validate
    condition: succeeded()
    jobs:
      - deployment: TerraformApply
        pool:
          name: 'azlocal-runners'
        environment: 'azr-prod-us'
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
                - task: TerraformInstaller@1
                  inputs:
                    terraformVersion: '1.7.0'
                - task: TerraformTaskV4@4
                  inputs:
                    provider: 'Terraform'
                    command: 'init'
                    workingDirectory: 'terraform/landing-zones'
                - task: TerraformTaskV4@4
                  inputs:
                    provider: 'Terraform'
                    command: 'apply'
                    workingDirectory: 'terraform/landing-zones'
                    environmentServiceName: 'azr-prod-us'

  - stage: DeployAzureLocal
    dependsOn: DeployLandingZones
    condition: succeeded()
    jobs:
      - deployment: ARMDeploy
        pool:
          name: 'azlocal-runners'
        environment: 'azr-prod-us'   # 需要审批
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
                - task: AzureResourceManagerTemplateDeployment@3
                  inputs:
                    deploymentScope: 'Subscription'
                    azureSubscription: 'azlocal-prod-serviceconnection'
                    location: 'eastus'
                    templateLocation: 'Linked artifact'
                    csmFile: 'arm/azure-local.json'
                    csmParametersFile: 'parameters/azr-prod-us.json'
                    deploymentMode: 'Incremental'

六、Phase 03: Azure Local 集群部署的具体 IaC

6.1 Microsoft 官方:Azure Portal + Template Spec(azloc-2606)

参考:Deploy an Azure Local instance using the Azure portal

部署入口

复制代码
Azure Portal → Search "Azure Local" → Azure Arc | Azure Local → 
  Get started → Deploy Azure Local → Create instance

Portal 部署 7 个 Step

|----------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------|
| Step | 名称 | 关键参数 |
| 1 | Basics | Subscription / Resource Group / Instance Name / Region / Cluster Options (Standard or Rack aware) / Identity Provider / Machines / Key Vault |
| 2 | Configuration | New configuration / Template Spec / Quickstart template |
| 3 | Networking | Network switch 选项 / Group traffic(Management / Compute / Storage)/ Network intent / VLAN ID / IP allocation |
| 4 | Management | Custom location / Storage account for witness / AD Domain / OU / Deployment account / Local admin |
| 5 | Security | Recommended security settings / Customized |
| 6 | Advanced | Workload volumes / Infrastructure volumes only / Use existing data drives |
| 7 | Tags | Tag 配置 |

Template Spec 模式(自动化友好)

在 Portal 第 2 步 Configuration 选 Template Spec,从订阅里加载已存好的部署模板。这样 CI/CD 流水线里可以预先把 Template Spec 推到订阅里,再触发 Portal 部署 / CLI 部署。

关键 OU 规则(MS 官方):

  • OU 不能是顶层域 ,必须至少有 1 级 OU(如 OU=Local001,DC=contoso,DC=com
  • 部署账户:用准备 AD 时创建的账户(MS 官方 New-HciAdArtifactsPreCreationTool 那个)
  • 本地管理员密码:≥ 14 字符 + 小写 + 大写 + 数字 + 特殊字符

6.2 ARM Template / Bicep(azloc-2606)

核心资源类型

复制代码
// 示例 Bicep 模板 - Azure Local 集群定义
targetScope = 'subscription'

@minLength(3)
@maxLength(12)
param clusterName string

@allowed(['eastus', 'westus2', 'westeurope'])
param location string = 'eastus'

param deploymentUser string
@secure()
param deploymentPassword string
@secure()
param localAdminPassword string

param domainFqdn string   // 如 contoso.com
param ouPath string       // 如 OU=Local001,DC=contoso,DC=com
param keyVaultId string
param storageAccountId string   // cloud witness

// Azure Local 集群定义, @2024-09-01-preview改为当前正式支持的API Version
resource azureLocalCluster 'Microsoft.AzureStackHCI/clusters@2024-09-01-preview' = {
  name: clusterName
  location: location
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    managedByResourceGroup: 'rg-${clusterName}-managed'
    deploymentSettings: {
      deploymentUser: {
        principalName: deploymentUser
        password: deploymentPassword
      }
      deploymentMode: 'Deploy'
      clusterDefinition: {
        kind: 'Standard'   // or 'RackAware'
        clusterVersion: '2503'  //改为当前支持的版本或参数化配置,如当前最新是2606
        ...
      }
      ...
    }
    azureLogicalNetwork: { ... }
    networkIntents: [
      {
        name: 'Compute_Management'
        adapters: ['ethernet 1', 'ethernet 2']
        trafficType: 'ManagementCompute'
      }
      {
        name: 'Storage'
        adapters: ['ethernet 3', 'ethernet 4']
        trafficType: 'Storage'
        vlanId: 711
      }
    ]
    secretOperations: {
      secretSource: {
        keyVaultId: keyVaultId
      }
      ...
    }
  }
}

6.3 Azure CLI 自动化(azloc-2606)

复制代码
# 1. 登录
az login --service-principal \
  -u $AZURE_CLIENT_ID \
  -p $AZURE_CLIENT_SECRET \
  --tenant $AZURE_TENANT_ID

# 2. 创建资源组
az group create --name "rg-${CLUSTER_NAME}" --location eastus

# 3. 创建 Azure Local 集群(通过 ARM Template / Bicep)
az deployment sub create \
  --location eastus \
  --template-file ./arm/azure-local.bicep \
  --parameters \
      clusterName=${CLUSTER_NAME} \
      deploymentUser=${LCM_USER} \
      deploymentPassword=${LCM_PASSWORD} \
      localAdminPassword=${LOCAL_ADMIN_PASSWORD} \
      domainFqdn=${DOMAIN_FQDN} \
      ouPath=${OU_PATH} \
      keyVaultId=${KEYVAULT_ID} \
      storageAccountId=${STORAGE_ACCOUNT_ID}

# 4. 查询部署状态
az deployment sub show --name <deployment-name>

七、AzureLocal.Cloud 8-Part 流水线(完整 view)

来源:Implementation Guide + Automation Guide

复制代码
Part 1: CI/CD 基础设施         ← Phase 01 (本文重点)
Part 2: CI/CD Pipelines        ← GitHub Actions / GitLab / Azure DevOps
Part 2: Azure 云端基础(5 phase)
  ├─ Phase 1: Landing Zones
  ├─ Phase 2: Resource Providers
  ├─ Phase 3: RBAC Permissions
  ├─ Phase 4: Azure Management Infrastructure
  └─ Phase 5: Identity & Access Management
Part 3: On-Premises Readiness(3 phase)
  ├─ Phase 01: Active Directory Preparation
  ├─ Phase 02: Enterprise Network Readiness Validation
  └─ Phase 03: Network Infrastructure Configuration
Part 4: Cluster Deployment(6 phase)
  ├─ Phase 1: Hardware Provisioning & BIOS/iDRAC
  ├─ Phase 2: OS Installation
  ├─ Phase 3: OS Configuration
  ├─ Phase 4: Arc Registration
  ├─ Phase 5: Cluster Deployment
  └─ Phase 6: Post-Deployment Configuration
Part 5: Operational Foundations(5 phase)
  ├─ Phase 1: SDN Integration
  ├─ Phase 2: Monitoring & Observability
  ├─ Phase 3: Backup & DR
  ├─ Phase 4: Security & Governance
  └─ Phase 5: Licensing & Telemetry
Part 6: Cluster Testing & Validation

每个 Part/Phase 都有自己的 Runbook + 对应的 CI/CD Pipeline。


八、关键交付物清单(Key Deliverables)

|-------|------------------------------|-------------------|----------------------------|
| # | 交付物 | Task | 来源 |
| 1 | CI/CD Service Principal | Task 01 | azurelocal.cloud |
| 2 | 源代码控制项目 | Task 02 | azurelocal.cloud |
| 3 | 项目安全设置 | Task 03 | azurelocal.cloud |
| 4 | 部署环境 | Task 04 | azurelocal.cloud |
| 5 | 环境变量 | Task 05 | azurelocal.cloud |
| 6 | 自托管 Runner | Task 06 | azurelocal.cloud |
| 7 | Landing Zones(云端基础) | Part 2 Phase 1 | 双视角 |
| 8 | Resource Providers 注册 | Part 2 Phase 2 | 双视角 |
| 9 | RBAC 权限模型 | Part 2 Phase 3 | 双视角 |
| 10 | Template Spec / ARM Template | MS Portal / Bicep | MS 官方 |
| 11 | Azure Local 集群资源 | Part 4 Phase 5 | 双视角 |
| 12 | 部署审计日志 | 全程 | MS Activity Log + Git PR 链 |


九、验证清单(Validation Checklist)

  • CI/CD Service Principal 已创建(带正确 RBAC)
  • 源代码项目已创建(命名符合 <org>-azurelocal 规范)
  • 分支保护 + Code Review + 安全扫描已配置
  • 部署环境已创建(prod / dev / staging / eu)
  • 环境变量已配置(所有 secrets 加密)
  • CI/CD Runner 已部署并注册
  • Runner 在平台显示 Online
  • Test Pipeline 跑成功
  • Landing Zones 部署成功
  • Resource Providers 已注册
  • RBAC 权限模型完整
  • Azure Local 集群部署成功
  • Arc 注册成功
  • AD 集成验证(LCM 账户可用)
  • 部署审计完整(PR / CI Run / Approval / Activity Log)

十、关键命令速查

10.1 创建 SP(OIDC 友好)

复制代码
APP_ID=$(az ad app create --display-name "azlocal-cicd-sp" --query appId -o tsv)
az ad sp create --id $APP_ID
az ad app federated-credential create \
  --id $APP_ID \
  --parameters "{
    \"name\": \"github-oidc\",
    \"issuer\": \"https://token.actions.githubusercontent.com\",
    \"subject\": \"repo:YOUR_ORG/iic-azurelocal:ref:refs/heads/main\",
    \"audiences\": [\"api://AzureADTokenExchange\"]
  }"

10.2 部署 Azure Local 集群

复制代码
az deployment sub create \
  --location eastus \
  --template-file arm/azure-local.bicep \
  --parameters @parameters/azr-prod-us.json

10.3 查询集群状态

复制代码
az azurestackhci cluster show --name <cluster-name> --resource-group <rg-name>
az azurestackhci cluster show --name <cluster-name> --resource-group <rg-name> --query "properties.status"

10.4 Arc 注册验证

复制代码
# 在 Azure Local 节点上
Get-AzureStackHCI

10.5 部署历史

复制代码
# Azure Activity Log
az monitor activity-log list --resource-group <rg-name> --max-events 50

十一、暗坑清单

|-------|--------------------------------------|-------------------------------------------------|
| # | 坑点 | 怎么避 |
| 1 | 用个人账户跑流水线 | 强制用 SP / OIDC / Workload Identity |
| 2 | Main 分支允许 force push | 严格分支保护 |
| 3 | Secrets 明文写在 YAML | 平台 encrypted secrets / Key Vault 引用 |
| 4 | 云托管 Runner 访问不到 on-prem | 必须自托管 Runner + VPN/ER |
| 5 | SP 在 Part 1 给 Owner 全权 | Part 1 只建 SP,权限按 RBAC 逐步加 |
| 6 | 没建 staging 环境 | 至少 prod + dev + staging |
| 7 | Runner 部署在云端,没法连 on-prem | Runner 在管理订阅 + VPN/ER 到 on-prem |
| 8 | Template Spec 用错 Location | Template Spec 必须和目标资源 location 一致 |
| 9 | OU 写在最顶层 | OU 必须至少有 1 级(如 OU=Local001,DC=contoso,DC=com) |
| 10 | Key Vault 用了 Private Endpoint | 使用 Private Endpoint 时需保证网络与 DNS 可达 |
| 11 | Storage Intent 自定义 IP | Portal 不支持自定义 storage IP,要用 ARM Template |
| 12 | 未启用 secret scanning | 启用平台内置 secret detection |
| 13 | Cluster 类型选错(Standard vs Rack Aware) | 物理部署前确认硬件拓扑 |
| 14 | LCM 密码 < 14 字符 / 复杂度不够 | 强制 ≥ 14 + 四类字符 |


十二、参考链接

Microsoft 官方

AzureLocal.Cloud 社区

相关 GitHub Actions / IaC 工具