Beginner

Azure Fundamentals – Compute

VMs, App Service, Functions, scale sets, ACI, AKS and Service Fabric with HA and cost trade-offs.

Module 1 – Virtual Machines (VMs)

VM Advantages

AdvantageDescription
FlexibilityChoose the size, OS, and configuration
Cost-efficiencyPay-as-you-go, predictable with Reserved Instances
AgilityDeploy in minutes via portal, CLI, or ARM templates
ReliabilityRedundant infrastructure, availability SLAs

Available OS

  • Windows Server: 2012, 2016, 2019, 2022.
  • Linux: Ubuntu (20.04, 22.04), RHEL, SUSE, Debian, CentOS, etc.

VM Lifecycle

StateResourcesBilling
RunningCPU, memory, storageCompute billing
Stopped (OS shutdown)Reserved (static IP retained)Still billed
DeallocatedReleased (IP may change)Storage only

Tip: Use Deallocate (not just Stop) to avoid compute charges.

Create a VM via CLI

az vm create \
  --resource-group myResourceGroup \
  --name MyUbuntuVM \
  --image Ubuntu2204 \
  --admin-username azureuser \
  --authentication-type ssh \
  --generate-ssh-keys \
  --size Standard_D2s_v3

# Manage the VM
az vm start --resource-group myRG --name MyVM
az vm stop --resource-group myRG --name MyVM
az vm deallocate --resource-group myRG --name MyVM
az vm restart --resource-group myRG --name MyVM

ARM Template for Automating VMs

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "parameters": {
    "computerName": {"type": "string"},
    "adminUsername": {"type": "string"},
    "adminPassword": {"type": "securestring"}
  },
  "resources": [
    {
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[concat(parameters('computerName'), '-vnet')]"
      // ...
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "name": "[parameters('computerName')]",
      "dependsOn": ["[resourceId('Microsoft.Network/networkInterfaces', ...)]"]
      // ...
    }
  ]
}

VM Sizes

SeriesUse Case
B-seriesDev/test, lightweight workloads (burstable)
D-series (D2s_v3: 2vCPU, 8GB)General applications, web, databases
E-seriesMemory-intensive (in-memory databases)
F-seriesCompute-intensive (simulations, batch)
N-seriesGPU (ML, 3D rendering)

Module 2 – Azure App Service

Characteristics

  • PaaS: Azure manages servers, patches, scalability.
  • Deploy code from: GitHub, Azure Repos, Bitbucket, Zip, Docker.
  • Languages: .NET, .NET Core, Java, Node.js, PHP, Python, Ruby.
  • Included features: HTTPS/TLS, custom domains, auto-scaling, load balancing.
  • Compliance: ISO, SOC, GDPR.

App Service Plans

PlanSKUDescription
Free/SharedF1, D1Dev/test, strict limits
BasicB1, B2, B3Small apps, no autoscaling
StandardS1, S2, S3Production, autoscaling, staging slots
PremiumP1v3, P2v3High performance, VNet, ACR
IsolatedI1, I2, I3Dedicated environment (ASE)

Deployment from GitHub Actions

name: Deploy to Azure App Service

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Deploy to Azure Web App
        uses: azure/webapps-deploy@v2
        with:
          app-name: 'my-app'
          publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
          package: .

Module 3 – Azure Functions (Fundamentals Summary)

Concept

  • Event-driven serverless: code triggered by events.
  • No servers to manage.
  • Pay per execution: 1 million free invocations/month.

Common Triggers

TriggerInitiator
HTTPWeb requests, webhooks, APIs
TimerScheduled (cron)
QueueNew message in a Storage queue
BlobNew file in Azure Blob Storage
Cosmos DBChanges in a collection

Compute Options Comparison

ServiceTypeControlScalabilityUse Case
Virtual MachinesIaaSHighManual + autoLift-and-shift, legacy apps
App ServicePaaSMediumAutoWeb apps, REST APIs
Azure FunctionsFaaS/ServerlessLowAutomaticEvent processing, microservices
Container InstancesContainersMediumManualIsolated/ephemeral containers
AKSKubernetesHighAutoComplex container orchestration

Key Takeaways

  • VM Deallocated ≠ VM Stopped → only Deallocated stops compute billing.
  • App Service = PaaS, Microsoft manages the server, you manage the app.
  • Functions = serverless, triggered by events, pay-per-execution.
  • Always prefer SSH keys over passwords for Linux VMs.
  • ARM templates = automate infrastructure deployment (Infrastructure as Code).


Advanced Sections – Course Enrichment


Module 4 – VM Scale Sets (VMSS)

Concept and Advantages

VM Scale Sets allow deploying and managing a set of identical VMs with automatic scaling. Azure monitors the load and adjusts the number of instances without manual intervention.

FeatureDescription
AutoscalingAutomatic increase/decrease based on CPU, memory, queue metrics
Integrated Load BalancerTraffic distribution across all instances
Coordinated updatesZero-downtime deployments
Managed disksSimplified storage management
Zone supportInstances spread across multiple Availability Zones

VMSS Architecture

graph TD
    LB[Azure Load Balancer / Application Gateway]
    LB --> VM1[VM Instance 1]
    LB --> VM2[VM Instance 2]
    LB --> VM3[VM Instance 3]
    LB --> VMn[VM Instance N...]
    AS[Autoscale Engine] -->|Scale Out / Scale In| LB
    MON[Azure Monitor - Metrics] --> AS
    HP[Health Probes] --> LB

Scaling Policies

Scale-Out (increase) and Scale-In (decrease)

# Create a VMSS with autoscaling
az vmss create \
  --resource-group myRG \
  --name myScaleSet \
  --image Ubuntu2204 \
  --upgrade-policy-mode Automatic \
  --admin-username azureuser \
  --generate-ssh-keys \
  --instance-count 2 \
  --vm-sku Standard_D2s_v3

