Azure is pretty good at getting you up and running quickly. You can get from nothing to a solution in production very quickly. Whilst this approach definitely reduces time to market, it can introduce growing pains along the way. Let’s consider Cloud Services as a specific example of how growing pains might manifest themselves.
When you create a Cloud Service you get two IP addresses, one for each slot, Staging and Production. These are allocated from a huge range Azure manages for each region and you have no guarantee of which IP you’ll get. When you’re setting up your Cloud Service you probably didn’t worry about that. As time passes and the solution matures you may have used those IP addresses to create firewall rules to your databases in Azure and perhaps even giving them to third parties in order for them to be whitelisted to allow your application to access another service.
Now the specific IP addresses that were allocated at random by Azure are now critical to the success of your solution. And guess what, those IP are not as secure as you might think. If for whatever reason your Cloud Service is deallocated, the IP addresses will be lost. When you recreate the Cloud Service it will be allocated a new IP address. All of your firewall rules now don’t work. That might not be a major problem for your own rules which you can hopefully change rapidly but it might be a problem if you are working with a supplier that has a 2 week turn around SLA for “minor changes”.
This is where Reserved IPs come in. They are a means to control the life span of an IP address by effectively taking ownership of it in your Azure subscription. Now Azure will never reclaim an IP Address whilst it is reserved in your subscription. The following PowerShell command will create a new reserved IP address.
New-AzureReservedIP –ReservedIPName very-important-ip –Location "UK South"
And this command associates the IP address with an existing Cloud Service.
Set-AzureReservedIPAssociation -ReservedIPName very-important-ip -ServiceName MyBrilliantService
However, we might already have a Cloud Service and its IP address has become important. Changing it would cause unacceptable problems. Luckily it is possible to create a reserved IP from an existing cloud service. The following Powershell command creates the reserved IP using the IP address of the Staging slot of a Cloud Service and also creates the association between the reserved IP and the Cloud Service
New-AzureReservedIP –ReservedIPName very-important-ip –Location "UK South" -ServiceName MyBrilliantService -Slot Staging
A couple of notes about these commands
-Locationis the region in which the reserved IP will be created
-Slotis an optional argument on these commands. It lets you target either the Staging or Production Cloud Service deployment slots. Production is the default.
- Reserved IPs are a “classic” Azure feature. As such resource groups are a meaningless concept. You’ll see all your reserved IPs deployed to a Default resource group.
- The first five reserved IPs are free but you should be aware managing more than this is not. You are charged based on the time you hold on to an IP address, which is in effective, to dissuade you from holding on to a large number of publically routable IPV4 addresses which are increasingly become a limited resource. https://azure.microsoft.com/en-us/pricing/details/ip-addresses/
Let’s talk about deallocation. Over the lifetime of your solution your architecture will evolve. You might need to move an IP address from one resource to another. You may want to release IP addresses that you no longer use. Once you have an IP address reserved you own it until the reserved IP resource is deleted. The only way it can used is by creating an association. To use it elsewhere it must be deallocated from the original resource and associated with the new resource. It is important to note that during the process the original resource will receive a new IP address from Azure’s pool.
When playing around with reserved IPs I noticed a couple of behaviours that are worth noting.
Firstly, once a Cloud Service has a reserved IP you must specify its name when deploying the Cloud Service. Remember that the name of the IP should map to the one used for the particular slot. You do this by adding a NetworkConfiguration section to the service ServiceConfiguration file
<?xml version="1.0" encoding="utf-8"?> <ServiceConfiguration serviceName="My Service" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="4" osVersion="*" schemaVersion="2015-04.2.6"> <Role name="MyRole"> … </Role> <NetworkConfiguration> <AddressAssignments> <ReservedIPs> <ReservedIP name="very-important-ip"/> </ReservedIPs> </AddressAssignments> </NetworkConfiguration> </ServiceConfiguration>
I found when the reserved IP was not referenced I received the following error when deploying. I believe by not specifying the IP the deployment process assumes you are changing the IP which is not allowed
Set-AzureDeployment : BadRequest: A reserved IP cannot be added, removed or changed during deployment update or upgrade.
Secondly if you added a reserved IP to one slot of your Cloud Service you must also add one to the other if you want to be able swap the deployment slots. You’ll get this error if you forget.
Move-AzureDeployment : BadRequest: Cannot swap VIPs when only one deployment has a Reserved IP.
Finally, as the number of Cloud Services in a particular environment grows and the number of environments increases the management overhead for the individual reserved IPs increases greatly. Let’s say you have 6 cloud services in 4 environments. That is:
6 cloud services * 2 deployment slots * 4 environments = 48 reserved IPs
In that case it might be better in the long run to build up a VNET with a subnets for each environment and then have a Virtual Network Appliance presenting these network to the Internet on a smaller range of IPs.
For further reading on Reserved IPs take a look at the following links.