This post will show how to deploy an Azure worker role running Apache Tomcat using Eclipse, where the worker role is joined to a VNet.
I have been working with a customer to deploy existing Java applications to Azure. One of their main requirements is to be able to communicate with on-premises resources using either a site to site VPN or ExpressRoute. Further, the components that they deploy must be able to communicate with virtual machines in separate cloud services within the same subscription, and those components must be accessible only from within the VNet. The components they utilize must not be accessible publicly over the internet. Finally, the components are currently deployed on-premises in an environment that is way under capacity in order to accommodate burst.
We first looked at Azure Websites because they are simple to use. While it is possible to integrate Azure Websites with a virtual network, however this does not grant access to the website from the virtual network, so this option doesn’t work for their scenario. We then looked at utilizing Azure virtual machines, but they were concerned about traffic bursts and pre-provisioning many virtual machines in order to use autoscaling of VMs.
Benefits of the Solution
Due to this customer’s particular scenario requiring advanced networking and ability to accommodate burst traffic, this was an ideal scenario to leverage Azure Role Instances. Azure Role Instances (aka Web Roles and Worker Roles) enable you to deploy the application to the Azure fabric and new instances are automatically provisioned or deprovisioned based on the autoscaling rules that you specify. The guest OS can be automatically updated, relieving you from many of the management tasks for the underlying operating system.
Further, because we are able to deploy the roles within an Azure Virtual Network (VNet), we are able to provide fast and secure communication between components as well as enable connectivity to on-premises resources.
Michael Washam wrote a great blog post that details how to join Azure Role Instances to a Simple Virtual Network in Microsoft Azure. Leveraging the content from his post, I was able to show the customer how to accomplish the task using Eclipse.
This particular customer that I am working with will deploy their worker role into a cloud service that needs to access resources in another cloud service. The solution that I will build will contain a virtual network with a worker role and two virtual machines, and another cloud service with a virtual machine that is not part of the virtual network.
The worker role that we deploy to Azure will be in its own cloud service, and we will deploy two VMs in their own cloud services to prove connectivity. Azure provides its own DNS that provides host-name resolution for virtual machines within the same cloud service, but does not span cloud services. In order to provide name resolution, we have to provide our own DNS. The easiest way to do this is to create a new Windows Server 2012 R2 image and create a new Active Directory Forest. That’s why I have the domain controller in the solution, because it will also create a DNS server. The virtual machine that is not part of the VNet will not have name resolution to resources within the second cloud service, proving that our DNS server is actually providing name resolution.
Create an Affinity Group
The first step is to create an affinity group. In the Azure Management Portal (http://manage.windowsazure.com), go to Settings / Affinity Groups and choose Add.
Provide a name and the region for your affinity group. The name doesn’t matter, I just use the location in the name as a convention so I can easily reference it later.
Create a Virtual Network
The next step is to create a virtual network. Go to Networks / New / Virtual Network / Custom Create.
On the next page, specify the name of the virtual network and use the same region as your previously created affinity group.
For the purposes of this post, we are going to leave the DNS server blank, and are not configuring point to site or site to site connectivity, we are just going to show how to deploy to a simple virtual network named kirke-java-west-vnet with just one subnet named JavaAppSubnet.
Click the Complete button (the check mark at the bottom right) to create the virtual network.
Create a new Active Directory Forest
I am not going to cover all of the required steps here as I’ve already written up the steps in my blog post, Install a New Active Directory forest on an Azure Virtual Network. Follow those steps to create the AD forest and then update the Azure Virtual Network to use that domain controller’s DNS. The key to creating the VM is to place it in the virtual network while you are creating it.
Once the VM is created, we assign a static IP, testing to see if the IP is available.
Next, follow the instructions in the blog post (Install a New Active Directory forest on an Azure Virtual Network) to add a disk and promote to a domain controller in a new AD forest.
After the VM is promoted to a domain controller, the VM is rebooted. Go to the Virtual Network and set the virtual machine as the DNS server.
Finally, restart the VM for the DNS settings to take effect.
Configure the Azure Role Instance in Eclipse
In my blog post, Creating an Eclipse Development Environment for Azure, I showed how to create a virtual machine that uses the Azure Toolkit for Eclipse. In that post, I showed how to create a simple Java application that is deployed to an Azure Worker Role running Apache Tomcat. Rather than rehash all the steps for creating the project, I will simply point you to that post for details on creating the initial project structure and Azure Deployment Project. Once you have the Azure Deployment Project created, the next step is to configure the Azure Role Instance using the Azure Toolkit for Eclipse.
In the Azure Deployment Project, locate the .cscfg file and open it, then go to the Source tab to view the XML markup.
Beneath the Role ending element, add the following markup:
Note that the roleName value needs to match the “name” attribute on the Role element, as shown in this image:
Make sure to Save All to save your work.
Enable Remote Access to the Azure Role Instance
In order for us to do some testing, we are going to need to be able to RDP to the Azure worker role. We can do this before we deploy, or even enable it for a previously deployed instance. In order to do this, we need a certificate. For our purposes, a self-signed certificate will work just fine.
In order for this to work in our environment, we need to enable .NET Framework 3.5. Just open PowerShell by clicking the icon in the taskbar.
In PowerShell, run the following command:
After a few minutes, .NET Framework 3.5 will be installed.
Now, in Eclipse, click the “New Self Signed Certificate” toolbar item.
I provide a password, then I then saved the .CER and .PFX files in the “cert” folder for my project.
Next, right-click the Azure Deployment Project and choose Azure / Properties.
Go to the Remote Access node and check the “Enable all roles to accept Remote Desktop connections with these login credentials” option. Provide a username, password, and the path to the .CER file that you just created.
Once you choose OK, the .CSCFG file will be updated with the values you just entered.
We can now publish our changes to Azure using the “Publish to Azure Cloud” button in the toolbar.
You are then prompted for the private key password.
Once the role is deployed, we can connect to it. Go to Cloud Services, Instances, click on the Staging tab, and the Connect button will be enabled.
You can now RDP into the Azure Role Instance that you just deployed!
Testing It Out
To prove how this works, I am going to create two new virtual machines in their own cloud services. Azure provides its own DNS, but name resolution does not span cloud services. In order to do this, I will need to provide my own DNS for the VNet.
The first virtual machine will be part of the same VNet. The second virtual machine will not be part of the VNet.
For both VMs, I will use a Windows Server 2012 R2 image.
For each VM, I will create a new cloud service. The first VM will be joined to the VNet. To join to a VNet, simply choose the virtual network from the dropdown.
The second VM will create a new cloud service and be in the same region, but not part of the virtual network.
Once the VMs are created, I RDP into them. Let’s just prove that the VM that is not part of the VNet (the VM named VM2) will not have connectivity. I show the IPConfig here to show it’s not part of the 10.0.x network that we are using for the other components.
OK, so that VM isn’t going to be able to connect, let alone use the domain controller for name resolution, so let’s move on to the case where things work.
The next test will test the VM that is part of the same virtual network. From VM1 (the one deployed into the VNet), I run a simple ping test using its IP address.
Cool, we can connect because this VM is part of the same VNet. Now, let’s try name resolution, since we provided our own DNS server. We first test by pinging the DNS server (corp.blueskyabove.us), and we see that it shows the reply from 10.0.0.7… proving it works.
OK, one last test. When we deployed our cloud service we configured it so that we could RDP into it. I connect and then run the same ping test to prove name resolution, and show ipconfig to show the DNS suffix is reddog.microsoft.com, which is consistent for worker roles deployed to Azure.
If we needed to communicate from the worker role to the virtual machine, we could update DNS to provide the name resolution (because Azure does not provide name resolution across cloud services).
Besides the fact that it’s cool, why did we do all of this? The fact is that in many deployments, you will need more than a single cloud service and will need name resolution across them. Further, you will use virtual networks to establish gateways to communicate to on-premises resources, in which case you would use your own DNS server to resolve to on-premises resources. It’s important to understand the connectivity options and how various components communicate.
Another huge benefit is that we also show how Azure roles (web and worker roles) can join in a virtual network. This enables scenarios such as Java applications that communicate to an on-premises Cassandra database in a secure manner.