Introduction
This article provides a step-by-step guide on deploying a Windows Server Storage Spaces Direct (S2D) cluster in Microsoft Azure with a highly available Active Directory domain. Storage Spaces Direct is a software-defined storage solution that enables the creation of highly available and scalable storage by leveraging locally attached disks across clustered servers.
Prerequisites
Before you start, make sure you have:
- An Azure subscription with permissions to create resource groups, VNets, VMs, managed disks, and a storage account (for Cloud Witness).
- A basic handle on Resource Groups, VNets, subnets, NSGs, VMs, and managed disks.
- Windows Server Datacenter for the S2D nodes (S2D isn’t in Standard). If you choose Windows Server Datacenter: Azure Edition, you can later enable Hotpatch to take most security patches without reboots—handy for clusters.
One more thing: S2D likes low latency between nodes. In Azure, put the cluster nodes in the same Availability Set (or the same Availability Zone) and use a Proximity Placement Group (PPG) to keep them physically close. Turn on Accelerated Networking on each NIC.
Step 1: Deploying a Highly Available Active Directory Domain
The Azure Resource Manager (ARM) template “active-directory-new-domain-ha-2-dc” is designed to establish a new Active Directory domain with built-in high availability. It provisions two virtual machines as domain controllers, placing them within an Azure Availability Set to ensure continuous availability.
Step-by-Step Guide on Deploying the AD Domain
You can deploy the Active Directory domain using the ARM template via the Azure portal or Azure CLI/PowerShell.
Option 1: Using the Azure Portal
- Navigate to the template link: https://learn.microsoft.com/en-us/samples/azure/azure-quickstart-templates/active-directory-new-domain-ha-2-dc/
- Click the “Deploy to Azure” button.
- Choose your subscription and create a new Resource Group.
- Fill out required parameters: Admin credentials, DNS prefix, Domain name.
Option 2: Using Azure CLI/PowerShell
Azure CLI Example:
az group create --name myResourceGroup --location eastus az deployment group create \ --resource-group myResourceGroup \ --template-uri https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.activedirectory/active-directory-new-domain-ha-2-dc/azuredeploy.json \ --parameters adminUsername=adminUser \ adminPassword="YourP@ssw0rd123" \ dnsPrefix=mydns \ domainName=mydomain.local
Azure PowerShell Example:
New-AzResourceGroup -Name myResourceGroup -Location "East US" New-AzResourceGroupDeployment \ -ResourceGroupName myResourceGroup \ -TemplateUri "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.activedirectory/active-directory-new-domain-ha-2-dc/azuredeploy.json" \ -adminUsername adminUser \ -adminPassword "YourP@ssw0rd123" \ -dnsPrefix mydns \ -domainName mydomain.local
Explanation of Key Parameters
- Subscription: Azure subscription under which resources will be provisioned.
- Resource Group: Logical container for deployed resources.
- Location: Azure region where resources will be physically located.
- Admin Username and Admin Password: Local administrator account credentials for domain controller VMs.
- Domain Name: Fully qualified domain name (FQDN) for the new Active Directory domain.
- Dns Prefix: Unique DNS name for the public IP address associated with the load balancer.
Verification Steps
- Confirm all resources are created in the Azure portal.
- Check the deployment status is “Succeeded” in the Resource Group’s “Overview” blade.
- Connect to the domain controller VMs via RDP.
- Verify the domain creation and the second domain controller VM listing using “Active Directory Users and Computers.”
Step 2: Configuring the Virtual Network for S2D Integration
The ARM template creates a Virtual Network (VNet) with a defined private IP address space and a default subnet for the domain controllers.
1. Create a Subnet for S2D Nodes (Azure CLI)
Create a new subnet within the existing Virtual Network for the S2D cluster nodes. Use a distinct IP address range that doesn’t overlap with the AD subnet.
Azure CLI Example:
az network vnet subnet create \ --resource-group myResourceGroup \ --vnet-name myVnet \ --name s2dSubnet \ --address-prefixes 10.0.1.0/24
Azure PowerShell Example:
$vnet = Get-AzVirtualNetwork -Name myVnet -ResourceGroupName myResourceGroup
Add-AzVirtualNetworkSubnetConfig -Name s2dSubnet -AddressPrefix “10.0.1.0/24” -VirtualNetwork $vnet | Set-AzVirtualNetwork
2. Configure Network Security Groups (NSGs)
Create NSGs for both the AD subnet and the S2D subnet. Allow necessary traffic between the subnets and for remote management access.
$nsg = New-AzNetworkSecurityGroup -ResourceGroupName myResourceGroup -Location "East US" -Name "s2d-nsg" # Allow RDP $nsgRule = New-AzNetworkSecurityRuleConfig -Name "Allow-RDP" -Protocol Tcp -Direction Inbound -Priority 1000 -SourceAddressPrefix "*" -SourcePortRange "*" -DestinationAddressPrefix "*" -DestinationPortRange 3389 -Access Allow $nsg.SecurityRules += $nsgRule Set-AzNetworkSecurityGroup -NetworkSecurityGroup $nsg
3. Ensure Proper DNS Configuration
Verify the DNS server settings for the Virtual Network. Ensure the private IP addresses of the domain controllers are listed as DNS servers.
$vnet.DhcpOptions.DnsServers = @("10.0.0.4", "10.0.0.5")
Set-AzVirtualNetwork -VirtualNetwork $vnet
Step 3: Deploying the Windows Server S2D Cluster
Deploy the S2D cluster template via the Azure portal or Azure CLI/PowerShell, specifying the existing Resource Group, Virtual Network, and dedicated subnet.
VM sizes & disks that behave well
- Esv5/Ebdsv5/Dsv5: solid general-purpose picks with Premium storage.
- Use Premium SSD v2 for most data volumes—lower latency, granular performance tuning, and good $/IOPS. If you need the absolute top end for logs/journals, Ultra Disk is still the ceiling.
Disk layout & caching
- Attach multiple identical data disks per node (P30/P40/etc. or Premium SSD v2) for the S2D pool.
- Set host caching = None on every disk used by S2D; S2D handles caching itself and Azure host caching just gets in the way.
To deploy the S2D cluster, follow these steps:
1. Create Virtual Machines
Deploy two or more Windows Server VMs (Datacenter or Datacenter: Azure Edition) into the same Availability Set for redundancy:
New-AzVM -ResourceGroupName "myResourceGroup" ` -Name "s2d-node01" ` -Location "East US" ` -VirtualNetworkName "myVnet" ` -SubnetName "s2dSubnet" ` -AvailabilitySetName "s2d-avset" ` -Image "Win2022Datacenter" ` -Size "Standard_DS4_v2" ` -AdminUsername "adminUser" ` -AdminPassword "YourP@ssw0rd123"
Repeat this for each cluster node.
2. Join VMs to the Active Directory Domain
From each node:
Add-Computer -DomainName "mydomain.local" -Credential (Get-Credential) Restart-Computer
3. Install Required Features
Install Failover Clustering and File Server roles:
Install-WindowsFeature -Name Failover-Clustering, FS-FileServer -IncludeManagementTools
4. Validate the Cluster
Run cluster validation tests:
Test-Cluster -Node s2d-node01, s2d-node02
Review the report and ensure all required checks pass.
5. Create the Cluster
New-Cluster -Name "s2d-cluster" -Node s2d-node01,s2d-node02 -StaticAddress "10.0.1.100" -NoStorage
6. Enable Storage Spaces Direct
Enable-ClusterS2D -Confirm:$false
Once S2D is enabled, it will automatically create the storage pool from all available eligible disks.
7. Tag the Disks (Optional)
If you’d like to manually tier storage (e.g., cache and capacity), tag disks:
Get-PhysicalDisk | Where-Object FriendlyName -Like "*P10*" | Set-PhysicalDisk -Usage Journal
Step 4: Configuring the S2D Cluster
Connect to the Cluster Nodes
RDP into each node and open PowerShell as Administrator.
Enable Storage Spaces Direct
Enable-ClusterS2D -Confirm:$false
Create Virtual Disks and Volumes
# Optional: list available physical disks Get-PhysicalDisk # Virtual disk New-Volume -StoragePoolFriendlyName "S2D on Cluster" -FriendlyName "Volume1" -FileSystem ReFS -Size 1TB
Setup Cloud Witness
Set-ClusterQuorum -CloudWitness -AccountName "mystorageacct" -AccessKey "<access_key>"
Step 5: Post-config & daily operations
- Hotpatch (optional): if you used Windows Server Datacenter: Azure Edition, consider enabling Hotpatch to apply security updates without reboots during most months. It plays nicely with clusters and shortens maintenance nights
- Placement: keep all S2D nodes in one PPG and the same zone/availability set unless you’re building a stretched cluster with very careful latency planning.
- Monitoring: watch cluster/volume health in Failover Cluster Manager and perf counters (storage latency, queue length).
- Backups: back up the VMs and the apps running on the volumes. Snapshots alone aren’t backups.
Best Practices and Considerations for S2D in Azure
- Support model: Running S2D inside VMs is a supported guest cluster pattern. If you’re after the hyperconverged “bare metal” experience managed by Azure, look at Azure Stack HCI.
- Latency matters: use PPG, Accelerated Networking, and keep nodes co-located.
- Disks: prefer Premium SSD v2 for balanced performance/price; use Ultra Disk for the truly hot write logs if needed. Keep host caching = None on S2D disks.
- Quorum: use Cloud Witness so you don’t need a third node.
- ASR: plan for crash-consistent only on S2D; layer application-aware backups for actual recovery points.
Troubleshooting Common Deployment Issues
- Domain join/DNS weirdness: if nodes can’t join the domain, check the VNet DNS points at your DC IPs, not Azure’s default. Confirm NSGs aren’t blocking LDAP/Kerberos/SMB between subnets.
- Disks not showing for S2D: make sure they’re unpartitioned, online, identical size/type across nodes, and mounted with host caching = None. Re-run Get-PhysicalDisk and Get-StoragePool.
- Validation failures: read the HTML from Test-Cluster. Most red flags are obvious: mixed disks, latency, or blocked ports.
- Performance feels off: confirm all nodes are in the same PPG, that you didn’t accidentally enable caching on pool disks, and that you’re not throttled by small SKUs. Consider Premium SSD v2 or Ultra Disk where it counts.
To conclude
You now have a supported, low‑latency guest cluster that survives node loss and keeps storage local to each VM. The big wins come from the choices you made on the way in: keeping nodes together in a Proximity Placement Group, disabling host caching on pool disks, picking Premium SSD v2 (or Ultra where it truly matters), and using a Cloud Witness for quorum so maintenance stays simple.
Keep the cluster boring and predictable. Watch latency and queue length, run Test-Cluster after meaningful changes, and patch on a steady cadence—Hotpatch helps if you picked Azure Edition. For recovery, remember that Azure Site Recovery offers crash‑consistent points for S2D VMs; pair it with app‑aware backups and regular restore drills so databases come back clean, not just fast.
Next steps
- Capture this build as code (ARM/Bicep/Terraform) so you can recreate it consistently.
- Wire up Azure Monitor/Log Analytics alerts for cluster health, disk latency, and capacity.
- Schedule quarterly validation and failover tests, and keep the runbook you actually used.
- Right‑size disk performance tiers and revisit costs after a week of real workload data.