Part 1 – Azure Environment Preparation (This Post)
I have found myself involved with a lot of projects focused around Microsoft Azure of late and one of those was to deploy Horizon Cloud on Azure. If you are new to Horizon, this is VMware’s End-User Computing offering that builds on top of the Azure public cloud platform. It is a virtual desktop environment that allows you to deploy both Windows and Linux desktops.
Microsoft does have their own offering called Windows Virtual Desktop, which to be fair looks like a decent offering and a lot of the license costs are rolled in with M365 licensing. However, if you are a VMware house, the simplicity, and flexibility offered by Horizon Cloud is compelling. You are not limited to deploying on a single cloud as you have options to deploy multiple desktop pods across Azure, AWS, IBM Cloud, and your own private cloud to name a few. This means you can deploy desktop workloads in a location that makes sense for the business use case in terms of geographical location and from a cost standpoint. Let’s say for argument’s sake you are a business based out of the UK, but you need to stand up a small desktop pod for a new venture for users working from Japan for 6 months. Why invest in capital expenditure for the hardware when you could stand up a desktop environment that runs only when it needs to, in Japan? Users are not connecting back to the UK to access resources, and the company only pays for the resources it needs, during business operating hours. As you can see from the Azure region’s webpage, there is a lot of choice in terms of where these workloads can be deployed.
One of the key draws for me with this project is that we can make use of the Windows 10 Multi-Session host image in Azure with Horizon. You can read a bit more about that here, but in essence, it is a Windows 10 desktop that can support multiple users connected to it concurrently. From a cloud consumption standpoint, this is awesome. We don’t need to offer a 1 to 1 desktop to user ratio, which means that cloud consumption costs are kept to a minimum. It also means that users get the full Windows 10 experience rather than some pseudo-Windows 10 desktops running on a Windows Remote Desktop Services server.
But I digress, the purpose of this blog series is to show you how you can stand up a simple Horizon Cloud pod on Azure.
Part 1 of this blog series will build upon the VMware quick start documentation to prepare Azure in readiness to deploy Horizon Cloud on Azure.
I am not going to lie, I am fairly new to Azure but I have completed an excellent course from Cloudskills.io for the AZ-104 Azure Administrator exam and since passed the exam.
Now for this environment, I am going to work with a self-contained environment in Azure. This would ordinarily likely be linked back to an on-premises environment with some kind of site to site VPN or an Azure Express Route, but this guide will give you a good taster of how to get things started.
The guide will break the components down to their simplest components, I will assume no prior knowledge of Azure.
We need the following items configured in Azure to be able to make this environment work.
- Subscription – The container that the costs for the environment are associated with.
- Resource Group – A container that is part of the subscription that other resources are associated with.
- VNET – A virtual network with a defined address space for IP addresses and subnets defined for infrastructure and desktop resources and a reference for DNS services.
- Azure Active Directory – Used as a minimum to define a Service Principal account. This is a service account used by Horizon Cloud to deploy HorizonCloud services into Azure
- Virtual Machine – A stand-alone domain controller that will provide user login for end-users as well as DNS services for Horizon Cloud.
Step 1 – Subscription
If you have not already, look at setting up a subscription in Azure. This could be linked to a credit card or on a CSP (Cloud Solution Provider) model amongst others. This is ultimately where all the costs for this solution will be captured and billed against.
Step 2 – Resource Group
Creating a resource group is a pretty straight forward affair. When logged into the Azure portal, search for resource group and then click to create a new one.
Link the resource group to the subscription created in step 1, give the resource group a meaningful name, and define in which Azure region the resource group should reside. If you chose to in the future, you can delete the resource group to delete all resources contained within it. Don’t have one resource group for everything, create one per project, or item type, etc.
To make it easier to find resources in Azure, it is good practice tag those resources. Just remember that resource tags do not propagate down from a resource group.
Click to create the resource group.
And you should have a new resource group.
Step 3 – VNET
The VNET or Virtual Network is where the network address space and network subnets are defined as well becoming the network integration layer for virtual machines, firewalls, etc.
Click into your new resource group and click on the Add button.
Search for and choose Virtual Network. Click create.
Choose the subscription and resource group that has already been created. Give the VNET a meaningful name and define the region it should be registered against.
The default address space is defined as 10.0.0.0/16 and the default subnet is defined as 10.0.0.0/24. If you plan to connect the Azure environment to another Azure VNET or to another location via a VPN, ensure that the address spaces do not overlap.
The defaults were fine for my use case. In this example, we will define 4 total subnets within the address space. They are Infrastructure, which will be used by the domain controller and the Horizon Cloud servers. Desktops, which will be used by the Horizon Windows 10 desktops, DMZ which will be used by the external Horizon Unified Access Gateways and a 4th subnet that will be defined later for use with the Azure Bastion service.
I renamed the default subnet to Infrastructure. It is important to ensure that the microsoft.sql service endpoint is available for this subnet. It is used by some of the Horizon services.
The Desktop and DMZ subnet address ranges are defined as below.
On the next screen, you have the option to enable Bastion Host on the VNET. The Bastion Host service allows you to connect to a virtual machine from within a browser window without having to expose the virtual machine over the internet either by RDP or SSH access. It keeps things a little more secure.
The Bastion service also needs a public IP address associated with it, that can be defined here. I found that the Bastion service was costing roughly £4-5 per day to run. The beauty of it is though is you can deploy a Bastion service only when you need access to a virtual machine.
Tag the resources so they can be found easily in the future.
Confirm all the settings look correct and then click to create the VNET.
Step 4 – Service Principal
Think of service principal as a service account that would be used in a traditional active directory environment. It is the account with enough permissions to be used by Horizon Cloud to deploy additional components in Azure. There is more info about service principals here.
To define a service principal, first, we need to browse to Azure Active Directory in the Azure portal and then click on App Registrations. Then choose to add a new registration.
Give the service principal a name, something meaningful like Horizon Azure access, and ensure that the account type is selected as below. Click on register.
Once the account has been registered click on overview and make a note of the Display Name, Application ID, Directory ID, and Object ID. You will need these later on when deploying HorizonCloud.
Now we need to associate a client secret to the service principal. Think of it as a password for the service account. Click on certificates and secrets and then click on new client secret.
Give the client secret a description and define how long it is valid.
Make a note of the automatically generated client secret for use later.
Now, we need to give the service principal appropriate permissions within Azure. The account needs to have a contributor role to allow it to create new resources.
Click on Access Control and click on add a role assignment.
Choose the contributor role type and search Azure AD for the service principal account that was created earlier.
The service principal is now configured.
Step 5 – Resource Providers.
Resource providers in Azure provide access to things like storage, Azure AD, Network access, etc. Horizon Cloud makes use of several different resources in Azure, we need to ensure that they are all in a registered state at the subscription level.
Click into the Subscription that was created as part of the first step and then click resource providers. Ensure the following resource providers are registered.
Step 6 – Deploying a Domain Controller Virtual Machine
We could make use of Azure Active Directory Domain Services here, but for the cost of running a VM as a DC VS running Azure ADDS, they are pretty much the same per month. A domain controller is easy enough to deploy, so that is the approach we are taking here.
We need to deploy a virtual machine. Search for virtual machines, click add choose virtual machine.
Ensure the subscription and resource group we created earlier are selected. Give the VM a name, choose the correct region, and choose the relevant operating system to deploy. I went with a 2019 server. The server does not need additional resilience nor does it need to make use of spot instances.
Choose the VM size. DS1_V2 is plenty for this demo environment. Define a username and password to use to log into the operating system. I disabled inbound public ports. If you recall earlier on, we created the Bastion service that will allow us to connect to this VM.
Choose if you are entitled to Azure Hybrid Benefit for operating system licensing and click next.
On the next screen, I changed the disk type to standard HDD, this server doesn’t need any more than that. There are no additional data disks added.
On the networking screen, choose the VNET we created earlier and the Infrastructure subnet. No public IP or inbound ports are required. The bastion service will handle this requirement.
On the management screen, choose the options you wish. I left boot diagnostics enabled. This will create a new storage account to store the logs. All of the other options can be configured once the VM has been deployed, like backup or auto shutdown.
In the advanced section, you can choose to install additional extensions like monitoring agents or to run a post-deployment script. I left this empty for this particular deployment.
Define tags as we have done for all other resources.
And then create the VM.
Step 7 – Configure The Domain Controller Virtual Machine
In this step, we will connect to the VM, configure Active Directory Domain Services, and also give the VM a static IP address. The static IP address is key as this server will be acting as the DNS server for the VNET.
Let’s define the static IP first, this is done at the Azure layer, not within the virtual machine.
With the VM selected, click on Networking and then click on the Network Interface name.
Click on IP Configuration and then click on the IP address.
Change the private IP address assignment to static and then define the static IP address.
Once this is complete, connect to the VM using the Bastion service. Click connect and choose Bastion
Populate the username and password that was generated when the VMwas deployed to allow you to connect to the VM.
Then configure Active Directory Domain Services. I used a script to do this, you can find this in one of my previous blog posts here.
Step 8 – Update DNS on the VNET.
This step will ensure that the domain controller is used to provide domain services for the VNET which ultimately will be used by the Horizon Cloud environment. It ensures that desktops and infrastructure VM’s will register against the domain correctly.
Click on the virtual network, select DNS servers and then change to a custom DNS server pointing to the IP address of the domain controller.
Check out the other parts in this series.