Deployed Wordpress on Aws EKS and database on aws RDS

Sahil Raj
5 min readOct 19, 2020

In this task we deploy the wordpress application on aws EKS(Elastic kubernetes service) and the database using RDS(relational database service) on aws.

Problem statement:

  1. Write infrastructure as a code using terraform which deploys wordpress on EKS and the wordpress app is accessible from public world.
  2. On aws use RDS service for the database for the wordpress app.

STEP 1:

We login in aws with a profile.

provider "aws" {
region = "ap-south-1"
profile = "sahil123"
}

STEP 2:

We create iam roles for the cluster i.e. give the necessary permissions to the cluster so tha it can create ec2 instances ,security groups etc needed for its operation.

//creating IAM role for cluster
resource "aws_iam_role" "sahil-iam-role" {
name = "sahil-eks-cluster-role"
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" "sahil-AmazonEKSClusterPolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
role = aws_iam_role.sahil-iam-role.name
}
resource "aws_iam_role_policy_attachment" "sahil-AmazonEKSVPCResourceController" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController"
role = aws_iam_role.sahil-iam-role.name
}

STEP 3: Creating the EKS CLUSTER.

//Creating the eks clusterresource "aws_eks_cluster" "sahil-eks-cluster" {
name = "sahil-eks-cluster"
role_arn = aws_iam_role.sahil-iam-role.arn
vpc_config {
subnet_ids = ["subnet-beaa17c5", "subnet-54a1ca18"]
}
depends_on = [
aws_iam_role_policy_attachment.sahil-AmazonEKSClusterPolicy,
aws_iam_role_policy_attachment.sahil-AmazonEKSVPCResourceController,
]
}

STEP 4:

Creating the iam roles for the slave node groups of EKS cluster in which the pods get deployed.

//Creating IAM role for node groupresource "aws_iam_role" "worker-nodes" {
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" "example-AmazonEKSWorkerNodePolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
role = aws_iam_role.worker-nodes.name
}
resource "aws_iam_role_policy_attachment" "example-AmazonEKS_CNI_Policy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
role = aws_iam_role.worker-nodes.name
}
resource "aws_iam_role_policy_attachment" "example-AmazonEC2ContainerRegistryReadOnly" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
role = aws_iam_role.worker-nodes.name
}

STEP 5:

Creating the node groups with desired size of two nodes and if the load increase i.e more requests come on the wordpress then the nodes can get scaled up to 4.

//Creating node groupsresource "aws_eks_node_group" "example" {
cluster_name = aws_eks_cluster.sahil-eks-cluster.name
node_group_name = "sahil-node-group"
node_role_arn = aws_iam_role.worker-nodes.arn
subnet_ids = ["subnet-beaa17c5", "subnet-54a1ca18"]
instance_types = ["t2.micro"]
scaling_config {
desired_size = 2
max_size = 4
min_size = 1
}
depends_on = [
aws_iam_role_policy_attachment.example-AmazonEKSWorkerNodePolicy,
aws_iam_role_policy_attachment.example-AmazonEKS_CNI_Policy,
aws_iam_role_policy_attachment.example-AmazonEC2ContainerRegistryReadOnly,
]
}

STEP 6:

We create a security group for the database and allow 3306 port so that the wordpress pod can connect to it.The skip snapshot option is used so that after deleting the database its snapshot wont be created.

resource "aws_security_group" "rds-sg" {
name = "rds-sg"
description = "Allow port 3306"
ingress {
description = "port 3306"
from_port = 3306
to_port = 3306
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 = "RDS-SG"
}
}

STEP 7:

NOW we create the database and use amazon RDS for it.We connect this database to the wordpress application.

resource "aws_db_instance" "sahil-db" {
allocated_storage = 20
storage_type = "gp2"
engine = "mysql"
engine_version = "5.7"
instance_class = "db.t2.micro"
name = "mydb"
username = "sahildb"
password = "sahil123"
parameter_group_name = "default.mysql5.7"
publicly_accessible = true
vpc_security_group_ids = [aws_security_group.rds-sg.id]
skip_final_snapshot = true
}

STEP 8:

Now we update the kubectl command in our system of the new kubernetes cluster.We use local exec provisioner for executing the command in our local system.

resource "null_resource" "null-1"{
depends_on=[
aws_eks_cluster.sahil-eks-cluster,
aws_eks_node_group.example,
]
provisioner "local-exec"{
command= "aws eks update-kubeconfig --name sahil-eks-cluster"
}
}

Step 9:

We launch the wordpress pod in the EKS cluster though kubernetes deployment with 2 replicas of the pod i.e two wordpress pods and give labels to the pods.

provider "kubernetes"{
}
resource "kubernetes_deployment" "deploy" {
metadata {
name = "terraform-example"
labels = {
test = "production"
}
}
spec {
replicas = 2
selector {
match_labels = {
test = "production"
}
}
template {
metadata {
labels = {
test = "production"
}
}
spec {
container {
name = "wordpress"
image = "wordpress:4.8-apache"
}
}
}
}
}

STEP 10:

Now we expose the wordpress pod and use a load balancer.By using the type loadBalancer aws uses internal aws load balancer.

resource "kubernetes_service" "sahil_lb" {
depends_on=[
kubernetes_deployment.deploy
]
metadata {
name = "example-com"
}
spec {
selector = {
test = kubernetes_deployment.deploy.metadata.0.labels.test
}
port {
port = 80
}
type = "LoadBalancer"
}
}

Now we run this code

terraform init
terraform apply --auto-approve

EKS cluster created:

Node groups created:

IAM roles created:

Database created:

Wordpress pods are created:

Load balancer is created:

WORDPRESS SITE:

TO delete the above setup:

terraform destroy --auto-approve

--

--