An open API service indexing awesome lists of open source software.

https://github.com/notharshhaa/aws-eks_terraform

PROVISION EKS (Amazon Elastic Kubernetes Service) CLUSTER ON AWS USING TERRAFORM
https://github.com/notharshhaa/aws-eks_terraform

aws-ec2 aws-ecr aws-s3 aws-terraform eks eks-cluster terraform terraform-modules

Last synced: 4 months ago
JSON representation

PROVISION EKS (Amazon Elastic Kubernetes Service) CLUSTER ON AWS USING TERRAFORM

Awesome Lists containing this project

README

          

# 🚀 **Provision Amazon EKS Cluster on AWS using Terraform**

![EKS Banner](https://imgur.com/oU5TMcv.png)

## 🔥 **Introduction**

### 🟢 What is Amazon EKS?

Amazon Elastic Kubernetes Service (**Amazon EKS**) is a **fully managed** Kubernetes service that simplifies deploying, managing, and scaling containerized applications on AWS.

### 🟢 What is Terraform?

Terraform is an **open-source Infrastructure as Code (IaC) tool** that enables declarative provisioning and management of cloud infrastructure.

---

## ✅ **Prerequisites**

Before proceeding, ensure you have the following:

- **AWS Account** (Free Tier Available)
- **AWS CLI** ([Install AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html))
- **Terraform** ([Install Terraform](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli))
- **Kubectl** ([Install Kubectl](https://docs.aws.amazon.com/eks/latest/userguide/install-kubectl.html))
- **VS Code** (Recommended IDE)

---

## 📂 **Project Structure**

```bash
📦 eks-cluster-terraform
├── 📜 provider.tf # AWS Provider Configuration
├── 📜 eks-backend-terra.tf # S3 Backend for Terraform State
├── 📜 vpc.tf # VPC Configuration
├── 📜 subnets.tf # Public Subnets
├── 📜 internetgw.tf # Internet Gateway
├── 📜 route.tf # Route Table
├── 📜 sg.tf # Security Groups
├── 📜 iam_role.tf # IAM Roles & Policies
├── 📜 eks_cluster.tf # EKS Cluster Configuration
├── 📜 eks_node_group.tf # EKS Worker Nodes
└── 📜 README.md # Project Documentation
```

---

## 📚 **References**

- **[Terraform Registry](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs)**
- **[AWS CLI Installation Guide](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)**
- **[EKS Documentation](https://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html)**

🔗 _This project follows AWS best practices for EKS deployment using Terraform._

---

_**Warning!!! You might incur costs in your AWS account by doing this**_

## 📌 **Getting Started**

Head to your AWS account and navigate to the S3 section. This is where we will store our **tf.state file** as it is considered best practice to keep our state file in a Remote Location. The primary purpose of Terraform state is to store bindings between objects in a remote system and resources declared in your configuration and I am going to keep mine in Amazon S3.

Create an S3 Bucket. You can choose whatever name suits your purpose, I am naming mine `terra-eks-backend`. You can provision your bucket in any region that suits your purpose but I am provisioning mine in the `us-east-1`.

![aws-eks](https://imgur.com/r1hBcxO.png)

It is highly recommended that you enable [Bucket Versioning](https://docs.aws.amazon.com/AmazonS3/latest/userguide/manage-versioning-examples.html) on the S3 bucket to allow for state recovery in the case of accidental deletions and human error.

![aws-eks](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*r_Qbo1YHAPMfcjjFyQJOAw.png)

![aws-eks](https://miro.medium.com/v2/resize:fit:750/format:webp/1*CtasAJc5N0WaX-P1y3CDnQ.png)

To make my `tf.state file` consistent I am going to enable State-Locking. File locking is a data management feature that allows only one user or process access to a file at any given time. It restricts other users from changing the file while it is being used by another user or process. In other to achieve this I need to create a Dynamo DB Table so let's head to Dynamo DB in our AWS account and create a Dynamo DB table

![aws-eks](https://miro.medium.com/v2/resize:fit:750/format:webp/1*--_Q2-Jr_OLP4kGCjvapbA.png)

![aws-eks](https://miro.medium.com/v2/resize:fit:750/format:webp/1*rw6mSFdFnIM-LBWdNFxkLQ.png)

You can choose any name for your DynamoDB Table but it is important to note that the partition key is case sensitive. I named the Partition Key LOCKID because this will enable Dynamo DB to lock and release the file. Scroll down the page and click on Create Table

![aws-eks](https://miro.medium.com/v2/resize:fit:750/format:webp/1*QJZKwa4UpaqGzkl5Y5NE2w.png)

### **CREATE TERRAFORM FILES**

**eks-backend-terra.tf**

```hashicorp
terraform {
backend "s3" {
bucket = "your-s3-bucket-name"
key = "terraform/state/eks-cluster.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "your-dynamodb-table-name"
}
}
```

**Provider.tf**

Name of provider AWS

Our source will be defined as hashicorp/aws. This is a short abbreviation for ```registry.terraform.io/hashicorp/aws```

The version is set to ~>5.0

Region is us-east-1

```hashicorp
terraform {
required_version = ">= 1.3.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}

provider "aws" {
region = "us-east-1"
}
```

**Vpc.tf**

```hashicorp
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true

tags = {
Name = "pc-vpc"
Environment = "dev"
}
}
```

The vpc.tf contains codes to create a new Vpc. The CIDR block is 10.0.0.0/16 and I have tagged the name of the VPC as PC-VPC

**subnets.tf**

```hashicorp
resource "aws_subnet" "public_1" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
map_public_ip_on_launch = true

tags = {
Name = "public-sub-1"
Environment = "dev"
}
}

resource "aws_subnet" "public_2" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-east-1b"
map_public_ip_on_launch = true

tags = {
Name = "public-sub-2"
Environment = "dev"
}
}

resource "aws_subnet" "private_1" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.3.0/24"
availability_zone = "us-east-1a"

tags = {
Name = "private-sub-1"
Environment = "dev"
}
}

resource "aws_subnet" "private_2" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.4.0/24"
availability_zone = "us-east-1b"

tags = {
Name = "private-sub-2"
Environment = "dev"
}
}
```

EKS requires a minimum of two subnets to function so this is creating two public subnets in two availability zones namely us-east-1a and us-east-1b respectively. I have also set _map public IP on launch = true_. This will assign our subnets with public IPV4 addresses. I have given the CIDR range of 10.0.1.0/24 to public-1 and 10.0.2.0/24 to public-2.

**Internetgw.tf**

```hashicorp
resource "aws_internet_gateway" "main_gw" {
vpc_id = aws_vpc.main.id

tags = {
Name = "main-gateway"
Environment = "dev"
}
}
```

This will create and attach the internet gateway to the Vpc created

**Route.tf**

```hashicorp
resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.main.id

route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main_gw.id
}

tags = {
Name = "public-route-table"
Environment = "dev"
}
}

resource "aws_route_table_association" "public_subnet_1_assoc" {
subnet_id = aws_subnet.public-1.id
route_table_id = aws_route_table.public_rt.id
}

resource "aws_route_table_association" "public_subnet_2_assoc" {
subnet_id = aws_subnet.public-2.id
route_table_id = aws_route_table.public_rt.id
}
```

This will create the Route table. The route table has been associated with the two subnets (public-1,public-2). An internet gateway id has also been associated with the Route table and the Vpc id has been assigned to the Route table.

**Sg.tf**

```hashicorp
resource "aws_security_group" "eks_sg" {
name = "eks-cluster-sg"
description = "Security group for EKS cluster"
vpc_id = aws_vpc.main.id

ingress {
description = "Allow SSH access"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

ingress {
description = "Allow HTTPS traffic"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

ingress {
description = "Allow HTTP traffic"
from_port = 80
to_port = 80
protocol = "tcp"
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-cluster-sg"
Environment = "dev"
}
}
```

This will create the security group attached to the created Vpc with both ingress and egress rules. Ingress rules allow incoming(inbound) connection with our Vpc while egress rule allows outgoing (outbound) connection.

**iam_role.tf**

```hashicorp
resource "aws_iam_role" "eks_cluster_role" {
name = "eks-cluster-role"

assume_role_policy = <