Skip to content

Commit 83762af

Browse files
feat(san): add SAN runbooks, post-deployment tasks, and FC appendices
- Add 4 SAN deployment runbooks (AD + Local Identity, Portal + ARM Template) under phase-05/deployment-methods/san/ - Extend task-05-storage-configuration with SAN workload LUN configuration steps (rescan, initialize, CSV, Azure path registration) - Extend task-09-post-deployment-verification with SAN storage health checks - Add Appendix P: FC fabric zoning reference (Brocade + Cisco MDS examples) - Add Appendix Q: FC maintenance procedures (firmware, port replacement, recurring schedule) - Update appendices/index.mdx with FC/SAN section and rows P-Q Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 1e759a0 commit 83762af

5 files changed

Lines changed: 497 additions & 1 deletion

File tree

docs/implementation/04-cluster-deployment/phase-06-post-deployment/task-05-storage-configuration.mdx

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ import TabItem from '@theme/TabItem';
3434
3535
**Status**: Active
3636

37+
:::info Storage Topology
38+
This task covers **two storage topologies**:
39+
- **[Storage Spaces Direct (S2D)](#section-1--volume-sizing--yaml-verification)** — Sections 1–3 below
40+
- **[SAN Disaggregated](#san-workload-lun-configuration)** — jump to the SAN section at the bottom of this page
41+
:::
42+
3743
## Section 1 — Volume Sizing & YAML Verification
3844

3945
:::warning This step should already be complete
@@ -985,6 +991,123 @@ The procedures in this task use the scripted methods shown in the tabs above. Ad
985991
| Azure CLI | PowerShell-based Azure CLI scripts for Azure resource operations |
986992
| Bash | Linux/macOS compatible shell scripts for pipeline environments |
987993

994+
---
995+
996+
## SAN Workload LUN Configuration
997+
998+
*This section applies only to **SAN disaggregated deployments**. Skip if using Storage Spaces Direct — use Sections 1–3 above instead.*
999+
1000+
After the cluster deployment wizard completes, the infrastructure and performance history LUNs are already claimed by the cluster. This section covers adding workload LUNs as Cluster Shared Volumes.
1001+
1002+
:::warning Workload LUNs only
1003+
Do **not** initialize the infrastructure volume or performance history LUN — those were claimed by the deployment wizard. Only initialize and add LUNs designated for VM workload storage.
1004+
:::
1005+
1006+
### Step 1: Rescan and Identify Workload LUNs
1007+
1008+
```powershell title="Rescan and list FC disks — run on a cluster node"
1009+
Invoke-Command -ComputerName "<cluster-node>" -ScriptBlock {
1010+
Update-HostStorageCache
1011+
Get-Disk | Where-Object BusType -eq 'Fibre Channel' |
1012+
Select-Object Number, FriendlyName, Size, PartitionStyle, OperationalStatus |
1013+
Format-Table -AutoSize
1014+
}
1015+
```
1016+
1017+
Identify the disk number(s) of workload LUNs with `PartitionStyle = RAW`.
1018+
1019+
### Step 2: Initialize and Format Workload LUNs
1020+
1021+
```powershell title="Initialize and format each workload LUN — run on a cluster node"
1022+
# Replace <disk-number> with the number identified in Step 1
1023+
$DiskNumber = <disk-number>
1024+
$LabelName = "WorkloadLUN01" # Change per LUN
1025+
1026+
Invoke-Command -ComputerName "<cluster-node>" -ArgumentList $DiskNumber, $LabelName -ScriptBlock {
1027+
param($disk, $label)
1028+
Initialize-Disk -Number $disk -PartitionStyle GPT -PassThru |
1029+
New-Partition -UseMaximumSize |
1030+
Format-Volume -FileSystem NTFS -NewFileSystemLabel $label -Confirm:$false
1031+
}
1032+
```
1033+
1034+
### Step 3: Add Workload LUNs to Cluster and Create CSVs
1035+
1036+
```powershell title="Add cluster disk and convert to CSV — run on a cluster node"
1037+
Invoke-Command -ComputerName "<cluster-node>" -ScriptBlock {
1038+
# List available disks the cluster can claim
1039+
Get-ClusterAvailableDisk | Format-Table Name, Size
1040+
1041+
# Add each available disk as a cluster resource
1042+
Get-ClusterAvailableDisk | Add-ClusterDisk
1043+
1044+
# Convert each Physical Disk cluster resource to a CSV
1045+
Get-ClusterResource | Where-Object { $_.ResourceType -eq 'Physical Disk' } |
1046+
ForEach-Object { Add-ClusterSharedVolume -Name $_.Name }
1047+
1048+
# Verify CSVs are online
1049+
Get-ClusterSharedVolume | Select-Object Name, State,
1050+
@{N='Path'; E={ $_.SharedVolumeInfo.FriendlyVolumeName }}
1051+
}
1052+
```
1053+
1054+
### Step 4: Register SAN Storage Paths in Azure
1055+
1056+
After CSVs are online, register them as Azure storage paths. Follow the same procedure as [Section 3 (Storage Paths)](#section-3--storage-path-registration) above — the az CLI commands are topology-agnostic.
1057+
1058+
```powershell title="Register SAN CSVs as Azure storage paths"
1059+
$rg = "rg-<customer>-azl-<region>-01" # variables.yml: azure_platform.resource_groups.cluster.name
1060+
$customLocation = "cl-<customer>" # variables.yml: compute.azure_local.custom_location
1061+
1062+
$StoragePaths = @(
1063+
[PSCustomObject]@{
1064+
Name = "sp-<customer>-clus01-san-01"
1065+
Path = "C:\ClusterStorage\<csv-name>\VMs"
1066+
}
1067+
)
1068+
1069+
foreach ($sp in $StoragePaths) {
1070+
az stack-hci-vm storagepath create `
1071+
--resource-group $rg `
1072+
--custom-location $customLocation `
1073+
--name $sp.Name `
1074+
--path $sp.Path `
1075+
--output none
1076+
Write-Host "Registered: $($sp.Name)"
1077+
}
1078+
```
1079+
1080+
### SAN Storage Validation
1081+
1082+
```powershell title="Validate SAN storage state"
1083+
Invoke-Command -ComputerName "<cluster-node>" -ScriptBlock {
1084+
# FC disk health
1085+
Get-PhysicalDisk | Where-Object BusType -eq 'Fibre Channel' |
1086+
Select-Object FriendlyName, HealthStatus, OperationalStatus, Size
1087+
1088+
# CSV volumes
1089+
Get-ClusterSharedVolume | Select-Object Name, State,
1090+
@{N='Path'; E={ $_.SharedVolumeInfo.FriendlyVolumeName }}
1091+
1092+
# MPIO path count
1093+
mpclaim -s -d
1094+
}
1095+
```
1096+
1097+
**Expected:**
1098+
1099+
| Check | Expected |
1100+
|-------|----------|
1101+
| FC disks `HealthStatus` | `Healthy` |
1102+
| `Get-ClusterSharedVolume` State | `Online` for all workload volumes |
1103+
| `mpclaim -s -d` path count | ≥2 per LUN (2 HBAs × 1 fabric minimum) |
1104+
| Azure storage paths | `provisioningState = Succeeded` |
1105+
1106+
**References:**
1107+
- [Storage Architecture Planning](../../../planning/07-storage-planning.mdx)
1108+
- [Microsoft Learn — Enable External Storage](https://learn.microsoft.com/en-us/azure/azure-local/deploy/enable-external-storage?view=azloc-2604)
1109+
- [Appendix P — FC Fabric Configuration](../../appendices/appendix-p-fc-fabric.mdx)
1110+
9881111
## Navigation
9891112

9901113
| Previous | Up | Next |

docs/implementation/04-cluster-deployment/phase-06-post-deployment/task-09-post-deployment-verification.mdx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ Verify that all Phase 06 tasks completed successfully. This task must pass befor
7070
| 03 | Operator AD group in `Remote Management Users` on all nodes | Present |
7171
| 04 | `sshd` service running on all nodes | `Running` |
7272
| 04 | Port 22 reachable on all nodes | `TcpTestSucceeded : True` |
73-
| 05 | Storage pool health | `Healthy` |
73+
| 05 | Storage pool health (S2D) | `Healthy` |
7474
| 05 | CSV volumes mounted and online | Count matches design |
75+
| 05 | FC LUN health (SAN only) | `Healthy` for all FC disks |
76+
| 05 | MPIO path count (SAN only) | ≥2 paths per LUN |
7577
| 06 | VM images in Azure | Provisioning state `Succeeded` |
7678
| 07 | Logical networks in Azure | Provisioning state `Succeeded` |
7779

@@ -121,9 +123,18 @@ Expected: `TcpTestSucceeded : True` for all nodes.
121123

122124
#### Task 05 — Storage
123125

126+
**S2D deployments:**
127+
124128
1. In WAC → `iic-clus01`**Storage****Volumes** — confirm all CSV volumes are **Healthy** and **Online**
125129
2. In Azure Portal → **Azure Local**`iic-clus01`**Storage paths** — confirm all show **Succeeded**
126130

131+
**SAN deployments:**
132+
133+
1. Verify FC disk health: `Get-PhysicalDisk | Where-Object BusType -eq 'Fibre Channel'` — all `HealthStatus = Healthy`
134+
2. Verify MPIO paths: `mpclaim -s -d` — ≥2 paths per workload LUN
135+
3. Confirm CSVs are `Online`: `Get-ClusterSharedVolume`
136+
4. In Azure Portal — confirm Azure storage paths show `Succeeded`
137+
127138
#### Task 06 — VM Images
128139

129140
In Azure Portal → **Azure Local**`iic-clus01`**VM images** — confirm all required images
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
---
2+
title: "Appendix P — Fibre Channel Fabric Configuration"
3+
sidebar_label: "Appendix P: FC Fabric"
4+
sidebar_position: 16
5+
description: "Fibre Channel fabric configuration reference — Brocade and Cisco MDS zoning, alias creation, zoneset activation"
6+
category: "Reference"
7+
scope: "Fibre Channel fabric configuration for SAN disaggregated Azure Local deployments"
8+
purpose: "Reference for FC fabric zoning, aliases, and port channels for SAN deployments"
9+
author: "Azure Local Cloud"
10+
created: 2026-05-02
11+
updated: 2026-05-02
12+
version: "1.0.0"
13+
tags:
14+
- azure-local
15+
- fibre-channel
16+
- san
17+
- zoning
18+
- brocade
19+
- cisco-mds
20+
keywords:
21+
- Fibre Channel
22+
- FC zoning
23+
- Brocade
24+
- Cisco MDS
25+
- WWPN
26+
- alias
27+
- zoneset
28+
status: "Active"
29+
---
30+
31+
# Appendix P — Fibre Channel Fabric Configuration
32+
33+
[![Reference](https://img.shields.io/badge/Type-Reference-green?style=flat-square)](./index.mdx)
34+
[![Azure](https://img.shields.io/badge/Platform-Azure_Local-0078D4?style=flat-square&logo=microsoftazure)](https://learn.microsoft.com/en-us/azure/azure-local/)
35+
36+
> **DOCUMENT CATEGORY**: Reference
37+
> **SCOPE**: Fibre Channel fabric configuration
38+
> **PURPOSE**: Reference for FC fabric zoning, aliases, and port channels for SAN deployments
39+
> **MASTER REFERENCE**: [Microsoft Learn — Enable External Storage](https://learn.microsoft.com/en-us/azure/azure-local/deploy/enable-external-storage?view=azloc-2604)
40+
41+
**Status**: Active
42+
43+
This appendix covers FC fabric configuration for SAN disaggregated Azure Local deployments — alias creation, zone definition, zoneset activation, and post-zoning validation. Both Brocade FOS and Cisco MDS NX-OS examples are provided.
44+
45+
---
46+
47+
## Zoning Policy — Single-Initiator/Single-Target
48+
49+
The Azure Local Cloud standard for FC zoning is **single-initiator/single-target**: each zone contains exactly one HBA port WWPN (initiator) and one SAN array port WWPN (target). This is the pattern recommended by Microsoft and eliminates the multi-initiator contention issues that arise when initiators share a zone.
50+
51+
**Zone count formula:** For an N-node cluster with 2 HBAs per node and 2 independent fabrics, expect **2N zones per fabric**.
52+
53+
| Cluster size | HBAs/node | Fabrics | Zones per fabric | Total zones |
54+
|---|---|---|---|---|
55+
| 2-node | 2 | 2 | 4 | 8 |
56+
| 4-node | 2 | 2 | 8 | 16 |
57+
| 8-node | 2 | 2 | 16 | 32 |
58+
59+
:::tip Why single-initiator/single-target?
60+
When multiple initiators share a zone, a LUN reset or RSCN storm from one initiator disrupts all others in the zone. Single-initiator/single-target zones contain blast radius to one host port, which is critical for Azure Local storage resiliency.
61+
:::
62+
63+
---
64+
65+
## Naming Conventions
66+
67+
Consistent naming makes zones auditable at a glance and simplifies troubleshooting. Apply these patterns across both fabrics.
68+
69+
| Element | Pattern | Example |
70+
|---|---|---|
71+
| WWPN alias | `<site>-AZL-<nodeNN>-HBA<P>` | `NYC01-AZL-N01-HBA1` |
72+
| FC zone | `Z_<initiator>_<target>` | `Z_NYC01-AZL-N01-HBA1_ARRAY-CT0FC0` |
73+
| Zoneset | `<fabric>_PROD_active` | `FAB-A_PROD_active` |
74+
75+
- `<site>` — a short 3–6 character site code (matches your naming standard, e.g. `NYC01`, `DAL02`)
76+
- `<nodeNN>` — zero-padded node number: `N01`, `N02`, etc.
77+
- `<HBA<P>` — HBA port number, 1-indexed: `HBA1`, `HBA2`
78+
- `<target>` — the array controller and port label as reported by the array vendor
79+
80+
---
81+
82+
## Brocade Fabric — Example Configuration
83+
84+
The following commands target **Fabric A** of a 2-node cluster connecting to a dual-controller SAN array. Collect HBA WWPNs from Windows before beginning (see [Phase 03 Task 12](#cross-references)).
85+
86+
```bash
87+
# Connect to Brocade switch
88+
ssh admin@brocade-fab-a.corp.azurelocal.cloud
89+
90+
# Create aliases for HBA WWPNs (collected from Windows: Get-InitiatorPort)
91+
alicreate "NYC01-AZL-N01-HBA1", "10:00:00:90:fa:11:22:01"
92+
alicreate "NYC01-AZL-N01-HBA2", "10:00:00:90:fa:11:22:02"
93+
alicreate "NYC01-AZL-N02-HBA1", "10:00:00:90:fa:11:23:01"
94+
alicreate "NYC01-AZL-N02-HBA2", "10:00:00:90:fa:11:23:02"
95+
96+
# Create aliases for SAN array target ports
97+
alicreate "ARRAY-CT0FC0", "52:4a:93:00:11:11:11:01"
98+
alicreate "ARRAY-CT1FC0", "52:4a:93:00:11:11:11:02"
99+
100+
# Create single-initiator/single-target zones
101+
zonecreate "Z_NYC01-AZL-N01-HBA1_ARRAY-CT0FC0", "NYC01-AZL-N01-HBA1; ARRAY-CT0FC0"
102+
zonecreate "Z_NYC01-AZL-N01-HBA2_ARRAY-CT0FC0", "NYC01-AZL-N01-HBA2; ARRAY-CT0FC0"
103+
zonecreate "Z_NYC01-AZL-N02-HBA1_ARRAY-CT0FC0", "NYC01-AZL-N02-HBA1; ARRAY-CT0FC0"
104+
zonecreate "Z_NYC01-AZL-N02-HBA2_ARRAY-CT0FC0", "NYC01-AZL-N02-HBA2; ARRAY-CT0FC0"
105+
106+
# Add zones to zoneset
107+
cfgcreate "FAB-A_PROD_active", "Z_NYC01-AZL-N01-HBA1_ARRAY-CT0FC0; Z_NYC01-AZL-N01-HBA2_ARRAY-CT0FC0; Z_NYC01-AZL-N02-HBA1_ARRAY-CT0FC0; Z_NYC01-AZL-N02-HBA2_ARRAY-CT0FC0"
108+
109+
# Save and enable
110+
cfgsave
111+
cfgenable "FAB-A_PROD_active"
112+
```
113+
114+
Repeat the same sequence on **Fabric B**, substituting the second-fabric port WWPNs for both the HBA aliases and the array target aliases, and naming the zoneset `FAB-B_PROD_active`.
115+
116+
:::note Existing zonesets
117+
If a zoneset already exists on the switch, use `cfgadd` to add new members rather than `cfgcreate`. Verify with `cfgshow` before enabling.
118+
:::
119+
120+
---
121+
122+
## Cisco MDS Fabric — Example Configuration
123+
124+
The following NX-OS commands configure **Fabric A** on a single VSAN. Adjust the VSAN ID to match your environment.
125+
126+
```
127+
# Connect to MDS
128+
ssh admin@mds-fab-a.corp.azurelocal.cloud
129+
configure terminal
130+
131+
# Create FC aliases (per VSAN)
132+
fcalias name NYC01-AZL-N01-HBA1 vsan 100
133+
member pwwn 10:00:00:90:fa:11:22:01
134+
exit
135+
fcalias name ARRAY-CT0FC0 vsan 100
136+
member pwwn 52:4a:93:00:11:11:11:01
137+
exit
138+
139+
# Create zone
140+
zone name Z_NYC01-AZL-N01-HBA1_ARRAY-CT0FC0 vsan 100
141+
member fcalias NYC01-AZL-N01-HBA1
142+
member fcalias ARRAY-CT0FC0
143+
exit
144+
145+
# Add to zoneset and activate
146+
zoneset name FAB-A_PROD_active vsan 100
147+
member Z_NYC01-AZL-N01-HBA1_ARRAY-CT0FC0
148+
exit
149+
zoneset activate name FAB-A_PROD_active vsan 100
150+
copy running-config startup-config
151+
```
152+
153+
Add additional `fcalias`, `zone`, and `zoneset member` blocks for each remaining initiator/target pair before activating the zoneset. Activate once, after all zones are added — each activation causes a fabric RSCN.
154+
155+
:::warning Activate after all zones are defined
156+
On Cisco MDS, each `zoneset activate` triggers an RSCN across the VSAN. Define all zones for the fabric before activating to avoid multiple disruptions during initial configuration.
157+
:::
158+
159+
---
160+
161+
## Validation After Zoning
162+
163+
Run the following on each cluster node after zoneset activation to confirm LUN visibility and MPIO path count.
164+
165+
```powershell
166+
# Run on each cluster node
167+
Get-PhysicalDisk | Where-Object BusType -eq 'Fibre Channel' |
168+
Select-Object FriendlyName, SerialNumber, OperationalStatus, Size
169+
mpclaim -s -d
170+
```
171+
172+
**Expected results:**
173+
174+
- Each LUN appears once per node with `OperationalStatus = OK`
175+
- Each LUN shows 2 or more MPIO paths (one per fabric)
176+
- `mpclaim -s -d` lists the LUN with paths in an `Active/Optimized` or `Active/Unoptimized` state per the array's preferred path policy
177+
178+
If a LUN does not appear, verify: (1) the zone is active on both fabrics, (2) the correct WWPN was aliased — use `Get-InitiatorPort` on the node to re-confirm, (3) the LUN has been mapped to the host in the array management interface.
179+
180+
---
181+
182+
## References
183+
184+
- [Microsoft Learn — Enable External Storage](https://learn.microsoft.com/en-us/azure/azure-local/deploy/enable-external-storage?view=azloc-2604)
185+
- [Microsoft Learn — FC pattern without backup](https://learn.microsoft.com/en-us/azure/azure-local/plan/fiber-channel-no-backup-disaggregated-pattern?view=azloc-2604)
186+
- [Microsoft Learn — FC pattern with backup](https://learn.microsoft.com/en-us/azure/azure-local/plan/fiber-channel-with-backup-disaggregated-pattern?view=azloc-2604)
187+
- [Appendix Q — FC Fabric Maintenance](./appendix-q-fc-maintenance.mdx)
188+
- [Appendix I — Dell Configuration](./appendix-i-dell-config.mdx)
189+
190+
---
191+
192+
## Cross-References {#cross-references}
193+
194+
| Phase | Task | Link |
195+
|---|---|---|
196+
| Phase 03 | Task 12 — Install FC HBA Drivers | [task-12-install-fc-hba-drivers-conditional.mdx](../04-cluster-deployment/phase-03-os-configuration/task-12-install-fc-hba-drivers-conditional.mdx) |
197+
| Phase 03 | Task 13 — Configure MPIO & MSDSM | [task-13-configure-mpio-and-vendor-msdsm-conditional.mdx](../04-cluster-deployment/phase-03-os-configuration/task-13-configure-mpio-and-vendor-msdsm-conditional.mdx) |
198+
| Phase 03 | Task 14 — Verify LUN Presentation | [task-14-verify-san-lun-presentation-conditional.mdx](../04-cluster-deployment/phase-03-os-configuration/task-14-verify-san-lun-presentation-conditional.mdx) |
199+
| Phase 05 | SAN/AD Portal | [portal-instructions.mdx](../04-cluster-deployment/phase-05-cluster-deployment/deployment-methods/san/active-directory/portal-instructions.mdx) |
200+
| Phase 05 | SAN/AD ARM | [arm-template-instructions.mdx](../04-cluster-deployment/phase-05-cluster-deployment/deployment-methods/san/active-directory/arm-template-instructions.mdx) |
201+
| Phase 05 | SAN/LI Portal | [portal-instructions.mdx](../04-cluster-deployment/phase-05-cluster-deployment/deployment-methods/san/local-identity/portal-instructions.mdx) |
202+
| Phase 05 | SAN/LI ARM | [arm-template-instructions.mdx](../04-cluster-deployment/phase-05-cluster-deployment/deployment-methods/san/local-identity/arm-template-instructions.mdx) |
203+
| Phase 06 | Task 05 — Storage Configuration | [task-05-storage-configuration.mdx](../04-cluster-deployment/phase-06-post-deployment/task-05-storage-configuration.mdx) |
204+
| Planning | Storage Architecture Planning | [07-storage-planning.mdx](../../planning/07-storage-planning.mdx) |

0 commit comments

Comments
 (0)