# Configure autoscaling (min 2, max 10 instances, 70% CPU threshold)
az monitor autoscale create \
  --resource-group myRG \
  --resource myScaleSet \
  --resource-type Microsoft.Compute/virtualMachineScaleSets \
  --name autoscaleProfile \
  --min-count 2 \
  --max-count 10 \
  --count 2

# Scale-Out rule: CPU > 70% for 5 min → +2 instances
az monitor autoscale rule create \
  --resource-group myRG \
  --autoscale-name autoscaleProfile \
  --scale out 2 \
  --condition "Percentage CPU > 70 avg 5m"

# Scale-In rule: CPU < 30% for 10 min → -1 instance
az monitor autoscale rule create \
  --resource-group myRG \
  --autoscale-name autoscaleProfile \
  --scale in 1 \
  --condition "Percentage CPU < 30 avg 10m"

Upgrade Policies

PolicyBehaviorUse Case
AutomaticAzure updates all instances automaticallyNon-critical environments
RollingUpdate in batches, health check between each batchProduction with high availability
ManualUpdate triggered manually by the operatorFull control, sensitive migrations
# Change the upgrade policy
az vmss update \
  --resource-group myRG \
  --name myScaleSet \
  --set upgradePolicy.mode=Rolling \
  --set upgradePolicy.rollingUpgradePolicy.maxBatchInstancePercent=20 \
  --set upgradePolicy.rollingUpgradePolicy.maxUnhealthyInstancePercent=20 \
  --set upgradePolicy.rollingUpgradePolicy.pauseTimeBetweenBatches="PT0S"

Health Probes and Application Health Extension

# Add an HTTP health probe (port 80, path /health)
az network lb probe create \
  --resource-group myRG \
  --lb-name myScaleSetLB \
  --name myHealthProbe \
  --protocol Http \
  --port 80 \
  --path /health \
  --interval 15 \
  --threshold 2

Managed vs Unmanaged Disks

CriteriaManaged DisksUnmanaged Disks
ManagementAzure manages the storage accountYou manage the storage account
Availability99.999% SLADepends on your configuration
SimplicityRecommended (default)Deprecated for new projects
SnapshotsNative, simpleManual
EncryptionSSE enabled by defaultConfigurable

Bicep — Full VMSS Deployment

param location string = resourceGroup().location
param vmssName string = 'myScaleSet'
param instanceCount int = 2
param vmSku string = 'Standard_D2s_v3'
param adminUsername string
@secure()
param adminPassword string

resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2023-03-01' = {
  name: vmssName
  location: location
  sku: {
    name: vmSku
    tier: 'Standard'
    capacity: instanceCount
  }
  properties: {
    upgradePolicy: {
      mode: 'Rolling'
      rollingUpgradePolicy: {
        maxBatchInstancePercent: 20
        maxUnhealthyInstancePercent: 20
        pauseTimeBetweenBatches: 'PT0S'
      }
    }
    virtualMachineProfile: {
      osProfile: {
        computerNamePrefix: 'vmss-node'
        adminUsername: adminUsername
        adminPassword: adminPassword
      }
      storageProfile: {
        imageReference: {
          publisher: 'Canonical'
          offer: '0001-com-ubuntu-server-jammy'
          sku: '22_04-lts-gen2'
          version: 'latest'
        }
        osDisk: {
          createOption: 'FromImage'
          managedDisk: {
            storageAccountType: 'Premium_LRS'
          }
        }
      }
      networkProfile: {
        networkInterfaceConfigurations: [
          {
            name: 'myNicConfig'
            properties: {
              primary: true
              ipConfigurations: [
                {
                  name: 'myIpConfig'
                  properties: {
                    subnet: {
                      id: resourceId('Microsoft.Network/virtualNetworks/subnets', 'myVnet', 'mySubnet')
                    }
                  }
                }
              ]
            }
          }
        ]
      }
    }
  }
}

Module 5 – Azure App Service (Deep Dive)

App Service Plans – Full Detail

PlanSKUvCPURAMStorageAutoscalingSlotsIndicative price/month
FreeF1Shared1 GB1 GBNo0Free
SharedD1Shared1 GB1 GBNo0~$10
BasicB1/B2/B31-41.75-7 GB10 GBNo0~$13-$55
StandardS1/S2/S31-41.75-7 GB50 GBYes (5)5~$73-$292
Premium v3P1v3/P2v3/P3v32-88-32 GB250 GBYes (20)20~$138-$552
Isolated v2I1v2-I6v22-328-128 GB1 TBYes (max)20~$302+

App Service Environment (ASE): deployment in your private VNet, full network isolation, requires the Isolated plan.

Deployment Slots — Blue/Green Strategy

graph LR
    DEV[Dev Branch] -->|CI/CD Push| STAGING[Staging Slot\n staging.azurewebsites.net]
    STAGING -->|Validation tests| SWAP{Swap to Production}
    SWAP -->|Success| PROD[Production Slot\n app.azurewebsites.net]
    SWAP -->|Failure| ROLLBACK[Reverse swap\n back to Staging]
    PROD -->|100% traffic| USERS[Users]
# Create a staging slot
az webapp deployment slot create \
  --resource-group myRG \
  --name myApp \
  --slot staging

# Deploy to the staging slot
az webapp deployment source config-zip \
  --resource-group myRG \
  --name myApp \
  --slot staging \
  --src ./app.zip

# Swap staging → production (zero-downtime)
az webapp deployment slot swap \
  --resource-group myRG \
  --name myApp \
  --slot staging \
  --target-slot production

# Auto-swap: automatic swap on every staging deployment
az webapp deployment slot auto-swap \
  --resource-group myRG \
  --name myApp \
  --slot staging \
  --auto-swap-slot production

Deployment Options

