Microsoft Azure
Azure is supported for organizations deeply integrated with the Microsoft ecosystem, requiring Active Directory integration, or with existing Azure commitments.
Note
When to Use Azure
| Requirement | Why Azure |
|---|---|
| Microsoft ecosystem | Active Directory, Office 365, Teams integration |
| Existing commitments | Azure Enterprise Agreements or credits |
| Azure services | Azure SQL, Blob Storage, Azure Functions |
| Managed Kubernetes | AKS with Azure-native integrations |
| Compliance | SOC 2, HIPAA, FedRAMP, and regional certifications |
Configuration
Service Principal
Create a service principal for Teabar:
# Login to Azure CLI
az login
# Create service principal
az ad sp create-for-rbac
--name "teabar-provisioner"
--role Contributor
--scopes /subscriptions/<SUBSCRIPTION_ID> This outputs:
{
"appId": "<CLIENT_ID>",
"displayName": "teabar-provisioner",
"password": "<CLIENT_SECRET>",
"tenant": "<TENANT_ID>"
} Configure in Teabar
teactl org provider set azure
--subscription <AZURE_SUBSCRIPTION_ID>
--tenant <AZURE_TENANT_ID>
--client-id <AZURE_CLIENT_ID>
--client-secret <AZURE_CLIENT_SECRET> Or via environment variables:
export ARM_SUBSCRIPTION_ID=<subscription-id>
export ARM_TENANT_ID=<tenant-id>
export ARM_CLIENT_ID=<client-id>
export ARM_CLIENT_SECRET=<client-secret> Regions
Azure offers 60+ regions. Common choices:
| Region | Code | Location | Use Case |
|---|---|---|---|
| East US | eastus | Virginia, USA | Default US region |
| West US 2 | westus2 | Washington, USA | US West Coast |
| West Europe | westeurope | Netherlands | European users |
| North Europe | northeurope | Ireland | Alternative EU |
| Germany West Central | germanywestcentral | Frankfurt | German data residency |
| Southeast Asia | southeastasia | Singapore | APAC users |
Specifying Region
In blueprints:
spec:
infrastructure:
provider: azure
region: eastus VM Sizes
General Purpose (B-series)
Burstable VMs for variable workloads:
| Size | vCPU | RAM | Temp Storage | Price/hr* | Use Case |
|---|---|---|---|---|---|
Standard_B1s | 1 | 1 GB | 4 GB | ~$0.01 | Minimal workloads |
Standard_B2s | 2 | 4 GB | 8 GB | ~$0.04 | Participant VMs |
Standard_B2ms | 2 | 8 GB | 16 GB | ~$0.08 | Development |
Standard_B4ms | 4 | 16 GB | 32 GB | ~$0.17 | K8s control plane |
*Prices are approximate and vary by region.
General Purpose (D-series)
Balanced compute for production workloads:
| Size | vCPU | RAM | Temp Storage | Price/hr* |
|---|---|---|---|---|
Standard_D2s_v5 | 2 | 8 GB | 0 GB | ~$0.10 |
Standard_D4s_v5 | 4 | 16 GB | 0 GB | ~$0.19 |
Standard_D8s_v5 | 8 | 32 GB | 0 GB | ~$0.38 |
Compute Optimized (F-series)
For CPU-intensive workloads:
| Size | vCPU | RAM | Temp Storage | Price/hr* |
|---|---|---|---|---|
Standard_F2s_v2 | 2 | 4 GB | 16 GB | ~$0.08 |
Standard_F4s_v2 | 4 | 8 GB | 32 GB | ~$0.17 |
Standard_F8s_v2 | 8 | 16 GB | 64 GB | ~$0.34 |
Memory Optimized (E-series)
For memory-intensive applications:
| Size | vCPU | RAM | Temp Storage | Price/hr* |
|---|---|---|---|---|
Standard_E2s_v5 | 2 | 16 GB | 0 GB | ~$0.13 |
Standard_E4s_v5 | 4 | 32 GB | 0 GB | ~$0.25 |
Standard_E8s_v5 | 8 | 64 GB | 0 GB | ~$0.50 |
Blueprint Examples
Single VM per Participant
apiVersion: teabar.dev/v1
kind: Blueprint
metadata:
name: azure-linux-workshop
spec:
infrastructure:
provider: azure
region: eastus
resources:
- name: participant-vm
type: vm
spec:
size: Standard_B2s
image:
publisher: Canonical
offer: 0001-com-ubuntu-server-jammy
sku: 22_04-lts-gen2
version: latest
perParticipant: true
customData: |
#!/bin/bash
apt-get update
apt-get install -y docker.io git vim
usermod -aG docker azureuser AKS Cluster
apiVersion: teabar.dev/v1
kind: Blueprint
metadata:
name: aks-workshop
spec:
infrastructure:
provider: azure
region: eastus
resources:
- name: k8s-cluster
type: cluster
spec:
distribution: aks
version: "1.29"
nodePools:
- name: system
vmSize: Standard_D2s_v5
count: 2
mode: System
- name: workers
vmSize: Standard_D4s_v5
minCount: 1
maxCount: 10
enableAutoScaling: true
mode: User
networkPlugin: azure # or kubenet
networkPolicy: calico Self-Managed Kubernetes (Talos)
apiVersion: teabar.dev/v1
kind: Blueprint
metadata:
name: talos-on-azure
spec:
infrastructure:
provider: azure
region: eastus
resources:
- name: k8s-cluster
type: cluster
spec:
distribution: talos
version: "1.29"
controlPlane:
count: 3
size: Standard_D4s_v5
workers:
count: 3
size: Standard_D2s_v5
cni: cilium Networking
Virtual Network Configuration
Each environment gets an isolated VNet:
spec:
infrastructure:
provider: azure
region: eastus
network:
vnetCidr: 10.0.0.0/16
subnets:
- name: control-plane
cidr: 10.0.1.0/24
- name: workers
cidr: 10.0.2.0/24
- name: participants
cidr: 10.0.10.0/24 Generated Terraform
resource "azurerm_virtual_network" "environment" {
name = "env-abc123-vnet"
resource_group_name = azurerm_resource_group.environment.name
location = azurerm_resource_group.environment.location
address_space = ["10.0.0.0/16"]
tags = {
environment = "env-abc123"
managed_by = "teabar"
}
}
resource "azurerm_subnet" "participants" {
name = "participants"
resource_group_name = azurerm_resource_group.environment.name
virtual_network_name = azurerm_virtual_network.environment.name
address_prefixes = ["10.0.10.0/24"]
} Network Security Groups
Default NSG rules:
spec:
infrastructure:
firewall:
ingress:
- name: SSH
priority: 100
port: 22
protocol: Tcp
source: "*"
- name: HTTPS
priority: 110
port: 443
protocol: Tcp
source: "*"
egress:
- name: AllOutbound
priority: 100
port: "*"
protocol: "*"
destination: "*" Load Balancers
Azure offers multiple load balancer options:
resources:
- name: app-lb
type: loadbalancer
spec:
type: standard # basic or standard
sku: Standard
frontend:
- name: web
publicIP: true
backend:
- resource: webserver
rules:
- name: https
frontendPort: 443
backendPort: 8080
protocol: Tcp
healthProbe:
port: 8080
protocol: Http
path: /health Storage
Managed Disks
Attach persistent storage:
resources:
- name: data-disk
type: volume
spec:
size: 100 # GB
sku: Premium_LRS # Standard_LRS, StandardSSD_LRS, Premium_LRS
- name: database
type: vm
spec:
size: Standard_D4s_v5
volumes:
- data-disk Disk SKUs
| SKU | Type | Use Case | Max IOPS |
|---|---|---|---|
Standard_LRS | HDD | Archives, backups | 500 |
StandardSSD_LRS | SSD | Web servers, dev | 6,000 |
Premium_LRS | Premium SSD | Production databases | 20,000 |
UltraSSD_LRS | Ultra disk | High-performance | 160,000 |
AKS Integration
AKS with Azure Integrations
AKS clusters can leverage Azure-native services:
resources:
- name: aks-cluster
type: cluster
spec:
distribution: aks
version: "1.29"
nodePools:
- name: system
vmSize: Standard_D2s_v5
count: 2
# Azure integrations
integrations:
# Azure AD Integration
azureAD:
enabled: true
adminGroupObjectIds:
- "<AAD_GROUP_ID>"
# Azure Monitor
monitoring:
enabled: true
logAnalyticsWorkspaceId: "<WORKSPACE_ID>"
# Azure Container Registry
acr:
enabled: true
registryId: "<ACR_ID>"
# Azure Key Vault
keyVault:
enabled: true
secretsProvider: true Workload Identity
Allow pods to access Azure resources:
resources:
- name: storage-identity
type: azure-managed-identity
spec:
serviceAccount: my-app
namespace: default
roles:
- scope: "/subscriptions/.../storageAccounts/mystorage"
role: "Storage Blob Data Reader" Active Directory Integration
AAD Authentication for VMs
resources:
- name: participant-vm
type: vm
spec:
size: Standard_B2s
image:
publisher: Canonical
offer: 0001-com-ubuntu-server-jammy
sku: 22_04-lts-gen2
perParticipant: true
authentication:
type: aad # Azure AD login AAD for AKS
resources:
- name: aks-cluster
type: cluster
spec:
distribution: aks
version: "1.29"
azureAD:
enabled: true
managed: true
adminGroupObjectIds:
- "00000000-0000-0000-0000-000000000000"
tenantId: "{{ .Org.azure.tenantId }}" DNS with Azure DNS
resources:
- name: app-dns
type: dns
spec:
provider: azure-dns
zone: workshop.example.com
resourceGroup: dns-rg
records:
- name: "app"
type: A
ttl: 300
value: "{{ .Resources.app-lb.public_ip }}"
- name: "www"
type: CNAME
ttl: 300
value: "app.workshop.example.com" Cost Management
Pricing Considerations
| Cost Factor | Notes |
|---|---|
| Pay-as-you-go | Default, per-minute billing |
| Reserved Instances | 1-3 year commitment for discounts |
| Spot VMs | Up to 90% discount, can be evicted |
| Hybrid Benefit | Use existing Windows/SQL licenses |
Using Spot VMs
For cost-sensitive, interruptible workloads:
resources:
- name: worker-vm
type: vm
spec:
size: Standard_D4s_v5
spot:
enabled: true
maxPrice: 0.10
evictionPolicy: Deallocate Warning
Cost Estimation
teactl env estimate --blueprint azure-workshop --participants 20 Resource Groups
Teabar creates a resource group for each environment:
rg-teabar-env-abc123
├── env-abc123-vnet
├── env-abc123-nsg
├── env-abc123-vm-0
├── env-abc123-vm-1
└── env-abc123-disk-0 All resources are tagged for tracking:
{
"environment": "env-abc123",
"organization": "acme-corp",
"managed_by": "teabar"
} Limitations
| Feature | Azure Notes |
|---|---|
| Cost | Similar to AWS, higher than Hetzner |
| Provisioning | Slower than Hetzner (~3-5 min) |
| Complexity | Many configuration options |
| AKS costs | Free control plane + node costs |
Troubleshooting
Common Issues
“AuthorizationFailed”
Service principal lacks required permissions. Check role assignments.
“QuotaExceeded”
Request a quota increase via Azure portal Support + Troubleshooting.
“SkuNotAvailable”
The VM size isn’t available in the region. Try a different size or region.
“ResourceGroupNotFound”
Ensure the subscription ID and region are correct.
View Provisioning Logs
teactl env logs my-workshop --component provisioner