Virtual Machines vs AKS in Azure

Virtual machines and AKS represent two fundamentally different approaches to running workloads in Azure. VMs give each workload its own dedicated machine; AKS lets multiple workloads share node capacity. The case for AKS is primarily about density and standardisation — and it only becomes compelling when the operational investment in Kubernetes is justified by the workload scale.

The core trade-off

Running a workload on a VM is straightforward: provision a VM, install the application, and it runs. The VM’s CPU and memory are dedicated to that workload. If the workload uses 10% of the VM’s capacity, 90% is idle and still billed.

Running on AKS means multiple workloads share node capacity. A pod that uses 0.5 vCPU and 512 MiB runs on a node alongside other pods. The node’s unused capacity is available to any pod scheduled there. When the cluster has 10 services, each using an average of 15% of node resources, a single node can potentially run all 10 services at reasonable utilisation — versus 10 individual VMs running at 15% utilisation each.

The break-even point — where AKS overhead is justified by density savings — is typically around 3–5 containerised services. Below that, the operational complexity of running Kubernetes outweighs the density benefits. Above it, AKS typically reduces compute costs while improving deployment consistency.

Comparison across key dimensions

DimensionAzure VMsAKS
Workload density1 VM per workload (typically)Multiple workloads per node via pod bin-packing
Deployment modelSSH + script, Azure VM extensions, or image-basedContainer image + Kubernetes manifests (Deployment, Service)
ScalingManual resize, VMSS autoscale (minutes to add new VM)HPA + Cluster Autoscaler (pods in seconds, nodes in 1–3 min)
Deployment rolloutIn-place update or blue/green with load balancer changesRolling update, blue/green, canary — built into Kubernetes
Self-healingVM Scale Set health probes can replace failed instancesKubernetes restarts failed pods automatically, reschedules on node failure
Operational overheadOS patches, agents, per-VM configurationKubernetes expertise, cluster upgrades, networking
NetworkingVNet, NSG, directly assigned IPPod networking (Azure CNI), Services, Ingress, Network Policies
ObservabilityAzure Monitor, Log Analytics agent per VMContainer Insights, Prometheus, Grafana — pod-level metrics
Application portabilityVM-specific — tied to Azure VHD formatContainer image — portable to any Kubernetes environment

Density and cost efficiency at scale

Consider 10 microservices, each requiring 0.5 vCPU and 512 MiB at average load. On VMs, the smallest reasonable VM for each is a Standard_B2s (2 vCPU, 4 GiB) at approximately $35/month — total: $350/month for 10 VMs, utilising roughly 25% of their combined CPU capacity.

On AKS, these 10 pods need a combined 5 vCPUs and 5 GiB RAM. A node pool of two Standard_D4s_v5 VMs (4 vCPU, 16 GiB each) at ~$140/month each = $280/month provides that capacity with headroom — a saving of $70/month at half the utilisation. At higher service count, the density advantage grows.

The AKS node cost also benefits from Spot node pools, which can reduce node VM costs by 60–90% for batch workloads and non-critical services. VM Scale Sets support Spot VMs too, but AKS makes managing mixed on-demand and Spot node pools more straightforward.

Note

The density calculation assumes workloads are containerised and stateless. Workloads with large in-memory state, persistent local storage requirements, or OS-level dependencies cannot always be containerised without significant rework, which changes the cost-benefit calculation.

Deployment consistency and rollouts

VM deployments are often heterogeneous — different VMs may have different versions of runtimes installed, different patch levels, or slightly different configurations that have accumulated over time. “Configuration drift” is a well-documented problem in VM-based infrastructure that leads to “works on this VM but not that one” issues.

Container images enforce reproducibility. Every pod running the same image runs exactly the same binaries, dependencies, and configuration. AKS Deployments support rolling updates natively — new pods are started before old pods are terminated, ensuring continuous availability. Rollbacks are a single command.

# Deploy a new image version with zero downtime
kubectl set image deployment/my-app my-app=myregistry.azurecr.io/my-app:v2.1

