What is an Environment?
Anyone who has worked on a software development project will be familiar with the concept of an “environment”. Simply put, an environment is a set of infrastructure that you can deploy your application to, supporting a specific activity in your software development lifecycle. Any significant project will have multiple environments, generally with names such as “Test”, “UAT”, “Staging” and “Production”.
On a traditional project, each environment is supported by dedicated physical infrastructure: for example, the Test environment is those two servers under the corner desk, the UAT environment is on Rack #4 in our lab, and production is hosted in the downtown datacentre. Typically these environments won’t be identically configured, with the “early” environments being hosted on whatever you can find lying around, with the “later” environments becoming increasingly more expensive and better managed.
Key Windows Azure Abstractions
When teams first start working with Windows Azure, they are often unsure about how to effectively represent the familiar concept of “environments” using the capabilities of the cloud. They note that every deployment has a “Production” and a “Staging” slot, but what about all their other environments such as Test or UAT? Other teams ask if they should host some environments on their own servers running under the compute emulator.
The short answer is that you probably want to have the same environments for a Windows Azure project as you would for any other project. The compute emulator is great for local development, but there are significant advantages to hosting every other environment in the cloud—for a start, the environments are identical so bugs will be picked up much earlier. But supporting multiple environments requires carefully planning how to use the various abstractions provided by Windows Azure (beyond just the “Production” and “Staging” deployment slots). Let’s take a look at the key abstractions and some considerations relating to environments:
- Billing Account. Everything in Windows Azure is ultimately tied back to a billing account. This is a key consideration as in many organisations different departments are responsible for paying for different applications and even for different activities such as development versus production use.
- Subscription. A billing account can contain multiple subscriptions. A subscription is essentially a unit of management. When a user has access to a subscription via a Windows Live ID or Management Certificate, they are able to perform any operation within that subscription. As such, a subscription should not be shared for environments with different operational or management requirements.
- Hosted Service. A subscription can contain multiple hosted services. A hosted service typically represents a specific application. While it may contain a number of resources, it is deployed as a unit and is given a single DNS name.
- Deployment Slot. Each hosted service contains exactly two deployment slots, which are called “Staging” and “Production”. When you deploy your hosted service, you must choose one of these slots. The slot names can be confusing as these slots apply to every service, even those used for development or testing. The functionality, quality and pricing of the two slots are identical. The only difference is that the production slot is given a DNS name of your choosing (e.g. myservice.cloudapp.net) while the staging slot is assigned a random GUID (e.g. 7f8e9d5ba73a4f7ea9ebd65a02ee195d.cloudapp.net). The value of having two slots is that you can deploy a new version of your application to the staging slot while the previous version remains in the production slot. The staging slot has an unpredictable URL so it won’t be discoverable, but your team is able to test it. When you are happy that the new version works as expected you can swap the virtual IP addresses of the two slots, with the new version instantaneously moving into the Production slot and the old version moving into the Staging slot. This is a great capability, but once again it applies to every managed service so you should not confuse this with the concept of a Production or Staging environment.
- Role. A hosted service can contain multiple roles, each of which provides a template for a virtual machine used in the application. A role is a unit of scaling, as you can dynamically change the number of instances within a single role.
Example Environment Use
Now that we understand the purpose of each of these abstractions, let’s look at how a typical organisation may use these to represent multiple environments for a single application. Note that depending on your requirements you may end up with a solution quite different to this one, but you should be able to use similar thought processes to arrive at a solution that makes sense for you.
The first thing you’ll note is that this organisation has chosen to use two different billing accounts. This is because one department is responsible for paying for the development (including testing) of solutions, while another is responsible for ongoing operations of production solutions.
Within the Development billing account, the organisation is using separate subscriptions for Development and Test. This was done because the developers and testers each wanted the ability to manage their own environments. The developers wanted to be able to make changes whenever they wanted for the purposes of experimenting and debugging. The testers wanted to ensure their environments were controlled, and in particular they didn’t want developers to be able to make changes without going through the automated build process. Within the Operations billing account, currently only a single subscription is used, which is only accessible to the operations team.
With the Subscriptions providing an appropriate management boundary for different teams, the organisation is using Hosted Services to represent the different environments. The development team has chosen to use a couple of different “Sandbox” services for experimenting and debugging, and can easily add or remove services as their needs change. The test team has chosen to use one “Test” service for their day-to-day testing of nightly builds, and a “UAT” service for user acceptance testing of a more stable build at the end of each sprint. Finally a single service is used in the Operations subscription for the hosting the production application.
As mentioned earlier, every service has a “Staging” and “Production” slot, but in this organisation only the “Production” slot is in constant use, with the “Staging” slots empty most of the time. The developers don’t bother using the “Staging” slot at all as they don’t care about downtime during the deployment process. For the test and production services, the “Staging” slot is used only when deploying new builds—once the new deployment has been signed off, the virtual IP addresses are swapped and the resulting “Staging” deployment is deleted to save money.
Securing Your Environments
Using multiple subscriptions for different disciplines is necessary to provide the necessary isolation and access control. However for this to work you also need to make sure you are also following good security practices. Some of the main considerations for Windows Azure are:
- Never share Windows Live ID accounts between multiple users. Instead, require each user to have their own Windows Live ID and add them as "co-admins" to the appropriate subscriptions.
- Use strong usernames and passwords for Windows Live ID, particularly for production environments
- Add password reset information to your Windows Live ID (such as backup email and phone numbers) and a security question/answer pair that cannot be guessed, researched or socially engineered. This will ensure a password can be recovered if necessary, but prevent anyone else from resetting your password.
- For production environments, minimise the use of the web portal and Windows Live ID by using management tools secured using Management Certificates. Protect the private keys of these certificates with ACLs tied to domain user accounts.
While Windows Azure contains many useful abstractions, there is no direct equivalent to an “Environment” in the sense used by the typical software team. Any organisation planning a production application on Windows Azure should consider how to best use the Windows Azure abstractions to provide the best mix of flexibility and control for each team and activity.
- Create Billing Accounts based on the organisation’s policies for funding projects and lifecycle activities
- Create Subscriptions based on groups of users with shared management requirements
- Create Hosted Services within appropriate Subscriptions for each environment
- Use the “Staging” deployment slot in any environment to enable testing of new deployments without requiring downtime for the existing deployment
- Protect environments by following secure account management practices.