DEV Community

Renato Mendoza
Renato Mendoza

Posted on • Edited on

One-Click Deployments #2: AWS EKS Fargate Cluster Using Terraform and Helm

Welcome to my One-Click AWS EKS Deployment tutorial. This is a complete guide to deploying a production-ready EKS Fargate cluster.

In this post, you'll deploy a complete EKS Fargate infrastructure with sample application using a single Terraform command. No more spending hours setting up VPCs, EKS clusters, RBAC, load balancers, and applications separately. We use Terraform modules + Helm charts to provision everything from network infrastructure to a running nginx website with load balancer automatically.


What You Get

A single terraform apply command creates:

  • 🌐 Complete networking infrastructure across 2 availability zones
    • VPC with public/private subnets
    • Internet Gateway, NAT Gateway with EIP (cost-optimized single NAT)
    • Security groups with least-privilege access
  • πŸš€ Production-ready EKS Fargate cluster
    • Managed control plane with Fargate-only execution (no EC2 management)
    • AWS Load Balancer Controller for native ALB/NLB integration
    • Comprehensive RBAC with IAM Groups (devops, developers, viewers)
    • CloudWatch logging and monitoring ready
  • πŸ“¦ Nginx sample application deployed automatically
    • Custom HTML content and health check endpoints
    • Kubernetes deployment, service, and ingress resources
    • Application Load Balancer with optional custom domain/SSL
  • πŸ”§ Multi-environment support for dev, staging, and production configurations

Why This Matters

Building a production-ready EKS cluster from scratch is complex and time-consuming. You need to understand AWS networking, EKS configuration, Kubernetes RBAC, load balancing, security best practices, and how all these components work together.

Most tutorials only show you isolated pieces - how to create a VPC, or how to set up EKS, or how to deploy an app. But getting everything to work together securely and reliably? That's where the real challenge lies.

This solution eliminates the complexity by providing:

  • βœ… Proven architecture that follows AWS best practices
  • βœ… Complete automation - no manual steps or configuration gaps
  • βœ… Production-ready security with proper RBAC and network isolation
  • βœ… Working example you can immediately extend with your own applications

Instead of spending weeks learning and debugging, you get a solid foundation in minutes.


Repository Structure

one-click-aws-eks/
β”œβ”€β”€ infra/
β”‚   └── envs/              # Root module with environment configs
β”‚       β”œβ”€β”€ dev/           # Development environment settings
β”‚       β”œβ”€β”€ staging/       # Staging environment settings
β”‚       └── prod/          # Production environment settings
β”œβ”€β”€ modules/
β”‚   β”œβ”€β”€ network/           # VPC, subnets, NAT gateway, security groups
β”‚   β”œβ”€β”€ eks/              # EKS cluster, Fargate profiles, RBAC, Load Balancer Controller
β”‚   └── applications/     # Helm charts for nginx sample application
└── scripts/              # Cleanup and utility scripts
Enter fullscreen mode Exit fullscreen mode

Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                    AWS VPC                                      β”‚
β”‚                                 (10.0.0.0/16)                                  β”‚
β”‚                                                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
β”‚  β”‚   Public Tier       β”‚                      β”‚   Public Tier       β”‚         β”‚
β”‚  β”‚  (us-east-1a)       β”‚                      β”‚  (us-east-1b)       β”‚         β”‚
β”‚  β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚                      β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚         β”‚
β”‚  β”‚ β”‚ Public Subnet   β”‚ β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ Public Subnet   β”‚ β”‚         β”‚
β”‚  β”‚ β”‚ 10.0.0.0/20     │◄┼─── Internet Gateway β”œβ”€β”€ 10.0.16.0/20    β”‚ β”‚         β”‚
β”‚  β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚         β”‚
β”‚  β”‚         β”‚           β”‚                      β”‚                     β”‚         β”‚
β”‚  β”‚    β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”      β”‚                      β”‚                     β”‚         β”‚
β”‚  β”‚    β”‚ ALB     β”‚      β”‚                      β”‚                     β”‚         β”‚
β”‚  β”‚    β”‚(nginx)  β”‚      β”‚                      β”‚                     β”‚         β”‚
β”‚  β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚                      β”‚                     β”‚         β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
β”‚              β”‚                                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”                               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚   Private App Tier  β”‚                               β”‚   Private App Tier  β”‚ β”‚
β”‚  β”‚    (us-east-1a)     β”‚                               β”‚    (us-east-1b)     β”‚ β”‚
β”‚  β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚  β”‚ β”‚ Private Subnet  β”‚ β”‚     β”‚                     β”‚   β”‚ β”‚ Private Subnet  β”‚ β”‚ β”‚
β”‚  β”‚ β”‚ 10.0.32.0/20    β”‚ β”‚     β”‚      EKS Cluster    β”‚   β”‚ β”‚ 10.0.48.0/20    β”‚ β”‚ β”‚
β”‚  β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚     β”‚   (Control Plane)   β”‚   β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚  β”‚                     β”‚     β”‚                     β”‚   β”‚                     β”‚ β”‚
β”‚  β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚     β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚   β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚  β”‚ β”‚   EKS Fargate   │◄┼─────┼──── API Server  β”‚   β”‚   β”‚ β”‚   EKS Fargate   β”‚ β”‚ β”‚
β”‚  β”‚ β”‚     Pods        β”‚ β”‚     β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚   β”‚ β”‚     Pods        β”‚ β”‚ β”‚
β”‚  β”‚ β”‚                 β”‚ β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚ β”‚                 β”‚ β”‚ β”‚
β”‚  β”‚ β”‚ β€’ nginx-sample  β”‚ β”‚                               β”‚ β”‚ β€’ apps namespaceβ”‚ β”‚ β”‚
β”‚  β”‚ β”‚ β€’ custom HTML   β”‚ β”‚                               β”‚ β”‚ β€’ ready for     β”‚ β”‚ β”‚
β”‚  β”‚ β”‚ β€’ /health       β”‚ β”‚                               β”‚ β”‚   more apps     β”‚ β”‚ β”‚
β”‚  β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚                               β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚   Private DB Tier   β”‚                               β”‚   Private DB Tier   β”‚ β”‚
β”‚  β”‚    (us-east-1a)     β”‚                               β”‚    (us-east-1b)     β”‚ β”‚
β”‚  β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚                               β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚  β”‚ β”‚ Private Subnet  β”‚ β”‚        (Ready for RDS,        β”‚ β”‚ Private Subnet  β”‚ β”‚ β”‚
β”‚  β”‚ β”‚ 10.0.64.0/20    β”‚ β”‚         ElastiCache)         β”‚ β”‚ 10.0.80.0/20    β”‚ β”‚ β”‚
β”‚  β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚                               β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