MethodDescriptionCI/CD
ZIP DeployCompress and push via CLI/RESTManual or scriptable
GitHub ActionsAutomated pipeline via .github/workflowsYes
Azure DevOps PipelinesYAML pipeline in Azure ReposYes
FTP/FTPSDirect file uploadNot recommended
Visual Studio PublishDirect publish from IDELocal development
Docker/ACRContainer image deploymentYes
Local GitPush to a Git repo hosted by AzureYes

App Service Autoscaling

# Enable autoscaling on the App Service plan
az monitor autoscale create \
  --resource-group myRG \
  --resource myAppServicePlan \
  --resource-type Microsoft.Web/serverfarms \
  --name webAppAutoscale \
  --min-count 1 \
  --max-count 5 \
  --count 1

# Rule: scale-out if CPU > 80%
az monitor autoscale rule create \
  --resource-group myRG \
  --autoscale-name webAppAutoscale \
  --scale out 1 \
  --condition "CpuPercentage > 80 avg 5m"

# Rule: scale-in if CPU < 20%
az monitor autoscale rule create \
  --resource-group myRG \
  --autoscale-name webAppAutoscale \
  --scale in 1 \
  --condition "CpuPercentage < 20 avg 10m"

Custom Domain + TLS

# Bind a custom domain
az webapp config hostname add \
  --resource-group myRG \
  --webapp-name myApp \
  --hostname www.mydomain.com

# Create and bind an Azure-managed TLS certificate (free on Standard+)
az webapp config ssl bind \
  --resource-group myRG \
  --name myApp \
  --certificate-thumbprint <THUMBPRINT> \
  --ssl-type SNI

# Enforce HTTPS
az webapp update \
  --resource-group myRG \
  --name myApp \
  --https-only true

Application Settings vs Connection Strings

