Azure Blueprints are dead: long live Specs and Stacks?

David PazderaDavid Pazdera
9 min read
💡
This article was written for the Festive Tech Calendar 2024 event. Visit the official website to see the schedule and links to great content from the technical community.

Introduction

I must admit that the title of my contribution and its content isn’t very festive. I just felt that paraphrasing the famous Kind is dead: long live the King quote is a spot on when talking about Azure Blueprints, a service I used to work with quite a lot back in the days.

Over time, it became well-known for its ‘forever in preview’ status, subject to jokes and speculations. Well, not anymore. When you check Microsoft Learn, you will see the following banner:

In this blog post, we will perform both conceptual and practical comparison of Azure Blueprints, Template Specs, and Deployment Stacks, and hopefully answer the following questions:

  • Is there a feature parity between Blueprints and Specs & Stacks combo?

  • What steps do I need to take to migrate away from Blueprints by leveraging the new tools?

  • Can I combine Template Specs with Bicep modules?

In case you haven’t worked much with any of these tools, don’t worry. We will do a proper introduction first:

Blueprints in a nutshell

Blueprints were designed to automate the deployment of compliant cloud environments by defining a set of Azure resources that implement your organization's standards and ensure compliance and consistency.

You begin with creating blueprint definitions - a declaration of various resource templates and other artifacts, such as role and policy assignments, and resource groups. This blueprint is saved to either a management group or a subscription (you needed Contributor access to create it on that scope). When you store it in a management group, the blueprint is available for assignments to any child subscription.

One caveat was that Blueprints were not stored directly in Azure Resource Manager, but in a Microsoft-managed Azure Cosmos DB.

Once a blueprint is created, it can be assigned to one or more subscriptions, and the deployment process will automatically provision the defined resources and configurations.

Blueprints provided versioning capability and lifecycle management. You could update blueprints as your requirements evolved, where any updates to the blueprints were propagated to the assigned environments. This versioning capability also enabled rollback to previous versions if needed. The definition is initially in Draft mode, and it had to be Published with a version (and optional ‘Change notes’). What was quite unique, was the option to assign different versions of the same blueprint to the same subscription.

Credit: Microsoft TechCommunity

There was also a possibility to declare parameters - either on the artifact or on the blueprint level - and pass their values at the assignment time.

💡
There was even an attempt to manage Blueprints as Code and provide CI/CD capabilities. This project on GitHub is for obvious reasons not active anymore.

Blueprints could be locked to prevent unauthorized changes, ensuring that the deployed environments remain compliant. Their seamless integration with Azure Policy allowed for continuous compliance monitoring and enforcement.

Before the Template Specs were introduced, there wasn’t a way to store ARM templates natively in Azure and when a deployment was completed, there wasn’t any active connection or relationship between the deployment and its template. Well, this is exactly what Blueprints with definitions (what should be deployed) and assignments (what was deployed) tried to fix.

There were several resource types associated with blueprints:

  • Microsoft.Blueprint/blueprints/

  • Microsoft.Blueprint/blueprints/artifacts

  • Microsoft.Blueprint/blueprints/versions

  • Microsoft.Blueprint/blueprintAssignments/

You can create blueprints in the Azure Portal, or by using Azure PowerShell, Az CLI, ARM templates, or REST API.

If you have a burning desire to learn more, you could watch an Azure Friday episode with Scott and Alex:

Specs and Stacks taking over

Azure Template Specs is a (new) resource type within ARM that allows you to store and manage templates natively in Azure, so they are available for later deployments. They provide a fantastic way to centralize template management with built-in version control and access management using RBAC (no surprise here).

Template Specs help you to overcome the need to stage linked templates in publicly accessible storage (most common way was to use Azure Blob storage with SAS token).

It is also a neat way for platform teams to develop, test, and publish a set of curated, compliant, and deployable artifacts that can be consumed directly by DevOps teams in their projects. It is a win-win situation, where developers don’t need to spend time authoring their own Infrastructure as Code configurations (and often being hit by Azure Policies), while platform engineers can promote IaC practices and keep their cloud environments compliant.

This illustration shows a typical Lifecyle:

  • You can author templates (1) in Bicep or ARM JSON format and maintain them e.g., in a GitHub repository, so you can automate validation, testing, and publishing (2) to Azure Resource Group(s). When you publish a Bicep file to a template spec, it's converted to JSON.

  • Command for publishing is either New-AzTemplateSpec (Az PWSH) or az ts create (Az CLI) as shown in the example below:

az ts create \
  --name StorageWithoutSAS \
  --location westus \
  --display-name "Storage account with SAS disabled" \
  --description "This template spec creates a storage account, which is preconfigured to disable SAS authentication." \
  --version 1.0 \ 
  --template-file main.bicep
  • You can also update an existing version of a spec or delete a particular version.

  • To deploy a template spec (3), you need its ResourceId, and at least Reader permission for the parent Resource Group. Since it is a regular Azure resource, you can deploy them using standard Azure tools like PowerShell, Azure CLI, Azure portal, REST, and other supported SDKs and clients.

  • Command for deploying is the same as for a regular template deployment, only the argument (parameter) is different, for example:

az deployment group create --template-spec "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/SharedTemplates/providers/Microsoft.Resources/templateSpecs/StorageWithoutSAS"