# Check rollout status
kubectl rollout status deployment/my-app

# Roll back if the new version is broken
kubectl rollout undo deployment/my-app

When VMs are the right choice

  • Running 1–3 services where AKS operational overhead exceeds density savings
  • Applications that cannot be containerised — legacy apps with deep OS dependencies, Windows Services, COM-based applications
  • Workloads requiring specific OS versions, kernel modules, or hardware-level isolation
  • Lift-and-shift migrations where containerisation would delay time-to-cloud significantly
  • Teams without Kubernetes expertise where the learning curve is not justified by current workload scale

When AKS is the right choice

  • Running 5+ containerised services where density savings justify the operational investment
  • Teams deploying frequently — AKS rolling updates and GitOps workflows are faster and safer than VM-based deployment scripts
  • Workloads with variable load that benefit from fast horizontal scaling — pods scale in seconds, new VMs take minutes
  • Polyglot microservice environments where different services use different runtimes — each runs in its own container with its own dependencies
  • Teams that want application portability across Azure, on-premises, or other clouds

Migration path from VMs to AKS

Moving from VM-hosted workloads to AKS is a multi-step process. The containerisation step is usually the most effort-intensive for legacy applications, but modern applications built with frameworks like .NET, Node.js, or Python containerise quickly.

  1. Containerise: Write a Dockerfile for each application. Test locally with Docker or Docker Compose. Ensure the application reads configuration from environment variables (not hardcoded or file-based).
  2. Build and push: Set up a CI pipeline to build the container image and push to Azure Container Registry (ACR). Tag images with the commit SHA or version number.
  3. Deploy to AKS: Write Kubernetes Deployment and Service manifests. Deploy to a staging AKS cluster and validate.
  4. Configure Ingress: Install an Ingress controller (NGINX, Azure Application Gateway Ingress Controller) and configure routing rules to replace the VM’s load balancer or direct DNS.
  5. Cut over traffic: Update DNS to point to the AKS Ingress. Monitor application behaviour. Keep the VM running for a short overlap period as a fallback.
  6. Decommission VM: Once the AKS deployment is stable, delete the VM, its managed disk, and associated resources.

Common mistakes

  1. Migrating to AKS before containerising properly. A container image that writes to a local filesystem, stores session state in memory, or assumes a specific hostname will fail unpredictably on Kubernetes. Externalise all state before deploying to AKS.
  2. Running one service on AKS and expecting cost savings. A single-service AKS cluster is almost always more expensive than the same workload on a VM. AKS cost efficiency comes from density across multiple services.
  3. Not setting resource requests and limits on pods. Without resource requests, the Kubernetes scheduler cannot make informed placement decisions. Without limits, a noisy pod can consume all node CPU and cause other pods to be throttled or evicted.
  4. Treating AKS like a VM by scheduling one pod per node. Deploying pods with very high resource requests that prevent bin-packing defeats the density advantage of AKS. Right-size pod requests to match actual utilisation, not theoretical maximums.

Frequently asked questions

Can I run the same application on both a VM and AKS?

If the application is containerised, yes. A Docker image runs on a VM (with Docker installed) or as a Kubernetes Deployment on AKS. The containerisation step is the prerequisite. If the application is not containerised and has deep OS dependencies, it typically cannot run on AKS without significant rework.

Is AKS more expensive than a VM for a single service?

For a single service, AKS is usually more expensive because you need at minimum one node VM (typically 2 vCPU, 8 GiB) to run the cluster, and that node cost is similar to or higher than a VM sized for the same workload. AKS delivers cost efficiency through density — multiple services sharing node capacity. For one service, a VM is often more cost-effective.

What is the migration path from VMs to AKS?

The migration path is: containerise the application (write a Dockerfile), test the container image locally and in staging, provision an AKS cluster, deploy the containerised application as a Kubernetes Deployment with a Service, configure an Ingress for HTTP traffic, set up CI/CD to build and push the container image, then decommission the VM. The containerisation step is often the largest effort for legacy applications.

Last verified: 19 March 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.