Minikube to Cloud Migration Guide#
Minikube is excellent for learning and local development. But almost everything that “just works” on minikube requires explicit configuration on a cloud cluster. Here are the 10 things that change.
1. Ingress Controller Becomes a Cloud Load Balancer#
On minikube: You enable the NGINX ingress addon with minikube addons enable ingress. Traffic reaches your services through minikube tunnel or minikube service.
On cloud: The ingress controller must be deployed explicitly, and it provisions a real cloud load balancer. On AWS, the AWS Load Balancer Controller creates ALBs or NLBs from Ingress resources. On GKE, the built-in GCE ingress controller creates Google Cloud Load Balancers. You pay per load balancer.
# AWS ALB Ingress annotation example
metadata:
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ipAction: Install the cloud-specific ingress controller via Helm. Update Ingress annotations to match.
2. StorageClass Needs Cloud-Specific Configuration#
On minikube: The default StorageClass uses hostPath or the built-in provisioner. PVCs just work.
On cloud: You need cloud-specific StorageClasses. AWS uses gp3 EBS volumes, GKE uses pd-standard or pd-ssd, AKS uses managed-premium.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "3000"
volumeBindingMode: WaitForFirstConsumerAction: Define StorageClasses for your cloud provider. Update PVCs to reference them.
3. Service Type LoadBalancer Actually Works#
On minikube: type: LoadBalancer services stay in Pending unless you run minikube tunnel. There is no real external IP.
On cloud: type: LoadBalancer provisions an actual cloud load balancer with a public IP. This costs money and takes 2-5 minutes to provision.
Action: Review all Service types. Use ClusterIP for internal services, LoadBalancer only for services that must be internet-facing, and prefer Ingress for HTTP traffic.
4. RBAC Is Enforced#
On minikube: RBAC is enabled but you operate as cluster-admin by default. Every API call succeeds.
On cloud: The cluster creator gets admin access, but no one else does. Every user, CI pipeline, and application service account needs explicit roles.
Action: Create Roles and RoleBindings for every service account. CI/CD pipelines need a ServiceAccount with permissions scoped to their deployment namespace. Developers need read access, not admin.
5. Network Policies Are Enforced#
On minikube: NetworkPolicy resources are accepted but not enforced unless you enable a CNI plugin like Calico.
On cloud: EKS with Calico, GKE with Dataplane V2, and AKS with Azure Network Policy all enforce NetworkPolicies. A pod with no matching policy can be blocked by default deny rules.
Action: Create NetworkPolicies before migrating. Test them on minikube by enabling Calico (minikube start --cni=calico), then deploy the same policies to cloud.
6. Node Sizing and Autoscaling#
On minikube: One node, fixed resources. Resource limits are suggestions that prevent OOM kills but do not affect scheduling.
On cloud: Multiple nodes with real resource boundaries. Pod scheduling depends on available node capacity. The Cluster Autoscaler adds nodes when pods are unschedulable and removes them when idle.
Action: Set realistic resource requests and limits. Configure node pools with appropriate instance types. Enable Cluster Autoscaler or Karpenter.
7. Container Registry Changes#
On minikube: You use the local Docker daemon (eval $(minikube docker-env)) or load images directly with minikube image load.
On cloud: Images must be in a registry the cluster can pull from: ECR for EKS, GCR/Artifact Registry for GKE, ACR for AKS. The cluster needs pull credentials.
Action: Push images to your cloud registry. Configure imagePullSecrets or use workload identity for registry authentication.
8. Secrets Need Cloud KMS Integration#
On minikube: Secrets are stored in etcd, base64-encoded, effectively plaintext. This is fine locally.
On cloud: Secrets are still base64 in etcd by default, but now they are accessible to anyone with cluster access. Use cloud KMS for encryption at rest and the Secrets Store CSI Driver to source secrets from AWS Secrets Manager, Google Secret Manager, or Azure Key Vault.
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: aws-secrets
spec:
provider: aws
parameters:
objects: |
- objectName: "my-app/db-password"
objectType: "secretsmanager"Action: Move sensitive values to a cloud secrets manager. Install the Secrets Store CSI Driver. Update pod specs to mount secrets from the provider.
9. DNS Requires ExternalDNS#
On minikube: You edit /etc/hosts or use nip.io domains. Internal DNS works via CoreDNS.
On cloud: Internal DNS still works via CoreDNS. But external DNS records (pointing your domain to your load balancer) require manual Route53/Cloud DNS updates – unless you use ExternalDNS. It watches Ingress and Service resources, then creates DNS records automatically.
Action: Install ExternalDNS via Helm. Annotate Ingress resources with the desired hostname. ExternalDNS creates the DNS record pointing to the load balancer.
10. Monitoring Moves to Managed Services#
On minikube: You might run a local Prometheus or skip monitoring entirely. Resource usage is visible via minikube dashboard.
On cloud: Use managed monitoring: Amazon Managed Prometheus, Google Cloud Monitoring, or Azure Monitor. Alternatively, deploy the kube-prometheus-stack Helm chart for self-managed Prometheus and Grafana. Either way, you need persistent storage for metrics and proper alerting rules.
Action: Deploy kube-prometheus-stack or configure the managed monitoring service. Set up alerts for node health, pod restarts, and resource pressure.
Migration Checklist#
Before migrating, verify each item in a staging cluster:
- All Ingress resources have cloud-specific annotations.
- PVCs reference a valid cloud StorageClass.
- No
type: LoadBalancerservices that should beClusterIP. - RBAC Roles and RoleBindings exist for every service account.
- NetworkPolicies are tested and applied.
- Resource requests and limits are set on every container.
- Images are pushed to the cloud registry and pullable.
- Secrets are sourced from the cloud secrets manager.
- ExternalDNS is configured for public-facing services.
- Monitoring and alerting are operational.
Test the full deployment in a non-production cluster before switching traffic. Minikube configurations rarely work on cloud clusters without modification – expect to iterate.