TypeStorageCode AccessRecommended Usage
App SettingsEncrypted key/valueEnvironment.GetEnvironmentVariable()General config, feature flags
Connection StringsEncrypted key/valueConfigurationManager.ConnectionStringsDB connection strings
Key Vault ReferenceReference to Azure Key VaultTransparent (same API)Sensitive secrets (production)
# Set App Settings
az webapp config appsettings set \
  --resource-group myRG \
  --name myApp \
  --settings \
    ENVIRONMENT=production \
    API_KEY=@Microsoft.KeyVault(SecretUri=https://myKV.vault.azure.net/secrets/apikey/)

# Set a Connection String
az webapp config connection-string set \
  --resource-group myRG \
  --name myApp \
  --connection-string-type SQLAzure \
  --settings DefaultConnection="Server=tcp:myserver.database.windows.net;..."

Module 6 – Azure Container Instances (ACI)

Concept — Serverless Containers

Azure Container Instances allows running Docker containers without managing servers or orchestrators. Ideal for ephemeral tasks, burst workloads, or CI/CD pipelines.

FeatureDetail
StartupA few seconds (no VM provisioning)
BillingPer second of execution + allocated resources
OSLinux and Windows
NetworkPublic IP or VNet integration
StorageAzure Files volumes, ephemeral volumes
RegistryDocker Hub, Azure Container Registry (ACR)

Architecture — Container Groups

A Container Group is the highest-level resource in ACI. It can contain multiple containers sharing the same network and lifecycle (sidecar pattern).

graph TD
    CG[Container Group\n IP: 40.x.x.x]
    CG --> APP[Main Container\n app:latest\n Port 80\n 1 vCPU / 1.5 GB]
    CG --> SIDECAR[Sidecar Container\n log-collector:latest\n Port 9090\n 0.5 vCPU / 0.5 GB]
    CG --> VOL[Shared Volume\n Azure Files]
    APP --> VOL
    SIDECAR --> VOL

Restart Policies

PolicyBehaviorUse Case
AlwaysAlways restarts after stoppingLong-running services
NeverNever restartsBatch tasks, one-time jobs
OnFailureRestarts only if the container failsScripts with retry logic

Deployment via Azure CLI

# Simple container deployment
az container create \
  --resource-group myRG \
  --name myContainer \
  --image mcr.microsoft.com/azuredocs/aci-helloworld \
  --cpu 1 \
  --memory 1.5 \
  --ports 80 \
  --dns-name-label myapp-demo \
  --restart-policy OnFailure \
  --environment-variables \
    ENV=production \
    APP_VERSION=1.0

# Check status
az container show \
  --resource-group myRG \
  --name myContainer \
  --query "{Status:instanceView.state, IP:ipAddress.ip}" \
  --output table

# View logs
az container logs --resource-group myRG --name myContainer

# Delete
az container delete --resource-group myRG --name myContainer --yes

Multi-container Deployment via YAML

# container-group.yaml
apiVersion: 2021-10-01
location: eastus
name: myContainerGroup
properties:
  containers:
  - name: main-app
    properties:
      image: mcr.microsoft.com/azuredocs/aci-helloworld
      resources:
        requests:
          cpu: 1.0
          memoryInGb: 1.5
      ports:
      - port: 80
        protocol: TCP
      volumeMounts:
      - name: shared-logs
        mountPath: /var/log/app
  - name: log-sidecar
    properties:
      image: busybox
      command: ["sh", "-c", "tail -f /var/log/app/app.log"]
      resources:
        requests:
          cpu: 0.5
          memoryInGb: 0.5
      volumeMounts:
      - name: shared-logs
        mountPath: /var/log/app
  osType: Linux
  ipAddress:
    type: Public
    ports:
    - protocol: TCP
      port: 80
  restartPolicy: OnFailure
  volumes:
  - name: shared-logs
    azureFile:
      shareName: myfileshare
      storageAccountName: mystorageaccount
      storageAccountKey: <key>
tags: {}
type: Microsoft.ContainerInstance/containerGroups
# Deploy via YAML file
az container create \
  --resource-group myRG \
  --file container-group.yaml

ACI Resource Limits

ResourceLimit per containerLimit per group
vCPU44
Memory16 GB16 GB
Temp storage50 GB50 GB
GPU4 (K80/P100/V100)4

Module 7 – Azure Kubernetes Service (AKS)

AKS Architecture

graph TB
    subgraph "Control Plane (managed by Azure)"
        API[API Server]
        ETCD[etcd]
        SCH[Scheduler]
        CM[Controller Manager]
    end
    subgraph "System Node Pool"
        NS1[Node 1\n Standard_D4s_v3]
        NS2[Node 2\n Standard_D4s_v3]
    end
    subgraph "Application Node Pool"
        NA1[Node 3\n Standard_D8s_v3]
        NA2[Node 4\n Standard_D8s_v3]
        NA3[Node 5\n Standard_D8s_v3]
    end
    API --> NS1
    API --> NS2
    API --> NA1
    API --> NA2
    API --> NA3
    INGRESS[Ingress Controller\n NGINX / App Gateway] --> NS1
    HPA[HPA\n Horizontal Pod Autoscaler] --> NA1
    PVC[Persistent Volume Claims\n Azure Disks / Files] --> NA1

Create an AKS Cluster

# Create an AKS cluster with 2 node pools
az aks create \
  --resource-group myRG \
  --name myAKSCluster \
  --node-count 2 \
  --node-vm-size Standard_D4s_v3 \
  --network-plugin azure \
  --enable-managed-identity \
  --enable-addons monitoring \
  --generate-ssh-keys \
  --kubernetes-version 1.28.0

# Get kubectl credentials
az aks get-credentials \
  --resource-group myRG \
  --name myAKSCluster

# Add an application node pool
az aks nodepool add \
  --resource-group myRG \
  --cluster-name myAKSCluster \
  --name apppool \
  --node-count 3 \
  --node-vm-size Standard_D8s_v3 \
  --mode User

Fundamental Kubernetes Objects

ObjectRole
PodMinimum deployment unit, 1+ containers
DeploymentManages pod lifecycle, rolling updates
ServiceStable network exposure of pods (ClusterIP, NodePort, LoadBalancer)
IngressExternal HTTP/HTTPS routing to services
ConfigMapNon-secret configuration
SecretSensitive data (credentials, certs)
PersistentVolumeClaimRequest for persistent storage
HorizontalPodAutoscalerMetrics-based autoscaling
NamespaceLogical isolation of resources

YAML Manifest Files

# deployment.yaml — Web application
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: myacr.azurecr.io/my-app:v1.2.0
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: "250m"
            memory: "256Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
        env:
        - name: ASPNETCORE_ENVIRONMENT
          value: "Production"
        - name: ConnectionStrings__DefaultConnection
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: db-connection
        livenessProbe:
          httpGet:
            path: /health/live
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 15
        readinessProbe:
          httpGet:
            path: /health/ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
---
# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-app-svc
  namespace: production
spec:
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP
---
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - app.mydomain.com
    secretName: app-tls-cert
  rules:
  - host: app.mydomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app-svc
            port:
              number: 80

HPA — Horizontal Pod Autoscaler

# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Essential kubectl Commands

# Context and cluster
kubectl config get-contexts
kubectl config use-context myAKSCluster

# Pods and deployments
kubectl get pods -n production -o wide
kubectl describe pod my-app-xxx -n production
kubectl logs my-app-xxx -n production --tail=100 -f
kubectl exec -it my-app-xxx -n production -- /bin/bash

# Deployment and updates
kubectl apply -f deployment.yaml
kubectl rollout status deployment/my-app -n production
kubectl rollout history deployment/my-app -n production
kubectl rollout undo deployment/my-app -n production     # Rollback

# Manual scaling
kubectl scale deployment my-app --replicas=5 -n production

# Services and ingress
kubectl get svc -n production
kubectl get ingress -n production

# Namespaces
kubectl create namespace production
kubectl get all -n production

# Resources
kubectl top pods -n production
kubectl top nodes

# PVC
kubectl get pvc -n production
kubectl describe pvc my-pvc -n production

AKS Network: Azure CNI vs Kubenet

CriteriaAzure CNIKubenet
IP assignmentEach pod gets a VNet IPNAT — pods share the node IP
PerformanceHigh (direct VNet connection)Slightly lower (NAT)
IP consumptionHigh (plan address space)Low
Azure servicesNative integration (Private Link, etc.)Limitations for some services
Use caseProduction, complex VNet integrationSimple environments, dev

PVC — Persistent Storage

# pvc.yaml — Azure Premium disk
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
  namespace: production
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: managed-premium
  resources:
    requests:
      storage: 32Gi

Module 8 – Azure Functions (Deep Dive)

Consumption and Hosting Plans

PlanBillingCold StartDuration LimitScalability
ConsumptionPer execution + GB-sYes (~1-3s)10 minAuto (0→∞)
PremiumAlways-warm planNoUnlimitedAuto + VNet
Dedicated (App Service)App Service planNoUnlimitedManual or auto
Container AppsPer vCPU-s + memoryYes (configurable)UnlimitedAuto

Triggers and Bindings

graph LR
    T1[HTTP Request] -->|Trigger| FUNC[Azure Function]
    T2[Timer\n CRON] -->|Trigger| FUNC
    T3[Azure Queue\n Storage] -->|Trigger| FUNC
    T4[Blob Storage\n New file] -->|Trigger| FUNC
    T5[Cosmos DB\n Change Feed] -->|Trigger| FUNC
    T6[Event Grid\n Event Hub] -->|Trigger| FUNC
    FUNC -->|Output Binding| OUT1[Azure Queue]
    FUNC -->|Output Binding| OUT2[Cosmos DB]
    FUNC -->|Output Binding| OUT3[SendGrid Email]
    FUNC -->|Output Binding| OUT4[SignalR]

Code Examples

// HTTP Trigger — Simple REST API
[FunctionName("GetWeather")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = "weather/{city}")] 
    HttpRequest req,
    string city,
    ILogger log)
{
    log.LogInformation($"Weather request for: {city}");
    var result = await weatherService.GetWeatherAsync(city);
    return new OkObjectResult(result);
}

