Skip to content

Lab 02 · Kubernetes Platform

DevOps StudioLabs › Lab 02 · ⏱ 2–3 hours · Intermediate

Stand up a production Amazon EKS cluster and run an app on it. By the end you'll have a managed Kubernetes control plane, worker node groups across availability zones, and a sample app reachable through an ingress.

On this page: Architecture · Prerequisites · Quick Start · Detailed Setup · Project Structure · Configuration · Troubleshooting · Cleanup

What you build

  • EKS cluster — a managed, multi-AZ control plane
  • Managed node groups — auto-scaling worker nodes
  • Helm-deployed sample app
  • Ingress controller — external access to your services
  • IRSA & security groups — pod-level AWS permissions

Skills you'll practice: EKS provisioning · node groups · Helm charts · Services and Ingress · kubectl basics · pod networking.

Architecture

Lab 02 — Amazon EKS cluster and traffic path

Component Details

ComponentPurposeHigh AvailabilitySecurity
EKS ClusterKubernetes control planeMulti-AZ (managed)IAM authentication
Node GroupsWorker nodes for podsMulti-AZ, auto-scalingSecurity groups, IRSA
VPC CNIPod networkingMulti-AZNetwork isolation
CoreDNSService discoveryReplicatedNamespace isolation
Ingress ControllerExternal accessReplicatedTLS termination

Prerequisites

Required Tools

ToolVersionPurpose
AWS CLI2.0+AWS resource management
Terraform1.9+Infrastructure provisioning
kubectl1.32+Kubernetes cluster management
Helm3.10+Kubernetes package management
Git2.0+Version control

AWS Requirements

  • AWS Account with billing enabled
  • IAM User with programmatic access
  • Required Permissions:
    • EKS Full Access
    • EC2 Full Access (for node groups)
    • VPC Full Access
    • IAM permissions for roles and policies
    • CloudWatch Full Access

Knowledge Prerequisites

  • Basic Kubernetes concepts (pods, services, deployments)
  • Understanding of Lab 01 (VPC, networking)
  • Command line comfort
  • Basic container concepts

Lab 01 Dependency

Important: Lab 02 can work standalone, but for best results, complete Lab 01 first. Lab 02 can optionally use Lab 01's VPC infrastructure.


Quick Start

For experienced users who want to deploy immediately:

bash
# 1. Navigate to lab directory
cd labs/02-kubernetes-platform

# 2. Set up backend (if not already done)
./scripts/setup-backend.sh

# 3. Configure
cp terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars with your preferences

# 4. Deploy EKS cluster
make apply

# 5. Configure kubectl
make configure-kubectl

# 6. Deploy sample application
make deploy-app

# 7. Test
make test

Deployment time: ~20-25 minutes
Estimated cost: $5-10 to complete (vs $120-180/month if kept running)


Detailed Setup

Step 1: Verify Prerequisites

bash
# Check AWS CLI
aws --version
aws sts get-caller-identity

# Check Terraform
terraform version

# Check kubectl
kubectl version --client

# Check Helm
helm version

Step 2: Repository Setup

bash
# Navigate to lab directory
cd labs/02-kubernetes-platform

# Verify file structure
ls -la

Step 3: Backend Configuration

bash
# Set up Terraform backend (S3 + DynamoDB)
./scripts/setup-backend.sh

Step 4: Configuration Customization

bash
# Copy example configuration
cp terraform.tfvars.example terraform.tfvars

# Edit with your preferences
nano terraform.tfvars

Key Configuration Options

hcl
# Basic settings
project_name = "devops-studio"
environment = "dev"
region = "us-west-2"

# EKS Configuration
cluster_version = "1.32"
cluster_name = "devops-studio-eks"

# Node Group Configuration
node_instance_type = "t3.medium"
node_min_size = 1
node_max_size = 3
node_desired_size = 2

# Networking (can use Lab 01 VPC or create new)
# vpc_id = ""  # Leave empty to create new VPC
# Or use existing VPC from Lab 01

Project Structure

