How To Deploy EKS, RDS cluster with Website Using Terraform

Ashutosh Singh
6 min readOct 9, 2020

Hi Guys, In this, I’m going to Launch the cluster (EKS, RDS) with the website(WordPress) using the Terraform so that It’s totally on the cloud, which very easy to manged.

Amazon Web Services(AWS)

So Whats EKS?

In simple words its the Amazon’s Elastic Kubernetes Service you can learn more about it here.

Again Whats RDS?

Amazon Relational Database Service provides us the database service on the cloud cost effective and many more. Want to learn more about it click here.

You can check out about the Terraform here.

So what we required to set up the infrastructure

Prerequisite: AWS account, AWS CLI(configure the IAM user with admin Power), kubectl(with empty config file), Terraform.

STEP1

Create the Security Group for the RDS

resource "aws_security_group" "rds-sec-grp" {name        = "RDS-Securty-Grp"description = "Allow MySQL Ports"ingress {description = "Allowing Connection for SSH"from_port   = 3306to_port     = 3306protocol    = "tcp"cidr_blocks = ["0.0.0.0/0"]}egress {from_port   = 0to_port     = 0protocol    = "-1"cidr_blocks = ["0.0.0.0/0"]}tags = {Name = "RDS-Server"}}

Here I have created the security group allowing the port 3306 as we know MySQL works by Default on this port only.

STEP2
Create The RDS instance template

resource "aws_db_instance" "rds" {allocated_storage    = 20storage_type         = "gp2"engine               = "mysql"engine_version       = "5.7"instance_class       = "db.t2.micro"name                 = "mydb"username             = "wp"password             = "wordpress123"parameter_group_name = "default.mysql5.7"publicly_accessible = trueskip_final_snapshot = truevpc_security_group_ids = [aws_security_group.rds-sec-grp.id]tags = {name = "RDS_Main"}}
RDS

Here I have provisioned the 20Gb storage with t2.micro flavor of instance and the credentials with other details.

STEP3
Now We have to provision the EKS Cluster with the Roles and Policies

resource "aws_iam_role" "role" {name = "eks-cluster"assume_role_policy = <<POLICY{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Service": "eks.amazonaws.com"},"Action": "sts:AssumeRole"}]}POLICY}resource "aws_iam_role_policy_attachment" "Mine-AmazonEKSClusterPolicy" {policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"role       = aws_iam_role.role.name}resource "aws_iam_role_policy_attachment" "AmazonEKSVPCResourceController" {policy_arn = arn:aws:iam::aws:policy/AmazonEKSVPCResourceController"role       = aws_iam_role.role.name}

STEP4
Now Since We have provisioned the Role and permissions, We can now start creating the cluster

resource "aws_eks_cluster" "MyCluster" {depends_on = [aws_iam_role_policy_attachment.AmazonEKSVPCResourceController,aws_iam_role_policy_attachment.Mine-AmazonEKSClusterPolicy]name = "Cluster"role_arn = aws_iam_role.role.arnvpc_config {subnet_ids = ["subnet-d2e2d8ba", "subnet-83056ecf"]}tags = {Name = "EKS_Subnet"}}
Cluster

It will automatically create a security group for the cluster

Security Group for The Cluster And RDS

NOTE: Now there’s a catch We have to make sure that ROLES and Permission are created Before Cluster and deleted after the Cluster otherwise It will not be able to create or delete it.

STEP5
Now Since we Have created the cluster and Master is managed by the Amazon we are only left to provision the slaves or nodes.

resource "aws_iam_role" "role2" {name = "eks-node-group"assume_role_policy = jsonencode({Statement = [{Action = "sts:AssumeRole"Effect = "Allow"Principal = {Service = "ec2.amazonaws.com"}}]Version = "2012-10-17"})}resource "aws_iam_role_policy_attachment" "AmazonEKSWorkerNodePolicy" {policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"role       = aws_iam_role.role2.name}resource "aws_iam_role_policy_attachment" "AmazonEKS_CNI_Policy" {policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"role       = aws_iam_role.role2.name}resource "aws_iam_role_policy_attachment" "AmazonEC2ContainerRegistryReadOnly" {policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"role       = aws_iam_role.role2.name}
ROLE For the CLUSTER and NODE group

Here Again, I have created the ROLE and Permissions for the NODE GROUP

NOTE: You must have the admin power IAM user to perform these steps.

STEP6
Since we have provided the role and permissions, Now we can create the Node Group

resource "aws_eks_node_group" "node" {cluster_name    = aws_eks_cluster.MyCluster.namenode_group_name = "node"node_role_arn   = aws_iam_role.role2.arnsubnet_ids      = ["subnet-d2e2d8ba", "subnet-83056ecf"]instance_types = ["t2.micro"]scaling_config {desired_size = 2max_size     = 3min_size     = 1}depends_on = [aws_iam_role_policy_attachment.AmazonEKSWorkerNodePolicy,aws_iam_role_policy_attachment.AmazonEKS_CNI_Policy,aws_iam_role_policy_attachment.AmazonEC2ContainerRegistryReadOnly,]}

Here The Cluster will have 2 slaves (NODE) with a maximum limit of 3 and a minimum of 1.

Instance of Slave

And We Have Created the EKS Cluster

Now we need to configure the Kubectl so that we can interact with our cluster

STEP7

resource "null_resource" "null1" {depends_on = [aws_eks_node_group.node]provisioner "local-exec" {command = "aws eks --region ap-south-1 update-kubeconfig --name Cluster"}}

NOTE: MAKE SURE THE CONFIG FILE IS EMPTY OTHERWISE IT WILL FAIL.

Now we have the kubectl configure, to test this I’ve run some command

kubectl get nodes
Output for the command

STEP8
Now We are going to Deploy the WordPress and run service to expose the port of the pods

provider "kubernetes" {}resource "kubernetes_deployment" "mydeployment" {depends_on = [null_resource.null1]metadata {name = "wordpress"labels = {app = "wordpress"}}spec {replicas = 2selector {match_labels = {app = "wordpress"}}template {metadata {labels = {app = "wordpress"}}spec {container {image = "wordpress"name  = "wordpress:4.8-apache"env{name = "WORDPRESS_DB_HOST"value = aws_db_instance.rds.address}env{name = "WORDPRESS_DB_USER"value = aws_db_instance.rds.name}env{name = "WORDPRESS_DB_PASSWORD"value = aws_db_instance.rds.password}port {container_port = 80}}}}}}resource "kubernetes_service" "Myservice"{depends_on = [kubernetes_deployment.mydeployment]metadata {name = "exposeportofwp"}spec {selector = {app = kubernetes_deployment.mydeployment.metadata.0.labels.app}port {node_port = 30001port        = 80target_port = 80}type = "LoadBalancer"}}

We have successfully deployed the container with WordPress running in it

Pods of WordPress
Service

As we Can see I have used the type as LoadBalancer so it will automatically create a classic L.B of AWS

Load Balancer

It will also create an Auto-Scaling Group for Load-Balancing

Auto-Scaling Group

AND at last, The WordPress is Launch

WordPress Starting Page

NOTE: The Setup requires almost 15–20 min to fully provision

Don’t delete any resource manually

terraform destroy --auto-approve

Use the above command in your terminal from your directory

Github Link For The Code

You Can Find The Whole Code in my GitHub Repository

THANKS FOR READING

--

--