The Migration Imperative
Legacy applications running on VMs or bare metal are expensive to maintain, difficult to scale, and increasingly hard to staff. Kubernetes offers a path to modernization -- but migrating without a clear strategy leads to "lift-and-shift" containerization that delivers none of Kubernetes' benefits while adding operational complexity.
This guide covers a practical approach to legacy migration that delivers real value at each stage.
Assess Before You Migrate
Not every application should be migrated to Kubernetes. Start with an honest assessment.
Good Candidates for Kubernetes Migration
- Applications that need horizontal scaling
- Services with frequent deployments (multiple times per week)
- Applications already using REST APIs or message queues
- Workloads with variable traffic patterns
- Applications where you want to improve deployment reliability
Poor Candidates
- Legacy monoliths with tight hardware dependencies (GPUs, specific NICs)
- Applications requiring stateful, sticky sessions that cannot be externalized
- Batch jobs that run once a day and are better served by serverless or simple cron
- Applications nearing end-of-life (migrating adds cost without long-term value)
Migration Readiness Checklist
Before starting, ensure you have: 1. Container runtime environment (Docker or containerd) 2. Container registry (ECR, ACR, GCR, or Harbor) 3. Kubernetes cluster (EKS, AKS, GKE, or self-managed) 4. CI/CD pipeline capable of building container images 5. Monitoring and logging infrastructure for containers
Phase 1: Containerize the Monolith
Do not try to decompose into microservices and containerize simultaneously. Start by putting the existing application into a container as-is.
Writing the Dockerfile
- Start with an official base image matching your runtime (Node.js, Java, Python, .NET)
- Copy application code and dependencies
- Configure the application to read settings from environment variables (not config files)
- Expose the application port
- Run as a non-root user
Externalize Configuration
Legacy applications often have configuration scattered across files, environment variables, and sometimes hardcoded values. Before containerizing: - Move all configuration to environment variables - Use Kubernetes ConfigMaps for non-sensitive configuration - Use Kubernetes Secrets (or external secret stores) for credentials - Ensure the application can be configured entirely without filesystem changes
Externalize State
Containers are ephemeral. Any local state will be lost on restart: - Move session storage to Redis or a database - Move file uploads to object storage (S3, Azure Blob) - Move caches to a dedicated cache service (Redis, Memcached) - Ensure the application can run multiple instances without conflicts
Phase 2: Deploy to Kubernetes
Kubernetes Resource Configuration
Create deployment manifests that define: - Deployment: Replica count, rolling update strategy, resource requests and limits - Service: Internal load balancing and service discovery - Ingress: External traffic routing with TLS termination - HPA (Horizontal Pod Autoscaler): Auto-scaling based on CPU, memory, or custom metrics
Resource Requests and Limits
Setting correct resource values is critical: - Requests: The guaranteed resources your pod gets. Set based on normal operation. - Limits: The maximum resources your pod can use. Set to prevent runaway processes. - Start with generous limits and tighten based on production observations - Use tools like Kubecost or VPA recommendations for rightsizing
Health Checks
Configure proper health checks so Kubernetes can manage your application lifecycle: - Liveness probe: Detects hung processes and triggers restart - Readiness probe: Controls when the pod receives traffic (critical during startup) - Startup probe: Gives slow-starting applications time to initialize
Persistent Storage
If your application needs persistent storage: - Use PersistentVolumeClaims with appropriate storage classes - Choose the right access mode (ReadWriteOnce for single-pod, ReadWriteMany for shared) - Configure backup strategies for persistent volumes - Consider whether you can eliminate persistent storage by using managed services instead
Phase 3: Optimize and Decompose
Once the monolith runs reliably on Kubernetes, you can optionally decompose it.
Identify Service Boundaries
Look for natural decomposition points: - Features with different scaling requirements - Components with different deployment frequencies - Modules with clear API boundaries - Features owned by different teams
Strangler Fig Pattern
Decompose incrementally using the strangler fig pattern: 1. Route traffic through a new API gateway in front of the monolith 2. Extract one feature into a new microservice 3. Route traffic for that feature to the new service 4. Repeat until the monolith is decomposed (or until further decomposition offers no value)
When to Stop Decomposing
Not every monolith needs to become 50 microservices. Stop decomposing when: - Remaining features are tightly coupled and separating them adds more complexity than value - The team is small enough that microservice operational overhead exceeds benefits - The monolith's remaining components deploy and scale adequately
Common Migration Pitfalls
Ignoring the database: Containerizing the application but leaving a single shared database creates a bottleneck. Plan your data migration strategy alongside application migration.
Skipping observability: Legacy applications often rely on server-level logging and monitoring. Kubernetes requires application-level observability.
Over-engineering on day one: Start with simple Deployments and Services. Add complexity (service mesh, advanced networking, custom operators) only when specific problems demand it.
No rollback plan: Always maintain the ability to route traffic back to the legacy system during early migration phases.
Getting Started
- Week 1: Assess your application portfolio and prioritize migration candidates
- Week 2-3: Containerize the first application (keep it running on VMs in parallel)
- Week 4-5: Deploy to Kubernetes staging, run parallel testing
- Week 6: Cut over production traffic with rollback capability
- Month 3+: Evaluate decomposition opportunities for high-value services
At Optivulnix, we have guided dozens of Indian enterprises through legacy-to-Kubernetes migrations. Our approach balances modernization benefits with practical risk management. Contact us for a free migration readiness assessment.

