Introduction:
Microsoft Server 2019 introduces a lot of enhancements to Microsoft Remote Desktop Services specifically on Azure integration. Microsoft hybrid strategy is pushing the boundaries of technological advancement to all of its services ultimately making the move to the cloud seamless and inevitable.
RDS is considered to be the underdog in the EUC realm but that is certainly a fallacy. Many Application/Desktop virtualization requirements can actually be covered by RDS and I have seen this over and over again in the market. Integration with Azure services further strengthens RDS offerings and with the newly announced Windows Virtual Desktop service, things are looking good for Microsoft in the VDI and DaaS world.
Competitors tend to undermine Remote Desktop Protocol because of its main use in remote administration but the protocol has been significantly enhanced in the past years especially in the audio/video/graphics area now with RDP 10.6 available on Server 2019 and Windows 10 1809 (has been pulled out recently due to a serious bug). Just recently in one of my projects, RDP outperformed another VDI vendor protocol , on a very high latency WAN link with GPU requirements which really showed me the advancement of this protocol.
The following is a comprehensive video describing the enhancements of RDS in Microsoft Server 2019:
Architecture:
The purpose of this post is to demonstrate the deployment of an highly available on-prem (sue me) Remote Desktop Services 2019 with Azure SQL Database for Connection Broker HA and VMware NSX ESG for load balancing all RDS components. Will also be installing and configuring RDS HTML5 preview portal for the sake of it and showing some of the policies required to get things running smoothly.
The following represents a high level architecture for the deployed highly available RDS components, note that I wont deploy full VDI, which is why a Windows 7/10 template is missing from this diagram:
The following represents a table describing the deployed highly available RDS components, note that I will deploy the licensing roles on the connection broker servers:
Name | Description | LB Name |
RDS-CB-01 | RDS Connection Broker 1 | RDS-CB-HA |
RDS-CB-02 | RDS Connection Broker 2 | |
RDS-CB-01 | RDS Licensing 1 | |
RDS-CB-02 | RDS Licensing 2 | |
RDS-WB-01 | RDS Web 1 | RDS-WB-HA |
RDS-WB-02 | RDS Web 2 | |
RDS-GW-01 | RDS Gateway 1 | RDS |
RDS-GW-02 | RDS Gateway 2 | |
RDS-FS-01 | File Server UPD DFS-R 1 | DFSR |
RDS-FS-02 | File Server UPD DFS-R 2 | |
RDS-SH-01 | RDS Session Host 1 | |
RDS-SH-02 | RDS Session Host 2 | |
RDS-VH-01 | RDS Virtualization Host 1 | |
RDS-ESG-01 | NSX Edge Gateway Service |
Requirements:
-
Virtualization Infrastructure for session based deployment that can host all required servers (can be any hypervisor, must be Hyper-V for VDI integration).
-
Active Microsoft Azure Subscription for Connection Brokers HA SQL DB.
-
VMware NSX Edge Gateway Service Appliance with routing configured for RDS components networks.
-
Microsoft Hyper-V 2019 Host/Cluster if VDI is to be implemented with RDS with Windows 10 base image template.
-
Connection Brokers will require internet access either direct or through proxy to reach the Azure hosted SQL DB for HA.
-
Two public IPs NATED to NSX ESG IP used for RDS Web service load balancing and Gateway service load balancing for remote access.
-
DFS-R for User Profile Disks consumes double the same so the use of a file server failover cluster is recommended if shared disk in an option ( Shared VHD in Hyper-V , ISCSI target in vSAN, or SAN ).
-
Microsoft Server 2019 template with a customization script for RDS backend servers. Microsoft Server 2019 optimized template (Citrix Optimizer if you don’t know exactly what you are doing or VMware OS Optimizer if you really know what you are doing) for session host servers.
-
Trusted public certificate for remote access. Trusted internal certificates for all components. Wildcard would save a lot of hassle.
Deployment:
Step 1: Deploy all RDS infrastructure servers using a template and customization script to get OS ready for roles deployment.
Step 2: Connect to RD-CB-01 (Connection Broker 1) and add all servers to Server Manager in order to start adding RDS roles to all components.
Step 3: Adding Connection Broker, Web, Licensing, and Gateway roles for 01 servers for now. Don’t try to add secondary servers for any role as of now as that is configured later.
Navigate to the Remote Desktop Services tab on the left and click on the green tab above RD Gateway.
Navigate to the Remote Desktop Services tab on the left and click on the green tab above RD Licensing.
We can configure certificates now but when HA is configured for every component it has to be reconfigured so leave it for now until all HA is configured then we will apply certificates.
Step 4: Configure RD Licensing High Availability, Right Click on the RD Licensing tab and Add RD Licensing Server. Configure licensing role on each server to activate and import required RDS CAS licenses.
Note that as of now Licensing does not have native HA so these added licensing servers are used in order (In Preview currently native licensing HA using DB which would not require independent configuration of licensing servers anymore and can be load balanced).
Now that the second RD licensing server has been added, its time to configure the licensing server on each server. To maintain HA since it is not native as of now, we need to split the licenses between the servers. I don’t have CALS as of now but follow the below and make sure that licenses are assigned to both servers.
Step 5: Time to configure Connection Broker High Availability using Azure SQL DB. For that we need to create the Azure DB, allow access from Connection Brokers Public IP, Install SQL Client on Connection Broker, and configure Load balancing for the same.
I want to keep all load balancing components till the end, so for just initializing the CB HA, I will create a DNS round-robin for the A-record of the CB HA name then later on will delete those records and create the A-record pointing to the LB virtual server IP on NSX.
Right Click on RD Connection Broker and choose configure High Availability to start the process.
Login to Microsoft Azure and create an SQL empty Database.
Go to newly created resource and click on the Set Server Firewall Tab on the top middle. Here we need to add the public IP that both Connection Brokers are connecting from ( A good way to know that is open the portal from the CB servers and Azure will show you the public IP being used ). Click on Add Client IP to add the public IP of the connecting machine, if you have multiple public IPs used for internet then make sure to add them.
Navigate back and go to DB Properties tab on the left then click on “Show Database Connection Strings”, go to ODBC tab, copy the content (insert your DB password), and note the version of SQL client listed in copied text. The version of this SQL client will need to be downloaded and installed on all CB servers.
Time to add the second connection broker after HA has been configured. Make sure the SQL Client 13 as per the ODBC settings has been installed on the second connection broker.
Mind the Certificate errors, after we configure the final HA for RD Web and RD Gateway, we will go on and configure certificates for all RDS components to avoid doing it multiple times.
Step 6: Time to configure RD Gateway high availability so right click on RD Gateway and click on Add RD Gateway Servers. Before we needed to do some manual work when RD Gateway HA was enabled to the authorization policies but with 2019 all seems auto-configured so no manual work.
Step 7: Time to configure RD Web HA, right click on RD WEB and Add RD Web Access Servers. Note that for Load balancing, we will need to configure some IIS settings as well on each RD Web server as detailed below.
Lets configure certificates now that all components have been configured with HA so click on the certificates tab in the wizard or on the main RDS page click on Tasks, Edit Deployment Properties, Certificates.
For every component, click on select existing certificate, point to the certificate and click apply, then move on to the other component, it has to be applied one by one. I have a wildcard certificate which I use internally and externally since its the same domain but just make sure if you are doing single certificates that they are issued to the HA hostname that will be assigned for every RDS component.
Lets navigate to IIS administration on every RD Web server to configure IIS to support load balancing which will be configured soon.The exact same values for Feed, FeedLogin, and Pages must be identical on all RD Web servers so Open IIS Manager, navigate to Default Web Site, RDWeb, Feed, right click Machine Key and Open Feature.
Remove the checkbox beside Validation Key “Automatically generate at runtime” and Decryption Key “Automatically generate at runtime” , then click on Generate Keys on the right side under Actions. Apply the changes the copy the content of both boxes.
The same keys generated above will be pasted to the same boxes on Feed, FeedLogin, and Pages on all RD Web servers.
Since we are here, lets make the default page for these RD Web servers redirect to the /RDWeb since by default it does not which would save end users the hassle of having to add /RDWeb to reach the RDS page. This has to be done on all RD Web servers. Navigate to Default Website in IIS and open HTTP Redirect.
Step 8: Now to create a collection and add the session host servers for users to be able to open shared desktops. We have two session host servers which have been optimized using Citrix Optimizer. Now is the time to install all required applications for end-users.
Because RDS does not have auto-provisioning for Session host collections unlike VDI collections that being for creation and also updating, every server needs to be created/updated manually and added to the right collection. Its a good practice to create a template with all required software for every host collection required and use it to add new session host servers.
Navigate to Collections on the left, go to TASKS on the upper right, and click on Create Session Collection.
Here is where the configured DFS-R namespace is used to store users user profile disk which is created per session host collection.
Step 9: Lets do a test to make sure that everything is working as planned up to this point after which we will start configuring load balancing. Connect to RD Web 01 and RD Web 02 to make sure both are operational and a session desktop can be launched.
Out of the box configuration will allow SSO when only using Internet Explorer since it has an RDS extension installed and by SSO I mean no password prompts when an icon is launched for a session or application. In order to enable the same for for other browsers, we need to do some setting changes for the session collection through PowerShell and also add couple of group policies for SH servers.
Here are some of the group policies I have configured for no prompt password from non IE browsers but I urge you to be careful in what is being applied as this is a lab environment. This can be taken a step further for internal users to enable true SSO so users are automatically logged in to the RD site without having to enter username/pass but that will require editing the RDWeb config file something that I wont do but plenty of resources are available online for the same.
Open Administrative PowerShell on the Connection Broker and apply the following command to your session collections. If you are going to copy the command just rewrite the quotation marks so that they are displayed correctly:
Import-Module remotedesktop
Get-RDSessionCollection
Set-RDSessionCollectionConfiguration –CollectionName “Shared Desktops” –CustomRdpProperty “connection type:I:1 `n networkautodetect:I:0 `n authentication level:I:0”
Step 10: Time to configure load balancing for Connection brokers, Web servers, and gateway servers using VMware NSX Edge Gateway Services. Note here that RDS components do not have to be deployed on NSX prepared VMware clusters but can be on any platform even physical as long as routing is configured between NSX ESG network and the network that the RDS components are configured on.
Another note here is the RD Gateway does UDP as well on port 3391 but because NSX ESG load balancing cannot monitor TCP and UDP services under the same LB virtual server, I am going to stick with TCP 443 for gateway so no UDP will be used which might impact performance.
Navigate to vCenter Networking & Security, click on NSX Edges, and click on the green + to create a dedicated ESG for RDS LB. This ESG will have three IP addresses, one for CB, one for Web, and one for Gateway. In DNS, we will create the LB hostname for each service and point to its respective IP on ESG. One Public IP will be Natted to Web URL LB hostname that users will use to access and another public IP will be Natted to Gateway URL LB hostname.
After the ESG has been created, double click on it and navigate to Load balancing, click Edit on the right, and enable load balancing feature with logging.
Navigate to application profiles and add an application profile for every service that is going to be load balanced with required protocol.
Navigate to Service Monitoring and add a service monitor for every service. Feel free to change the metrics depending on your load balancing/Failover requirements. For the RDWeb service monitor, make sure to add /RDWeb to URL so that it checks the actual application not just the port.
Navigate to Pools and add a virtual pool for every service, this pool will have the virtual machines required to be load balanced which can added by IP if the RDS infra is not hosted on vSphere or can be added as a virtual machine is the RDS infra is hosted on vSphere.
Navigate to virtual servers and create a virtual server for every RDS service with its respective LB IP which will also be created in internal and public DNS to reflect the same.
Delete the Round Robin connection broker records we created to configure HA earlier and lets create an A record for every service pointing to its load balanced virtual server on internal DNS.
On External DNS, create A records for Web and Gateway pointing to the public IP used for Natting which is pointing to the LB IP of each service.
Test the configured load balanced servers internally and externally to make sure that everything is operational.
Step 11: Add a Virtualization Hyper-V Host/Cluster to enable RDS to create VDI Windows 10 Pools. I wont go over creating a VDI Pool but it is fairly straight forward, just make sure to create a Windows 10 optimized base image and to sysprep (generalize/shutdown) it when done.
Deployment settings will have two added options after a virtualization host has been added, one is for specifying the OU that the virtual desktops machine accounts will be stored and the other for specifying where the copy of the base image will be stored during VDI collection creation (VDI machines will be stored on the default location of Hyper-V that being local or cluster). Make sure to click Apply so that the OU is granted the required security settings for VDI provisioning.
Step 12: Microsoft has released an HTML5 based web portal for launching RDS resources within a browser which is currently in technical preview. This needs to be applied on all RD WEB servers and if you choose to make it the default site, make sure HTTP Redirection is changed to point to the new URL for this service which is /rdweb/webclient/index.html .
Open an Administrative PowerShell on each RD Web server and run the following commands. Export the wildcard cert or the RD Web LB hostname cert as a .cer ( without private key ) and save on C:\ . Licensing also needs to be changed to Per User licensing rather than Per Device.
Find-Module –Name PowerShellGet
Install-Module –Name PowerShellGet –RequiredVersion 2.0.1 –Force
Import-PackageProvider –Name PowerShellGet –RequiredVersion 2.0.1 –Force
Install-Module –Name RDWebClientManagement –Confirm:$false
Import-RDWebClientBrokerCert c:\wildcard.cer
Install-RDWebClientPackage
Publish-RDWebClientPackage –Type Production –Latest
Many customizations can be done on the RD Web page to make it more user friendly and you just google customize RDS 2012 or 2016 to find many great online resource for the same. You can remove the domain extension requirement, change the logos, change the background, add a disclaimer, add a change password link and much much more …
Conclusion:
RDS has gone a long time way since its introduction with Windows NT Server 4.0 Terminal Server Edition and Server 2019 is a great example of the innovation being put into this technology. Yes many defacto-standard features are still missing like auto-provisioning for Session hosts, an adequate web interface, and many others but I can still see RDS dominating a much bigger market share if positioned correctly.
In the end, Microsoft is making money from RDS whether one uses it or not, since RDS CALs are a requirement when shared desktops/applications are used with Citrix and VMware not to mention Desktop VDAs as well. I believe this is why Microsoft is not heavily investing in RDS as a VDI solution and now shifting to DaaS on Azure which financially makes much more sense investment wise for them.
As soon as Server 2019 latest build is up on Azure, I will demonstrate the same using Azure LB for HA and Azure AD for authentication.