Thursday, August 18, 2016

Full HA RDS 2016 deployment in Azure IaaS in < 30 minutes, Azure Resource Manager FTW!

More information on RDS on Azure IaaS
Remote Desktop Services (RDS) deployment on the Azure Infrastructure as a Service (IaaS) platform is becoming more common. The announcement of the deprecation of Azure RemoteApp, the turn-key solution on Azure to publish classic Windows applications, also made RDS on Azure IaaS one of the migration options going forward. Microsoft has also published various whitepapers that provide guidance to implement RDS 2012 R2 on Azure IaaS http://aka.ms/rdsonazure. Recently they have also updated this for Windows Server 2016 http://aka.ms/rdsonazure2016 which will be released this September of this year.

Automated deployments in the classic Azure Portal
I decided to take a closer look at the deployment itself, more specifically an automated deployment. RDS can obviously be deployed manually in Azure IaaS by creating new Virtual Machines, Virtual Networks, load balancers etc. Based on the classic Azure Portal (http://manage.windowsazure.com) this is what you would typically do. Optionally you could use Azure PowerShell to automate that process.

Automated deployments in the new Azure Portal
The new Azure Portal, codename Ibiza, (http://portal.azure.com) is all about Azure Resource Manager (ARM). ARM introduces a completely new way of thinking about your resources. Instead of creating individual resources, you start by thinking about the entire solution, a resource group, which contains all the resources you need for your solution. You manage and deploy a resource group as a sort of a logical unit, which helps identify all the resources a solution uses. Another benefit of ARM is that it allows you to retrieve billing and monitoring information for all the resources within a resource group and manage the access to those resources as a set rather than individually.

Besides the benefit of having all resources in logical units called Resource Groups, another huge benefit of ARM is the deployment itself. Sure you can create a Resource Group manually using the Portal or use Azure PowerShell. Typically, however, an Azure PowerShell script is sequential, you create a PowerShell script to automate the commands needed to create objects in Azure. When you run such a script those PowerShell commands are fired off sequentially creating your deployment. ARM provides the opportunity to have Azure create that same deployment for you in the most optimal way. For example, by defining dependencies ARM knows it must create a virtual NIC prior to the Virtual Machine and can for example create 10 Virtual Machines at the same time. This significantly improves the overall deployment time for any Azure deployment.

Where does JSON come into play?
You can feed ARM by something that is called a JSON (JavaScript Object Notation) template. JSON is a syntax for storing and exchanging data in lightweight data-interchange format and an easier-to-use alternative to XML. Basically you create a JSON template with the Azure objects you want to have created, provide that to ARM and ARM will provision everything for you in the most optimal way. The end result is an x amount of Azure Objects grouped together in an Azure Resource Group.

Introduction into JSON Azure Templates
There are various editors out there to create JSON Templates, in my case I choose Virtual Studio Enterprise 15 because it has awesome integration with the Azure Portal as you can start and monitor your deployments directly from Virtual Studio. Make sure you install the Azure SDK for this as well.
clip_image002
If you want to get started with JSON templates for Azure I can recommend to read the article Authoring Azure Resource Manager templates. It describes the JSON format and the template structure as well.

After getting familiar with the JSON template structure I recommend to look at several JSON template examples for Azure to sort of get the idea on how objects in Azure can be build. The Azure Quickstart Templates is great place to start, I based parts of my deployment on examples I found there too.

After installing the Azure SDK, you will see a new option in Visual Studio to create a new Azure Resource Group.
clip_image004

When you select this template you immediately see the power of the combination Azure SDK and Visual Studio! Directly from Visual Studio you can create predefined objects for Azure. If you want to start from scratch, you can select the option Blank Template.clip_image006

Even after the creation of the (blank) project you can easily add Azure Objects from within Visual Studio using the Add New Resource option.
clip_image008

JSON & ARM in action to deploy RDS on Azure IaaS!
What is described in the previous paragraphs is exactly what I have been working on for RDS on Azure IaaS. The goal was to create an automated RDS deployment in Azure IaaS using JSON Templates. As a starting point for the execution of this JSON template I assume that the following exists

- An active Azure Subscription
- A Virtual machine with a basic Active Directory deployment
- A Virtual Network containing a Subnet

To simply the process and focus on RDS for the most, I basically assume that the fictive customer already has deployed other resources to Azure, which is actually very common these days. However, adding the deployment of the resources outlined in the bullet list above is obviously no problem as well.

The screenshot below shows the described starting point in the Azure Portalclip_image009

So, what does my JSON template create inside the Azure Resource Group show above?

- A Storage account
- 2 Virtual Machines with the RD Connection Broker and RD Licensing role
- 2 Virtual Machines with the RD Gateway & RD Web Access role
- 2 Virtual Machines with the RD Session Host role
- Each Virtual Machine is created with a NIC and a fixed IP address
- Each Virtual Machine is joined to the Active Directory Domain
- 3 Availability sets are created and each set of 2 VM’s is added to an Availability Set
- A load balancer including the configuration to load balance RD Web Access & RD Gateway
- A public IP address for external access or RD Web Access & RD Gateway
- An Azure SQL Server
- An SQL Server database for the RD Connection Broker Role
- An RDS Deployment with all the RDS roles added to that deployment
- RD Connection Broker is configured as HA and the database is placed on Azure SQL
- The entire template leverages Azure Key Vault

As mentioned before you can trigger ARM to start building the resources you defined in your JSON Template directly from Visual Studio. To do so, select the Deploy option and provide the parameters to connect to the correct subscription and Resource Group.clip_image011

Basically what Visual Studio does is launch the PowerShell command to initiate ARM to process your JSON template. This means that you can also use PowerShell yourself to initiate ARM by running the script Deploy-AzureResourceGroup.ps1. However, you can track the deployment directly from Visual Studio as well because Visual Studio polls the ARM deployment and shows you the status changes! Below you see the first 2 minutes of the deployment where availability sets, NICs, Virtual Machines etc. are starting to be created.clip_image013

Upon completing, and again this only takes < 30 minutes, refreshing the Resource group in the Azure Portal shows the created deployment
clip_image014

After opening Server Manager, we can see that an entire HA deployment of RDS has been deployed and is accessible from the outside as well!clip_image016

Obviously ARM on it’s own can only deploy resources and configurations in Azure itself. So how does ARM add those servers to the domain, deploy the roles and perform the RDS deployment within the machines itself? For this to work, custom extensions are needed inside your JSON template. By using extensions, you can push DSC configurations to the deployed servers to perform actions inside the machines. And you can also use extensions to launch PowerShell scripts inside the Virtual Machines. In my case I’m using custom extensions to have DSC add the servers to the domain and launch various custom extensions to run PowerShell scripts to perform the RDS deployment, perform HA settings etc. A very powerful combination! I’m planning to dive a little deeper into the specifics of custom extensions in an upcoming blog post.

What’s also great about JSON Templates is that you can define parameter files. So I could run the exact same JSON Template against to 2 different Azure Subscriptions and use 2 separate parameter files to define specific settings for those 2 subscriptions. To give you an example, using the parameter file below I’m defining that I’m using Server 2016 (TP5) as the Server SKU. If I wanted the entire deployment to run Server 2012 R2, I would only have to change that single parameter here. And also, I define the credentials that my SQL Server uses inside the template file. Obviously not in plain text, but by using Azure Key Vault to store & retrieve credentials safely. General advice; use Azure Key Vault when dealing with passwords in ARM deployments!
clip_image018

Conclusion
Azure Resource Manager fundamentally changes any deployment on Azure! As far as I’m concerned, ARM should be the standard for any Azure deployment going forward! For this example, it helped to create an entire Remote Desktop Services deployment in less than half an hour! The JSON Template used also becomes your documentation, it specifies exactly how the deployment was performed, and allows standardization to the max!

Some additions that I’ve already planned for this JSON template are:
- Add the creation of a parametrized RemoteApp Collection
- Configure Deployment properties like SSL certificates & RD Licensing
- Configure specific collection settings like i.e. session timeouts, redirection options etc.
- Automate the creation of GPO’s to perform lockdown of the RDS environment
- Provide the option to use a custom template image for the RDSH environment
- …



9 comments:

  1. Great post! Are you thinking about sharing your templates!?

    ReplyDelete
  2. Yes - I'd love to see more of these templates :) However, it seems overly complicated to use Visual Studio for deploying VMs - at least if you're an IT-Pro rather than a developer. I wonder if that would be the way to go for us or if we should stick with PowerShell or maybe something with Azure Automation...

    ReplyDelete
    Replies
    1. Ho Jones,

      Thank you. In regards to Visual Studio, that is a fair comment! You are right that Visual Studio is the most optimal way to deploy a few VM's in Azure. Reason I chose VS here is to create a standardized way to deploy an entire RDS environment in a subscription. It allows to deploy the exact same RDS deployment in various (customer) subscriptions. But I agree there are many use cases to stick to PowerShell or use Azure Autmation.

      Delete
  3. See this
    https://blogs.technet.microsoft.com/enterprisemobility/2015/07/13/azure-resource-manager-template-for-rds-deployment/, and this
    https://github.com/Azure/azure-quickstart-templates/tree/master/rds-deployment

    ReplyDelete
    Replies
    1. Hi Michael,

      I provided this URL in the article already and mentioned I used those templates as a starting point. In case you're interested, I added many additional features in the mean time:

      http://microsoftplatform.blogspot.nl/2016/09/rds-on-azure-iaas-using-arm-json-part-2.html

      http://microsoftplatform.blogspot.nl/2016/10/added-new-features-to-rds-on-azure-iaas.html

      http://microsoftplatform.blogspot.nl/2016/10/azure-resource-manager-and-json.html

      Delete
  4. How do I kill the AD deployment and VNET deployments? I have a DC in azure and I have VNETS and subnets allocated for these deployments. I just don't know what I need to get rid of in the coding to cleanly eliminate those resources.

    ReplyDelete
  5. I see you only have an external load balancer, do you not need an internal load balancer for the RD Connection Broker? I have it setup (and working) using DNS RR but it seems to cause issues when a user is directed to the 2nd server. I followed the documentation to implement an internal Azure LB but it does'nt work. Also is there any guidance that states you cannot HA all the RDS roles on two servers?

    ReplyDelete
  6. Did I miss something or this template has never been shared? I would love to see it even if it's not finished.

    ReplyDelete
  7. Nice article, can you share your templates?

    ReplyDelete