Greetings. Today we’re happy to share an article by Robin Shahan, one of the authors of our recently published free ebook Microsoft Azure Essentials: Fundamentals of Azure. Enjoy!
Robin here. One of the common uses of Azure is the dev/test scenario. In most cases, you can replicate all or part of your on-premises infrastructure or production Azure infrastructure in Azure and use that for development, staging, and testing.
There are several benefits related to using Azure for this scenario, not the least of which is saving you from having to purchase hardware that sits around unused when you are not doing development or testing. I covered the business case for using Azure for this scenario in the free Fundamentals of Azure ebook (see Chapter 9, “Business Cases”) that Michael Collier and I wrote. In this article, I want to talk about considerations to think about when setting up your dev/test environment.
Before you start, give some thought as to what you want to do and how you want to do it. For example, you may decide you want to be able to have three environments -- one for developers, one for staging/testing, and one for production. If possible, separate out the three environments into separate subscriptions. If you can’t do that, can you at least separate development and staging from production? Or do they all have to be in the same subscription?
You also want to figure out what nomenclature you are going to use for your objects in Azure (more on that below).
You might want to be able to create the staging environment and then be able to shut it down and delete it, so you are not paying for it while you're not using it. This can even be scripted and you can just run the script when needed. You can get even more complicated, and decide you need to run a test version of an application against a production database (dangerous, but sometimes required).
Let's look at some of the scenarios you can implement. These are examples of how you might use Azure for dev/test, not definitive answers. Every company's infrastructure is different, and you will have to figure out what works best for you. Fortunately, everything is virtualized, so it's kind of like Lego® – if you don't like what you have built, take it apart and use the pieces in a different way.
Naming conventions: Naming your services, storage accounts, and so on
First, think about naming your services. You should pick a naming standard for your Azure objects. For production, this is pretty easy, you can more or less name them as you like. But what if your staging and development infrastructure is in the same subscription as production? It can get very confusing.
What I’ve done in this case is set the production names, then prefix the same names with “st” or “dev” to indicate staging and development versions of the same object. Or you can put “st” or “dev” after the object name, whichever works for you. Note that if you put the label in front, all of the staging services will appear together in the sorted list in the portal, and the same for development. If you take this a step further and start the production objects with p, or the first couple of characters of the company name, the production objects will also sort together.
For example, let’s look at PaaS cloud services. If you have a web application running in a web role (PaaS cloud service), you might name the cloud service for the production version "mycompany", the cloud service for the staging version "stmycompany", and the development cloud service “devmycompany”. If you’re consistent, you always know if a service is being used in production, staging, or development.
You can carry this naming convention through all of your infrastructure. Whether your dev/test scenarios are in the same subscription as production or not, this is nice to do because it makes it completely obvious which environment is being used at all times.
Your production environment uses Virtual Machines
For Azure Virtual Machines, you can create new VMs and install software on them. To create multiple copies of the same VM, you can use the Capture feature to create a generalized image of the VM which includes both the OS and the data disks. This will register the image in your Image gallery, and you can use it to provision multiple copies of the same VM. You can also use this image to create one or more new VMs for dev/test.
If you don’t have a captured image, your setup is complicated, and you have enough instances running in production that you can afford to temporarily lose one, you could capture an image of one of the production instances and use that to create your VM(s) for dev/test. The reason the number of instances is important is because the Capture feature deletes the VM that you’re capturing, so if it’s a production instance, you have to turn around and re-provision it from the image.
You can write a PowerShell script to create custom VMs. You can then use these scripts to create and deploy virtual machines identical to what you have running in production, but with dev/test versions of software on them. You can also have a script to deallocate the VMs when you're finished, so you won't be charged. To deallocate a VM, you can shut it down in the portal or with PowerShell. If you do this, it incurs no more charges except for storage of the VHD file. Note that if you shut down the VM from within the VM itself then Azure will not deallocate the VM and you will continued to be billed for it.
There are other tools available for managing and configuring VMs that can be used to create your dev/test environment. One such tool is the Azure PowerShell DSC (Desired State Configuration) extension, which you can use to upload and apply a PowerShell DSC configuration on an Azure VM. For all developers using Linux or Mac (or Windows), you can use the Cross-Platform Command-Line Interface (xplat-cli) tools. And last, but not least, Chef and Puppet can both be used to manage and configure your VMs.
Your production environment uses PaaS cloud services
In this case, you want to figure out which way of retaining the configuration data for the various environments makes sense to you.
Multiple configuration files in one cloud project
For PaaS Cloud Services, you can set up multiple configuration files in the same cloud project, with the configurations pointing to production, staging, and development resources that are used, such as storage, a database, or another cloud service. Here’s a solution set up this way; you can see the different .cscfg files.
Once you have this set up, you can publish directly from Visual Studio and select the appropriate configuration file. You can also create the deployment package and upload it to the appropriate cloud service manually or automate the cloud service deployment.
Note that the image above shows multiple cscfg files, but only one csdef file. The cscfg file has the role names, instance counts, configuration values, and so on. The one csdef file is used with whichever configuration you select when you publish. It has a list of all of the configuration settings (but not the values), setup tasks (if applicable), the size of the VM to be used, and so on. The value you want to especially note is the VM size.
Using this methodology of multiple configuration files in one cloud project, you only have one place to set the size of the VM regardless of whether you are publishing to staging or production. You may not want to use the same sizes for staging and production, especially if you are using medium or larger VMs in production and small VMs in staging. In that case, you either have to change this every time you publish, or you have to have another solution.
Multiple cloud projects with their own configuration settings
This solution is a bit cumbersome at first, but will provide you with the ability to publish completely different configurations to all three environments, including different VM sizes.
To do this, add separate cloud projects for production, staging, and development to the solution, selecting no roles to be added. Next, add the same web and/or worker roles to each of those cloud projects. To do this, right-click on each cloud project’s Roles and select “Add web role already in solution” or “Add worker role already in solution”, then select the appropriate project to be added as a role. This will give you completely separate cloud projects for each of the environments with completely separate configurations, including the VM size. The only thing you have to remember is if you add or remove configuration values from one cloud project, you have to add or remove those from all three cloud projects. Here’s what your solution could look like when using this approach:
Notice there are separate cscfg AND csdef files for each cloud project, and the same roles – ComposerWebRole and ProcessMobileSlidesQ – are assigned to each cloud project. Just set whichever cloud project you want to publish as the Startup Project and publish it. It will use the configuration specified for that project.
The other advantage of using this method is you can set the production and staging configurations and tell the developers not to modify them, and let them have their own configuration file to change as they want to. Then you can publish the appropriate cloud project without having to check that the configuration values are correct.
One last option
Another option is to script the deployment using the CSPack Command Line tool. If you do this, you can create a second csdef file and add it to Visual Studio, and refer to that one specifically when creating the packaged deployment to be uploaded and used in Azure. This is more complicated because you have to write the script, and you have to remember to keep the csdef file up-to-date if any changes are made to the one updated in Visual Studio through the GUI.
PaaS Deployment Slots and URLs
PaaS cloud services have two deployment slots -- staging and production. The production slot has a fixed URL; the staging slot has a URL that is a GUID that changes every time you deploy a new version. You can deploy to the staging slot and test the application using the staging URL. When you're happy with it, you can do a VIP swap, which swaps the virtual IP address assigned to each slot so that the production URL points to the deployment that had been in the staging slot while the staging URL points to the deployment that had been in the production slot. If you have problems with the new version, you can swap them back.
Because the staging URL is changed each time you deploy to it, you will have to update the URL of any other application that points to the staging URL. For example, if you are calling a Web API hosted in a cloud service from an Azure Website, you need to point to the right deployment by changing the URL you are targeting in the website each time you publish the Web API.
One way to handle this is simply setting up an additional cloud service for testing. You could have a production service called MyWebsite, and another service called stMyWebsite. To test the application, you publish to stMyWebsite. When you are finished and are ready to put the application into production, you then publish to the staging slot of MyWebsite and do the VIP swap. This way, you get the advantage of the quick move into production, but you don't have to change the URL every time you need to test something that uses your new version. (This example uses the aforementioned method for naming PaaS cloud services with a prefix of “st” for staging. This will work regardless of what you call the staging cloud service, or what subscription it resides in.)
One last note: the staging URL only changes if you are deploying a brand new version. After that, if you deploy an update instead, it does not change the URL. If this is a test version, at some point you are going to delete the deployment (to save money, if for no other reason), and then the next time you deploy, you will get a different URL.
Your production environment uses Azure Websites
With Azure Websites, you can create a new website (such as stMyCompany) and deploy the web application to it for testing. You probably want to do this if the website uses other staging components or for the purpose of being consistent. Even if you choose this route, you should deploy the final ready-for-production version of your website to a staging deployment slot in production and do the swap to put the website in production, as described next.
If your website stands alone, or you want to test it using the production components, you have the option to create an additional deployment slot for the production website. Unlike the staging slots in the PaaS cloud services, the deployment slots for websites can retain the same name when you use them repeatedly.
Depending on the particular Azure Websites SKU used, a website may have up to five deployment slots – a production slot and four staging slots that can be used for testing. You can deploy a new version of the website to one of the staging slots and when you have finished testing, you can quickly swap the deployment slots to promote the tested version to production and demote the original production deployment. If you have a problem, you can then swap the two websites back.
If you deploy a site to a staging slot and then swap it into production, all instances of the new version are warmed up before being swapped into production. This eliminates downtime when you deploy a new version of your site.
By default, your deployment slots share the same resources as your production slot, and they run on the same VMs. If you run load testing on a website deployed to a staging slot, it will also impact your production website. In this case, you might want to move the staging slot to a different Web Hosting Plan using the Preview Management Portal. Don't forget to move it back to the original Web Hosting Plan if you decide you want to swap it into production.
For more information about staged deployment, check out the article here http://azure.microsoft.com/en-us/documentation/articles/web-sites-staged-publishing/.
Your production environment uses a database
If your production environment uses one or more databases, you have to decide how to represent that in staging. Here are some options:
- Make a copy of the production database, export a backup to blob storage. Next, restore it to the server hosting the staging database. This is one way to restore the same database to multiple locations if you need to, such as both staging and development. If your staging or development environment is in a different subscription, you can copy the file from the first subscription’s storage account to a storage account under the staging or development subscription and do the restore from there.
- Do a point-in-time restore of your production database. This creates a completely new copy of the original database from that point in time. You can then resize it down if you don’t need the full performance of the production database. You specify the name of the restored database, so you can create any number of these.
This creates the new database on the same server as the original database. If you have your whole staging or development environment in a separate subscription, you probably don’t want to choose this, as the new database will end up in the same subscription as production.
- Create a new, empty database in the staging area.
- Use the SQL Azure Migration Wizard to copy specific tables from one SQL Server database to another.
One thing you have to think about is if you need to change the data in the database for staging. If you have URLs or partial paths or anything like that pointing to files in storage, for example, you may need to modify them to point to production. For example, if you have URLs to files in blob storage stored in the database, you might have to do a global replace to change all occurrences of http://mycompany.storage.com/ to http://stmycompany.storage.com. You can do this kind of global replace in a SQL script, save it, then use the script each time you recreate the staging or development version of the database.
Any services that access the database will need to be modified to point to the database in staging.
Your production environment uses Azure Storage
If your applications in production use Azure Storage, you will probably want to change the staging versions to point to a staging storage account rather than production. Hopefully you have stored those connection strings in a configuration file, and you can change the configuration file to point to the staging storage account.
If you are using Azure Diagnostics, be sure to change the connection string to point to a staging storage account, so the diagnostics do not get written to the production storage account.
Another consideration to be decided ahead of time is how you use your DNS entries. For example, if you are using cloud services, you can create a DNS entry for stmycompany.com to point to stmycompany.azurewebsites.net. If you decide to change the name of the website later, you can just change the DNS entry to point to the new staging website.
This works well with the different configurations in a cloud service, as well -- you can just put in the URLs to use for staging. If you use the staging slot URLs with the GUIDs in them, you have to change the DNS entries every time you deploy a new version of the cloud service, and then wait for the DNS entries to propagate; that may not be the optimal solution. This is another reason using separate services for staging and production may work better for you than using the staging slot of one service for testing.
This article discussed several of the methods for using Azure for dev/test environments, and provided recommendations for some of the common services being used. Azure is very flexible, providing multiple ways to set up your dev/test environment, and is easily reconfigurable if you need to make modifications.