ECS to EKS Migration Without Rebuilding Your Deployment Pipeline
Migrate services one at a time without rebuilding your CI pipeline or risking deployment.

Sponsored by Porter
- Written by
- Ship It Yourself Editors
- Published
- October 22, 2026
- Reading time
- 9 min read
What this covers
Moving from ECS to EKS does not require rebuilding your deployment pipeline. You need to change the layers that connect your containers to the platform, which are networking, IAM, service definitions and the deployment mechanism. The build, test and security stages can stay. With both platforms receiving releases behind a shared load balancer, teams can migrate service by service without stopping delivery or betting everything on one cutover.
Why teams on ECS hit a ceiling that has nothing to do with their workloads
ECS can still run workloads well when the pressure to leave it arrives. By 2026, tools including Karpenter, ArgoCD, External Secrets Operator, OpenTelemetry collectors and KEDA are Kubernetes-first projects. The attraction is access to that ecosystem. Figma’s blockers were concrete, including the absence of StatefulSets, no Helm and no clean way to run open source software such as Temporal. Figma moved to three EKS clusters for resilience and used Karpenter to scale compute with demand.
Portability and hiring add pressure. ECS is AWS-proprietary, so workloads cannot move natively to another cloud or a non-ECS Kubernetes cluster without refactoring. EKS clusters can be recreated locally or on another provider with standard Kubernetes tooling. There are also more engineers who know Kubernetes, which changes the cost of onboarding and the risk of relying on a narrow skill set.
That does not make migration an automatic upgrade. Around ten to fifteen distinct services is a rough inflection point where repetitive ECS service management starts making Kubernetes abstractions worth their complexity. Below that threshold, well-named ECS services in a single cluster are faster to reason about. A small system should not take on the work of maintaining a larger platform just to get options it does not need.
What actually changes and what does not when you cross the ECS–EKS boundary
The concept map starts with the smallest unit. An ECS Task becomes a Kubernetes Pod, while an ECS Task Definition becomes Deployment YAML containing a Pod template. The container definition carries over, but its wrapper has more configuration knobs. An ECS Cluster maps to an EKS Cluster, with EKS separating the control plane from nodes. An ECS Capacity Provider maps to a Karpenter NodePool.
Cloud Map service discovery becomes a Kubernetes Service plus CoreDNS. ECS Service Auto Scaling becomes HPA for workloads and Karpenter for nodes. A Task IAM Role becomes a service-account IAM binding through Pod Identity or IRSA. CodeDeploy or an ECS deployment gives way to ArgoCD or Flux, with Argo Rollouts where needed.
Docker/OCI images, ECR registries, image tags, startup commands, environment variables and container security scanning require no change. Secret injection and logging need new ways to deliver their data, but the upstream stores and destinations can stay the same. ALB target groups also carry forward through Kubernetes-native configuration. Resource settings must be converted from ECS CPU units to Kubernetes millicores and from memory in MB to Mi/Gi, and requests and limits must be set. Most mappings are straightforward, but networking and IAM each need a plan before the deployment mechanism changes.
Why VPC CNI networking is where migrations stall silently
Subnet sizing that worked for ECS is not a safe assumption for EKS pod density. ECS awsvpc mode gives each task an ENI, while the AWS VPC CNI gives each pod an IP and can share ENIs across pods. That flexibility does not remove address limits. A t4g.small instance can run far more ECS tasks than EKS pods under VPC CNI, so the same logical services can hit IP exhaustion after moving. Without a plan, teams may only find the shortage when the services are under production load.
Audit subnet CIDR allocations before provisioning the EKS cluster. Resizing CIDRs later is significantly more disruptive than doing it during migration preparation. This infrastructure work must precede workload movement. A successful build cannot compensate for a cluster that has no addresses left for its pods.
The AWS Load Balancer Controller replaces the ECS ALB integration, using TargetGroupBinding or Ingress for Kubernetes-native configuration. The existing ALB and target groups can be reused during a gradual migration. That keeps the client endpoint in place and removes the need for a DNS cutover while services move.
How IAM changes from task roles to pod identity and why it affects every service
IAM work grows with the service inventory. Every service with an ECS Task IAM Role needs a corresponding Kubernetes service account and IAM binding. Giving all pods on a node the node’s EC2 instance permissions is a security anti-pattern. Inventory these bindings before migration and plan their replacement in parallel with pipeline changes. Otherwise, a ready cluster can still contain services that cannot access the AWS resources they need.
AWS recommends Pod Identity “whenever possible” for supported node types. It is the post-2024 default for new EC2-based workloads and does away with the need to set up OIDC for each cluster. IRSA uses OIDC federation and a service-account annotation to bind an IAM role instead. It remains required for Fargate, Windows nodes, EKS Anywhere and older SDK versions that do not support Pod Identity.
SDK compatibility is a service-level prerequisite. SailPoint’s migration required updating every service to an AWS SDK that supported IRSA so it could retrieve STS tokens and assume its designated role. Team access changes too, with EKS Access Entries replacing the deprecated aws-auth ConfigMap and AWS SSO or IAM Identity Center preferred over individual IAM user bindings. Permission patterns that need Kubernetes RBAC require explicit Role and RoleBinding definitions.
Why the ECS deployment model doesn't translate and what to adopt instead
An ECS pipeline calls aws ecs update-service, ECS swaps tasks, and nothing watches the repository afterward. The GitOps model uses a controller that continuously reconciles declared state with running state. That changes who deploys the application and what the pipeline hands over. It does not require replacing the stages that produce and validate an image.
Docker builds, ECR pushes, static analysis, dependency scanning, container scanning, IaC scanning and image signing can carry forward with minimal modification. The replacement is at the end of that chain. After building, testing, scanning and pushing the image, the pipeline updates the GitOps repository with the new image tag in a manifest or Helm values file. ArgoCD or Flux detects that change and syncs it to EKS. GitHub Actions can continue handling the CI stages and repository update.
SailPoint’s dual-target pipeline technique makes that distinction practical during migration. Its deployment job checks whether an ArgoCD application exists for the service and whether an ECS service exists, then deploys to whichever targets it finds. When both exist, both receive the release from the same pipeline trigger. Services can therefore migrate individually without disrupting deployment for services still on ECS. Policy enforcement through OPA/Gatekeeper or Kyverno and automated promotion through ArgoCD are later gains.
The platform layer that must exist before the first workload migrates
Teams must sign off that the cluster tooling is ready before any service moves. Karpenter must be installed and verified because it replaces the node provisioning and capacity role of ECS Capacity Providers. External Secrets Operator must sync values from Secrets Manager and Parameter Store into Kubernetes Secrets because ECS task-definition injection does not move with the container. ArgoCD must be running before a pipeline switches to GitOps delivery. Fluent Bit must forward logs before FireLens per-task logging disappears, so CloudWatch log groups remain populated from day one.
Secrets are an easy gap to miss because the application code does not change even though the delivery mechanism does. Configure and test that mechanism before moving the service. The same sequencing applies to persistent storage, where ECS EFS volumes become the EFS CSI Driver and Docker volumes become Persistent Volume Claims with the EBS CSI Driver. For applications requiring persistent storage, StatefulSets replace Deployments.
Monitoring must be ready too. CloudWatch Container Insights for EKS can preserve the existing monitoring approach. Prometheus and Grafana can be adopted incrementally. Migrate or duplicate existing CloudWatch dashboards and alarms before decommissioning ECS. A workload is not ready to move merely because its container starts.
How to shift traffic gradually with a shared ALB instead of cutting over
With a shared ALB, teams can deploy services and move traffic in separate steps. Keep the existing target group pointing at ECS tasks and add a second target group for EKS pods, managed by the AWS Load Balancer Controller. Both sit behind the same ALB, so clients need neither a new endpoint nor a DNS change. Weighted routing rules then move traffic one service at a time.
A weekly schedule gives the team a flexible template. In Week 1, send a small fraction of traffic to EKS and watch error rates. In Week 2, increase to roughly a quarter and validate under real load. In Week 3, reach an even split and confirm performance parity. In Week 4, send all traffic to EKS, with timing and error-rate thresholds governed by the team’s own service reliability objectives.
Athenahealth’s AR Finance migration achieved zero production downtime across six engineering teams in Q1, grounding the gradual-migration approach at production scale. After full cutover, keep ECS idle for a 48-hour fallback window. Before deleting the cluster, audit scheduled tasks, one-off run-tasks, ECS-specific CloudWatch alarms, ECS-only IAM roles, security groups and log groups. None migrate themselves, and forgotten dependencies can leave silent gaps in monitoring or compliance evidence.
How to handle autoscaling, GPU workloads, and cost structure after the move
EKS scaling has two layers that must work together. HPA or KEDA scales pods from workload metrics, while Karpenter adds and removes nodes to meet pod demand. Configuring only one layer leaves either idle nodes or unschedulable pods. The split gives more control, but it also creates a coordination requirement that ECS Capacity Providers handled as one.
For intermittent training and batch inference, that control changes GPU economics. Karpenter can bring GPU nodes to a schedulable state quickly and terminate them when idle, though driver initialization means full GPU readiness takes longer. This reduces the need to keep ECS EC2 GPU instances always on. NVIDIA GPU Operator time-slicing also allows multiple virtual GPU replicas per physical GPU, raising utilization for inference workloads that do not need the whole GPU at every moment.
The bill changes as well. EKS charges per cluster-hour for its control plane, while ECS has no control plane fee, so many small clusters carry a disproportionate overhead. It costs more to run older Kubernetes versions that are in extended support. Rightsize pods first, then improve Karpenter bin-packing and Spot fallback for stateless workloads, and move eligible workloads to Graviton. Buy Compute Savings Plans only afterward, because buying before rightsizing can tie teams to spending they do not need for one to three years. ADN reported lower operational cost after moving its spiky streaming workload to EKS with Karpenter, showing where demand-based provisioning can pay off.
Where a managed PaaS layer fits teams that want EKS without owning the cluster lifecycle
The ongoing cost of EKS is not confined to the AWS bill. Cluster upgrades, CNI version matrices, add-on compatibility, CVE patching and Kubernetes-specific incidents all require engineering time. Kubernetes releases three versions per year, and falling behind brings extended-support surcharges. Small teams face the sharpest trade-off because platform maintenance competes directly with product delivery.
A managed PaaS layer fits teams that want Kubernetes ecosystem access and GitOps pipelines without owning all that maintenance. In this model, the cluster stays in the team’s own cloud account while the platform takes care of cluster lifecycle work. That preserves cloud ownership, cost visibility, compliance posture and data residency guarantees rather than moving workloads into a shared-tenant platform. It changes who operates the platform while preserving the reason for choosing EKS.
The same parts need to change whether the cluster is self-managed or managed through a PaaS layer. Keep the image pipeline, replace the deployment handoff, and prepare networking, IAM and platform services before moving traffic. That is how an ECS-to-EKS migration remains a sequence of ordinary releases rather than a delivery freeze followed by a risky cutover.
This article is sponsored by Porter.