Amazon ECS (Elastic Container Service) and EKS (Elastic Kubernetes Service) are two powerful container orchestration solutions provided by AWS. While ECS simplifies container management with tight AWS integration, EKS leverages Kubernetes, an industry-standard open-source orchestration tool.
Why Consider Migrating from ECS to EKS?
Many organizations choose EKS to harness Kubernetes’ advanced features like multi-cluster management, flexibility in choosing tools, and a robust open-source ecosystem. Migrating to EKS provides better scalability, portability, and compatibility with multi-cloud and hybrid environments.
Preparing for the Migration
Assessing Your ECS Workloads
Before starting, evaluate your ECS tasks. Document task definitions, resource requirements, environment variables, secrets, and network configurations. Identify which workloads are suited for Kubernetes and any potential challenges in migrating them.
Tools and Prerequisites for Migration
Ensure the following prerequisites are in place:
- Terraform for infrastructure as code.
- AWS CLI configured with appropriate permissions.
- kubectl installed and configured for Kubernetes.
- Helm, a Kubernetes package manager.
- Argo CD for CI/CD automation.
Setting Up Your EKS Cluster with Terraform
To set up an EKS cluster, we will use Terraform to create the infrastructure required, including VPC, subnets, IAM roles, and other essential components.
Terraform Code for EKS Setup
Below is a comprehensive Terraform configuration to create an EKS cluster:
# Provider provider "aws" { region = "us-west-2" # Replace with your desired AWS region } # VPC resource "aws_vpc" "eks_vpc" { cidr_block = "10.0.0.0/16" enable_dns_support = true enable_dns_hostnames = true tags = { Name = "eks-vpc" } } # Subnets resource "aws_subnet" "eks_subnet" { count = 2 # Two subnets for HA vpc_id = aws_vpc.eks_vpc.id cidr_block = cidrsubnet(aws_vpc.eks_vpc.cidr_block, 8, count.index) availability_zone = data.aws_availability_zones.available.names[count.index] map_public_ip_on_launch = true tags = { Name = "eks-subnet-${count.index}" } } # Internet Gateway resource "aws_internet_gateway" "eks_igw" { vpc_id = aws_vpc.eks_vpc.id tags = { Name = "eks-igw" } } # Route Table resource "aws_route_table" "eks_rt" { vpc_id = aws_vpc.eks_vpc.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.eks_igw.id } tags = { Name = "eks-rt" } } # Route Table Association resource "aws_route_table_association" "eks_rta" { count = 2 subnet_id = aws_subnet.eks_subnet[count.index].id route_table_id = aws_route_table.eks_rt.id } # Security Group resource "aws_security_group" "eks_sg" { name_prefix = "eks-sg" vpc_id = aws_vpc.eks_vpc.id ingress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "eks-sg" } } # IAM Role for EKS resource "aws_iam_role" "eks_role" { name = "eks-cluster-role" assume_role_policy = jsonencode({ Version = "2012-10-17", Statement = [ { Effect = "Allow", Principal = { Service = "eks.amazonaws.com" }, Action = "sts:AssumeRole" } ] }) tags = { Name = "eks-role" } } # IAM Policy Attachment resource "aws_iam_role_policy_attachment" "eks_policy" { role = aws_iam_role.eks_role.name policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy" } # EKS Cluster resource "aws_eks_cluster" "eks_cluster" { name = "eks-cluster" role_arn = aws_iam_role.eks_role.arn vpc_config { subnet_ids = aws_subnet.eks_subnet[*].id security_group_ids = [aws_security_group.eks_sg.id] } tags = { Name = "eks-cluster" } } # Output output "cluster_endpoint" { value = aws_eks_cluster.eks_cluster.endpoint } output "cluster_arn" { value = aws_eks_cluster.eks_cluster.arn }
Applying the Terraform Configuration
Initialize Terraform:
terraform init
Validate and apply the configuration:
terraform apply
Retrieve the EKS cluster endpoint and ARN from the outputs.
Converting ECS Task Definitions to Helm Charts
Breaking Down ECS Task Definitions\
ECS task definitions encapsulate container configurations, including:
- Container image and version.
- CPU and memory allocation.
- Networking and port mappings.
- Environment variables and secrets.
Writing Your First Helm Chart
- Create a new Helm chart:
helm create my-application
- Map ECS configurations to Kubernetes resources in the Helm chart files. For example:
- Define a Deployment for the container image.
- Use ConfigMap and Secret for environment variables and secrets.
- Set Service definitions for network configurations.
Automating the Conversion Process\
To streamline migration, consider writing a script to translate ECS task definitions to Helm templates. Tools like eksctl and kube2iam can help with IAM role mappings.
Implementing CI/CD with Argo CD
Introduction to Argo CD and ApplicationSets\
Argo CD is a declarative GitOps tool for Kubernetes. ApplicationSets allow dynamic application deployments based on Helm charts or other templates, making it ideal for managing EKS workloads.
Setting Up Argo CD for Your EKS Environment
- Install Argo CD in the EKS cluster:
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
- Access the Argo CD UI and connect it to your Git repository.
Automating Helm Chart Deployments with ApplicationSets
- Define an ApplicationSet template for your Helm chart:
apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: my-application-set spec: generators: - git: repoURL: https://github.com/your-repo.git revision: main directories: - path: helm/my-application template: metadata: name: '{{appName}}' spec: project: default source: repoURL: https://github.com/your-repo.git targetRevision: main path: helm/my-application destination: server: https://kubernetes.default.svc namespace: my-namespace
- Apply the ApplicationSet YAML:
kubectl apply -f applicationset.yaml
Also read about Probes for Implementing Robust Health Checks in Kubernetes Here
Deploying and Testing Applications on EKS
Deploying Your Converted ECS Workloads to EKS\
Deploy the Helm chart using Argo CD. Once synced, the workload will run in the EKS cluster. Verify the deployment:
kubectl get pods -n my-namespace
Validating the Migration\
Ensure the application behaves as expected by:
- Testing API endpoints.
- Monitoring logs with kubectl logs.
- Verifying external access using Kubernetes Ingress or LoadBalancer services.
Example Application Migration: Nginx Web Server
Step 1: ECS Setup
- Create an ECS task definition for Nginx:
{ "family": "nginx-task", "containerDefinitions": [ { "name": "nginx", "image": "nginx:latest", "memory": 512, "cpu": 256, "portMappings": [ { "containerPort": 80, "hostPort": 80 } ] } ] }
- Deploy the task to ECS and verify its functionality.
Step 2: Convert ECS Task Definition to Helm Chart
- Translate the ECS configurations to a Helm template:
- Define a Deployment in templates/deployment.yaml:
yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: – name: nginx image: nginx:latest ports: – containerPort: 80 - Define a Service in templates/service.yaml: “`yaml apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
“`
- protocol: TCP
- Package the Helm chart:
helm package .
Step 3: Deploy Using AWS Console and CLI
- AWS Console:
- Upload and deploy the Helm chart via Argo CD’s UI.
- AWS CLI:
Deploy the Helm chart manually:
helm install nginx ./nginx-chart
- Verify the deployment:
kubectl get svc
Note the external IP of the LoadBalancer and access it in your browser.
Post-Migration Best Practices
Monitoring and Scaling Applications on EKS\
Leverage Kubernetes-native tools like:
- Kubernetes Metrics Server for resource monitoring.
- Horizontal Pod Autoscaler (HPA) for scaling based on resource usage.
- AWS CloudWatch and Prometheus for in-depth insights.
Securing Your EKS Cluster
- Use Network Policies to restrict pod communication.
- Enable RBAC for access control.
- Regularly patch and update Kubernetes and associated tools.
Challenges and Lessons Learned
Common Issues During Migration
- Misconfigurations in Helm charts.
- Network discrepancies between ECS and Kubernetes.
- Differences in IAM role handling.
Tips to Ensure a Smooth Transition
- Start with non-critical workloads.
- Automate testing to catch issues early.
- Document every step to streamline future migrations.
Conclusion
Migrating from ECS to EKS unlocks the full potential of Kubernetes, allowing for better scalability, flexibility, and access to a vast ecosystem of tools. By following this guide, you can transition smoothly and start leveraging Kubernetes for your workloads. As you embrace this change, remember to continuously optimize and adapt your infrastructure to maximize the benefits of EKS.