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:
-
Azure DevOps (Pipelines and Repos) – including a build worker VM in Azure and Azure Storage for the Terraform State File
-
HashiCorp Terraform
-
HashiCorp Packer
-
Azure CLI
-
Azure PowerShell
Environment Overview
The diagram below provides an overview of the build environment I use to deploy lab environments:
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:
-
Code is stored within a Repository in Azure Repos.
-
I edit the code to change any elements or variables for the Lab I need to deploy.
-
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.
-
The Pipeline process completes, and the Lab environment is deployed.
-
I then use the Lab – be it for demos, learning, or testing.
-
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:
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!):
I’ve broken down the stages below:
- Install Terraform latest – This stage sets up the latest version of Terraform, ready for deployment.
- Terraform: init – This stage initialises Terraform, and ensures that the backend is configured correctly for State File Access.
- Terraform: validate – This stage validates the Terraform code within the Azure DevOps Repo, to ensure it is valid code.
- Terraform: plan – This stage runs Terraform Plan – if required, I could split this out so I can review the plan before the apply stage.
- 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):
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:
✅ 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.
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:
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:
- Single Region Azure BaseLab V2 – Many of my lab environments are built around this baseline lab environment.
- Using Packer and Azure DevOps to create Machine Images – This post runs through configuring Azure DevOps to use Packer to create Azure Machines Images. This is very useful for VDI Labs – e.g. Azure Virtual Desktop or Citrix.
- Automating Domain Controller promotion in Azure DevOps – Sometimes Lab environments require a Domain Controller available – this post runs through provisioning a DC within Azure DevOps.
- Deploying Azure NetApp Files within Azure DevOps, using the Azure CLI – If you require Azure NetApp Files, this post explains how to deploy it in Azure DevOps using the Azure CLI.
- Deploying Azure NetApp Files within Azure DevOps, using Terraform – If you require Azure NetApp Files, this post explains how to deploy it in Azure DevOps using Terraform.