// Timer Trigger — Daily report at 8:00 AM UTC
[FunctionName("DailyReport")]
public static async Task Run(
    [TimerTrigger("0 0 8 * * *")] TimerInfo timer,
    [CosmosDB("myDB", "myCollection", Connection = "CosmosDBConnection")] 
    IAsyncCollector<ReportDocument> reports,
    ILogger log)
{
    var report = await generateReportAsync();
    await reports.AddAsync(report);
    log.LogInformation("Daily report generated and saved.");
}

// Queue Trigger + Blob Output Binding
[FunctionName("ProcessImage")]
public static async Task Run(
    [QueueTrigger("images-to-process", Connection = "StorageConnection")] 
    string messageJson,
    [Blob("processed-images/{rand-guid}.jpg", FileAccess.Write, Connection = "StorageConnection")] 
    Stream outputBlob,
    ILogger log)
{
    var message = JsonSerializer.Deserialize<ImageMessage>(messageJson);
    var processedImage = await resizeImageAsync(message.BlobUrl);
    await processedImage.CopyToAsync(outputBlob);
}

Durable Functions — Workflow Orchestration

// Orchestrator — E-commerce order
[FunctionName("ProcessOrder")]
public static async Task<string> RunOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var order = context.GetInput<Order>();

    // Sequential execution
    await context.CallActivityAsync("ValidatePayment", order.PaymentId);
    await context.CallActivityAsync("ReserveStock", order.Items);

    // Parallel execution
    var parallelTasks = new List<Task>
    {
        context.CallActivityAsync("SendConfirmationEmail", order.Email),
        context.CallActivityAsync("NotifyWarehouse", order.Items),
        context.CallActivityAsync("UpdateCRM", order.CustomerId)
    };
    await Task.WhenAll(parallelTasks);

    return $"Order {order.Id} processed successfully";
}

// Activity
[FunctionName("ValidatePayment")]
public static async Task<bool> ValidatePayment(
    [ActivityTrigger] string paymentId,
    ILogger log)
{
    log.LogInformation($"Validating payment: {paymentId}");
    return await paymentService.ValidateAsync(paymentId);
}

Deploy Functions via Azure CLI

# Create the Function App (Consumption plan)
az functionapp create \
  --resource-group myRG \
  --consumption-plan-location eastus \
  --runtime dotnet-isolated \
  --runtime-version 8 \
  --functions-version 4 \
  --name myFunctionApp \
  --storage-account mystorageaccount \
  --os-type Linux

# Deploy the code
func azure functionapp publish myFunctionApp

# Configure app settings
az functionapp config appsettings set \
  --resource-group myRG \
  --name myFunctionApp \
  --settings \
    CosmosDBConnection="AccountEndpoint=https://..." \
    StorageConnection="DefaultEndpointsProtocol=https;..."

# Enable Application Insights
az monitor app-insights component create \
  --resource-group myRG \
  --app myFunctionApp-insights \
  --location eastus \
  --kind web

Module 9 – Azure Service Fabric

Microservices Platform

Azure Service Fabric is a distributed platform for deploying and managing scalable and reliable microservices. Unlike AKS (containers), Service Fabric can host native processes or containers.

graph TD
    SF[Service Fabric Cluster\n 5-7 Primary Nodes + Secondary Nodes]
    SF --> APP1[Application\n Product Catalog]
    SF --> APP2[Application\n Order Management]
    APP1 --> SS1[Stateless Service\n Frontend API]
    APP1 --> ST1[Stateful Service\n Product Cache\n Reliable Collections]
    APP2 --> SS2[Stateless Service\n Orders API]
    APP2 --> ST2[Stateful Service\n Order State\n Reliable Dictionary]
    APP2 --> ACT[Reliable Actors\n Customer Cart Session]

Stateless vs Stateful Services

CriteriaStatelessStateful
StateNo persistent local stateLocal persistent state via Reliable Collections
ScalabilityTrivial — add instancesAutomatic partitioning (sharding)
ExamplesWeb APIs, stateless workersShopping cart, distributed cache, counters
ReliabilityRestart = state lostAutomatic replication on 3+ replicas
Use caseCalculations, gateways, orchestratorsFrequently accessed data, low latency

Reliable Collections

// Stateful Service with Reliable Dictionary
public class CartManagement : StatefulService
{
    protected override async Task RunAsync(CancellationToken cancellationToken)
    {
        // Get (or create) a replicated reliable dictionary
        var carts = await StateManager
            .GetOrAddAsync<IReliableDictionary<string, Cart>>("carts");

        while (!cancellationToken.IsCancellationRequested)
        {
            using var tx = StateManager.CreateTransaction();

            // Read
            var result = await carts.TryGetValueAsync(tx, "customer123");
            var cart = result.HasValue ? result.Value : new Cart();

            // Modify
            cart.AddItem(new Item("PROD-001", 2));

            // Transactional write (automatically replicated)
            await carts.SetAsync(tx, "customer123", cart);
            await tx.CommitAsync();

            await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
        }
    }
}

When to Choose Service Fabric vs AKS?

CriteriaService FabricAKS
Service typeNative statefulContainers (stateless recommended)
Learning curveHigh (specific SDK)Moderate (standard Kubernetes)
PortabilityLimited (Microsoft proprietary)High (universal Kubernetes)
Distributed stateNative and optimizedVia volumes / external databases
EcosystemMicrosoft-centricUniversal cloud-native ecosystem
RecommendationLegacy Fabric apps or very stateful servicesNew projects, modern microservices

