Kubernetes
AWS
GCP
Cloud Migration
DevOps

Migrate a Kubernetes application to GCP from AWS

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Migrating a Kubernetes application from AWS to GCP is rarely just a matter of copying YAML from one cluster to another. The Kubernetes objects may be portable, but the surrounding storage, load balancing, IAM, DNS, observability, and CI assumptions are often cloud-specific. A clean migration starts with separating what is cluster-portable from what depends on AWS services, then planning a controlled cutover to GKE.

Start With an Inventory, Not a Cluster Create Command

Before creating anything in GCP, inventory the current application in AWS.

You need to know:

  • namespaces and releases
  • Deployments, StatefulSets, Services, Ingresses, and Jobs
  • ConfigMaps and Secrets
  • PersistentVolumeClaims and storage classes
  • external dependencies such as RDS, S3, Route 53, IAM, and ECR
  • CI pipelines and image registries

Useful commands for a first pass are:

bash
kubectl get all -A
kubectl get ingress,pvc,configmap,secret -A
helm list -A

This reveals which parts are Kubernetes-native and which parts are really AWS integrations hiding behind them.

Build the Target Environment in GCP

On the GCP side, prepare the target project, VPC, IAM model, container registry strategy, and GKE cluster before moving workloads.

A basic cluster creation flow can start from the CLI:

bash
gcloud container clusters create my-gke-cluster \
  --region us-central1 \
  --num-nodes 3

Then fetch credentials:

bash
gcloud container clusters get-credentials my-gke-cluster \
  --region us-central1

That only gives you a cluster. It does not yet solve ingress, DNS, secrets, storage classes, or image delivery.

Replace AWS-Specific Assumptions

This is where most migrations actually succeed or fail.

Examples of AWS-specific items that often need changes:

  • EBS-backed storage classes must become GCE PD or another GKE-compatible class.
  • Classic ELB or AWS ALB controller assumptions may need GKE Ingress or another ingress controller.
  • IAM roles for service accounts may need a GCP Workload Identity design.
  • ECR image references may need to move to Artifact Registry or another accessible registry.
  • Route 53-driven DNS automation may need a GCP equivalent or a cross-cloud design.

A storage class reference that worked in EKS may need to change in a manifest or Helm values file:

yaml
1persistence:
2  enabled: true
3  storageClass: standard-rwo
4  size: 20Gi

Likewise, image references may need to change:

yaml
image:
  repository: us-central1-docker.pkg.dev/my-project/my-repo/my-app
  tag: "1.4.0"

Move Data Separately From Deployments

Stateless services are usually the easy part. Stateful migration is the real project.

If your application relies on databases, object storage, or persistent volumes, migrate that data with its own plan. Do not treat data cutover as an afterthought.

A practical approach is often:

  1. stand up the GKE environment
  2. mirror or migrate the backing data store
  3. deploy the application against a staging copy
  4. validate behavior under load
  5. perform final sync and cut over production traffic

For Kubernetes resource backup and restore, tools such as Velero can help with cluster object migration. For databases, use database-native migration tooling rather than hoping PVC copies are enough.

Test Before DNS Cutover

A migration is not complete when pods are running. It is complete when traffic, secrets, storage, and observability work end to end.

Before switching DNS:

  • test external connectivity and ingress
  • verify service discovery and health checks
  • confirm logs and metrics land in the expected destination
  • run smoke tests and representative workload tests
  • validate rollback steps

A common low-risk cutover is to reduce DNS TTL in advance, deploy the GKE stack, then switch traffic only after verification passes.

Use Helm or GitOps to Make the Move Repeatable

If the application is already managed by Helm or a GitOps flow, update that source of truth instead of hand-editing manifests on the destination cluster.

That usually means maintaining environment-specific values files such as:

yaml
cloud: gcp
storageClass: standard-rwo
ingressClassName: gce

Then deploy with:

bash
helm upgrade --install my-app ./chart -n production -f values-gcp.yaml

This keeps the migration auditable and makes future cluster rebuilds much easier.

Common Pitfalls

The most common mistake is assuming Kubernetes portability means cloud portability. The YAML may be similar, but storage, networking, and IAM usually are not.

Another mistake is migrating stateless deployments first and discovering too late that the data plane still depends on AWS-specific services.

Teams also often skip a rollback plan. If cutover fails, you need to know whether traffic returns to AWS, how data divergence is handled, and who makes that decision.

Finally, do not leave observability for last. A migrated workload without logs, metrics, and alerts is much harder to stabilize under real traffic.

Summary

  • Treat the migration as an application-platform move, not just a manifest copy.
  • Inventory cloud-specific dependencies before building the GKE target.
  • Replace AWS storage, ingress, IAM, registry, and DNS assumptions explicitly.
  • Migrate stateful data with its own plan and validate before cutover.
  • Use Helm or GitOps so the new GCP deployment remains reproducible.

Course illustration
Course illustration

All Rights Reserved.