Azure Local 离线模式 Azure CLI 配置(系列篇十一)

Azure Local 离线模式 Azure CLI 配置 Runbook(生产级)

适用场景:Azure Local + Azure CLI Disconnected Operations 文档定位:可直接用于生产执行的 Runbook(工程 SOP) 来源:Use Azure CLI for Disconnected Operations for Azure Local
体例说明:本 Runbook 用 3 类标签组织:

  • 执行步骤(必须按顺序完成)
  • 故障模式(已知问题与排查方向)
  • 💡 Best Practice(仅 production hardening,不重复官方内容)

理论推断统一收纳到末尾"🔍 Technical Analysis(Including Inferred Behavior)"------不混入执行步骤。


0. 执行前置条件(Pre-flight Checklist)

✔ 必须满足

  • Azure Local appliance 已部署完成
  • 已存在:
    • Appliance Root CA(applianceRoot.cer
    • Local portal FQDN(例:autonomous.cloud.private
  • 已具备:
    • LocalMachine 管理员权限
    • 离线软件分发路径(SMB / ISO / Repo)

⚠ 风险检查(部署前签字)

|--------------------------------|--------|
| 项目 | 状态 |
| Root CA 已导入 | ⬜ |
| CLI 版本已确认 | ⬜ |
| 离线 extension 源已就绪 | ⬜ |
| Cloud config FQDN 已与 portal 一致 | ⬜ |


1. 安装 Azure CLI(统一 64-bit)

✔ 执行步骤

Step 1:从内网镜像源下载官方 64-bit MSI

Step 2:静默安装

复制代码
msiexec /i AzureCLI.msi /quiet

或标准安装:

复制代码
# 官方 MSI(64-bit only)
# https://aka.ms/install-azure-cli-windows

✔ 验证

复制代码
az version

期望输出

复制代码
azure-cli: 2.81.0

⚠ 故障模式

|------------------------|-----------------------|---------------------|
| 问题 | 原因 | 排查 |
| az command not found | PATH 未刷新 | 重启 shell / 重新登录 |
| CLI version mismatch | 装错 MSI(32-bit / 旧版) | 重装 64-bit 官方 MSI |
| extension load fail | architecture mismatch | 32-bit 卸载,统一 64-bit |

💡 Best Practice

  • 所有节点统一 64-bit CLI
  • 禁止混用 32-bit CLI
  • 离线环境不要 az upgrade------直接重新装新版 MSI

2. 安装 CA 信任链(企业级标准)

✔ 执行步骤

Step 1 :导入根 CA 到 OS Trust Store(唯一推荐方式

复制代码
Import-Certificate `
    -FilePath "C:\AzureLocal\applianceRoot.cer" `
    -CertStoreLocation Cert:\LocalMachine\Root

Step 2 :安装 pip-system-certs(让 Python 走 OS trust store)

复制代码
& "C:\Program Files\Microsoft SDKs\Azure\CLI2\python.exe" `
    -m pip install pip-system-certs

✔ 验证

复制代码
Get-ChildItem Cert:\LocalMachine\Root |
    Where-Object { $_.Subject -like "*Azure*" }

期望:看到 appliance root CA 出现在列表中。

⚠ 故障模式

|-----------------|------------------------|-------------------|
| 问题 | 影响 | 修复 |
| 未导入 CA | az login TLS failure | 重新 import |
| 仅改 cacert.pem | upgrade 后失效 | 改回 OS trust store |
| 多节点不一致 | 部署漂移 | GPO / Intune 统一分发 |

💡 Best Practice(关键)

  • 唯一推荐方式:OS Trust Store + GPO / Intune 分发
  • 禁止 :修改 certifi/cacert.pem

3. 配置 Azure CLI Cloud(Disconnected Cloud)

✔ 执行步骤

Step 1:加载 OperationsModule

复制代码
Import-Module "<OperationsModule>\Azure.Local.DisconnectedOperations.psd1"

Step 2 :生成 cloud config(参数以 module introspection 为准

复制代码
$cloudConfig = Get-ApplianceAzCliCloudConfig `
    -ExternalFqdn "autonomous.cloud.private"

⚠️ 不要硬编码 其他参数------用 Get-Help Get-ApplianceAzCliCloudConfig -Full 查实际参数集。

Step 3:写入配置

复制代码
$cloudConfig | Set-Content "$env:APPDATA\Azure\myCloud.json"

Step 4:应用 cloud

复制代码
az cloud set --cloud-config "$env:APPDATA\Azure\myCloud.json"
az cloud show

✔ 验证

复制代码
az cloud list

期望 :当前 cloud = custom disconnected cloud,endpoints 全部指向本地 FQDN。

⚠ 故障模式

|--------------------------|-------------------------|---------------------|
| 问题 | 原因 | 排查 |
| login 仍走 azure.com | cloud 未 set | 重新 az cloud set |
| endpoint resolution fail | FQDN 不匹配 portal | 比对 portal 实际 FQDN |
| JSON schema error | module version mismatch | 升级 OperationsModule |

💡 Best Practice

  • Cloud config 当成不可解析配置文件------不要复制字段名当 schema
  • 必须纳入 CMDB / Git version control------多节点共享同一份
  • 每次升级 OperationsModule 后重新生成 cloud config

4. 登录验证(Disconnected Login)

✔ 执行步骤

复制代码
az login --use-device-code

浏览器打开显示的 URL,在本地 portal 输入 device code 完成认证。

✔ 验证

复制代码
az account show

期望:返回包含本地 subscription 的 JSON。

⚠ 故障模式

|--------------------------------|---------------------|----------------------------------------|
| 问题 | 原因 | 排查 |
| device code fail | portal endpoint 不可达 | Test-NetConnection <portal FQDN> 443 |
| login redirect to public cloud | cloud config error | 重新跑 §3 |


5. 安装 Azure CLI Extensions(离线模式)

✔ 执行步骤

不允许直接 online install(离线下会失败)

Step 1:在能联网的镜像机上下载

复制代码
az extension add -n aksarc
az extension add -n stack-hci-vm
az extension add -n customlocation

Step 2:复制 extension 目录到内网分发路径

复制代码
%USERPROFILE%\.azure\cliextensions\

Step 3:在离线节点安装

复制代码
az extension add --source <local-path>

✔ 验证

复制代码
az extension list

期望 :列出 3 个 extension,状态为 Installed

⚠ 故障模式

|---------------------|-----------------|-------------------------------------|
| 问题 | 原因 | 排查 |
| extension not found | repo missing | 检查分发路径 |
| version conflict | CLI 不兼容 | 升级 / 降级 CLI |
| module load fail | corrupted cache | az extension remove -n <name> 后重装 |

💡 Best Practice

  • 不写死版本号------extension 版本会随 Azure Local release train 变化
  • 内网镜像机每月同步一次最新 extension 索引

6. CLI 升级(离线模式)

❗ 关键约束

az upgrade 在离线环境不可直接使用 ------会拉 https://aka.ms/... 失败。

✔ 正确流程

Step 1:从内网 mirror repo 下载新版 MSI

Step 2:静默升级安装

复制代码
msiexec /i AzureCLI.msi /quiet

Step 3:重启 shell,重新加载

✔ 验证

复制代码
az version

期望azure-cli 字段显式显示新版本号(不是缓存旧值------这是"假升级"陷阱)。

⚠ 故障模式

|-------------------|---------------|--------------------------------|
| 问题 | 原因 | 排查 |
| upgrade no effect | cached CLI | 重启 shell / where.exe az 确认路径 |
| extension broken | version drift | 重新装匹配版本的 extension |


7. 健康检查(Post-Install Validation Gate)

✔ 必须全部通过

复制代码
az version
az cloud show
az account show
az extension list

✔ 成功标准

|-----------|-------------------------------------|
| 项目 | 条件 |
| CLI | 2.81.0(或当前文档版本) |
| cloud | custom disconnected cloud |
| login | az account show 返回本地 subscription |
| extension | 全部 Installed |

4 项检查全部通过 才能认为 CLI 配置完成------任一失败不能进入下一阶段。


8. Failure Recovery(恢复路径)

❌ Cloud misconfiguration

复制代码
az cloud set --name AzureCloud
# 重新生成 cloud config(参考 §3)

❌ CA failure

复制代码
# 删除错误 cert
Get-ChildItem Cert:\LocalMachine\Root | Where-Object { ... } | Remove-Item
# 重新 import
Import-Certificate -FilePath "C:\AzureLocal\applianceRoot.cer" -CertStoreLocation Cert:\LocalMachine\Root

❌ Extension corruption

复制代码
az extension remove -n <name>
# 重新 copy 离线包
az extension add --source <local-path>

❌ CLI 假升级(缓存旧版)

复制代码
where.exe az
# 确认实际加载的 CLI 路径
# 删除旧 MSI 残留,重装新版

9. 最终架构总结(理解层)

复制代码
         User CLI
            ↓
   Azure CLI Runtime (Python)
            ↓
   Cloud Config (custom endpoint)
            ↓
   OS Trust Store (CA chain)
            ↓
   Azure Local Control Plane

一句话总结 :这套 Runbook 的本质是 把 Azure CLI 从"云 CLI"变成"本地控制平面客户端"



🔍 Technical Analysis(Including Inferred Behavior)

本节是 Runbook 推理依据的存档------所有"为什么这么做"都在这里。不混入执行步骤

A. CLI 与架构选择

A.1 为什么统一 64-bit

官方从未说 Azure Local 禁止 32-bit,但也不支持 32-bit 作为推荐路径

32-bit 不是 hard failure ,而是 unsupported + untested

  • 32-bit Azure CLI 实际可装、可运行
  • 不在 Microsoft 测试矩阵
  • 可能引入兼容性 / 内存 / extension 加载问题

企业部署原则:按 supported 路径走,不赌 untested 边缘场景。

A.2 32-bit 实际风险(不是技术禁止)

  • Python 32-bit 内存上限(典型 2 GB)------ 大型 ARM 调用可能 OOM
  • Extension 兼容性矩阵窄
  • 32-bit MSI 不是 Microsoft 在 Azure Local 场景的推荐路径

结论 :技术上不"禁止",但工程上不推荐------Runbook 不应该把"unsupported"包装成"禁止"。

B. CA 信任链

B.1 pip-system-certs 的真实作用范围

pip-system-certs 只影响 Python requests 的 HTTP 调用。

关键点

  • Python-based extension → 受影响 ✔
  • Go / .NET / native binary extension不受影响
  • WinHTTP / Schannel 路径不受影响

因此 OS trust store + pip-system-certs增强信任不是完全替代 trust chain ------但已经是最稳妥的方案。

B.2 完整 CA 信任链路(企业部署应全部覆盖)

|---------------------------------------|---------------------------------------|
| 信任层 | 是否受 pip-system-certs 影响 |
| OS trust store(LocalMachine\Root) | OS 层 + 多数 native TLS |
| Python requests 信任 | ✔(通过 pip-system-certs) |
| CLI extension 内部 native TLS | ❌(自行保证) |
| Embedded tools(K8s client、Arc bridge) | ❌(走各自 trust chain) |
| 浏览器(用于本地 portal) | 系统级,OS trust store 已覆盖 |

缺失任一环节都可能导致部分功能 SSL 失败

B.3 为什么禁止改 cacert.pem

|------------------|------------------------------------|
| 风险 | 说明 |
| az upgrade 覆盖 | CLI 升级时 cacert.pem 被重置 |
| pip upgrade 重置 | 任何包管理操作都可能 drift |
| 配置漂移 | 多节点场景下很快不一致 |
| 审计风险 | 标为 enterprise security baseline 偏离 |

C. Extension 与 Versioning

C.1 Extension 版本是 release-train 绑定

  • stack-hci-vm / aksarc / customlocation 强依赖 Azure Arc / Azure Local release train
  • 经常月更甚至周更
  • 不存在 "跨文档统一推荐版本"
  • VM 文档与 AKS 文档给的版本经常不一致------优先以最新文档为准

C.2 Extension 解析源(implementation-dependent)

⚠️ extension resolution 取决于 configured source------不是固定机制:

可能是以下之一(或组合):

  • Azure endpoint(az extension add 默认)
  • Arc resource provider feed
  • local cache(离线环境)
  • custom repo(内网镜像)

不要在文档中固化 "Appliance 内置 extension 索引"这种说法------它不是稳定公开机制

C.3 Get-ApplianceAzCliCloudConfig 的版本漂移

官方没说"参数会变化"------但 OperationsModule 是 Microsoft 持续更新的组件。

真实风险

  • 字段命名 / 必需参数可能随版本调整
  • 输出 JSON schema 可能更新
  • 甚至 function itself may be replaced across module versions(更激进的版本变化)

应对

  • 不要把生成的 JSON 当成"稳定 API"
  • 每次升级 OperationsModule 后重新跑 Get-Help

D. CLI 升级与"假升级"风险

D.1 Air-gapped 下 az upgrade 的陷阱

  • Air-gapped 模式下 az upgradehttps://aka.ms/... 会失败
  • 部分 CLI 工具会静默 fallback 到本地缓存版本
  • 表面看 az version 没变------实际你以为升级了,但没有

验证 :升级后 az version 必须显式显示新版本号,否则视为升级失败。

D.2 正确的离线升级路径

|--------|----------------------------------|
| 步骤 | 操作 |
| 1 | 内网 mirror repo 下载新版 MSI |
| 2 | msiexec /i AzureCLI.msi /quiet |
| 3 | 重启 shell |
| 4 | where.exe az 确认路径 |
| 5 | az version 显式验证 |

E. Cloud Config 的实际语义

  • Azure Local disconnected environment 确实需要 custom cloud definition
  • endpoint override 指向本地 portal 的 ingress FQDN
  • 这是离线场景的核心 ------没有这一步,az login 会去找 management.azure.com 然后失败

F. 跨版本兼容性

官方没给出"完整兼容矩阵"------但可以从 release train 推断:

|---------------------------|-------------------------|
| 组件 | 升级顺序 |
| Azure Local release notes | 起点 |
| Appliance build | 配套 |
| OperationsModule | 配套 |
| CLI | 与 OperationsModule 兼容 |
| extension | 绑定到 CLI + release train |

生产升级顺序

  1. 升级前:看 Azure Local release notes
  1. CLI → 2. extension → 3. OperationsModule → 4. Appliance
  1. 逐项验证------不要跨大版本

G. 为什么离线下 az login --use-device-code 是关键

  • --use-device-code 不要求本地有浏览器
  • 用户在任何能访问 local portal 的机器上输入 code 即可
  • 这正是离线场景的登录模式 ------az login 走 local portal,认证回调走 device code

H. 文档未明确的边界(汇总)

|-------------------------------------|-----------------------------------|
| 文档没说 | Runbook 推断 |
| 是否能装 32-bit | unsupported + untested,按 64-bit 走 |
| cacert.pem 修改的后果 | drift / 升级丢失 / 审计风险,禁止 |
| extension source 机制 | implementation-dependent,看内网配置 |
| Get-ApplianceAzCliCloudConfig 稳定性 | 每次升级重新跑 Get-Help |
| az upgrade 离线行为 | 静默 fallback,必须显式验证 |

相关推荐
XUHUOJUN3 小时前
Azure Local离线模式注册(系列篇之十)
dell·azure local
XUHUOJUN1 天前
Azure Local离线模式PKI规划(系列篇之五)
microsoft·azure local