Module 10 – Comparisons and Architectural Choices

Complete Decision Table

CriteriaVMVMSSApp ServiceACIAKSFunctions
OS ControlFullFullNoneNonePartialNone
Infrastructure managementYouYou (auto)AzureAzureSharedAzure
StartupMinutesMinutesSecondsSecondsSecondsms (warm)
AutoscalingManualAutomaticAutomaticNoHPA autoAutomatic
BillingPer hour (deallocated=0)Per hour × instancesPer plan/hourPer secondPer node/hourPer execution
ContainersVia Docker manualNot nativeYes (via Docker)Yes (native)Yes (orchestrated)Yes (Premium)
StateWith disksWith disksStateless recommendedEphemeralVia PVCStateless
VNetNativeNativePremium/IsolatedOptionalNativePremium
Use caseIaaS/LegacyWeb scaleWeb/APIShort tasksMicroservicesEvent-driven

Decision Tree — Choosing a Compute Service

flowchart TD
    START([New Azure workload]) --> Q1{Need full\nOS control?}
    Q1 -->|Yes| Q2{Automatic\nscalability required?}
    Q1 -->|No| Q3{Container-based\napplication?}
    Q2 -->|Yes| VMSS[VM Scale Sets\nBuilt-in autoscaling]
    Q2 -->|No| VM[Virtual Machine\nFull IaaS control]
    Q3 -->|Yes| Q4{Complex\norchestration required?}
    Q3 -->|No| Q5{Web application\nor REST API?}
    Q4 -->|Yes| AKS[Azure Kubernetes Service\nOrchestrated microservices]
    Q4 -->|No| Q6{Short or\nephemeral task?}
    Q6 -->|Yes| ACI[Azure Container Instances\nServerless containers]
    Q6 -->|No| AKS
    Q5 -->|Yes| Q7{Need complete\nnetwork isolation?}
    Q5 -->|No| Q8{Event-driven logic\nor short processing?}
    Q7 -->|Yes| ASE[App Service\nEnvironment - Isolated]
    Q7 -->|No| APPSVC[Azure App Service\nPaaS web/API]
    Q8 -->|Yes| FUNC[Azure Functions\nServerless FaaS]
    Q8 -->|No| APPSVC

Cost Comparison (East US region estimates)

ServiceExample configEstimated cost/month
VMStandard_D2s_v3 (2vCPU, 8GB) Linux~$70
VMSS3× Standard_D2s_v3~$210
App ServiceStandard S2 (2vCPU, 3.5GB)~$146
App ServicePremium P1v3 (2vCPU, 8GB)~$138
ACI1 vCPU, 1.5GB, 730h~$43
AKS3× Standard_D4s_v3 nodes~$420 (nodes only)
Functions1M executions, 400K GB-sFree (within quota)
Functions10M executions, 5M GB-s~$4

These prices are estimates. Use the Azure Pricing Calculator (calculator.azure.com) for accurate estimates.


Module 11 – High Availability and Resilience

Availability Sets vs Availability Zones

graph TD
    subgraph "Availability Set — same Datacenter"
        FD1[Fault Domain 1\nServer Rack A\nPower supply A]
        FD2[Fault Domain 2\nServer Rack B\nPower supply B]
        FD3[Fault Domain 3\nServer Rack C\nPower supply C]
        UD1[Update Domain 1\nVM1 + VM4]
        UD2[Update Domain 2\nVM2 + VM5]
        UD3[Update Domain 3\nVM3]
    end
    subgraph "Availability Zones — Separate Datacenters"
        AZ1[Zone 1\nDatacenter A]
        AZ2[Zone 2\nDatacenter B]
        AZ3[Zone 3\nDatacenter C]
    end

HA Comparison Table

MechanismProtects AgainstSLAGranularity
Availability SetHardware failures, planned updates99.95%VMs in same datacenter
Availability ZonesComplete datacenter failure99.99%VMs across 3 separate datacenters
Azure Site RecoveryComplete regional disasterDepends on RPO/RTO configCross-region replication
Geo-Redundant StorageLoss of an Azure region99.9999999999999% durabilityData replicated to 2nd region

Configuring High Availability

# Create an Availability Set
az vm availability-set create \
  --resource-group myRG \
  --name myAvailabilitySet \
  --platform-fault-domain-count 3 \
  --platform-update-domain-count 5

# Deploy 3 VMs in the Availability Set
for i in 1 2 3; do
  az vm create \
    --resource-group myRG \
    --name "myVM-$i" \
    --availability-set myAvailabilitySet \
    --image Ubuntu2204 \
    --admin-username azureuser \
    --generate-ssh-keys
done

# Deploy VMs across Availability Zones
az vm create \
  --resource-group myRG \
  --name myVM-Zone1 \
  --zone 1 \
  --image Ubuntu2204 \
  --admin-username azureuser \
  --generate-ssh-keys

az vm create \
  --resource-group myRG \
  --name myVM-Zone2 \
  --zone 2 \
  --image Ubuntu2204 \
  --admin-username azureuser \
  --generate-ssh-keys

Azure Site Recovery (ASR)

Azure Site Recovery ensures business continuity by replicating workloads to a secondary region.

ParameterDescription
RPO (Recovery Point Objective)Maximum tolerated data loss (e.g. 15 min)
RTO (Recovery Time Objective)Maximum tolerated recovery time (e.g. 1h)
FailoverSwitch to secondary region
FailbackReturn to primary region
Test FailoverSimulate DR without production impact
# Enable ASR replication for a VM (via Recovery Services Vault)
az backup protection enable-for-vm \
  --resource-group myRG \
  --vault-name myRecoveryVault \
  --vm myProductionVM \
  --policy-name DefaultPolicy

Geo-Redundancy of Managed Services