labs/02-kubernetes-platform/
├── README.md                    # This file
├── Makefile                     # Automation commands
├── main.tf                      # Main EKS infrastructure
├── variables.tf                 # Input variables
├── outputs.tf                   # Output values
├── backend.tf.example           # Backend configuration template
├── terraform.tfvars.example     # Example configuration
├── modules/
│   └── eks/                     # EKS cluster module
│       ├── main.tf             # EKS resources
│       ├── variables.tf        # Module variables
│       └── outputs.tf          # Module outputs
├── environments/               # Environment-specific configs
│   ├── dev.tfvars             # Development settings
│   ├── staging.tfvars         # Staging settings
│   └── prod.tfvars            # Production settings
├── manifests/                  # Kubernetes manifests
│   ├── namespace.yaml         # Namespace definitions
│   ├── deployment.yaml        # Sample deployments
│   ├── service.yaml           # Service definitions
│   └── ingress.yaml           # Ingress configurations
├── helm-charts/                # Helm charts
│   ├── nginx-ingress/         # NGINX Ingress chart
│   └── sample-app/            # Sample application chart
└── scripts/                   # Automation scripts
    ├── setup-backend.sh       # Backend initialization
    ├── configure-kubectl.sh   # kubectl configuration
    ├── validate.sh            # Cluster validation
    └── cleanup.sh             # Resource cleanup

Configuration

Environment Variables

The lab supports environment-specific configurations:

bash
# Deploy to different environments
make apply ENV=dev        # Uses environments/dev.tfvars
make apply ENV=staging    # Uses environments/staging.tfvars
make apply ENV=prod       # Uses environments/prod.tfvars

Variable Validation

All variables include validation rules:

hcl
variable "cluster_version" {
  description = "Kubernetes version for EKS cluster"
  type        = string
  default     = "1.32"
  
  validation {
    condition     = can(regex("^1\\.(2[0-9]|3[0-9])$", var.cluster_version))
    error_message = "Cluster version must be a valid Kubernetes version (1.20-1.39)."
  }
}

Deployment

bash
# Initialize Terraform
make init

# Create execution plan
make plan

# Apply changes (deploys EKS cluster)
make apply

# Configure kubectl to use the cluster
make configure-kubectl

# Verify cluster access
make verify-cluster

# Deploy sample application
make deploy-app

# View cluster information
make cluster-info

Direct Terraform Commands

bash
# Initialize
terraform init

# Plan with specific environment
terraform plan -var-file="environments/dev.tfvars"

# Apply
terraform apply -var-file="environments/dev.tfvars"

# Show outputs
terraform output

Deployment Phases

The deployment creates resources in this order:

  1. Networking (2-3 minutes)

    • VPC (if not using existing)
    • Subnets for EKS
    • Security groups
  2. IAM Roles (1-2 minutes)

    • EKS cluster role
    • Node group role
    • Service account roles
  3. EKS Cluster (10-15 minutes)

    • Control plane creation
    • Add-ons installation
    • Cluster endpoint configuration
  4. Node Groups (5-8 minutes)

    • Launch template creation
    • Node group provisioning
    • Node registration
  5. Helm Charts (2-3 minutes)

    • NGINX Ingress installation
    • Metrics Server installation
    • Chart validation (lint + template rendering)

Total deployment time: 20-25 minutes


Testing & Validation

Automated Validation

bash
# Run all validation tests
make test

# Individual test components:
./scripts/validate.sh

Helm Chart Validation

Before deploying Helm charts, validate them:

bash
# Lint Helm charts (checks for errors and best practices)
make lint-helm

# Validate template rendering (ensures templates are valid)
make validate-helm

# Both validations run automatically before deployment
make deploy-helm-chart

Validation checks:

  • Chart structure and metadata
  • Template syntax correctness
  • Values file validation
  • Kubernetes manifest rendering

Test Coverage

TestDescriptionSuccess Criteria
Cluster Accesskubectl can connectkubectl get nodes succeeds
Node HealthAll nodes are readyAll nodes show Ready status
CoreDNSDNS resolution worksCoreDNS pods running
IngressIngress controller readyIngress controller pods running
Sample AppApplication deploysDeployment shows available replicas
Helm ChartsCharts are validhelm lint passes, templates render

