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

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

⚠ 故障模式

问题

原因

排查

azcommand 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 loginTLS 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.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 信任链路(企业部署应全部覆盖)

信任层

是否受pip-system-certs影响

OS trust store(LocalMachine\Root)

OS 层 + 多数 native TLS

Pythonrequests信任

✔(通过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.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 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,必须显式验证