Recently I have been focusing on learning more about Azure Stack HCI – it’s an area that continues to be a focus point in my daily role. Key to the uptake of Azure Stack HCI is a drive to centralise on the Azure Ecosystem that I see with many of the customers I work with. For this post I wanted to share some of the learning I’ve been undertaking, and explore some of the technical testing steps I’ve conducted – as well as sharing some of the other aspects like using Infrastructure as Code (another focus area for myself) with Azure Stack HCI, to explore what options we have there too.
As well as being key to customers exploring Stack HCI to run on-premises Compute workloads, I’ve also seen a drive towards mixed Cloud/On-premises VDI estates, whereby those applications needing to be on-premises remain so (via a solution like Stack HCI) and the rest is run in Azure taking advantage of the scaling and flexibility. It is worth also noting that Citrix support Azure Stack HCI too – see here.
This article is designed to detail my own learning – it’s far from exhaustive, but hopefully will help people in a similar position to myself, who are keen to learn more about Azure Stack HCI, and the various options for labs, learning, and IAC usage!
In other news…
I also wanted to extend a huge thanks to the Microsoft MVP Team, and everyone in the Community who has read my blogs, attended my presentations, used my code samples – I’ve just been renewed as an MVP for 2024-2025! You can view my MVP Profile here.
Getting Started… the right lab setup
Having a lab environment for Azure Stack HCI can be a challenge, especially if you don’t have hardware you can use, or access to hardware. This is the case for myself – so I found myself looking into alternative options. Fortunately, the awesome Azure Stack HCI Jumpstart HCIBox is available – https://azurearcjumpstart.com/azure_jumpstart_hcibox.
The Jumpstart HCIBox provides an Azure Stack HCI sandbox that deploys easily to an Azure Subscription. Using nested virtualization, and full Azure Stack HCI deployment is setup – giving you two nodes, networking, and a Domain Controller. Deploying of the Jumpstart HCIBox is very simple – and entirely automated. One thing to bear in mind is that it can take a number of hours to deploy – it took around 3-5 hours for my deployment to complete, so this may be something to set running well in advance of when you are likely to need it.
If you are going to utilise the Jumpstart HCIBox option, I would recommend using the Azure Developer CLI deployment, as this is a very simple and easy option – and gets things running quickly, with minimal effort. I won’t cover the deployment in this post – as it’s covered brilliantly in the Jumpstart HCIBox guide, available here: https://azurearcjumpstart.com/azure_jumpstart_hcibox/deployment_azd.
An overview of the deployed architecture is shown below – this is from the Jumpstart site:
Once the deployment completes – you’ll see a number of Azure Resources:
Next up – testing the deployment and exploring our IAC options!
Testing – Quick Steps
In testing the deployment of Azure Stack HCI, there are many routes you can take, and this will largely depend on your intended use case. For myself, I wanted to test out Virtual Machines – specifically for use with AVD and general VM workloads. To do this, I’ll explore a the use of IAC for both of these use cases – and see what options we have available.
This post will cover some of what is currently possible – it won’t be exhaustive, but aimed to give a general view of options and additional resources to help!
Infrastructure as Code – Our Options
As with all of the components and solutions I deploy to Azure – my focus is around Infrastructure as Code (mainly Terraform), and how we can utilise DevOps tooling and methodologies to deploy these solutions repeatably with ease. In the case of Azure Stack HCI we have a number of options to explore. It’s worth noting that as always, with IAC there are a number of different options and solutions we could look at; Terraform, Bicep, PowerShell, Azure CLI to name a few. I’ll focus on Terraform (with some PowerShell also needed) in this article and explore a few of the resources we could deploy, but will also provide links to the Bicep reference too.
Note – most of the below makes reference to the Azure Resources Reference with some tweaks. You can view the original Resources Reference here: https://learn.microsoft.com/en-us/azure/templates/
I’m going to cover a few of the aspects here, as mentioned, but it is worth noting that to create a cluster, the following high-level steps need to be completed:
-
OS deployment (done on the physical hardware or HCIBox)
-
Create a Cluster
-
Setup a Cluster Witness (usually a Storage Account)
-
Register with Azure
-
Validate
An overview and more detail on this process is available here: https://learn.microsoft.com/en-us/azure-stack/hci/deploy/create-cluster?tabs=use-network-atc-to-deploy-and-manage-networking-recommended
Need a starting guide for Azure Terraform? Check out my previous series here.
Creating Clusters:
Creating a cluster is a simple process:
Native provider option (AzureRM Provider):
data "azuread_application" "ashci1" { display_name = "Allowed resource types" } data "azurerm_client_config" "current" {} resource "azurerm_resource_group" "ashcirg1" { name = "azure-stack-witness1" location = var.region1 } resource "azurerm_stack_hci_cluster" "ashcic1" { name = "azure-stack-hci-cluster1" resource_group_name = azurerm_resource_group.ashcirg1.name location = azurerm_resource_group.ashcirg1.location client_id = data.azuread_application.ashci1.application_id tenant_id = data.azurerm_client_config.current.tenant_id identity { type = "SystemAssigned" } }
AzAPI Option:
resource "azapi_resource" "ashcicluster1" { type = "Microsoft.AzureStackHCI/clusters@2023-11-01-preview" name = var.cluster_name location = var.region1 parent_id = azurerm_resource_group.ashci1.id identity { # Managed Service Identity type = "string" identity_ids = [] } body = jsonencode({ properties = { aadApplicationObjectId = "string" aadClientId = "string" aadServicePrincipalObjectId = "string" aadTenantId = "string" cloudManagementEndpoint = "string" desiredProperties = { diagnosticLevel = "string" windowsServerSubscription = "string" } softwareAssuranceProperties = { softwareAssuranceIntent = "string" } } }) }
Cluster Shared Storage:
Terraform: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_blob
resource "random_id" "storageacc1" { byte_length = 6 } resource "azurerm_resource_group" "ashcirg1" { name = "azure-stack-witness1" location = var.region1 } resource "azurerm_storage_account" "witness1" { name = "stg${random_id.storageacc1.hex}" resource_group_name = azurerm_resource_group.ashcirg1.name location = azurerm_resource_group.ashcirg1.location account_tier = "Standard" account_replication_type = "LRS" } resource "azurerm_storage_container" "witness1" { name = "witness" storage_account_name = azurerm_storage_account.witness1.name container_access_type = "private" }
Note – the above makes use of the random provider to prevent issues with Storage Account names (these need to be unique). See here for more information: https://registry.terraform.io/providers/hashicorp/random/latest/docs.
Azure Arc Setting/Registration:
This section will require some difference based on the version you are deploying – there are different processes pre 23H2, so please consult Microsoft Docs if you are not deploying at least 23H2. For 23H2… read on!
To register the nodes with Azure we need to run PowerShell on each of the nodes we are deploying:
Step 1 – Module Install:
#Register PSGallery as a trusted repo Register-PSRepository -Default -InstallationPolicy Trusted #Install required PowerShell modules in your node for registration Install-Module Az.Accounts -RequiredVersion 2.13.2 Install-Module Az.Resources -RequiredVersion 6.12.0 Install-Module Az.ConnectedMachine -RequiredVersion 0.5.2 #Install Arc registration script from PSGallery Install-Module AzsHCI.ARCinstaller
Step 2 – Setup Script:
#Define the subscription where you want to register your server as Arc device $Subscription = "YourSubscriptionID" #Define the resource group where you want to register your server as Arc device $RG = "YourResourceGroupName" #Define the region you will use to register your server as Arc device $Region = "eastus" #Define the tenant you will use to register your server as Arc device $Tenant = "YourTenantID" #Define the proxy address if your HCI deployment access internet via proxy $ProxyServer = "http://proxyaddress:port" #Connect to your Azure account and Subscription Connect-AzAccount -SubscriptionId $Subscription -TenantId $Tenant -DeviceCode #Get the Access Token for the registration $ARMtoken = (Get-AzAccessToken).Token #Get the Account ID for the registration $id = (Get-AzContext).Account.Id #Invoke the registration script. Use a supported region. Invoke-AzStackHciArcInitialization -SubscriptionID $Subscription -ResourceGroup $RG -TenantID $Tenant -Region $Region -Cloud "AzureCloud" -ArmAccessToken $ARMtoken -AccountID $id -Proxy $ProxyServer
The Stack HCI nodes should then be registered within the Azure Portal – for more information on this process, please see here: https://learn.microsoft.com/en-us/azure-stack/hci/deploy/deployment-arc-register-server-permissions?tabs=powershell#register-servers-with-azure-arc
Creating Virtual Machines:
Terraform:
Again, here the AzAPI option is utilised – the code for this is a large block of JSON embedded within Terraform, that provides numerous ways for us to adjust the required Virtual Machine. Note that before you can deploy a Virtual Machine, you will also need to deploy a Stack HCI Virtual Network – see here for more details on that. The code to create a Virtual Machine is shown below:
resource "azapi_resource" "symbolicname" { type = "Microsoft.AzureStackHCI/virtualMachineInstances@2023-09-01-preview" name = "default" parent_id = "string" identity { type = "SystemAssigned" } body = jsonencode({ properties = { guestAgentInstallStatus = {} hardwareProfile = { dynamicMemoryConfig = { maximumMemoryMB = int minimumMemoryMB = int targetMemoryBuffer = int } memoryMB = int processors = int vmSize = "string" } httpProxyConfig = { httpProxy = "string" httpsProxy = "string" noProxy = [ "string" ] trustedCa = "string" } networkProfile = { networkInterfaces = [ { id = "string" } ] } osProfile = { adminPassword = "string" adminUsername = "string" computerName = "string" linuxConfiguration = { disablePasswordAuthentication = bool provisionVMAgent = bool provisionVMConfigAgent = bool ssh = { publicKeys = [ { keyData = "string" path = "string" } ] } } windowsConfiguration = { enableAutomaticUpdates = bool provisionVMAgent = bool provisionVMConfigAgent = bool ssh = { publicKeys = [ { keyData = "string" path = "string" } ] } timeZone = "string" } } resourceUid = "string" securityProfile = { enableTPM = bool securityType = "string" uefiSettings = { secureBootEnabled = bool } } storageProfile = { dataDisks = [ { id = "string" } ] imageReference = { id = "string" } osDisk = { id = "string" osType = "string" } vmConfigStoragePathId = "string" } } extendedLocation = { name = "string" type = "CustomLocation" } }) }
Terraform – the (current) importance of using AzAPI:
AzAPI provides a method to extend the capability of Terraform by allowing Terraform to deploy to Azure using Azure Resource Manager JSON. In the case of new or preview features (which are not added until GA to the AzureRM provider), it provides a way that we can extend the capability of Terraform and use it to deploy these types of Resources. At the current time we need to use the AzAPI provider when working with Azure Stack HCI and Terraform, as the AzureRM provider has limited support for Stack HCI.
If you are planning to use the AzAPI provider, I would recommend exploring the following resources:
- AzAPI Docs – https://registry.terraform.io/providers/Azure/azapi/latest/docs
- VSCode Extension – https://marketplace.visualstudio.com/items?itemName=azapi-vscode.azapi
- AzAPI Examples Library – https://github.com/Azure/terraform-provider-azapi/tree/main/examples
Update, as of the AzureRM Provider version 3.114.0 you can now create Stack HCI Logical Networks, see here: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/stack_hci_logical_network
Conclusion & Next Steps
I hope this was a helpful post – happy Azure Stack HCI learning! If you are keen to develop your Stack HCI skills, I would recommend testing the Jumpstart HCIBox initially, and then consider deploying, testing, and importing Resources if you are working with Terraform – this will allow you to continue testing and using IAC with Stack HCI.
Thanks for reading!