Manual Testing

bash
# Get cluster endpoint
CLUSTER_NAME=$(terraform output -raw cluster_name)
REGION=$(terraform output -raw region)

# Configure kubectl
aws eks update-kubeconfig --name $CLUSTER_NAME --region $REGION

# Check cluster status
kubectl cluster-info

# List nodes
kubectl get nodes

# List all pods
kubectl get pods --all-namespaces

# Check services
kubectl get services --all-namespaces

# Test sample application
kubectl get ingress -n default

Monitoring

CloudWatch Integration

The EKS cluster includes comprehensive monitoring:

Metrics Collected

  • EKS: Cluster health, API server metrics
  • Node Groups: CPU, memory, disk usage
  • Pods: Resource utilization
  • Services: Request rates, latency

Log Groups

  • /aws/eks/${cluster-name}/cluster: Control plane logs
  • /aws/containerinsights/${cluster-name}/performance: Container insights

Accessing Metrics

bash
# View cluster metrics in CloudWatch
aws cloudwatch list-metrics --namespace "ContainerInsights"

# View node group metrics
aws cloudwatch get-metric-statistics \
  --namespace AWS/EKS \
  --metric-name CPUUtilization \
  --dimensions Name=ClusterName,Value=$(terraform output -raw cluster_name)

Troubleshooting

Common Issues

kubectl Connection Fails

bash
# Error: Unable to connect to the server
# Solution: Update kubeconfig
make configure-kubectl

# Or manually:
aws eks update-kubeconfig --name <cluster-name> --region <region>

Nodes Not Joining Cluster

bash
# Check node group status
aws eks describe-nodegroup \
  --cluster-name <cluster-name> \
  --nodegroup-name <nodegroup-name>

# Check node group IAM role
# Ensure node group role has required policies

Pods Stuck in Pending

bash
# Check pod events
kubectl describe pod <pod-name>

# Check node resources
kubectl top nodes

# Check for taints
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

Ingress Not Working

bash
# Check ingress controller
kubectl get pods -n ingress-nginx

# Check ingress status
kubectl describe ingress <ingress-name>

# Check service
kubectl get svc -n ingress-nginx

Cleanup

Quick Cleanup

bash
# Destroy all infrastructure
make destroy

# Confirm destruction
# Type 'y' when prompted

Complete Cleanup

bash
# Destroy infrastructure and backend resources
./scripts/cleanup.sh

Selective Cleanup

bash
# Delete specific resources
kubectl delete namespace <namespace>
terraform destroy -target=module.eks

Cost Considerations

Estimated Costs

Monthly Cost (if running continuously): ~$120-180

  • EKS Control Plane: $73/month
  • Node Instances: $30-60/month (2x t3.medium)
  • Load Balancer: $22/month
  • Data Transfer: $5-10/month

Cost to Complete (run for 4 hours then destroy): ~$5-10

  • Pro-rated hourly costs
  • Most expensive component is control plane ($0.10/hour)

Cost Optimization

bash
# Scale down node groups when not in use
terraform apply -var="node_desired_size=0" -var="node_min_size=0"

# Use smaller instance types for dev
node_instance_type = "t3.small"  # Instead of t3.medium

# Destroy immediately after completion
make destroy

Next Steps

Immediate Next Actions

  1. Deploy the cluster and verify all components work
  2. Experiment with deployments by scaling applications
  3. Review CloudWatch metrics and understand the data
  4. Test Ingress by accessing applications externally
  5. Explore Helm charts and customize values

Continue Your Learning Journey


Additional Resources

Documentation

Learning Resources


Outcome: a production-ready EKS cluster with worker nodes, IRSA, and a sample app reachable through an ingress.

Next: Lab 03 · CI/CD Pipelines — automate deployments to this cluster.


Navigation: ◀ Lab 01 · Terraform Foundations · All labs · Lab 03 · CI/CD Pipelines ▶

Released under the MIT License.