Prerequisites

Required setup:

  • AWS account with EKS permissions
  • Terraform installed locally
  • kubectl installed locally (for post-deployment testing)
  • AWS CLI configured with appropriate credentials
  • Terraform backend with S3 + DynamoDB (optional but recommended)

Manual Deployment

1. Clone and setup

git clone https://github.com/rnato35/one-click-aws-eks.git
cd one-click-aws-eks
Enter fullscreen mode Exit fullscreen mode

2. Configure your environment

# Edit development configuration
# Modify infra/envs/dev/terraform.tfvars with your settings:

# Basic settings
region      = "us-east-1"  # Your preferred AWS region
aws_profile = "your-aws-profile"  # AWS CLI profile to use

# Optional: For public load balancer with custom domain
nginx_sample_domain_name     = "demo.yourdomain.com"  # Your domain
nginx_sample_certificate_arn = "arn:aws:acm:us-east-1:ACCOUNT:certificate/YOUR-CERT-ID"  # ACM certificate

# Or leave these unset for local port-forwarding access
Enter fullscreen mode Exit fullscreen mode

3. Deploy with Terraform

# Navigate to infrastructure directory
cd infra/envs

# Initialize Terraform (with optional remote backend)
terraform init
# terraform init -backend-config="bucket=YOUR_BUCKET" -backend-config="key=eks-dev/terraform.tfstate" -backend-config="region=us-east-1"

# Deploy everything with one command!
terraform apply -var-file="dev/terraform.tfvars"
Enter fullscreen mode Exit fullscreen mode

What happens during deployment (5-15 minutes):

  1. Infrastructure phase (3-8 min): VPC, subnets, EKS cluster, RBAC, Load Balancer Controller
  2. Applications phase (4-8 min): nginx sample app with Kubernetes resources and ingress
  3. Verification: Health checks and load balancer readiness

All in one Terraform configuration - No need to manage separate infrastructure and application deployments!


What Gets Deployed in Detail

🌐 Networking Infrastructure

  • VPC: 10.0.0.0/16 with DNS support across 2 availability zones
  • Public subnets: For load balancers (10.0.0.0/20, 10.0.16.0/20)
  • Private subnets: For EKS Fargate workloads (10.0.32.0/20, 10.0.48.0/20)
  • Single NAT Gateway: Cost-optimized outbound internet access (~50% cost reduction)
  • Security Groups: Least-privilege firewall rules for EKS and load balancers
  • Route Tables: Proper routing for public/private subnet traffic

πŸš€ EKS Cluster Components

  • Managed control plane: High availability, managed by AWS across multiple AZs
  • Fargate profiles: Serverless container execution for default, kube-system, and apps namespaces
  • OIDC provider: For secure Kubernetes service account authentication
  • EKS add-ons: VPC CNI, CoreDNS, kube-proxy (auto-managed versions)
  • AWS Load Balancer Controller: Native integration with ALB/NLB via Helm deployment
  • CloudWatch logging: API server and audit logs with configurable retention

