Hosting WordPress and MySQL on AWS using Terraform

Hosting WordPress and MySQL on AWS using Terraform

Task

1. Create an AWS EC2 instance.

2. Configure the instance with Apache Webserver. Download PHP application name ""WordPress"". As Wordpress stores data at the backend in MySQL Database server. Therefore, you need to setup a my SQL server using AWS RDS service using Free Tier.

3.Provide the endpoint/connection string to the WordPress application to make it work.



Project Directory Structure and Configuring the Providers

The folder structure for our objective is as shown below. Keeping the files for provisioning resources separate from the main.tf helps in management and maintenance of the code.

No alt text provided for this image

Directory Structure for all the files and folders


In the file main.tf, all the modules will be called for provisioning of the resources, and the providers of the resources will also be defined here. In k8s_wp.tf, we will be setting up WordPress as a deployment exposed as a NodePort service. In rds.tf, we will be provisioning the database with the help of Amazon RDS. Finally, the security group to restrict access to the database only to port 3306 (default port to communicate with MySQL) will be created using the file my_sgs.tf.

First, we need to configure the providers of the resources we will be using, namely AWS and Kubernetes.The variables being used in the main.tf file will be stored in the variables.tf file in the same directory.

/* Contents of variables.tf */

#------------ VARIABLES FOR CONFIGURING AWS PROFILE -------------#
variable "profile_name" {
  type = string
  default = "your-profile-name"
}
variable "region_name" {
  type = string
  default = "ap-south-1"
}
#------------ VARIABLES FOR VPC -------------#
variable "vpc_id" {
  type = string
  default = "your vpc-id"
}
#------------ VARIABLES FOR KUBERNETES CLUSTER -------------#
variable "cluster_name" {
  type = string
  default = "minikube"
}
variable "pod_img" {
  type = string
  default = "wordpress"
}
variable "update_method" {
  type = string
  default = "RollingUpdate"
}
/* Configuring AWS and Kubernetes providers in main.tf */
provider "aws" {
  profile = var.profile_name
  region  = var.region_name
}
provider "kubernetes" {
  config_context_cluster = var.cluster_name
}

Provisoning the Database using Amazon RDS

/* Contents of my_sgs.tf */

variable "vpc_id" {}
resource "aws_security_group" "db_sg" {
  name        = "db_sg"
  description = "SG for Database (SQL) instances"
  vpc_id      = var.vpc_id
ingress {
    description = "Allow SQL DB Access only for 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"]
  }
}
#--------- OUTPUTS FOR SECURITY GROUP ---------#
output "db_sg"{
  value = aws_security_group.db_sg
}

First, we define the module for creating the security group which will restrict access to the Database only through port 3306. We also declare an output, which will allow us to access the attributes of the security group from the main.tf file to create the database.

/* Contents of rds.tf */

variable db_sg {}
variable alloc_store {}
variable store_type {}
variable engine {}
variable engine_ver {}
variable inst_type {}
variable db_name {}
variable db_username {}
variable db_password {}
resource "aws_db_instance" "rds_inst" {
  depends_on        = [var.db_sg]
  allocated_storage = var.alloc_store # Storage size for DB
  storage_type      = var.store_type #Storage type of DB
  engine = var.engine # Type of DB Engine (Eg: mysql, mariadb)
  vpc_security_group_ids = [var.db_sg.id]
  engine_version         = var.engine_ver 
  instance_class         = var.inst_type #DB instance type (Eg: db.t2.micro)
  
  # Giving Credentials for the DB table and user access
  name                 = var.db_name
  username             = var.db_username
  password             = var.db_password
  
  # Making the DB publicly accessible to integrate with WordPress running on K8s
  publicly_accessible = true
  
  # Setting this true so that there will be no problem while destroying the infrastructure
  skip_final_snapshot = true
tags = {
    Name = "my_rds_db"
  }
}
#--------- OUTPUTS FOR RDS DATABASE ---------#
# Gives DB table name
output "db_name" {
  value = aws_db_instance.rds_inst.name
}
# Gives the DB host address
output "db_addr" {
  value = aws_db_instance.rds_inst.address
}
# Gives the username for DB access
output "db_username" {
  value = aws_db_instance.rds_inst.username
}
# Gives the password for DB access
output "db_passwd" {
  value = aws_db_instance.rds_inst.password
}

