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)
- Appliance Root CA(
- 已具备:
- 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⚠ 故障模式
问题 | 原因 | 排查 |
| 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\RootStep 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 |
| 重新 import |
仅改 | 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 仍走 | 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 不可达 |
|
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 customlocationStep 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 |
|
💡 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 /quietStep 3:重启 shell,重新加载
✔ 验证
az version期望:azure-cli字段显式显示新版本号(不是缓存旧值——这是"假升级"陷阱)。
⚠ 故障模式
问题 | 原因 | 排查 |
upgrade no effect | cached CLI | 重启 shell / |
extension broken | version drift | 重新装匹配版本的 extension |
7. 健康检查(Post-Install Validation Gate)
✔ 必须全部通过
az version az cloud show az account show az extension list✔ 成功标准
项目 | 条件 |
CLI |
|
cloud |
|
login |
|
extension | 全部 |
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.1pip-system-certs的真实作用范围
pip-system-certs只影响 Pythonrequests库的 HTTP 调用。关键点:
- Python-based extension→ 受影响 ✔
- Go / .NET / native binary extension→不受影响❌
- WinHTTP / Schannel 路径→不受影响❌
因此 OS trust store +
pip-system-certs是增强信任,不是完全替代 trust chain——但已经是最稳妥的方案。
B.2 完整 CA 信任链路(企业部署应全部覆盖)
信任层 | 是否受 |
OS trust store(LocalMachine\Root) | OS 层 + 多数 native TLS |
Python | ✔(通过 |
CLI extension 内部 native TLS | ❌(自行保证) |
Embedded tools(K8s client、Arc bridge) | ❌(走各自 trust chain) |
浏览器(用于本地 portal) | 系统级,OS trust store 已覆盖 |
缺失任一环节都可能导致部分功能 SSL 失败。
B.3 为什么禁止改cacert.pem
风险 | 说明 |
| CLI 升级时 |
| 任何包管理操作都可能 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.3Get-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 upgrade拉https://aka.ms/...会失败
- 部分 CLI 工具会静默 fallback到本地缓存版本
- 表面看
az version没变——实际你以为升级了,但没有验证:升级后
az version必须显式显示新版本号,否则视为升级失败。
D.2 正确的离线升级路径
步骤 | 操作 |
1 | 内网 mirror repo 下载新版 MSI |
2 |
|
3 | 重启 shell |
4 |
|
5 |
|
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 |
生产升级顺序:
- 升级前:看 Azure Local release notes
- CLI→ 2.extension→ 3.OperationsModule→ 4.Appliance
- 逐项验证——不要跨大版本
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 走 |
| drift / 升级丢失 / 审计风险,禁止 |
extension source 机制 | implementation-dependent,看内网配置 |
| 每次升级重新跑 |
| 静默 fallback,必须显式验证 |