πŸ”’ Security & RBAC

  • Comprehensive IAM Groups-based access control:
    • πŸ”΄ eks-devops: Full cluster administration access (platform team)
    • 🟑 eks-developers: Namespace-scoped access with read/write in apps, read-only elsewhere
    • 🟒 eks-viewers: Read-only cluster access for monitoring and troubleshooting
  • Assumable IAM roles: Team members assume roles based on group membership
  • Service accounts: Secure pod-level AWS permissions using OIDC
  • Network isolation: Private subnets with no direct internet access
  • Encryption: EKS secrets encryption and secure communication

πŸ“¦ Sample Nginx Application (Automatically Deployed)

  • Custom HTML content: Professional landing page with architecture information
  • Health endpoint: /health for application monitoring and load balancer health checks
  • Production-ready Kubernetes resources:
    • Deployment with configurable replicas and resource limits
    • Service for internal load balancing
    • Ingress for external access with SSL termination
    • ConfigMaps for HTML content and nginx configuration
  • Load balancer options: Public ALB with custom domain/SSL OR local port-forwarding

Post-Deployment: Access Your Website & Cluster

1. Set up cluster access (for admins)

Add your IAM user to the appropriate IAM Group, then:

# Assume the cluster admin role
aws sts assume-role \
  --role-arn arn:aws:iam::ACCOUNT:role/one-click-dev-eks-cluster-admins \
  --role-session-name admin-session

# Export the temporary credentials, then configure kubectl
aws eks update-kubeconfig --name one-click-dev-eks --region us-east-1

# Verify cluster access
kubectl get nodes
kubectl get namespaces
kubectl get pods -n apps
Enter fullscreen mode Exit fullscreen mode

2. Access your website

There are two options to visualize the nginx sample application:

Option 1: Public ALB with Custom Domain (Production-ready)

  1. Configure a certificate and put its ARN in the nginx_sample_certificate_arn variable
  2. Set your custom domain in the nginx_sample_domain_name variable
  3. Access via your custom domain over HTTPS

Option 2: Local Port Forwarding (Development/Testing)

  1. Don't define the certificate and domain variables
  2. Use kubectl port forwarding to access the service locally:
# Forward local port to the nginx service
kubectl port-forward -n apps service/nginx-sample 8080:80

# Visit your website locally
curl http://localhost:8080/architecture
curl http://localhost:8080/health
Enter fullscreen mode Exit fullscreen mode

For Option 1 (Public ALB):

# Get the load balancer URL
kubectl get ingress -n apps

# Visit your website
curl http://<your-alb-dns-name>/architecture

# Test health endpoint
curl http://<your-alb-dns-name>/health
Enter fullscreen mode Exit fullscreen mode

3. Test RBAC with different roles

# For developers (namespace-scoped access)
aws sts assume-role \
  --role-arn arn:aws:iam::ACCOUNT:role/one-click-dev-eks-developers \
  --role-session-name dev-session

# Test permissions
kubectl get pods -n apps              # βœ… Allowed  
kubectl get nodes                     # βœ… Allowed (read-only)
kubectl delete namespace kube-system  # ❌ Forbidden
Enter fullscreen mode Exit fullscreen mode

Deployment Process Explained

Unified Deployment Process

This project uses a single Terraform configuration that handles everything:

  1. Infrastructure deployment

    • VPC, subnets, EKS cluster, load balancer controller
    • All networking components and security groups
  2. Applications deployment

    • nginx sample app and all Kubernetes resources
    • Deployed automatically after infrastructure is ready

Environment Management

  • Terraform workspaces: Isolate state for different environments
  • Separate tfvars files: Environment-specific configurations
  • Sequential deployment: Infrastructure first, then applications automatically

Environment Isolation

Each environment uses:

  • Separate tfvars files (dev/, staging/, prod/)
  • Different cluster names and configurations
  • Isolated AWS resources and namespaces
  • Terraform workspace isolation

IAM Groups Integration

  • Automatic creation: IAM Groups are created for each cluster
  • User management: Add IAM users to groups for appropriate access
  • Role assumption: Users assume roles based on group membership
  • MFA support: Optional MFA requirements for role assumption

Advanced Features

Cost Optimization

  • Fargate pricing: Pay-per-pod, no idle EC2 instances
  • Resource limits: Prevent resource waste in containers

Production Readiness

  • Multi-AZ deployment: High availability by default
  • Health checks: Application-aware load balancer probes
  • Auto scaling: Horizontal Pod Autoscaler ready
  • Monitoring: CloudWatch integration ready for extension

Extensibility

  • Modular design: Add applications via additional Helm charts
  • RBAC foundation: Easy to add users to IAM Groups

πŸš€ Call to Action

Deploy your own production-ready EKS Fargate cluster with one command:

πŸ”— GitHub Repository: one-click-aws-eks

This Terraform solution gives you:

  • βœ… Complete EKS infrastructure in 10-15 minutes
  • βœ… Working nginx application with load balancer
  • βœ… Comprehensive RBAC ready for your team
  • βœ… Multi-environment support (dev/staging/prod)

Perfect starting point for your next Kubernetes project on AWS!


Found this helpful? ⭐ Star the repository and let me know what you'd like to see deployed with one click next!

Top comments (0)