ServiceHA OptionDetail
Azure SQL DatabaseGeo-Replication, Failover GroupsRead replica in secondary region
Azure StorageGRS / GZRS6 copies (3 local + 3 paired region)
Cosmos DBMulti-region writesSimultaneous writes to N regions
App ServiceTraffic Manager + multi-region deploymentGeographic routing
AKSMultiple clusters + Azure Front DoorMulti-region resilience

Module 12 – Costs and Optimization

Cost Optimization Strategies

graph LR
    COST[Azure Cost\nOptimization]
    COST --> RI[Reserved Instances\n-40% to -72%]
    COST --> SPOT[Spot VMs\n-60% to -90%]
    COST --> HB[Azure Hybrid\nBenefit\nExisting licenses]
    COST --> RS[Rightsizing\nAdapted size]
    COST --> AS[Auto-Shutdown\nDev environments]
    COST --> DEV[Dev/Test\nPricing]

Reserved Instances

DurationSavings (vs pay-as-you-go)Flexibility
1 year~40%Size/region change possible
3 years~60-72%Less flexible
Single paymentMaximum savingsNo refund flexibility
# View reservation recommendations (Azure CLI)
az reservations reservation-order list \
  --output table

# Calculate potential savings
az consumption reservation recommendation list \
  --look-back-period Last7Days \
  --scope "/subscriptions/SUBSCRIPTION_ID" \
  --reserved-resource-type VirtualMachines

Spot VMs — Interruption-tolerant Workloads

Use cases: Batch, CI/CD workers, ML training, simulations.

# Create a Spot VM
az vm create \
  --resource-group myRG \
  --name mySpotVM \
  --image Ubuntu2204 \
  --priority Spot \
  --eviction-policy Deallocate \
  --max-price 0.10 \
  --admin-username azureuser \
  --generate-ssh-keys

# Spot in a VMSS (recommended for eviction tolerance)
az vmss create \
  --resource-group myRG \
  --name mySpotScaleSet \
  --image Ubuntu2204 \
  --priority Spot \
  --eviction-policy Delete \
  --max-price -1 \
  --instance-count 5 \
  --admin-username azureuser \
  --generate-ssh-keys

Azure Hybrid Benefit

Allows using your on-premises Windows Server or SQL Server licenses (with Software Assurance) on Azure.

ScenarioSavings
Windows Server VM~40% on OS license cost
SQL Server VMUp to 55%
SQL Managed InstanceUp to 55%
AKS (Windows nodes)Windows license included
# Enable Azure Hybrid Benefit on an existing Windows VM
az vm update \
  --resource-group myRG \
  --name myWindowsVM \
  --license-type Windows_Server

# During creation
az vm create \
  --resource-group myRG \
  --name myWindowsVM \
  --image Win2022Datacenter \
  --license-type Windows_Server \
  --admin-username azureuser \
  --admin-password 'P@ssw0rd123!'

Auto-Shutdown — Dev/Test Environments

# Configure auto-shutdown at 6:00 PM (local time)
az vm auto-shutdown \
  --resource-group myRG \
  --name myDevVM \
  --time 1800 \
  --email devops@mycompany.com

# PowerShell — Auto-shutdown via script for all VMs in a RG
$rg = "myDevRG"
$shutdownTime = "1800"
$timezone = "Eastern Standard Time"

