EKS to AKS: How to Migrate Kubernetes Workloads When You Move to Azure for Better Enterprise Pricing
A step-by-step runbook for migrating Kubernetes workloads from Amazon EKS to Azure AKS: what actually breaks (IRSA, load balancer annotations, EBS storage classes, ECR, DNS, egress), how to validate the Azure enterprise discount before you move, and how to run both clouds in parallel during cutover.
An EKS to AKS move is a platform migration, not a Kubernetes migration. Deployments, Services, ConfigMaps and Helm charts move unchanged. IAM Roles for Service Accounts, EBS/EFS storage classes, AWS Load Balancer Controller annotations, Route 53 records, ECR pull credentials and Secrets Manager wiring all have to be rebuilt against Azure equivalents. Budget roughly 80% of the effort for that glue layer.
The only structural cost difference between the two managed services is the control plane. EKS charges about $0.10 per cluster-hour, roughly $73/month per cluster. The AKS Free tier charges nothing for the control plane but carries no financially backed SLA. Nodes, disks, load balancers and egress are priced per resource on both clouds, so a single 200-node cluster sees almost no structural saving.
Enterprise Azure savings come from commitments and licensing, not from AKS. An Enterprise Agreement or Microsoft Customer Agreement, Azure Reserved VM Instances, the Azure savings plan for compute, and Azure Hybrid Benefit for Windows Server and SQL Server are where the discount lives. Validate that quote against your remaining AWS Savings Plans first, because stranded commitments routinely erase year-one savings.
The lowest-risk sequence is eight steps: inventory and dependency map, Azure landing zone, replatform manifests, move images, replicate data, parallel run behind weighted DNS, traffic shift, then decommission EKS after 2 to 4 weeks warm.
Stateful workloads set the timeline. Stateless services cut over in hours. Databases need logical replication or a dual-write window plus a tested rollback. Plan 6 to 14 weeks end to end for a mid-size estate, and expect the dual-infrastructure overlap to cost more than the engineering time.
Qovery provisions and operates AKS inside your own Azure subscription (and EKS in your AWS account, GKE in GCP, Scaleway, or your existing Kubernetes cluster), so one application definition runs on both clouds during the cutover and the Azure invoice plus your commitment discount stay in your name. Qovery does not migrate your data or convert RDS to Azure Database for you.
The Kubernetes part of an EKS to AKS migration is the easy part. Your Deployments, Services and Helm charts move almost untouched. What eats the quarter is everything around them: IRSA, load balancer annotations, EBS storage classes, the image registry, and the CI pipeline that has to learn a second cloud.
I have spent years operating Kubernetes clusters across AWS, GCP, Azure and Scaleway at Qovery, and I have talked to more than 200 CTOs about why they move. The pattern for an Azure move is almost always the same. Finance or procurement negotiates an Azure Enterprise Agreement that beats current AWS spend, and then the platform team gets handed the job of moving production without breaking it. This is the runbook for that job. It is written for 2026 pricing, and every price here was last checked in October 2026.
Is AKS actually cheaper than EKS, or does the saving come from your Azure enterprise agreement?
AKS is not intrinsically cheaper than EKS. The only structural difference between the two managed services is the control plane: EKS bills about $0.10 per cluster-hour (roughly $73/month) under standard support, while the AKS Free tier bills nothing for the control plane and carries no financially backed SLA. Every meaningful enterprise saving comes from commitments, licensing and a negotiated EA or MCA, not from the Kubernetes service itself.
Do the arithmetic out loud and the point lands. The control plane delta is a fixed fee per cluster. For a fleet of 40 small clusters that is roughly $2,900 a month of pure control plane that AKS Free can zero out. For one 200-node cluster, $73 a month is a rounding error against the node bill. On AWS, running an old Kubernetes version past standard support adds an extended support surcharge of about $0.50 per cluster-hour (so $0.60/hour total), which is a real reason to keep clusters current on either cloud.
Nodes are the bill on both clouds, and they are priced per resource either way. Compare equivalent families (AWS m7i/c7i against Azure Dsv5/Fsv2) at your real node shapes and your real region, using the EC2 on-demand pricing and the Azure Linux VM pricing pages, not the list price of a single VM in us-east-1. The enterprise discount is applied on top of those node prices through commitments.
Here is where the Azure savings actually come from, and it is worth naming each instrument so your finance team models the right one:
Two things routinely wipe out year-one savings. The first is stranded AWS commitments: unused Savings Plans and Reserved Instances keep billing until term end regardless of usage, so if you move off AWS while a one-year Savings Plan still has eight months to run, you pay for both clouds. Model that overlap explicitly. The second is the dual-run period itself, which I cover at the end.
The one-time migration cost is smaller than people fear. AWS waives data transfer out charges when you are leaving AWS, on request to AWS Support, with 180 days to complete the move for non-EU customers and the EU Data Act addendum for EU customers. So the decision rule is simple: get a priced Azure quote for your actual estate (node shapes, disks, egress, managed databases), plus a TCO model that includes the dual-run overlap, before a single manifest is edited.
What actually breaks when you move a Kubernetes workload from EKS to AKS?
Your Kubernetes objects are portable. The cloud integration layer is not. Eight things break in practice: pod identity (IRSA), ingress annotations, the CNI and pod IP plan, storage classes, ReadWriteMany volumes, the image registry and pull secrets, the secrets driver, and every AWS SDK call in your application code.
The silent blocker is application code. Every SDK call to S3, SQS, DynamoDB, Kinesis or STS keeps pointing at AWS after the pods move to Azure. Grep the codebase for those calls before you plan anything else, because they decide whether you can cut a service over cleanly or whether it has to keep talking back to AWS over a VPN during the overlap.
Repoint External Secrets or CSI SecretProviderClass
Platform
Medium
CloudWatch Container Insights
Azure Monitor managed Prometheus, or keep Prometheus/Grafana/OTel
Repoint exporters, or stay cloud-neutral
App + Platform
Low to Medium
Cluster Autoscaler / Karpenter
AKS cluster autoscaler + Node Autoprovisioning; KEDA managed add-on
New autoscaler config and node pools
Platform
Medium
AWS SDK calls (S3, SQS, DynamoDB, Kinesis, STS)
Blob, Service Bus, Cosmos DB, Event Hubs, Entra
Rewrite SDK calls or keep calling AWS over VPN
App
High
A note on the parts you can choose not to port. If you already run Prometheus, Grafana and OpenTelemetry instead of CloudWatch, your observability layer moves with the manifests and you never pay this tax again. The same logic applies to ingress: a cloud-neutral ingress-nginx is less work over two migrations than rewriting ALB annotations once and Application Gateway annotations later.
What are the steps to migrate from EKS to AKS, in order?
The safe order is eight steps: inventory, Azure landing zone, replatform manifests, move images, replicate data, parallel run, traffic shift, decommission. Reordering it, especially moving data before the landing zone is proven, is the single most common reason a six-week project becomes a quarter.
The discipline that makes this work is a validation gate after every step. You do not start the next step until a named, measurable thing is green. That is what keeps a migration from turning into a big-bang cutover with no way back.
Step
What you do
Tooling
Validation gate
Duration
Rollback if the gate fails
1. Inventory
Map namespaces, CRDs, PVCs, secrets, cron jobs, and every AWS API call; record p95 latency, error rate and cost per service
kubectl, repo grep, cost explorer
Baseline metrics captured and signed off
1 to 2 weeks
N/A (no changes yet)
2. Landing zone
Subscription, VNet and subnet sizing for your CNI mode, AKS with Workload ID and Azure RBAC, ACR, Key Vault, Log Analytics
Terraform/Bicep, az CLI
A smoke-test pod runs, pulls from ACR, reads a Key Vault secret
1 to 2 weeks
Tear down and rebuild the zone
3. Replatform manifests
Push env-specific config into Helm values or Kustomize overlays; replace annotations, storage classes, service accounts
Helm, Kustomize
Same chart deploys clean on a scratch AKS namespace
2 to 6 weeks
Revert chart changes in Git
4. Move images
az acr import from ECR, or re-push from CI; add ACR to the pipeline
az acr, CI
Both registries hold the same tags for every service
Days, in parallel
Keep pulling from ECR
5. Data
Logical replication to Azure Database, Azure DMS online mode, AzCopy for S3 to Blob, Velero for PVs
DMS, AzCopy, Velero
Row counts and checksums match source
1 to 4 weeks
Stop replication; AWS stays source of truth
6. Parallel run
Both clusters live; weighted split via Route 53, Traffic Manager or Front Door; compare against the step 1 baseline
Weighted DNS
Error rate and p95 on AKS within baseline tolerance
2 to 4 weeks
Shift weight back to EKS
7. Cutover
Drop DNS TTL to 60s days ahead; define the numeric rollback trigger; shift 100%
Weighted DNS
Error budget intact for an agreed window
Hours
Flip weight back (EKS still warm)
8. Decommission
Delete node groups, reconcile remaining AWS commitments, confirm the Azure invoice matches the quote
eksctl, billing
EKS deleted, invoice reconciled
Days, after 2 to 4 weeks warm
N/A
Step 1 is the one teams rush and regret. The baseline you capture here (p95 latency, error rate, cost per service) is the only objective way to answer "is the AKS version actually as good?" during the parallel run. Without it, the go/no-go decision becomes a vibe.
How do you migrate stateful workloads and databases from AWS to Azure without downtime?
Stateless services cut over in hours. Stateful ones set the whole timeline. Only two patterns reliably avoid downtime: logical replication with a replica promotion, or a dual-write window. Both require a tested rollback plus a verified row-count or checksum comparison before you touch DNS.
Be honest about the hard case up front. There is no zero-downtime path for a ReadWriteOnce volume with a single writer. EBS snapshots cannot restore natively to Azure Disks, so a cross-cloud volume move goes through Velero File System Backup (Kopia or restic), which means a restore window and downtime. Budget a maintenance window for those volumes and tell stakeholders early, in week one, not the night before.
Sequences, extensions and large objects need checking
MySQL
Binlog replication or Azure DMS online
Seconds (write freeze)
Low to Medium
Verify binlog format and GTID consistency
MongoDB / DocumentDB
Azure Cosmos DB for MongoDB
Short cutover window
Medium
API and index compatibility is not 1:1
DynamoDB
Azure Cosmos DB for NoSQL
Dual-write or export/import
High
Partition-key and consistency-model redesign, not a config change
S3 objects
AzCopy or Azure Data Factory
None with dual-read
Low
Keep a dual-read window so the app tolerates either backend
For relational databases the clean pattern is native logical replication (PostgreSQL) or binlog replication (MySQL), or Azure Database Migration Service in online mode, which supports RDS and Aurora as sources. You replicate continuously, then promote the Azure replica during a short write freeze. NoSQL is harder and I will not pretend otherwise: moving DynamoDB to Cosmos DB for NoSQL means rethinking partition keys and the consistency model, which is real engineering work.
During the overlap, workloads on AKS often still need to reach data that is still on AWS. That means a Site-to-Site VPN or ExpressRoute plus Direct Connect, and it means a round-trip latency tax on every cross-cloud query. Factor that into the parallel-run metrics so you do not mistake network latency for an application regression.
Your cutover checklist for each stateful service is the same every time: freeze writes, drain queues and in-flight jobs, verify row counts and checksums, flip the weighted DNS record, then watch the error budget for 60 minutes with the rollback trigger agreed in advance.
Ship faster on infrastructure you control.
Qovery gives your team self-service deployments on your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster. Start deploying in under 10 minutes.
Should you lift-and-shift, build your own platform layer, or use a platform that already runs on both clouds?
There are three realistic options. Lift-and-shift with hand-rolled Terraform or Bicep is fastest to a running AKS cluster but leaves you maintaining two sets of cloud-specific glue forever. Building your own abstraction with Crossplane or Backstage is clean but means funding a platform team to run it. Adopting a platform that already provisions both EKS and AKS in your own accounts is the shortest path to a genuine side-by-side parallel run.
The reason this choice matters for a migration specifically is the parallel run. Steps 6 and 7 above require both clusters live from the same application definition. If your CI/CD only knows how to deploy to EKS, you are rebuilding the pipeline for AKS before you can even start comparing the two, and you are maintaining both pipelines for the length of the overlap.
Approach
Time to first workload on AKS
Ongoing ops burden
Parallel-run support
Who owns the cloud bill
Lock-in risk
Suits
Lift-and-shift IaC (Terraform/Bicep)
Days to weeks
High (two sets of glue, forever)
Manual, you wire it
You, directly
Low to cloud, high to your scripts
Teams with a strong platform team
Build your own (Crossplane, Backstage, OpenTofu modules)
Weeks to months
High (you run a platform product)
You build it
You, directly
Low
Large orgs funding a platform team
IDP / multi-cluster control plane
Hours to days
Low to medium
Built in
You (runs in your account)
Varies by vendor
Teams without a dedicated platform team
The Microsoft-native route for the third option is Azure Arc plus AKS Fleet Manager, which is a reasonable fit if you are standardizing everything on Azure and do not need the AWS side to stay first-class. The independent platforms in this space include Qovery, Northflank, Porter, Humanitec, Rafay and Spectro Cloud Palette, and they differ mainly in how much of the cloud account they run inside and how even their support is across clouds.
Here is where Qovery fits, and I will be specific because the migration case is where it earns its place. Qovery provisions and operates AKS inside your own Azure subscription, and it also runs EKS in your AWS account, GKE in GCP, Scaleway, or your existing Kubernetes cluster. Because the cluster lives in your subscription, the Azure commitment discount and the invoice stay in your name. One application definition drives git-push deployments, preview environments per pull request, environment auto-stop for non-production, managed cluster upgrades and per-environment RBAC, and all of that survives the move.
For the cutover that means you run the EKS and AKS environments side by side from the same definition instead of rebuilding the pipeline twice, then delete the AWS side once traffic has shifted. I want to be equally clear about the limits. Qovery does not migrate your data, does not convert RDS to Azure Database for you, and does not remove the work of mapping managed services or rewriting AWS SDK calls. Those stay on your plate regardless of which approach you pick.
How long does an EKS to AKS migration take and what does it really cost?
Plan 6 to 14 weeks for a mid-size estate: assessment 1 to 2 weeks, landing zone 1 to 2 weeks, replatforming 2 to 6 weeks, and a parallel run of 2 to 4 weeks per tranche. The dual-infrastructure overlap, not the engineering hours, is usually the largest line item on the invoice, because for the length of the parallel run you are paying two clouds for the same traffic.
Profile
Services
Assessment
Landing zone
Replatform
Parallel run
Total
Biggest cost line
Small, stateless
A handful
Days
Days to 1 week
1 week
Days
2 to 3 weeks
Engineering time
Mid-size, 2 to 3 databases
Dozens
1 to 2 weeks
1 to 2 weeks
2 to 6 weeks
2 to 4 weeks
6 to 14 weeks
Dual-run compute and storage overlap
Regulated enterprise
Many, with data residency
2 to 4 weeks
2 to 4 weeks
Several weeks
Weeks per tranche
One to two quarters
Dual-run overlap plus stranded AWS commitments
The cost lines to budget are duplicate compute and storage during overlap, AWS egress (often free on exit, as noted above), engineering time, the Azure support plan, cross-cloud VPN or ExpressRoute, and any stranded AWS commitment running to term. On funding, ask your Microsoft account team about Azure Migrate and Modernize and partner-led migration credits, and get the amount in writing before you sign the EA. Migration funding that was verbally promised and never materialized is a classic way a "cheaper" move ends up flat.
The risk controls are boring and they work. Migrate the least critical namespace first. Keep one rollback-tested canary service through the whole project. Never migrate a database and shift traffic in the same change window. And budget time for the three things teams underestimate every single time: CI/CD rework, DNS and certificate management, and re-tuning autoscaling and resource requests for a different VM family, because a pod sized for an m7i node is not sized for a Dsv5 node.
How do I run the EKS to AKS move from Claude Code or Cursor?
You can drive the Azure side of the migration from the coding agent you already use. Install the Qovery Agent Skills once, and your agent can connect your Azure subscription, provision AKS and deploy workloads, asking you to approve every change before it runs.
Install globally for any compatible agent (Claude Code, Cursor, Codex, OpenCode, Gemini CLI):
Add the MCP Server to Claude Code, which uses OAuth and is read-only by default:
BASH
claude mcp add --transport http qovery https://mcp.qovery.com/mcp --callback-port 4242
Enable write access only when you want the agent to change things, which also requires turning on write access in the Qovery Console:
BASH
claude mcp add --transport http qovery "https://mcp.qovery.com/mcp?read_write=true" --callback-port 4242
Each skill owns a phase of the move. qovery-onboard connects the Azure subscription and creates the cluster, qovery-deploy ships the workload, qovery-terraform handles the IaC side, qovery-preview sets up per-PR environments, and qovery-troubleshoot and qovery-optimize cover the post-cutover phase. The MCP Server operates what already exists.
Then you ask in plain language, for example "deploy this service to my Azure subscription with Qovery and keep the AWS environment running," and the agent proposes each change and waits for your approval. The full walkthrough is in the AI agent quickstart and the Claude Code integration page.
Frequently asked questions
Is AKS cheaper than EKS?
Not on the Kubernetes service itself in general. The only structural difference is the control plane: EKS charges about $0.10 per cluster-hour (roughly $73/month), while the AKS Free tier charges nothing for the control plane but gives up the financially backed SLA. That delta matters for many small clusters and is noise for one large cluster. Real enterprise savings come from commitments and licensing (Reserved Instances, the savings plan for compute, Azure Hybrid Benefit) negotiated in your EA or MCA, not from AKS.
Can I use the same Helm charts and Kubernetes manifests on AKS that I used on EKS?
Mostly yes. Deployments, Services, ConfigMaps and plain Helm charts move unchanged. What you rewrite is the cloud-specific glue: AWS Load Balancer Controller annotations become Azure Load Balancer or Application Gateway for Containers settings, EBS storage classes become Azure Disk CSI classes, IRSA service-account wiring becomes Microsoft Entra Workload ID, and ECR references become ACR references. Push that env-specific config into Helm values or Kustomize overlays so one chart targets both clouds.
What replaces IAM Roles for Service Accounts (IRSA) on AKS?
Microsoft Entra Workload ID replaces IRSA. You create a federated credential on a user-assigned managed identity, annotate the Kubernetes service account with the identity's client ID, and add the azure.workload.identity/use: "true" label to the pod spec. The older AAD Pod Identity was deprecated in 2022 and its add-on supported only through September 2025, so do not use it for new clusters.
How do I migrate persistent volumes from EBS to Azure Disks?
Use Velero File System Backup (Kopia or restic) for the cross-cloud copy, because EBS snapshots are provider-specific and cannot be restored natively to Azure Disks. Expect a restore window and plan downtime for any ReadWriteOnce volume with a single writer, since there is no live cross-cloud sync for it. Target Azure Disk CSI with Premium SSD v2 and set the IOPS and throughput to match your old gp3 baseline.
Do I have to pay AWS egress fees to move my data to Azure?
Usually not for the migration itself. AWS waives data transfer out to the internet when you are leaving AWS, on request to AWS Support, with 180 days to complete the move for non-EU customers and the EU Data Act addendum covering EU customers. You still pay normal egress for ongoing cross-cloud traffic during the parallel run, so minimize how much AKS has to call back to AWS-hosted data.
Can I run EKS and AKS in parallel during the migration, and for how long?
Yes, and running two clusters in parallel is a mainstream pattern, not an exotic one. Keep EKS warm for 2 to 4 weeks after you shift traffic to AKS so you have a fast rollback path, then decommission it once the Azure metrics hold against your baseline. A platform that deploys the same application definition to both clouds, such as Qovery, makes the parallel run a weighting change rather than a second pipeline build.
Melanie leads content at Qovery. She covers platform engineering trends, Kubernetes operations, FinOps, and the tools that help engineering teams ship faster.
Next step
Ship faster on infrastructure you control.
Qovery gives your team self-service deployments on your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster. Start deploying in under 10 minutes.