Have the cluster's dependencies assessed before you leave? The cloud exit assessment from €1,490 net classifies every service as transferable, replaceable or in need of rework and delivers target architecture, migration path with fallback path and a fixed-price proposal. One possible target is Kubernetes on Hetzner.
Kubernetes manifests that use only the Kubernetes API run on any conformant cluster. Leaving EKS, AKS or GKE is still more than moving manifests, because load balancers, ingress, volumes, identities, registry, logs and the network model depend on the cloud. This guide treats the three services as migration sources, separates the portable from the bound, describes six phases with parallel run and fallback path, and shows what the data transfer costs. Status October 2026.
Table of contents
- What is portable and what is not
- Provider-bound components in EKS, AKS and GKE
- The approach in six phases
- Moving data: volumes, databases, registry
- Cutover and fallback path
- Egress and data transfer when leaving
- Targets: where the cluster goes
- Deadlines, Data Act and UP KRITIS
- Checklist: taking inventory of dependencies
- Our approach at WZ-IT
- Status and methodology
- Further guides
What is portable and what is not
Portable is whatever uses only the Kubernetes API: Deployments, StatefulSets, ConfigMaps, ClusterIP Services, Helm charts and the GitOps repository. Bound is whatever the cluster obtains through the cloud integration. The cloud-controller-manager embeds the cloud-specific control logic, a Service of type LoadBalancer creates a load balancer at providers with external load balancers, a StorageClass names the volume plugin through provisioner, and ingress controllers are often configured through annotations whose meaning depends on the controller.
| Component | Portable | What determines the switch |
|---|---|---|
| Deployments, StatefulSets, ConfigMaps, Helm charts, GitOps repository | yes | Kubernetes version and API groups in the target |
| Container images | yes | Registry access, copy with unchanged digest |
| Service type LoadBalancer, ingress annotations | no | Provider-prefixed annotations, replacement in the target |
| StorageClass, PersistentVolumes | no | Provisioner, data copy per volume |
| Identity of service accounts | no | Binding to IAM, Entra ID or Google IAM |
| Managed databases, queues, object storage | no | Export or continuous replication |
| Network model: pod IPs, peering, firewall rules | no | Address plan, egress IPs, allowlists at third parties |
Provider-bound components in EKS, AKS and GKE
| Component | EKS | AKS | GKE | Replacement in the target |
|---|---|---|---|---|
| Load balancer | AWS Load Balancer Controller (ALB, NLB) | Azure Load Balancer | Cloud Load Balancing | Cloud controller manager of the target, MetalLB or kube-vip |
| Ingress | ALB ingress with alb.ingress.kubernetes.io/* |
Application routing add-on (NGINX) | GKE Ingress with BackendConfig and FrontendConfig | Gateway API with standard resources |
| Volumes | EBS CSI driver | Azure Disk CSI driver | Persistent Disk CSI driver | CSI driver of the target, Longhorn or Ceph |
| Pod identity | IRSA or EKS Pod Identity | Microsoft Entra Workload ID | Workload Identity Federation | Issue credentials per application anew |
| Registry | ECR | Azure Container Registry | Artifact Registry | Registry in the target |
| Logs and metrics | CloudWatch | Azure Monitor | Cloud Logging, Cloud Monitoring | Prometheus, Grafana, Loki |
| Managed add-ons | EKS add-ons | AKS add-ons and extensions | GKE add-ons | Helm charts of the upstream projects |
| Network model | Amazon VPC CNI | Azure CNI (overlay or VNet addresses) | VPC-native network, Dataplane V2 | CNI of your choice, plan the pod CIDR anew |
Sources, load balancer and ingress: AWS, Azure, GKE load balancers, GKE Ingress. Volumes: EBS, Azure Disks, Persistent Disk. Identity: EKS, AKS, GKE. Network and add-ons: VPC CNI, Azure CNI, EKS add-ons, AKS add-ons.
The approach in six phases
The source stays unchanged and runnable to the end. Each phase has a result and a condition for rolling it back.
| Phase | Result | Roll back when |
|---|---|---|
| 1. Inventory and deadlines | Dependency list, contract deadlines, target selection | Target does not meet the requirements |
| 2. Target cluster from Git | Empty cluster, platform through GitOps, Kubernetes version at least that of the source | Bootstrap not reproducible |
| 3. Copy data | Images, volume data, running database replication | Replication lag grows: the database stays in the source |
| 4. Parallel run | Application reachable in the target under a test address, functional and load test passed | Test failed: repeat phase 3 |
| 5. Cutover | Write traffic in the target, DNS switched | Error rate above the agreed threshold: switch back |
| 6. Observation and teardown | Source dismantled after the agreed observation period, contracts terminated | Source stays while the observation runs |
Three rules apply to phase 2. The target has at least the Kubernetes version of the source, because Velero does not restore into a cluster with a lower version. Ingress moves to the Gateway API: ingress-nginx has not been maintained since March 2026, and for the NGINX add-on of AKS Microsoft provides critical security patches until November 2026. Certificates are issued before the cutover: cert-manager knows HTTP01 and DNS01, and HTTP01 needs a name that already points to the new cluster.
Moving data: volumes, databases, registry
Volumes. Velero does not migrate volume snapshots across cloud providers; for volume data between cloud platforms the documentation names File System Backup, which reads the files through the nodes, and the CSI Snapshot Data Mover. According to the documentation, File System Backup backs up only volumes that a pod has mounted, is listed as beta and takes long on large files such as databases because of deduplication. The development version of the documentation adds that a restore onto Azure Files (SMB) and blob FUSE mounts can lose file ownership without an error message. Here, file volumes go through File System Backup and databases through replication or dump. The backup storage is attached read-only in the target (--access-mode=ReadOnly, as recommended).
Databases. Logical replication first copies a snapshot of the tables and then streams the changes. Schema and DDL, sequences and large objects are not replicated (PostgreSQL 18 documentation): create the schema beforehand with pg_dump --schema-only and advance the sequences before the switch. PostgreSQL 19 (release candidate, status 28 October 2026) can synchronize sequences with ALTER SUBSCRIPTION ... REFRESH SEQUENCES. The managed services document logical replication: Amazon RDS, Cloud SQL, Azure Database for PostgreSQL. Where a maintenance window is acceptable, dump and restore suffice (RDS and Aurora guide).
Images and object storage. crane copy copies images into the target registry and retains the digest, so manifests with digest pinning run unchanged. For S3 see the rclone guide.
Cutover and fallback path
Beforehand, lower the DNS TTL, issue the certificates through DNS01 and fix the fallback condition in writing. On the day of the switch:
- Stop write traffic or put the application into read mode.
- Check that replication lag is zero, set the sequences, detach the subscription, make the target database writable.
- Switch DNS to the target, read traffic first or gradually through weighted records.
- Watch error rate and latency against the agreed threshold.
The fallback path is fixed before phase 5. The source stays unchanged and ready to start. For the reverse direction there are two options: a prepared replication from the target back into the source, or the decision that after the cutover only a restore from the backup leads back. The choice depends on how much data loss the application tolerates.
Egress and data transfer when leaving
The Data Act has applied since 12 September 2025. According to the European Commission, switching charges including egress charges are removed from 12 January 2027; until then providers may charge reduced switching charges up to the level of their costs (Article 29 of Regulation (EU) 2023/2854). The three hyperscalers have their own exit programs (status of the pages: 28 October 2026):
| Provider | Program | Application and period | Conditions |
|---|---|---|---|
| AWS | Waiver of data transfer out to the internet charges | Request through AWS Support at least two months before the transfer begins (FAQ); 180 days outside the EU, EU customers under the EU Data Act Addendum | Account in good standing; all data of all eligible accounts or of one service |
| Azure | Free egress when leaving | Support request with subscription or enrollment ID and volume estimate; 60 days from the start date | Cancel all subscriptions afterwards; credit for at most 60 calendar days; ExpressRoute, VPN, Front Door, CDN excluded |
| Google Cloud | Free data transfer when exiting | Exit Notice before the transfer; after 14 days 30 days to start, then at least 30 days of migration | Internet transfer only; the service is left completely; credit on the final invoice |
All three programs apply to the switch, not to permanent parallel operation, and require advance notice before the transfer. For ongoing exchange between clouds, Google names Data Transfer Essentials for European customers.
Without a credit the list price applies, for example on Azure 0.087 USD per GB for the next 10 TB after 100 GB per month (pricing page, North America and Europe, Premium Global Network, retrieved 28 October 2026): 9,900 GB × 0.087 USD = 861.30 USD for 10 TB. The transfer duration often limits the schedule more than the price:
| Data volume | 1 Gbit/s | 10 Gbit/s |
|---|---|---|
| 1 TB | 3.2 hours | 0.3 hours (19 minutes) |
| 10 TB | 31.7 hours | 3.2 hours |
| 50 TB | 158.7 hours (6.6 days) | 15.9 hours |
Assumptions: 1 TB equals 8,000 Gbit, usable throughput 70 percent of the line rate.
Targets: where the cluster goes
| Target | Fits when | Responsibility |
|---|---|---|
| Hosting by WZ-IT | Location Germany required, no own infrastructure | WZ-IT provides infrastructure and operates the cluster |
| Kubernetes on Hetzner | Cloud or dedicated servers under your own contract | Provider contract with you, operations by WZ-IT possible |
| Proxmox private cloud | Own hardware, VMs and containers on one platform | Hardware with you, operations by WZ-IT possible |
| European managed provider | Managed control plane should stay | Provider operates the control plane, see the provider guide |
Leaving a managed control plane makes etcd, upgrades and control plane security your responsibility; k3s, RKE2 or Talos helps choose the distribution. Migration pages by source: AWS, Azure, Google Cloud.
Operations by WZ-IT cost from €590 net per cluster per month including 3 worker nodes, each additional worker node €129.90. With hosting in Germany, the cluster base from €129.90 (HA control plane with 3 nodes, load balancer, IPv4, 100 GB storage, backup storage) and the worker nodes are added: S from €64.90 (4 vCPU, 8 GB), M from €119.90 (8 vCPU, 16 GB), L from €179.90 (bare metal, 8 cores, 64 GB).
| Example cluster, hosting by WZ-IT | Service level Essential | Service level Production |
|---|---|---|
| 3 × worker S | from €914.60 | from €1,364.30 |
| 3 × worker M | from €1,079.60 | from €1,529.30 |
| 3 × worker L | from €1,259.60 | from €1,709.30 |
Amounts net per month from operations, cluster base and worker nodes, status October 2026. Essential is included, Production provides a 60-minute response to P1 incidents (service levels). Monitoring runs 24/7, the response to P1 incidents follows the service level. Hosting can be terminated monthly, 30 days to the end of the month.
Deadlines, Data Act and UP KRITIS
Notice periods, commitments and support plans in the contract run independently of the technical schedule; the Data Act regulates switching charges from 12 January 2027 (see above). The UP KRITIS paper Empfehlungen zur Vorbereitung einer Exit-Strategie bei Nutzung von Cloud Dienstleistungen (in German; version 1.0, released 31 March 2022, published on bsi.bund.de) addresses operators of critical infrastructure. Its questions carry over to any cloud use:
- Guarantee that the data can be retrieved, document the retrieval process, specify data formats and target system, and where appropriate keep the target system available (section 2.1.1).
- Agree a minimum transition period in the contract (2.2.2).
- Define which data is needed in which form, which outage is acceptable and which switchover times apply, at night or during the day (2.3.1).
- Design the entry address of portals independently of the platform (2.3.4).
Checklist: taking inventory of dependencies
- Version and CRDs: Kubernetes version, custom resources, their operators. Done when every CRD has an operator in the target.
- Load balancers and ingress: Services of type LoadBalancer, ingress objects with provider annotations. Done when every annotation has a counterpart or is dropped.
- Storage: StorageClasses, provisioners, sizes, access mode (ReadWriteMany for file services). Done when every volume has a copy path.
- Identity and secrets: service accounts with a cloud binding, origin and rotation of secrets. Done when every application gets its credentials without the source store.
- Data services outside the cluster: databases, queues, object storage. Done when the switch is tested per service.
- Registry and images: registry hosts, pull secrets, signatures. Done when all images are reachable in the target.
- Logs, metrics, alerts: agents, dashboards, alert routes. Done when alerts reach the same recipients.
- Network: pod and service CIDR, peerings, VPN, fixed egress IPs, allowlists at third parties, DNS zones. Done when every allowlist is switched.
- Managed add-ons: list per provider. Done when every add-on has a replacement.
- Contracts: notice periods, commitments, marketplace contracts, support plans, exit program applied for. Done when all deadlines are scheduled.
- Fallback path: condition, reverse direction, observation period in writing. Done when approved before the cutover.
Commands for items 2, 4, 6 and 9:
# Item 2: services and ingress with cloud annotations
kubectl get svc,ingress -A -o json | jq -r '.items[] | . as $o
| ($o.metadata.annotations // {} | keys | map(select(test("aws|azure|gcp|cloud\\.google|gke\\.io|alb\\.ingress"))))
| select(length > 0) | "\($o.kind)/\($o.metadata.namespace)/\($o.metadata.name): \(join(", "))"'
# Item 4: service accounts with a cloud binding
kubectl get sa -A -o json | jq -r '.items[]
| select((.metadata.annotations // {}) | keys | any(test("eks\\.amazonaws\\.com|azure\\.workload\\.identity|iam\\.gke\\.io")))
| "\(.metadata.namespace)/\(.metadata.name)"'
# Item 6: registry hosts of the running images (images without a host come from Docker Hub)
kubectl get pods -A -o jsonpath='{range .items[*]}{range .spec.containers[*]}{.image}{"\n"}{end}{range .spec.initContainers[*]}{.image}{"\n"}{end}{end}' \
| awk -F/ 'NF > 1 && ($1 ~ /[.:]/ || $1 == "localhost") { print $1; next } { print "docker.io (implicit)" }' \
| sort | uniq -c | sort -rn
# Item 9: managed add-ons and pod identity associations
aws eks list-addons --cluster-name <name>
aws eks list-pod-identity-associations --cluster-name <name>
az aks show -g <resource-group> -n <name> --query addonProfiles
gcloud container clusters describe <name> --location <location> --format="yaml(addonsConfig)"
The annotations come from the providers' documentation: eks.amazonaws.com/role-arn for IAM roles for service accounts, azure.workload.identity/client-id for Entra Workload ID and iam.gke.io/gcp-service-account for GKE identities with impersonation. The command for item 4 finds only annotated service accounts: EKS Pod Identity assigns roles through associations in the EKS API (see item 9), and GKE can grant service accounts access directly through IAM principal identifiers, without an annotation. CLI reference: AWS, AWS Pod Identity, Azure, Google Cloud.
Our approach at WZ-IT
The cloud exit assessment (from €1,490 net) starts with invoices, resource list and architecture documents. It classifies every service as directly transferable, replaceable by open source software or removable only with rework, sizes the target operation and delivers workload order, risks, fallback path and a fixed-price proposal. Read access, exports and a talk with IT suffice; the cloud environment stays unchanged.
Afterwards WZ-IT builds the target cluster, moves data and applications and secures tests, cutover and fallback path. Managed Kubernetes then operates it on Proxmox, bare metal, at a European provider or as hosting in Germany.
Status and methodology
Status: 28 October 2026. Programs, prices and deadlines of the providers were read on that day on the linked pages and change without notice; the page at the time of the application is binding. The table of bound components names typical services, not every variant. The transfer duration is a calculation with disclosed assumptions, not a measurement. The Azure list price is in USD without discounts. The UP KRITIS paper dates from 2022. WZ-IT prices are from-prices, net. A cost comparison with the source provider depends on the individual case.
Further guides
- Kubernetes backup: the four layers and Taking over a cluster: audit checklist
- Kubernetes on Hetzner and Kubernetes on Proxmox as targets
- OpenShift alternatives for OpenShift as a service at the hyperscalers
- Cloud exit strategy for SMEs, Leaving AWS and Egress costs compared
The cloud exit assessment from €1,490 net clarifies dependencies, target operation and fallback path. Managed Kubernetes describes operating a cluster on own or hosted infrastructure.