Get-AzVM -ResourceGroupName $rg | ForEach-Object {
    $vmId = $_.Id
    $scheduleName = "shutdown-computevm-$($_.Name)"
    
    New-AzResource `
        -ResourceId "/subscriptions/$((Get-AzContext).Subscription.Id)/resourceGroups/$rg/providers/microsoft.devtestlab/schedules/$scheduleName" `
        -Properties @{
            status = "Enabled"
            taskType = "ComputeVmShutdownTask"
            dailyRecurrence = @{ time = $shutdownTime }
            timeZoneId = $timezone
            targetResourceId = $vmId
        } `
        -Force
}

Rightsizing — Identifying Under-utilized VMs

# List VMs and their CPU metrics (last 7 days)
az monitor metrics list \
  --resource "/subscriptions/SUBSCRIPTION_ID/resourceGroups/myRG/providers/Microsoft.Compute/virtualMachines/myVM" \
  --metric "Percentage CPU" \
  --interval PT1H \
  --start-time $(date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
  --aggregation Average \
  --output table

Azure Advisor — Automatic Recommendations

Azure Advisor analyzes your resources and offers recommendations in 5 categories:

CategoryExample Recommendations
CostResize under-utilized VMs, delete orphaned disks
High availabilityAdd Availability Zones, configure backups
SecurityEnable MFA, patch VMs, enable Defender
PerformanceSwitch to Premium disks, use CDN
Operational excellenceUpdate deprecated APIs, use tags
# View Advisor recommendations via CLI
az advisor recommendation list \
  --category Cost \
  --output table

# VM-specific recommendations
az advisor recommendation list \
  --category Cost \
  --query "[?impactedField=='Microsoft.Compute/virtualMachines']" \
  --output table

Module 13 – Review Questions (AZ-900 Exam)

10 Exam-Style Questions with Answers


Question 1 You have an Azure VM in the Stopped state (shut down from the OS). Which statement is correct?

  • A) Compute billing has stopped
  • B) The VM is still billed for compute because resources are allocated
  • C) The VM loses its public IP address
  • D) Disks are no longer billed

Answer: B A VM in the Stopped state (OS shutdown) retains its allocated resources (CPU, RAM, IP) and continues to be billed. Only the Deallocated state (az vm deallocate) releases resources and stops compute billing. Disks remain billed in both cases.


Question 2 Your team is developing a .NET 8 web application without wanting to manage servers or OS patches. Which Azure solution is the best fit?

  • A) Azure Virtual Machines with IIS
  • B) Azure Kubernetes Service
  • C) Azure App Service
  • D) Azure Container Instances

Answer: C Azure App Service is a PaaS service that allows deploying web applications without managing the underlying infrastructure. Azure manages servers, OS patches, scaling and availability.


Question 3 You need to run a Docker container one-time to process an uploaded CSV file, then stop. What is the most appropriate and cost-effective solution?

  • A) Azure Kubernetes Service with a Job
  • B) Azure Container Instances with restartPolicy: Never
  • C) Azure Virtual Machine with Docker installed
  • D) Azure App Service with container

Answer: B ACI with restartPolicy: Never is ideal for ephemeral tasks. It starts in seconds, runs the task, stops, and billing stops per second. AKS would be oversized for a one-time task.


Question 4 Which Azure App Service feature allows you to test a new version of your application in production before making it available to all users, with the possibility of immediate rollback?

  • A) Azure Traffic Manager
  • B) Deployment Slots with Swap
  • C) Azure Front Door
  • D) Availability Zones

Answer: B Deployment Slots allow deploying to a staging slot and performing a swap to production without downtime. If an issue occurs, a reverse swap immediately restores the previous version.


Question 5 Your application generates unpredictable traffic spikes. You want Azure to automatically increase the number of VM instances based on CPU load. Which Azure resource do you use?

  • A) Azure Load Balancer alone
  • B) VM Scale Sets with autoscaling rules
  • C) Virtual Machines with Availability Set
  • D) Azure Application Gateway alone

Answer: B VM Scale Sets combined with Azure Monitor autoscaling rules allow automatically increasing or decreasing the number of instances based on metrics (CPU, memory, queue length, etc.).


Question 6 In Azure Functions, what is a binding?

  • A) The network configuration of a function
  • B) A declarative connection to data resources (input or output) without writing infrastructure code
  • C) The function’s hosting plan
  • D) An authentication mechanism

Answer: B A binding is a declarative connection in function.json or via C# attributes. It can be an input (read from Cosmos DB, Blob Storage) or an output (write to a queue, send an email). The developer writes the business logic; Azure handles the connection.


Question 7 You are deploying an application on 3 VMs in Azure. You want to protect your application against hardware failures and Azure-planned updates. Which configuration do you use?

  • A) 3 VMs in the same Resource Group
  • B) 3 VMs in an Availability Set (3 Fault Domains, 3 Update Domains)
  • C) 3 VMs in the same region
  • D) 3 VMs with Azure Backup enabled

Answer: B An Availability Set distributes VMs across different Fault Domains (separate physical racks with independent power supplies) and Update Domains (groups updated separately). This ensures that a hardware failure or planned update doesn’t affect all your VMs simultaneously, offering a 99.95% SLA.


Question 8 Your company has active Windows Server licenses with Software Assurance. How do you reduce the cost of Windows Azure VMs?

  • A) Use Spot VMs
  • B) Enable Azure Hybrid Benefit
  • C) Switch to the Free plan
  • D) Use Reserved Instances only

Answer: B Azure Hybrid Benefit allows using your existing Windows Server or SQL Server licenses (with Software Assurance) to cover the OS license cost on Azure, reducing costs by up to 40% for Windows Server and 55% for SQL Server.


Question 9 What is the difference between Azure Container Instances (ACI) and Azure Kubernetes Service (AKS)?

  • A) ACI does not support Linux containers
  • B) ACI is serverless for isolated/simple containers; AKS orchestrates microservices at scale with advanced features (HPA, rolling deployments, networking, etc.)
  • C) AKS is free, ACI is paid
  • D) ACI supports more containers per group than AKS per namespace

Answer: B ACI is ideal for simple, ephemeral or isolated containers — without an orchestrator. AKS is a full Kubernetes orchestrator suited for complex microservices architectures with autoscaling, advanced traffic management, namespaces, and network integration.


Question 10 You have an Azure VM whose CPU load is consistently below 5%. Azure Advisor flags this VM. What action is recommended?

  • A) Delete the VM immediately
  • B) Migrate to a smaller VM size (rightsizing) to reduce costs
  • C) Enable autoscaling on the VM
  • D) Move the VM to another region

Answer: B Azure Advisor identifies under-utilized resources and recommends rightsizing — moving to a smaller VM size (e.g. from Standard_D4s_v3 to Standard_D2s_v3) to align costs with actual usage. This is one of the most effective cost optimization methods.


Final Recap — Visual Summary

mindmap
  root((Azure Compute))
    IaaS
      Virtual Machines
        Sizes B D E F N
        Lifecycle Running Stopped Deallocated
        Availability Sets & Zones
      VM Scale Sets
        Autoscaling
        Rolling Automatic Manual
        Health Probes
    PaaS
      App Service
        Plans Free Basic Standard Premium Isolated
        Deployment Slots Swap
        ASE for VNet isolation
      Azure Functions
        Consumption Premium Dedicated
        Triggers HTTP Timer Queue Blob CosmosDB
        Durable Functions
    Containers
      ACI
        Serverless containers
        Container Groups
        Sidecar pattern
      AKS
        Control Plane managed by Azure
        Node Pools
        kubectl HPA PVC Ingress
        Azure CNI vs Kubenet
    Microservices
      Service Fabric
        Stateless vs Stateful
        Reliable Collections
    Optimization
      Reserved Instances 1 yr 3 yr
      Spot VMs -60 to -90%
      Azure Hybrid Benefit
      Rightsizing via Advisor
      Auto-shutdown dev

Enriched document — Azure Fundamentals Compute — All sections covered for the AZ-900 exam and beyond.


Search Terms

azure · fundamentals · compute · core · infrastructure · microsoft · service · deployment · aks · app · functions · via · vms · architecture · availability · cli · comparison · concept · plans · policies · vmss · aci · advantages · application

Interested in this course?

Contact us to book it or get a custom training plan for your team.