Azure Setup Guide
This guide explains how to configure EasyLab to provision lab environments on Microsoft Azure using AKS (Azure Kubernetes Service).
Overview
EasyLab supports Azure as a cloud provider, creating:
- An Azure Resource Group per lab (
easylab-{stackName}) - An AKS cluster with a node pool in the selected region
- Student workspaces running on the cluster, created on demand
Networking is AKS-managed (Kubenet default). No custom VNet or subnet configuration is required.
Prerequisites
- An Azure subscription
- Permissions to create resource groups, AKS clusters, and assign roles
RBAC scope (important)
EasyLab calls subscription-level Azure Resource Manager APIs for regions (Microsoft.Resources/subscriptions/locations/read) and loads VM sizes for a chosen region (Microsoft.Compute/locations/virtualMachineSizes/read). Your service principal needs a role assignment on the subscription (/subscriptions/<SUBSCRIPTION_ID>), not only on a resource group.
- Minimum for “Refresh from Azure” / region dropdowns: Reader at subscription scope (includes read on locations and discovery).
- For lab provisioning (AKS, networking, etc.): Contributor at subscription scope (as in the command below), or an equivalent custom role that includes both read and write where you deploy.
If you see an error like does not have authorization to perform action Microsoft.Resources/subscriptions/locations/read, grant Reader or Contributor at the subscription for that app registration, then save credentials again and retry Refresh from Azure.
# Example: add subscription-scoped Reader for least privilege on discovery APIs only
az role assignment create \
--assignee <APP_ID_OR_OBJECT_ID> \
--role Reader \
--scope /subscriptions/<SUBSCRIPTION_ID>
# If you already use Contributor on the subscription, you do not need a separate Reader assignment.
Create a Service Principal
EasyLab authenticates to Azure using a Service Principal with a client secret.
# Login to Azure CLI
az login
# Create a Service Principal with Contributor role on your subscription
az ad sp create-for-rbac \
--name "easylab-sp" \
--role Contributor \
--scopes /subscriptions/<SUBSCRIPTION_ID>
The command outputs JSON like:
{
"appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"displayName": "easylab-sp",
"password": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"tenant": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
Map these values to EasyLab credentials:
| Azure output | EasyLab field |
|---|---|
appId |
Client ID |
password |
Client Secret |
tenant |
Tenant ID |
| (your subscription) | Subscription ID |
Required Environment Variables
You can pre-configure credentials via environment variables (loaded at startup):
AZURE_CLIENT_ID=<appId>
AZURE_CLIENT_SECRET=<password>
AZURE_TENANT_ID=<tenant>
AZURE_SUBSCRIPTION_ID=<subscription-id>
Or use the --env-file flag:
./easylab --env-file /path/to/.env
Configure Credentials in the UI
- Navigate to Credentials in the EasyLab admin UI
- Select Microsoft Azure from the provider dropdown
- Enter your Service Principal credentials:
- Client ID — the
appIdvalue - Client Secret — the
passwordvalue - Tenant ID — the
tenantvalue - Subscription ID — your Azure subscription ID
- Click Save Credentials
By default the credentials are kept in memory only and cleared when EasyLab restarts. Set up credential storage to keep them, encrypted, across restarts.
Configure Azure Options
After saving credentials, set up default regions and VM sizes:
- Navigate to Azure → Options (or
/admin/azure-options) - Click Refresh from Azure to load the subscription’s regions (locations)
- Enable the regions you want to offer in the lab creation form
- Set a default region
- Expand each region to load VM sizes from Azure; enable the VM sizes you want per region
- Click Save Options
Create a Lab on Azure
- Go to New Lab
- Select Create New Infrastructure
- Choose Microsoft Azure as the cloud provider
- In the Azure Region step, choose the target region — VM sizes for the node pool load after a region is selected
- Configure the node pool (name, VM size, node counts)
- Complete the workspace and template steps (see Workspace template examples)
- Click Create Lab
EasyLab will:
- Create resource group easylab-{stackName} in the selected region
- Provision an AKS cluster with the configured node pool
- Prepare the cluster so student workspaces can be created on demand
Workspace storage on AKS
Student workspaces get a persistent volume by default, backed by the cluster's default StorageClass — Azure Disk on AKS. Two Azure-specific things are worth knowing.
Attach limits on large cohorts. Each Azure Disk is attached to the node
running its pod, and every VM size has a limit on how many disks it can hold.
A workshop that starts several hundred workspaces at once can exceed those
limits, leaving pods stuck waiting to attach. If you are running a very large
cohort, either pick a VM size with a higher disk-attach limit and enough nodes to
spread the load, or set ephemeral: true on the template to trade the students'
data for a reliable mass start — see
Persistence.
Azure Disks are zone-pinned. EasyLab enables the AKS cluster autoscaler
whenever node counts are configured, so pods can be rescheduled onto a node in a
different availability zone — where a zonal disk cannot follow, leaving the pod
unschedulable. Setting storage_class on the template to a zone-redundant class
avoids this.
Cleanup
Destroying a lab via the EasyLab UI runs pulumi destroy, which removes:
- The AKS cluster and all node pools
- The resource group and all contained resources
No manual cleanup is needed.