Skip to content

Commit d6c172f

Browse files
design: ADR 0011 L3 scope + signal catalog expansion (physical disk, storage pool size/reserve, physical NIC/RDMA, Arc agent local checks, extension probes, cluster network)
- ADR 0011: defines two-tier L3 strategy - Tier A (agent-local): HIMDS/GCArcService state, Arc connection registry, heartbeat event log, AMA/DCMA/ExtensionManager service state, extension installation registry probes — all collected by SCOM agent, no ARM required - Tier B (management server ARM probes): HCI cluster ARM state, KV expiry, RBAC drift, SPN expiry — Limited impact by default, upgradeable via override - signal-catalog.md expanded with: - Physical Disk subsection (HealthStatus, OperationalStatus, Retired, Lost, PredictiveFailure, reserve policy, retired capacity %) - Storage Pool: added Size.TiB, AllocatedSize.Percent, FreeSpace.TiB, RetiredCapacity.TiB, Reserve.Policy, FaultDomain.Count, tier drive count - Volume: added Size.TiB, AllocatedSize.TiB, Write.Latency, Dedup - Physical NIC & RDMA subsection (per-NIC status, RDMA, LinkSpeed, Driver, RSS, PFC, ETS, Cluster.Network.State, LiveMigration network) - Arc agent locally observable (ADR 0011 Tier A): HIMDS, GCArcService, connection status registry, heartbeat event log age, ExtensionManager, GuestConfigAgent - Arc extensions (ADR 0011 Tier A): AMA, DCMA, OsSettings installed + service state + version, HCI registration, DCMA upload age - scope-topology.md: added AzureLocal.PhysicalDisk (hosted by StoragePool) and AzureLocal.NetworkAdapter (hosted by NetworkIntent); updated entity count to ~27; updated Mermaid diagram; added ADR 0011 Tier A note to L2 - decisions/index.md: ADR 0011 row added - PLAN.md: ADR 0011 checked, signal catalog expansion noted, Phase 3 authoring tasks expanded to cover new classes and Tier A/B monitor split
1 parent d17595b commit d6c172f

5 files changed

Lines changed: 339 additions & 31 deletions

File tree

