In this lab, we will develop and deploy a scalable and reliable WordPress site on LEMP stack. Different from LAMP stack, LEMP uses nginx [engine x], instead of Apache as web server. Compared with Apache, nginx can handle much more concurrent hits. I found an article on the Internet, demonstrating the performance difference ‘Web server performance comparison‘.
Please refer to nginx official site https://nginx.org/en/ for further details.
A design proposed for production environment is as below. Firewall is not illustrated in the digram, but required in production environment.
Design Key Points:
- A pair of load balancers in active/passive HA cluster, sharing single virtual IP (VIP). DNS name will be associated to the VIP.
- The separation of web, application and backend layers in different subnets, allows flexibility to enforce security.
- Web cluster, PHP cluster, database cluster and file server cluster are created to achieve high availability and horizontal scalability
- PHP servers, file serves and database servers are external to web serves, which helps scalability. File server cluster will store WordPress files and mounted to web nodes and PHP nodes.
Due to the limit of my time and computing resource (= ‘money’), the boxes highlighted in RED in the above diagram are in the current lab scope. If time allows, I will deploy LVS load balancers as well. If you are interested in pfSense as load balancer, please refer to my posts Use pfSense to Load Balance Web Servers (1) and Use pfSense to Load Balance Web Servers (2).
Lab Servers and Software
I used DigitalOcean for cloud servers. It is cheaper than AWS. The cheapest instance is only US$5/month.
DigitalOcean $5 deal provides: 1 CPU, 512MB RAM, 20GB SSD, and 1000GB transfer. All servers used in this lab are $5 servers.
If you decide to use DigitalOcean, please use my referral link http://www.digitalocean.com/?refcode=81650e396096. You will get US$10 in credit immediately; and I may get some referral benefits as well, so win-win.
The downside is DigitalOcean provides less features. It allows private IP… but the private IP is automatically generated based on the selected datacentre (DC). For example, all my servers are in New York 3 DC, and their private IPs are all in the same subnet. It means I cannot manipulate IP allocation and routing as I did in AWS. In addition, it provides little ready-to-use security mechanism, though we can use Linux native firewall and install additional security services.
It is good and bad: good for quick DevOp testing, no hustle with network; bad for production environment or if you particular like network…myself for example 🙂
|Web Service Layer||Application/Service||Platform|
|Load Balancer Layer||Linux Virtual Server(LVS)||Not deployed yet|
|Web Server Layer||Nginx||Ubuntu16.04.1×64|
|Application Layer||php-fpm php-mysql||Ubuntu16.04.1×64|
|Backend Layer-File System||Gluster||Ubuntu16.04.1×64|
Step 1 – MySQL Database
#update and install mysql server on DB01. A GUI window will appear to assign mysql root password sudo apt-get update sudo apt-get -y install mysql-server #create 'wordpress1' database. '-u' followed by username.'-p' means password, it will require password in a separate line. sudo mysqladmin -u root -p create wordpress1 #change root password if required. sudo mysqladmin -u root -p password #enter mysql shell and enter password in separate line. sudo mysql -u root -p #create a user (CREATE USER 'wpuser1'), who can access from any host (@'%'), and with a password ('password'). Remember to add ';' at the end of each command under mysql shell to complete a command. CREATE USER 'wpuser1'@'%' IDENTIFIED BY 'password'; #grant user 'wpuser1' full permission in particular to 'wordpress1'database, but not global database. GRANT ALL PRIVILEGES ON wordpress1.* TO 'wpuser1'@'%'; #verify the existence of 'wordpress1' database and 'wpuser1' show databases; select User from mysql.user; #Update database permissions and exit mysql shell flush privilege; exit #Edit mysql config file to update the bind address from 127.0.0.1(loopback) to the actual private address. #Refer 'Note' section for details. sudo nano /etc/mysql/my.cnf #restart mysql service sudo service mysql restart
Note – MySQL Bind Address:
If the bind address in ‘my.cnf’ remains loopback, the database will not allow remote database access. When accessing the website, the following will show:
We will need to edit ‘/etc/mysql/my.cnf‘ as following, where ‘10.132.88.196’ is the DB server’s private IP.
Then we execute ‘service mysql restart‘ to restart mysql service. The following screenshot shows the DB server was listening on localhost port 3306 before restarting mysql service; and listening on DB01’s IP after restarting the service.
I also checked firewall status to make no traffic is accidentally blocked.