Pro tip: You can call a template spec as a module in your Bicep deployment file by following a special format - ts:{subscriptionId}/{resourceGroupName}/{templateSpecName}:{version} as you can see in this example:

module storageAccountTemplateSpec 'ts:f0750bbe-ea75-4ae5-b24d-a92ca601da2c/sharedTemplates/StorageWithoutSAS:1.0' = {
  name: 'storageAccountTemplateSpec'
}

This also means that you can combine template specs with Bicep modules in a single deployment definition!

💡
There is a great Microsoft Learn module available for learning more: Publish libraries of reusable infrastructure code by using template specs.

Let’s pause here for a moment and assess feature parity between Blueprints and Template specs:

  • Blueprints combine artifacts like resource groups, resource templates, role assignments, and policy assignments (not definitions). Template specs give you the same flexibility, since all those artifacts are resource types that can be declared with Bicep. You would create a Bicep deployment file with subscription as targetScope and compose resource group(s) and resources as modules.

  • Blueprints come with versioning, same as Template Specs.

  • The lifecycle of blueprints is more complex with Draft and Published modes, you “only” publish a template spec to its target RG.

  • Both blueprints and specs give you the possibility to declare parameters, making them flexible and reusable. When deploying a template spec (either directly or as a Bicep module in a complex deployment), you would provide all parameter values at the deployment time.

  • You would assign blueprints to one or more subscriptions to trigger the deployment of all artifacts. A central IT team (platform team) typically does this. They stamp each subscription with this standard collection of resources. Template specs are often published for internal customers like DevOps teams. Also, specs can target higher scopes than subscriptions. This doesn’t mean they couldn’t be used by the platform team in a similar way as Blueprints.

  • You can apply a blueprint lock, effectively adding a deny permission to the resources deployed as part of the blueprint. This feature is not available in Template Specs directly… but you can achieve the same goal when you use Deployment Stacks! Stay tuned ;)

Let’s dive into the Stacks now…

Azure Deployment Stacks is an Azure resource type that enables you to manage the lifecycle of a collection of Azure resources as a single atomic unit even if they span multiple resource groups or subscriptions.

Without stacks, if you deploy a collection of resources, there is no connection between them and the deployment (apart from seeing the deployment and its logs in the Deployments history). This could be a challenge for applications that are designed to span several RGs or even subscriptions.

Credit: Microsoft Learn

Stacks allows you to group all the resources that make up your application, manage them as a single unit, and perform lifecycle operations on the whole collection of resources that make up the stack.

Here are some highlights:

  • You can use Bicep, ARM templates, or Template specs for deployment stacks, which gives you flexibility in how resources are defined and managed.

  • Commands for creating deployment stacks are similar to regular deployment, for example in Azure CLI, you use az stack group create instead of az deployment group create. There are some additional arguments that support the lifecycle management, as you can see in the example below:

az stack group create \
  --name stack-deposits \
  --resource-group rg-depositsApplication \
  --template-file ./main.bicep \
  --action-on-unmanage detachAll \ 
  --deny-settings-mode none
  • You can do a cleanup of your environment by deleting the stack and all of its resources through a single API call. This makes the removal of the resources more reliable and faster. There is a set of delete flags (arguments) you can configure when creating your stack. For example, in Azure CLI, you can use —-action-on-unmanage argument with three values: deleteAll, deleteResources, and detachAll. While delete is self-explanatory, when you choose to ‘detach’, this will keep the resource intact, but it will stop tracking it as part of the stack.
💡
In my mind, this is a way to perform terraform destroy using Azure native tooling. An evolution of the complete deployment mode combined with tracking the state of your resources without the need to manage local or remote state.
  • The last notable feature is configuration drift prevention, where you could configure deny settings and prevent unauthorized modifications to managed resources, ensuring consistency and compliance. If this option resembles Blueprint locks to you, you got it right :)

The lifecycle of deployment stacks and its resources is a bit more complex, so I would recommend you watch a deep dive tutorial created by none other than Mr. John Savill:

Second learning resource I would recommend is Introduction to Deployment Stacks module on Microsoft Learn.

The migration path

If you are using Blueprints and want to gradually transition to Specs & Stacks, you could follow a ‘Migrate blueprints to deployment stacks’ guide.

In short, you would:

  • Export Blueprint definitions to ARM JSON format

  • Convert and refactor these files into a single Bicep or ARM template

  • Deploy that new main template using deployment stacks, typically one stack per subscription (to mimic the original Blueprint assignment model).

  • Optionally, you could create Template Specs from that main template which makes the lifecycle managment easier with versioning.

Conclusion aka TLDR;

I encourage you to make your own evaluation and conclusion, but here are my final thoughts:

  • If you haven’t used Azure Blueprints in the past, it doesn’t make sense to explore them. There is a clear ‘expiration date’ on this tool and it will be superseeded by Template Specs and Deployment Stacks.

  • I believe there is almost full feature parity between Blueprints and Specs & Stacks combo, so you shouldn’t miss any important benefit by switching.

  • If you are still using Blueprint in production, you should start planning your ‘exit strategy’ and use the guide from Microsoft to gradually switch to Specs and Stacks.

0
Subscribe to my newsletter

Read articles from David Pazdera directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

David Pazdera
David Pazdera

Principal Solution Architect, working daily with Azure, primarily focusing on automation and "everything as code".