PLAN.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,10 @@ Every threshold, alert severity, and behavior is **parameterized** so customers
335335
- [x] ADR 0008 — Customization strategy (sealed MP + override pack tiers; Bicep params + tiers) — Accepted
336336
- [x] ADR 0009 — Alert vs health-state separation policy — Accepted
337337
- [x] ADR 0010 — Cloud-side prerequisites contract (HCI Insights, AMA, DCMA, Service Group, RBAC, networking) — Accepted
338+
- [x] ADR 0011 — L3 Azure-side scope: agent-local Arc health checks (Tier A) vs. management server ARM probes (Tier B) — Accepted
338339
- [x] Build full structural inventory tables in `docs/design/`
339-
- [x] Component inventory (~25 entities across 3 layers) — `scope-topology.md`
340-
- [x] Signal inventory (~60 signals × dimensions × thresholds × source) — `signal-catalog.md`
340+
- [x] Component inventory (~27 entities across 3 layers — updated with `AzureLocal.PhysicalDisk`, `AzureLocal.NetworkAdapter`, Arc agent Tier A group) — `scope-topology.md`
341+
- [x] Signal inventory (~90+ signals × dimensions × thresholds × source — expanded with physical disk health, storage pool size/reserve/retired, volume size detail, physical NIC/RDMA, Arc agent local checks, extension installation probes, cluster network state) — `signal-catalog.md`
341342
- [x] SCOM ↔ Azure Monitor concept mapping table — `concept-mapping.md`
342343
- [x] Cloud-side prerequisites table — `azure-monitor/prerequisites.md`
343344
- [x] Complete draw.io diagrams (replace Phase 1 stubs with real visuals)
@@ -349,13 +350,17 @@ Every threshold, alert severity, and behavior is **parameterized** so customers
349350
### Phase 3 — Track 1: SCOM MP Authoring
350351
- [ ] Watch/review Brian Wren's SC 2012 R2 video series (23 modules) as primary authoring reference — see [Brian Wren Resources](#brian-wren--mpauthor-resources) below
351352
- [ ] Set up VSAE project + fragment library references (Kevin Holman fragments)
352-
- [ ] Define Azure Local classes (Cluster, Node, Storage Pool, Volume, VM) in XML
353-
- [ ] Author WMI discovery rules for each class
354-
- [ ] Author unit monitors (availability + performance + configuration)
355-
- [ ] Wire aggregate monitors (4 standard + custom rollups)
353+
- [ ] Define Azure Local classes (Cluster, Node, Storage Pool, StorageTier, Volume, Network Intent, **Physical Disk**, **Network Adapter**) in XML — see `docs/design/scope-topology.md` for full class list
354+
- [ ] Author PowerShell discovery rules for each class (including hosted `AzureLocal.PhysicalDisk` from `Get-PhysicalDisk` and `AzureLocal.NetworkAdapter` from `Get-NetAdapter`/`Get-NetAdapterRdma`)
355+
- [ ] Author unit monitors — coverage per signal-catalog.md:
356+
- [ ] L1 availability + performance monitors (Cluster, Node, Storage Pool, Volume, Storage Tier, Physical Disk, Network Intent, Network Adapter, Storage Replica, LCM)
357+
- [ ] L2 Tier A "Arc agent local checks" monitors (HIMDS service, connection status, heartbeat age, extension installation — no ARM required, runs on SCOM agent)
358+
- [ ] L2 DCMA + AKS Arc monitors
359+
- [ ] L3 Tier B ARM probe monitors (HCI Cluster resource, KV expiry, RBAC drift, SPN expiry — management server only, Limited impact by default)
360+
- [ ] Wire aggregate monitors (4 standard + custom rollups for Physical Disk → StoragePool, NetworkAdapter → NetworkIntent)
356361
- [ ] Wire dependency monitors between classes
357362
- [ ] Create Distributed Application for Azure Local
358-
- [ ] Create override companion pack
363+
- [ ] Create override companion pack (including Tier B Limited → Standard impact overrides for L3 ARM probes)
359364
- [ ] Run MP Best Practice Analyzer + MPVerify
360365
- [ ] Test in pre-production SCOM environment
361366

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
# ADR 0011 — L3 Azure-side scope: agent-local checks vs. management server ARM probes
2+
3+
- **Status**: Accepted
4+
- **Date**: 2026-05-05
5+
- **Deciders**: @AzureLocal/azurelocal-scom-mp-maintainers
6+
7+
## Context
8+
9+
[ADR 0001](0001-scope-and-topology.md) defines three layers. [ADR 0004](0004-scom-discovery-strategy.md)
10+
says L3 is discovered from a designated management server using `Az` PowerShell modules. But it
11+
doesn't answer the harder question this project must resolve before Phase 3 authoring:
12+
13+
> **Which "Azure-side" signals actually require connecting to Azure, and which can be
14+
> checked locally from the SCOM agent on the cluster node?**
15+
16+
This matters because:
17+
18+
- The SCOM agent on each Azure Local node is a standard Windows agent. It **can** make
19+
outbound HTTPS calls, but doing so from every node on every monitoring interval
20+
contradicts the SCOM architecture (agents monitor local state; management servers
21+
proxy external calls).
22+
- Azure Local nodes typically operate in hardened network environments where
23+
`management.azure.com` is only reachable through a designated proxy or from a specific
24+
management host — not from every cluster node.
25+
- Some "Azure connectivity" signals are actually surfaced **locally** by the Arc Connected
26+
Machine Agent and the DCMA without needing a separate outbound call.
27+
- Some L3 signals (Key Vault expiry, RBAC drift, SPN credential) require ARM API access
28+
and **cannot** be surfaced from agent scripts on the cluster node.
29+
30+
Reference:
31+
- [Azure Local — firewall requirements](https://learn.microsoft.com/en-us/azure/azure-local/concepts/firewall-requirements?view=azloc-2604)
32+
— outbound HTTPS-inspection prohibited; Arc Private Link Scopes unsupported; specific
33+
endpoints listed for each service (Arc, AMA, DCMA, Update Manager, etc.)
34+
- [Azure Arc-enabled servers overview](https://learn.microsoft.com/en-us/azure/azure-arc/servers/overview)
35+
— the `HIMDS` (Hybrid Instance Metadata Service) and `AzureConnectedMachineAgent` services
36+
manage and report Arc connectivity state locally.
37+
- [Azure Monitor Agent overview](https://learn.microsoft.com/en-us/azure/azure-monitor/agents/azure-monitor-agent-overview)
38+
— AMA manages its own connection lifecycle; its service state and last-write timestamp
39+
are available locally.
40+
41+
## The core question answered
42+
43+
### SCOM agents NEVER make direct ARM calls
44+
45+
This is the governing rule. No monitor script targeting `AzureLocal.Cluster`,
46+
`AzureLocal.Node`, or any other L1/L2 class shall call `management.azure.com`. The
47+
SCOM agent's job is to observe local state. ARM calls belong on the management server.
48+
49+
### "Soft L3" — locally observable Arc state (agent-side)
50+
51+
A significant amount of what looks like "Azure connectivity" is actually **surfaced
52+
locally** by the agents Microsoft already ships with every Azure Local deployment. These
53+
are checkable from the SCOM agent without any outbound ARM call:
54+
55+
| What to check | How to check it locally | SCOM class | Collection host |
56+
|---|---|---|---|
57+
| Arc Connected Machine Agent service state | `Get-Service "HIMDS"` + `Get-Service "GCArcService"` | `AzureLocal.Node` | Each cluster node |
58+
| Arc agent connection status | Registry: `HKLM:\SOFTWARE\Microsoft\Azure Connected Machine Agent\Config``Status` | `AzureLocal.Node` | Each cluster node |
59+
| Arc agent last-heartbeat age | Event log: `Microsoft-AzureArc-HybridAgent/Operational` channel — Event ID 50 (heartbeat sent) / Event ID 70 (connection error) | `AzureLocal.Node` | Each cluster node |
60+
| AMA (AzureMonitorWindowsAgent) extension state | `Get-Service "AzureMonitorWindowsAgent"` + extension health event log `Microsoft-AzureMonitorWindowsAgent/Operational` | `AzureLocal.DCMA` | Each cluster node |
61+
| DCMA (diagnostics extension) service state | `Get-Service "AzHCSvc"` (Azure HCI Service) | `AzureLocal.DCMA` | Each cluster node |
62+
| DCMA last telemetry upload | Registry: `HKLM:\SOFTWARE\Microsoft\AzureStackHCI``LastConnectedTime` | `AzureLocal.DCMA` | Each cluster node |
63+
| Required Arc extension installed | Registry: `HKLM:\SOFTWARE\Microsoft\Azure Connected Machine Agent\Extensions\<ExtensionName>``Status` | `AzureLocal.Node` | Each cluster node |
64+
| Required Arc extension version currency | Same registry path → `Version` | `AzureLocal.Node` | Each cluster node |
65+
| HCI Registration status | Registry: `HKLM:\SOFTWARE\Microsoft\AzureStackHCI``RegistrationStatus` + `DiagnosticLevel` | `AzureLocal.HCIRegistration` | Each cluster node |
66+
67+
All of the above are **L1/L2 signals on L1/L2 classes**, collected by the SCOM agent
68+
on each node. They tell the operator "is this node's Azure connectivity healthy?" without
69+
ever calling Azure.
70+
71+
### "Hard L3" — signals that genuinely require ARM access (management server only)
72+
73+
These signals require calling Azure management APIs. They run from the designated
74+
management server only, targeting `Class="Microsoft.SystemCenter.ManagementServer"`:
75+
76+
| Signal | ARM endpoint | SCOM class | Why it can't be done locally |
77+
|---|---|---|---|
78+
| HCI cluster resource provisioning state | `microsoft.azurestackhci/clusters` ARM property | `AzureLocal.Azure.HCICluster` | ARM-only; not in local registry |
79+
| Arc Machine connection status (authoritative) | `microsoft.hybridcompute/machines` ARM property | `AzureLocal.Azure.ArcMachine` | Local check is self-reported; ARM is authoritative |
80+
| Key Vault Resource Health + secret expiry | `microsoft.keyvault/vaults` + Key Vault data plane | `AzureLocal.Azure.KeyVault` | KV is a pure Azure resource |
81+
| Storage Account Resource Health | `microsoft.storage/storageaccounts` | `AzureLocal.Azure.StorageAccount` | Storage Account is a pure Azure resource |
82+
| Required RBAC role assignments | ARM Authorization API | `AzureLocal.Azure.RBAC` | Role assignments live in ARM only |
83+
| SPN credential expiry | Microsoft Graph `servicePrincipals/{id}/passwordCredentials` | *(management server monitor)* | Microsoft Graph only |
84+
| Update Manager linkage freshness | `microsoft.maintenance/maintenanceconfigurations` | `AzureLocal.Azure.HCICluster` | ARM-only |
85+
| DCR existence and association | ARM Resource Graph | `AzureLocal.Azure.HCICluster` | ARM-only |
86+
87+
## Decision
88+
89+
We adopt a **two-tier L3 strategy**:
90+
91+
### Tier A — "Soft L3": Agent-local Arc health checks (required, blocking)
92+
93+
Every signal in the "soft L3" table above is implemented as a standard SCOM unit monitor
94+
on the L1/L2 class it belongs to. These run on every cluster node, use the SCOM agent's
95+
standard PowerShell/registry/event-log data sources, and have **Standard** health impact.
96+
They directly answer "is this cluster's Azure connectivity working?" from on-prem.
97+
98+
Because these checks run locally, they:
99+
- Work even if the management server has no network path to Azure
100+
- Respond immediately when the Arc agent drops (service stops → monitor fires within one
101+
polling interval, default 5 min)
102+
- Don't require any Azure credentials on the cluster nodes
103+
104+
### Tier B — "Hard L3": Management server ARM probes (optional by default, configurable to Standard)
105+
106+
L3 ARM probes run from the management server. The management server requires:
107+
- `Az.Accounts`, `Az.Resources`, `Az.ResourceGraph` PowerShell modules
108+
- A SCOM Run As account backed by a service principal with the role assignments defined
109+
in [ADR 0010](0010-cloud-prerequisites-contract.md)
110+
- Outbound HTTPS to `management.azure.com`, `login.microsoftonline.com`, `graph.microsoft.com`
111+
112+
By default, all Tier B monitors ship with **`Impact = Limited`** (health visible, does not
113+
propagate to the cluster's top-level health state). Operators can upgrade individual monitors
114+
to `Impact = Standard` via the override pack. Rationale:
115+
116+
1. Not every SCOM deployment has a management server with Azure network access
117+
2. KV secret expiry, RBAC drift, and SPN expiry are configuration warnings — important
118+
to know, but a missing KV secret doesn't stop the cluster from running
119+
3. The SCOM MP should not require Azure credentials to function for operators who only
120+
want on-prem monitoring
121+
122+
### The "is the cluster connected to Azure?" answer lives in Tier A
123+
124+
The canonical SCOM health state for Azure connectivity comes from the agent-local checks:
125+
126+
- `ArcAgent.HimdsService.State` — is the HIMDS service running?
127+
- `ArcAgent.ConnectionStatus.Local` — does the local registry report Connected?
128+
- `ArcAgent.Heartbeat.EventLog.Age` — how old is the most recent heartbeat event?
129+
- `DCMA.Service.State` + `DCMA.LastUpload.Age` — is telemetry flowing?
130+
131+
If any of these are unhealthy, the Node's Availability aggregate goes Degraded/Unhealthy,
132+
which propagates to the Cluster. **No ARM call required.**
133+
134+
## Consequences
135+
136+
- **Positive**: SCOM MP works fully on deployments with no management-server-to-Azure
137+
connectivity. Tier A is fully self-contained.
138+
- **Positive**: Tier A provides immediate response to Arc agent failures — no Azure round-trip.
139+
- **Positive**: Tier B gives rich configuration drift detection (KV expiry, RBAC) for
140+
operators who do have management server Azure access.
141+
- **Positive**: Operators can choose their L3 depth by flipping impact from Limited to
142+
Standard on the Tier B monitors — no MP fork required.
143+
- **Negative**: Tier B requires `Az` modules + SPN credentials on the management server.
144+
Some operators will not configure this.
145+
- **Negative**: The management server becomes a single point of collection for all L3 ARM
146+
data. If it goes offline, L3 Tier B monitors show Unknown.
147+
- **Neutral**: Tier B checks run on a 1-hour polling interval (see ADR 0004) — not real-time.
148+
This is acceptable for configuration drift, not acceptable for availability signals (which
149+
is why availability lives in Tier A).
150+
151+
## Required extensions to monitor (Tier A — locally checkable)
152+
153+
These extensions are required for a supported Azure Local deployment. The MP checks each one:
154+
155+
| Extension | Service / Registry key | Signal |
156+
|---|---|---|
157+
| `AzureMonitorWindowsAgent` | `AzureMonitorWindowsAgent` service + `Microsoft-AzureMonitorWindowsAgent/Operational` channel | `Extension.AMA.State` |
158+
| `AzureEdgeTelemetryAndDiagnostics` (DCMA) | `AzHCSvc` service | `Extension.DCMA.State` |
159+
| `AzureConnectedMachineAgent` (Arc for Servers) | `HIMDS` + `GCArcService` services | `ArcAgent.HimdsService.State`, `ArcAgent.GCArcService.State` |
160+
| `WindowsOSSettings` (Arc extension) | Registry probe | `Extension.OsSettings.Installed` |
161+
162+
References:
163+
- [Azure Local — firewall requirements](https://learn.microsoft.com/en-us/azure/azure-local/concepts/firewall-requirements?view=azloc-2604)
164+
- [Azure Monitor Agent network / DCE settings](https://learn.microsoft.com/en-us/azure/azure-monitor/agents/azure-monitor-agent-data-collection-endpoint?tabs=PowerShellWindows)
165+
- [Azure Local Insights — single cluster](https://learn.microsoft.com/en-us/previous-versions/azure/azure-local/manage/monitor-hci-single?view=azloc-2604&tabs=22h2-and-later)
166+
- [Azure Local — required permissions](https://learn.microsoft.com/en-us/azure/azure-local/deploy/deployment-arc-register-server-permissions?view=azloc-2604)
167+
168+
## Alternatives considered
169+
170+
- **No L3 monitoring at all** — rejected: Tier A local checks are low cost and directly
171+
answer the "is Arc healthy?" question operators ask every day. Not implementing them
172+
leaves a real gap.
173+
- **All L3 from management server** — rejected: forces every operator to provision Azure
174+
credentials, breaks deployments without management-server-to-Azure connectivity, and
175+
creates ARM rate-limit exposure from many agents.
176+
- **L3 via ARM from each cluster node** — rejected: violates SCOM architecture (agents
177+
observe local state), adds Azure credential management to 4–16 nodes, creates ARM
178+
throttling risk, and violates most customer firewall policies.
179+
- **L3 Tier B with Standard impact by default** — rejected: would make the MP health state
180+
"Unknown" for operators who haven't provisioned management server Azure credentials, even
181+
though on-prem monitoring is fully functional.
182+
183+
## References
184+
185+
- ADR 0001 — [Scope & topology](0001-scope-and-topology.md)
186+
- ADR 0002 — [Primary signal source](0002-signal-source.md)
187+
- ADR 0004 — [SCOM discovery strategy](0004-scom-discovery-strategy.md)
188+
- ADR 0010 — [Cloud prerequisites contract](0010-cloud-prerequisites-contract.md)
189+
- [Azure Local — firewall requirements](https://learn.microsoft.com/en-us/azure/azure-local/concepts/firewall-requirements?view=azloc-2604)
190+
- [Azure Arc-enabled servers overview](https://learn.microsoft.com/en-us/azure/azure-arc/servers/overview)
191+
- [Azure Monitor Agent overview](https://learn.microsoft.com/en-us/azure/azure-monitor/agents/azure-monitor-agent-overview)
192+
- [SCOM — Heartbeat overview](https://learn.microsoft.com/en-us/system-center/scom/manage-agent-heartbeat-overview?view=sc-om-2025)
193+
- [Kevin Holman — SCOM 2025 Security Account Matrix](https://kevinholman.com/2024/11/25/scom-2025-security-account-matrix/)

docs/design/decisions/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ These are project-scoped ADRs. Org-wide platform standards live in
1010

1111
| # | Title | Status |
1212
|---|---|---|
13-
| [0001](./0001-scope-and-topology.md) | Scope & topology — Azure Local infrastructure (3 layers, ~25 entities) | ✅ Accepted |
13+
| [0001](./0001-scope-and-topology.md) | Scope & topology — Azure Local infrastructure (3 layers, ~27 entities) | ✅ Accepted |
1414
| [0002](./0002-signal-source.md) | Primary signal source — Azure Local PowerShell APIs + ARM/Resource Graph | ✅ Accepted |
1515
| [0003](./0003-health-rollup-policy.md) | Health rollup policy — worst-state default with documented exceptions | ✅ Accepted |
1616
| [0004](./0004-scom-discovery-strategy.md) | SCOM discovery strategy — PowerShell Discovery (not WMI) | ✅ Accepted |
@@ -20,6 +20,7 @@ These are project-scoped ADRs. Org-wide platform standards live in
2020
| [0008](./0008-customization-strategy.md) | Customization strategy — sealed MP + override pack tiers; Bicep params + tiers | ✅ Accepted |
2121
| [0009](./0009-alert-vs-health-state.md) | Alert vs health-state separation policy | ✅ Accepted |
2222
| [0010](./0010-cloud-prerequisites-contract.md) | Cloud-side prerequisites contract (HCI Insights, AMA, DCMA, Service Group, RBAC, networking) | ✅ Accepted |
23+
| [0011](./0011-l3-azure-scope-and-connectivity.md) | L3 Azure-side scope: agent-local Arc health checks (Tier A) vs. management server ARM probes (Tier B) | ✅ Accepted |
2324

2425
## When to write an ADR
2526

0 commit comments

Comments
 (0)