How I deploy my Azure Lab Environments

A recent topic of conversation with colleagues, friends in the technical community, and customers I work with, has been how I manage and deploy lab environments. I have to regularly deploy lab environments both for my own use (learning, training, etc.), and for customer demos – and often need to spin up/down these environments with little notice, relying on as much automation and infrastructure as code as possible.

In this post I’ll break down how I deploy (and destroy!) lab environments regularly and with ease ✅

Technologies that I use to create my Azure Lab Environments:

Environment Overview

The diagram below provides an overview of the build environment I use to deploy lab environments:

Lab Build Environment
Lab Build Environment

As you can see, the environment comprises an Azure DevOps environment, using Azure Repos to store Terraform and Packer files that define the images and infrastructure that I require. I also use a Virtual Machine within Azure that has the Azure DevOps Pipeline Agent on – so I can run whatever tooling versions that I require, as much as I require. An Azure Storage Account with a Container is used to Store the Terraform State Files for each lab or environment I wish to deploy. Whilst I could use the Microsoft Hosted Job option (and then not use the Virtual Machine), some of my lab environments take an hour to deploy and destroy – so having my own Pipeline Agent inside a funded Subscription allows me to run as many jobs as I need.

The actual deployment of environments is simple – within my Repositories in Azure DevOps, I have a range of environments saved, most of which are based on the code available within my GitHub Terraform-Azure Repository.

Deployment Process

When deploying (and destroying!) environments, the process is as follows:

  1. Code is stored within a Repository in Azure Repos.
  2. I edit the code to change any elements or variables for the Lab I need to deploy.
  3. I create a release which runs an Azure DevOps Pipeline (detailed below) – which then runs Terraform, Packer, Azure CLI or PowerShell as required for the Lab.
  4. The Pipeline process completes, and the Lab environment is deployed.
  5. I then use the Lab – be it for demos, learning, or testing.
  6. I then run a subsequent Pipeline process that destroys the Lab resources – this one is important to save on Azure consumption costs!

Azure DevOps Pipeline Configuration

For my Lab environments, I use a really simple pipeline – I’ve opted to keep things as simple as possible, so as to reduce complexity and make things easy to manage.

✅ As a note – if you want a starter project and pipeline, you can use the Azure DevOps Demo Generator – which has a Terraform Demo that is great for getting started:

Azure DevOps Demo Generator - Terraform Demo Project, a great place to start learning.
Azure DevOps Demo Generator – Terraform Demo Project, a great place to start learning.

I use a simple release Pipeline – which allows me to deploy environments that only require Terraform with just 5 steps (this is based on the Demo Generator above!):

Azure DevOps Pipeline Overview
Azure DevOps Pipeline Overview

I’ve broken down the stages below:

  1. Install Terraform latest – This stage sets up the latest version of Terraform, ready for deployment.
  2. Terraform: init – This stage initialises Terraform, and ensures that the backend is configured correctly for State File Access.
  3. Terraform: validate – This stage validates the Terraform code within the Azure DevOps Repo, to ensure it is valid code.
  4. Terraform: plan – This stage runs Terraform Plan – if required, I could split this out so I can review the plan before the apply stage.
  5. Terraform: apply – This stage runs the Terraform Apply phase, and applies the required changes to the environment.

Within the Terraform: init stage, the backend configuration is important, as we need to define a Subscription and Storage Account to use (Subscription ID and Storage Account Name have been obscured in the below):

Core Lab - Create
Core Lab – Create

As a note, some of my environments also require additional steps – whereby I run other elements like Azure CLI or PowerShell commands, or build machine images using Packer.

These are added as Pipeline stages easily using the Add (+) option:

Adding other tasks to Pipelines
Adding other tasks to Pipelines

✅ My advice here if you’re interested in creating and deploying environments using Azure DevOps, particularly when learning, is just to use the Demo Generator – and then experiment and tweak using that example. It is a great place to start learning!

What about removing the Labs?

Removing the labs is something I have chosen to split out into another Pipeline Stage, so that I can delay this stage from applying, before I need to destroy the lab. The actions within the destroy pipeline are simple – and similar to the creation phase, other than the apply being changed to destroy. In some lab environments I also have Azure CLI and PowerShell steps within the removal phase too.

Destroy Phase of the Pipeline
Destroy Phase of the Pipeline

Splitting out the Pipeline Stages is simple – and allows me to have a second stage that will destroy the environment, but only when activated manually:

Pipeline Phases showing Creation and Destruction Stages
Pipeline Phases showing Creation and Destruction Stages

It would, of course, be possible to automate the running of the destroy Stage, using either a time based activation or building in additional approvals if required. In most cases I just choose to do this manually so I can easily control the amount of time the environment is deployed for.

Why create lab environments like this?

There are a wide range of benefits to using this method to create lab environments. Much in the same way that DevOps practices provide organizations with a flexible, structured, and controlled approach to deployment – these same benefits can be realised when deploying Lab environments too.

For my own usage, the key benefit is that I can be a passive participant in deploying many of the labs – I just execute a release and the pipeline does the work, based on existing and known good code. This means in many cases, I can be hands-off whilst the lab is deployed for me – and there’s no requirement for me to remain connected or online. I can trigger the pipeline and come back to a created lab later on. This has been a huge help to me many times, when I need to get an environment deployed quickly or at late notice, but I am already busy with other work, or sometimes, travelling to visit a customer.

✅ Here’s a summary of the Key Benefits, particularly for deploying lab environments using this methodology:

  • Easily repeatable deployment – same code, same deployment each time.
  • Reliable deployment – from known code I’ve tested and used many times.
  • Hands-off deployment – no manual involvement in the deployment, just trigger and wait. I’ve deployed labs from hotel rooms, trains, etc.
  • Change Tracking and Version Control via use of Git Repos. All changes to my Lab code are tracked and I can easily roll these back if required.
  • Automated destruction – once I have finished using a Lab I can destroy it easily, saving Azure Consumption Costs.
  • Further integration options – I can add new Cloud Services and Technologies into the Pipeline with ease.

Further Reading

Here’s a range of additional posts I’ve written around this subject that may also be of interest if you enjoyed this article:

Skip to content