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.
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.
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.
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.
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.
Figure 6: Setting up WordPress (Part 4)
Yayyy, We have successfully hosted Wordpress and MySQL on AWS.
Thank You !!
DevOps Engineer | AWS | Azure | CI/CD | Kubernetes | Docker | Ruby on Rails | Jenkins | Terraform | GCP | Linux
2 年copied https://akshayavb99.medium.com/hosting-wordpress-and-mysql-using-aws-kubernetes-and-terraform-efbb8c73950c and not even implemented :D
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