Next, we define the module to create a database. Many of the arguments are declared as variables which will help in user customization. The outputs are important, as they will help in setting up WordPress.

Launching WordPress using Kubernetes Deployments and Services

/* Contents of my_k8s_wp.tf */

variable deploy_name {}
variable deploy_label {}
variable pod_replicas {type = number}
variable pod_label {}
variable pod_img {}
resource "kubernetes_persistent_volume_claim" "wp_pvc" {
  metadata {
    name = "wp-pvc"
    labels = {
      app = "wp-pvc"
    }
  }
  spec {
    access_modes = ["ReadWriteMany"]
    resources {
      requests = {
        storage = "1Gi"
      }
    }
  }
}
resource "kubernetes_deployment" "wp_deploy" {
  depends_on = [kubernetes_persistent_volume_claim.wp_pvc,]
  metadata {
    name = var.deploy_name
    labels = {
      app = var.deploy_label
    }
  }
  
  spec {
    
    # Defining no. of replicas
    replicas = var.pod_replicas
    
    selector {
      match_labels = {
        app = var.pod_label
      }
    }
    
    template {
      
      metadata {
        labels = {
          app = var.pod_label
        }
      }
      
      spec {
        volume {
          name = "wp-pv"
          persistent_volume_claim {
            claim_name = kubernetes_persistent_volume_claim.wp_pvc.metadata.0.name
          }
        }
        
        container {
          # Defining the image 
          image = var.pod_img
          name = "wp-container"
          port {
            container_port = 80
          }
          volume_mount {
            name       = "wp-pv"
            mount_path = "/var/www/html"
          }
        }
      }
    }
  }
}
resource "kubernetes_service" "wp_svc" {
  depends_on = [kubernetes_deployment.wp_deploy]
  metadata {
    name = "wp-svc"
    labels = {
      app = var.pod_label
    }
  }
  spec {
    selector = {
      app = var.pod_label
    }
    port {
      port        = 8080
      target_port = 80
      node_port   = 30303
    }
    type = "NodePort"
  }
}

To launch WordPress on Kubernetes using deployments and expose it using services, we being by creating a persistent volume claim of 1GiB which makes the data related to WordPress (in the directory /var/www/html) persistent. Next, we provision a deployment which takes input from the users for the container image, the number of pod replicas, and labels for deployments and pods. The inputs will be defined when the modules are called in the main.tf file.

Provisioning all the resources

/* Contents of main.tf */

provider "aws" {
  profile = var.profile_name
  region  = var.region_name
}
module "sg_rds" {
  source = "./my_sg"
  vpc_id = var.vpc_id
}
module "rds_inst" {
  source = "./my_rds"
  db_sg = module.sg_rds.db_sg
  alloc_store = 10
  store_type = "gp2"
  engine = "mysql"
  engine_ver = "5.7.30"
  inst_type = "db.t2.micro"
  db_name = "my_db"
  db_username = "ananya"
  db_password = "ananya123"
  
}
provider "kubernetes" {
  config_context_cluster = var.cluster_name
}
module "wordpress" {
  source = "./my_k8s_wp"
  deploy_name = "wp-dp"
  deploy_label = "wp"
  pod_replicas = 1
  pod_label = "wp"
  pod_img = var.pod_img
}
output "db_name" {
  value = "Database name: ${module.rds_inst.db_name}"
}
output "db_addr" {
  value = "Database Host Address: ${module.rds_inst.db_addr}"
}
output "db_username" {
  value = "Username for DB Access: ${module.rds_inst.db_username}"
}
output "db_passwd" {
  value = "Password for DB Access: ${module.rds_inst.db_passwd}" 
}

