Deploy Kubernetes Cluster on AWS EKS Using Terraform

Objective

The goal of this task is to provision an AWS EKS (Elastic Kubernetes Service) cluster using Terraform, integrate IAM roles for service accounts, and deploy a sample application.

Architecture

AWS Services Used:

Project Implementation Steps

Step 1: Prerequisites

Step 2: Create a Terraform Project Directory

mkdir eks-terraform && cd eks-terraform

Create the following Terraform files:

Step 3: Define Terraform Variables (variables.tf)

variable "region" {
  default = "us-east-1"
}

variable "cluster_name" {
  default = "eks-cluster"
}

variable "vpc_cidr" {
  default = "10.0.0.0/16"
}

variable "subnet_cidrs" {
  type    = list(string)
  default = ["10.0.1.0/24", "10.0.2.0/24"]
}

Step 4: Configure AWS Provider (provider.tf)

provider "aws" {
  region = var.region
}

Step 5: Create VPC and Subnets (vpc.tf)

resource "aws_vpc" "eks_vpc" {
  cidr_block = var.vpc_cidr
  enable_dns_support = true
  enable_dns_hostnames = true
  tags = {
    Name = "eks-vpc"
  }
}

resource "aws_subnet" "eks_subnet" {
  count = length(var.subnet_cidrs)
  vpc_id = aws_vpc.eks_vpc.id
  cidr_block = var.subnet_cidrs[count.index]
  map_public_ip_on_launch = false
  availability_zone = element(["us-east-1a", "us-east-1b"], count.index)
  tags = {
    Name = "eks-subnet-${count.index}"
  }
}

Step 6: Deploy EKS Cluster (eks.tf)

resource "aws_eks_cluster" "eks" {
  name     = var.cluster_name
  role_arn = aws_iam_role.eks_role.arn
  
  vpc_config {
    subnet_ids = aws_subnet.eks_subnet[*].id
  }
  
  depends_on = [aws_iam_role.eks_role]
}

Step 7: IAM Role for EKS (iam.tf)

resource "aws_iam_role" "eks_role" {
  name = "eksClusterRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action    = "sts:AssumeRole"
      Effect    = "Allow"
      Principal = {
        Service = "eks.amazonaws.com"
      }
    }]
  })
}

resource "aws_iam_role_policy_attachment" "eks_policy" {
  role       = aws_iam_role.eks_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
}

Step 8: Create an IAM Role for Service Accounts

resource "aws_iam_openid_connect_provider" "eks_oidc" {
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = ["9e99a48a9960b14926bb7f3b02e22da2b0ab7280"]
  url             = aws_eks_cluster.eks.identity[0].oidc[0].issuer
}

resource "aws_iam_role" "app_role" {
  name = "app-service-account-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRoleWithWebIdentity"
      Effect = "Allow"
      Principal = {
        Federated = aws_iam_openid_connect_provider.eks_oidc.arn
      }
      Condition = {
        StringEquals = {
          "oidc.eks.us-east-1.amazonaws.com/id/${aws_eks_cluster.eks.identity[0].oidc[0].issuer}:sub" = "system:serviceaccount:default:app-service-account"
        }
      }
    }]
  })
}

Step 9: Apply Terraform Configuration

terraform init
terraform apply -auto-approve

Once applied, Terraform provisions the EKS cluster and IAM roles

Step 10: Configure Kubectl for EKS

aws eks update-kubeconfig --name eks-cluster --region us-east-1
kubectl get nodes

Step 11: Deploy a Sample Application

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-app
  labels:
    app: sample-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      serviceAccountName: app-service-account
      containers:
      - name: sample-app
        image: nginx
        ports:
        - containerPort: 80

Create a Service for Load Balancer

apiVersion: v1
kind: Service
metadata:
  name: sample-app-service
spec:
  selector:
    app: sample-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer

Apply the deployment:

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

Step 12: Verify the Application

Get the external URL:

kubectl get svc sample-app-service

Conclusion

This project automates AWS EKS cluster creation using Terraform, integrates IAM roles for Kubernetes service accounts, and deploys a sample Nginx application behind a LoadBalancer service.

This setup is a solid foundation for deploying microservices on AWS EKS using Terraform and Helm.