Subscription Provisioning¶
Every spoke needs a clean subscription. This page records the decision on how a platform gets that subscription: not from a pool, but created or prepared when the spoke is deployed. It explains the problem, the options that were considered, the consequences, and what this means for the MCP configuration.
Decision record
This is a design decision, written from an architecture decision record of the spoke canvas. It is guidance: your contract, your Azure agreement and your policies decide what you can do. See Design guidance.
The problem¶
Each spoke environment needs a clean subscription in which its resources and RBAC are set up. A pool of pre-created subscriptions looks attractive: a script claims one when a spoke is deployed. In practice it is risky, because spokes are deployed in parallel. Two spoke deployments can claim the same subscription.
Provisioning on demand also solves more than the claim problem:
- no manual process is needed to fill up a pool,
- no subscription exists without a purpose,
- provisioning is more than creating the subscription. It also covers:
- naming the subscription by convention when the spoke file gives no name,
- setting the tags from the spoke file,
- moving the subscription to the management group from the spoke file.
Options¶
| Option | Idea | Why not, or why |
|---|---|---|
| Claim from a pool | A pool of free subscriptions is ready. The deployment claims one | Parallel deployments can claim the same subscription. Subscriptions in the pool need an import solution. A second solution must watch the pool and refill it |
| A provisioning step in the spoke deployment (chosen) | The deployment detects, per spoke environment, whether a subscription is needed. If so, it creates it and passes the result on. Terraform then also sets name, management group and tags | Fully automated. Compatible with existing spokes |
Decision¶
Add a separate provisioning step to the spoke deployment that creates a subscription when needed, and let the same Terraform set the name, the management group association and the tags.
Consequences¶
- Functionality is added without changing existing deployments. One new setting in the common spoke settings is needed to use it.
- No pool has to be filled, monitored or cleaned up.
- The step needs a billing relationship through which subscriptions can be created. That depends on your Azure agreement; see below.
How it maps to MCP¶
flowchart LR
spoke["Spoke JSON file"] --> sub["Subscription layer<br/>deploy/subscription"]
sub -->|"subscriptionId"| canvas["Spoke canvas layer<br/>deploy/spoke"]
canvas --> r["Name, tags, management group,<br/>network, identity, resources"]
The spoke run has two Terraform layers with separate state (Provisioning). The subscription layer runs first and writes the subscription ID to a small output file. The spoke canvas layer reads that file (Spoke canvas module reference), moves the subscription to the management group, renames it and sets the tags.
| Situation | What happens |
|---|---|
azureSubscriptionId is set in the spoke file |
The subscription is used as it is. This is how the pipelines are used today |
azureSubscriptionId is empty and the CSP billing values are supplied |
The subscription layer can create the subscription |
Creating subscriptions needs a billing route
Creating a subscription from code needs a billing account and a service principal with the rights to do so (the
xmscsp_* inputs). The pipelines pass those inputs as empty strings. In a standard setup you create the subscription
with your own EA, MCA or CSP process first, and put its ID in the spoke file
(New spoke). Decide in your
governance process who creates subscriptions.
If the pipeline cannot create subscriptions in your environment, the decision still holds in one respect: do not build a pool. Create a subscription per spoke request, and let the spoke deployment give it its name, tags and management group.