Finally, we can call the modules from their respective sources and provision all the required resources. To provision the resources, we need to use the following commands on the command line, with the working directory as the location of main.tf.

terraform init # To initialise all the modules and providers

terraform plan # To get an overview of all the resources being added, modified and deleted
terraform validate # Validating the configurations used in the files
terraform apply --auto-approve # Applying the changes as per the output of terraform plan

If the resources have been successfully created, we get the following output.

No alt text provided for this image

Output after successful provisioning of all resources

Now, we can use the minikube IP, with the allocated node port to access WordPress from our local system.

No alt text provided for this image

Setting up WordPress (Part 2)

When setting up WordPress, we will be asked to give information about the Database (Database name, username, password, and the host address of the database). These details have been printed as outputs after the successful provisioning of all resources.

No alt text provided for this image

Setting up WordPress (Part 3)

Once the installation is complete, we can now access the dashboard of the new blog with the username and password we have set.

No alt text provided for this image

Figure 6: Setting up WordPress (Part 4)


Yayyy, We have successfully hosted Wordpress and MySQL on AWS.

Thank You !!

Tayyab Liaqat

DevOps Engineer | AWS | Azure | CI/CD | Kubernetes | Docker | Ruby on Rails | Jenkins | Terraform | GCP | Linux

2 年
回复
Nnaemeka Anyanwu, MBA, PMP, ACP

Managing Consultant @Luckyway Global Consulting LLC | SN Community Rising Star '24 | Deloitte + Accenture AFS Alum|CSA|CAD|7xCIS -APM, FSM, SAM, SPM, ITSM, ITSMPro, ITSMPro+, CSM, CSMPro, CSMPro+, HR, HRPro, HRPro+|

3 年

Congratulations Ananya Jain

回复

要查看或添加评论,请登录

Ananya Jain的更多文章

  • Configuring Webserver, VPC on AWS

    Configuring Webserver, VPC on AWS

    ?? Write terraform code to configure the following things on AWS - ??Launch One VPC in north verginia having name as…

  • Configuring Multi-Cloud using Terraform

    Configuring Multi-Cloud using Terraform

    ??Task 1. Create 3 different workspace and create a full stack webserver on 3 different cloud.

  • Configure AWS EC2 using Terraform

    Configure AWS EC2 using Terraform

    Task: To create and setup key pair, security groups, ec2 instance and attaching it with EBS with storage of 1 GB. First…

  • Coursera Case Study

    Coursera Case Study

    Coursera is an educational technology company with a mission to provide universal access to the world’s best curricula.…

  • MY EXPERIENCE WITH GIT AND GITHUB

    MY EXPERIENCE WITH GIT AND GITHUB

    Git and GitHub are not the same thing. Git is an open-source, version control tool created in 2005 by developers…

    1 条评论
  • Ansible Training Experience

    Ansible Training Experience

    What is Ansible? Ansible is an open-source software that automates software provisioning, configuration management, and…

    2 条评论
  • Configure Load Balancer with HAproxy using AWS EC2 instances.

    Configure Load Balancer with HAproxy using AWS EC2 instances.

    ?? Task Description Statement: Deploy a Load Balancer and multiple Web Servers on AWS instances through ANSIBLE!…

    3 条评论
  • Configuration of Apache Webservers Dynamically using Ansible on AWS

    Configuration of Apache Webservers Dynamically using Ansible on AWS

    ?? Task Description Statement: Deploy Web Server on AWS through ANSIBLE! ??Provision EC2 instance through ansible…

  • Ansible Playbook that will dynamically load the variable file.

    Ansible Playbook that will dynamically load the variable file.

    ?? Objective : Create an Ansible Playbook which will dynamically load the variable file named same as OS_name and just…

    2 条评论
  • Configuring Docker Container As WebServer Using Ansible

    Configuring Docker Container As WebServer Using Ansible

    >Task Description ?Write an Ansible Playbook that does the following operations in the managed nodes: ?Configure Docker…

社区洞察

其他会员也浏览了