วิธีทำ load balance wordpress ด้วย haproxy

จาก Wiki Opensource

บันทึกนี้ปรับปรุงล่าสุดเมื่อวันที่ 7-07-2560
ดูแลโดย WIBOON

คำอธิบาย

  • server ทั้งหมดเป็น ubuntu 16.04 server จำนวน 4 เครื่อง
  • ประกอบด้วย mysql server + nfs server 1 เครื่อง, wordpress 2 เครื่อง และ haproxy 1 เครื่อง
  • เป็น load balance ใน layer 7 และทำ load balance แบบบ round robin


[เครื่องที่ 1 mysql server + nfs server]
server ip = 10.0.0.51
1. ติดตั้ง mysql server ที่เครื่องที่ 1
ผลลัพธ์คือ
เราจะได้ ubuntu server ที่มี mysql server ที่กำหนดค่าให้สามารถเข้าถึงจาก IP เครื่องอื่นได้
และเราจะสร้าง database เตรียมไว้สำหรับ wordpress
ขั้นตอน
1.1 ติดตั้งโปรแกรม

sudo apt install mysql-server

1.2 แก้ไขค่าตัวแปร bind-address

sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
bind-address = ::

1.3 restart service

sudo systemctl restart mysql.service
sudo systemctl status mysql.service

1.4 สร้าง database

mysql -u root -p
mysql> CREATE DATABASE mydb CHARACTER SET 'UTF8';
mysql> CREATE USER 'myuser'@'%' IDENTIFIED BY 'mypassword';
mysql> GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'%';
mysql> FLUSH PRIVILEGES;
mysql> exit

2. ติดตั้ง nfs server ที่เครื่องที่ 1
ผลลัพธ์คือ
เราจะได้พื้นที่ /sharewordpress สำหรับเป็นพื้นที่เดียวให้เก็บไฟล์ของ wordpress จากทุกเครื่อง
ขั้นตอน

sudo apt-get install nfs-kernel-server
sudo cp -a /etc/exports /etc/exports.backup
sudo mkdir -p /nfsdisk/sharewordpress
sudo chmod 777 /nfsdisk/sharewordpress
echo '/nfsdisk/sharewordpress  10.0.0.0/24(rw,async,insecure,no_subtree_check,nohide)' | sudo tee -a /etc/exports
sudo exportfs -ra
sudo service nfs-kernel-server restart
ls -ld /nfsdisk
ls -ld /nfsdisk/sharewordpress/

3. ติดตั้ง apache2 web server ที่เครื่องที่ 1
ผลลัพธ์คือ
เราจะได้ ubuntu server ที่มี web server เปิด port 80/TCP
สามารถใช้งาน http://10.0.0.51
ขั้นตอน

sudo apt install apache2
sudo apt install php php-mysql php-xml
sudo apt install libapache2-mod-php7.0
sudo apt install wget
sudo apt install unzip
sudo service apache2 restart

4. ติดตั้ง wordpress ลงใน apache2 web server ที่เครื่องที่ 1
เพื่อเป็นพื้นที่ /var/www/html/wordpress ให้แก่ wordpress1 และ wordpress2 เท่านั้น
ในการตั้งค่า wordpress กำหนดให้ใช้ database ที่สร้างไว้ที่ mysql server บนเครื่องที่ 1
สมมติ
ชื่อ database คือ mydb
ชื่อ user คือ myuser
รหัสผ่านของ myuser คือ mypassword
และให้ใช้พื้นที่ /var/www/html/wordpress จาก /nfsdisk/sharewordpress บนเครื่องที่ 1
ผลลัพธ์คือ
สามารถใช้งาน http://10.0.0.51/wordpress
ขั้นตอน

sudo ln -s /nfsdisk/sharewordpress /var/www/html/wordpress
cd /tmp
wget http://wordpress.org/latest.zip
sudo unzip -q latest.zip -d /var/www/html/
sudo chown -R www-data:www-data /nfsdisk/sharewordpress/ 
sudo chmod -R 755 /nfsdisk/sharewordpress/*  
sudo mkdir -p /nfsdisk/sharewordpress/wp-content/uploads 
sudo chown -R www-data:www-data /nfsdisk/sharewordpress/wp-content/uploads

เข้าหน้าเว็บ wordpress เพื่อติดตั้งครั้งแรก

[เครื่องที่ 2 wordpress1]
server ip = 10.0.0.52
1. ติดตั้ง nfs client ที่เครื่องที่ 2
ผลลัพธ์คือ
สามารถใช้งานพื้นที่ /sharewordpress บนเครื่องที่ 1
ขั้นตอน

sudo apt install nfs-common
sudo mkdir -p /sharewordpress

ทดสอบ

sudo mount  -t  nfs  -o  proto=tcp,port=2049  10.0.0.51:/nfsdisk/sharewordpress  /sharewordpress
mount -l | grep nfs

หลังจากทดสอบถูกต้อง ก็ทำให้ใช้ถาวร

sudo cp  -a  /etc/fstab  /etc/fstab.backup
echo '10.0.0.51:/nfsdisk/sharewordpress  /sharewordpress  nfs  nosuid  0  0' | sudo tee -a /etc/fstab


2. ติดตั้ง apache2 web server ที่เครื่องที่ 2
ผลลัพธ์คือ
เราจะได้ web server เปิด port 80/TCP
สามารถใช้งาน http://10.0.0.52
ขั้นตอน

sudo apt install apache2
sudo apt install php php-mysql php-xml
sudo apt install libapache2-mod-php7.0
sudo apt install wget
sudo apt install unzip
sudo service apache2 restart

3. ติดตั้ง wordpress ลงใน apache2 web server ที่เครื่องที่ 2
เนื่องจากติดตั้ง wordpress ไว้แล้วตอนที่ทำเครื่องที่ 1 (ต้นฉบับ)
ดังนั้นการติดตั้ง wordpress เครื่องต่อ ๆ ไป ก็ทำเพียงแค่ สร้าง link file ไปยัง /sharewordpress บนเครื่องที่ 1
ผลลัพธ์คือ
สามารถใช้งาน http://10.0.0.52/wordpress
ขั้นตอน

sudo ln -s /sharewordpress /var/www/html/wordpress


[เครื่องที่ 3 wordpress2]
server ip = 10.0.0.53
1. ติดตั้ง nfs client ที่เครื่องที่ 3
ผลลัพธ์คือ
สามารถใช้งานพื้นที่ /sharewordpress บนเครื่องที่ 1
ขั้นตอน

sudo apt install nfs-common
sudo mkdir -p /sharewordpress

ทดสอบ

sudo mount  -t  nfs  -o  proto=tcp,port=2049  10.0.0.51:/nfsdisk/sharewordpress  /sharewordpress
mount -l | grep nfs

หลังจากทดสอบถูกต้อง ก็ทำให้ใช้ถาวร

sudo cp  -a  /etc/fstab  /etc/fstab.backup
echo '10.0.0.51:/nfsdisk/sharewordpress  /sharewordpress  nfs  nosuid  0  0' | sudo tee -a /etc/fstab

2. ติดตั้ง apache2 web server ที่เครื่องที่ 3
ผลลัพธ์คือ
เราจะได้ web server เปิด port 80/TCP
สามารถใช้งาน http://10.0.0.53
ขั้นตอน

sudo apt install apache2
sudo apt install php php-mysql php-xml
sudo apt install libapache2-mod-php7.0
sudo apt install wget
sudo apt install unzip
sudo service apache2 restart

3. ติดตั้ง wordpress ลงใน apache2 web server ที่เครื่องที่ 3
เนื่องจากติดตั้ง wordpress ไว้แล้วตอนที่ทำเครื่องที่ 1 (ต้นฉบับ)
ดังนั้นการติดตั้ง wordpress เครื่องต่อ ๆ ไป ก็ทำเพียงแค่ สร้าง link file ไปยัง /sharewordpress บนเครื่องที่ 1
ผลลัพธ์คือ
สามารถใช้งาน http://10.0.0.53/wordpress
ขั้นตอน

sudo ln -s /sharewordpress /var/www/html/wordpress


[เครื่องที่ 4 haproxy]
ในการตั้งค่า haproxy จะใช้ mode http เพื่อทำ layer 7 load balance
server ip = 10.0.0.54
ผลลัพธ์คือ
สามารถใช้งาน http://10.0.0.54/wordpress
จะได้หน้าเว็บเพจตอบกลับจากเครื่องที่ 2 สลับกับ เครื่องที่ 3
ขั้นตอน
1. ติดตั้งโปรแกรม haproxy

sudo apt update
sudo apt install haproxy

2. ตั้งค่า

sudo vi /etc/default/haproxy
ENABLED=1

3. ตรวจสอบสถานะ

sudo service haproxy status

4. เก็บสำรองไฟล์ haproxy.cfg ไว้ด้วย

cd /etc/haproxy; sudo cp haproxy.cfg haproxy.cfg.orig

5. แก้ไขไฟล์ haproxy.cfg

sudo vi /etc/haproxy/haproxy.cfg

นำท่อนข้างล่างนี้ต่อท้ายไฟล์ haproxy.cfg

frontend www-http
   bind *:80
   mode http
   default_backend wordpress-backend

backend wordpress-backend
   mode http
   balance roundrobin
   option forwardfor
   http-request set-header X-Forwarded-Port %[dst_port]
   http-request add-header X-Forwarded-Proto https if { ssl_fc }
   option httpchk HEAD / HTTP/1.1\r\nHost:\ localhost
   server wordpress1 10.0.0.52:80 check
   server wordpress2 10.0.0.53:80 check

6. แก้ไข wordpress config
ให้แก้ไขที่เครื่องที่ 1

sudo vi /nfsdisk/sharewordpress/wp-config.php

เพิ่ม 2 บรรทัดนี้ ก่อนชุด MySQL settings ประมาณบรรทัดที่ 20

define('WP_SITEURL', 'http://10.0.0.54/wordpress');
define('WP_HOME', 'http://10.0.0.54/wordpress');

7. restart service

sudo service rsyslog restart
sudo service haproxy restart

8. ทดสอบเข้าหน้าเว็บ

http://10.0.0.54/wordpress 

9. ตรวจสอบ haproxy log

tail -f /var/log/haproxy.log


[การปรับปรุงเพิ่มเติม เรื่องที่ 1]
ตั้งค่า apache2 และ wordpress เปลี่ยน wordpress SITE_URL ให้เป็น FQDN
กำหนดค่า FQDN คือ tblog1.mydomain มี IP คือ 10.0.0.54
ผลลัพธ์คือ
สามารถใช้งาน http://tblog1.mydomain
จะได้หน้าเว็บเพจของ wordpress ได้ โดยไม่ต้องระบุ path /wordpress
ขั้นตอน
1. จดโดเมนเนมให้เรียบร้อยที่ dns server ที่เราใช้งาน
2. แก้ไข wordpress config
ให้แก้ไขที่เครื่องที่ 1

 
sudo vi /nfsdisk/sharewordpress/wp-config.php

แก้ไข 2 บรรทัดนี้ ก่อนชุด MySQL settings ประมาณบรรทัดที่ 20

define('WP_SITEURL', 'http://tblog1.mydomain');
define('WP_HOME', 'http://tblog1.mydomain');

3. แก้ไข apache2 site config
ให้แก้ไขที่เครื่องที่ 2 (wordpress1) และ เครื่องที่ 3 (wordpress2) แก้ไข ServerName กับ DocumentRoot

cd /etc/apache2/sites-available/
sudo cp 000-default.conf tblog1.mydomain.conf
sudo vi tblog1.mydomain.conf
        ServerName tblog1.mydomain
        DocumentRoot /var/www/html/wordpress

เพิ่ม site นี้ให้ apache2 รู้จัก

sudo a2ensite tblog1.mydomain

ไม่ใช้ default

sudo a2dissite 000-default.conf
sudo service apache2 reload

ตรวจสอบ log file

tail /var/log/haproxy.log

จะเห็น round robin ใช้ server wordpress1 สลับกับ server wordpress2

Jul  6 12:46:01 ubuntu haproxy[1792]: 10.0.0.12:58667 [06/Jul/2017:12:45:19.611] www wordpress-backend/wordpress1 41677/0/1/54/41733 200 17973 - - ---- 1/1/0/1/0 0/0 "GET / HTTP/1.1"
Jul  6 12:46:13 ubuntu haproxy[1792]: 10.0.0.12:58667 [06/Jul/2017:12:46:01.344] www wordpress-backend/wordpress2 12064/0/1/52/12118 200 17973 - - ---- 1/1/0/1/0 0/0 "GET / HTTP/1.1"


[การปรับปรุงเพิ่มเติม เรื่องที่ 2]
เราจะทำ haproxy SSL Termination เพื่อใช้ https แทน http
หากไม่มี cert ที่ซื้อมาก็ทดสอบได้ด้วย ssl-cert-snakeoil.pem ที่ ubuntu เตรียมไว้สำหรับทดสอบ
ขั้นตอน 1. สร้าง my.pem

sudo su -
apt install ssl-cert
cd /etc/ssl/private/
cat ../certs/ssl-cert-snakeoil.pem ssl-cert-snakeoil.key > my.pem
chgrp ssl-cert my.pem
exit

2. แก้ไขไฟล์ haproxy.cfg

sudo vi /etc/haproxy/haproxy.cfg

3. นำท่อนข้างล่างนี้ต่อท้ายไฟล์ haproxy.cfg
เพิ่มต่อท้ายในชุด defaults

        option forwardfor
        option http-server-close

แล้วตามด้วยท่อนนี้

frontend www-http
   bind *:80
   reqadd X-Forwarded-Proto:\ http
   default_backend wordpress-backend

frontend www-https
   bind *:443 ssl crt /etc/ssl/private/my.pem
   reqadd X-Forwarded-Proto:\ https
   default_backend wordpress-backend

backend wordpress-backend
   balance roundrobin
   redirect scheme https if !{ ssl_fc }
   server wordpress1 10.0.0.52:80 check
   server wordpress2 10.0.0.53:80 check

4. restart service haproxy

sudo service haproxy restart

5. แก้ไข wordpress config
ให้แก้ไขที่เครื่องที่ 1

sudo vi /nfsdisk/sharewordpress/wp-config.php

แก้ไข 2 บรรทัดนี้ ก่อนชุด MySQL settings ประมาณบรรทัดที่ 20

define('WP_SITEURL', 'https://tblog1.mydomain');
define('WP_HOME', 'https://tblog1.mydomain');

และเพิ่มท่อนนี้ก่อนบรรทัด /* That's all, stop editing! Happy blogging. */

if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
    $_SERVER['HTTPS'] = 'on';
    $_SERVER['SERVER_PORT'] = 443;
}
/* That's all, stop editing! Happy blogging. */


[การปรับปรุงเพิ่มเติม เรื่องที่ 3]
แก้ไข LogFormat ของ apache2 ให้รับ X-Forwarded-For

sudo vi /etc/apache2/apache2.conf
#LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

แล้ว restart service apache2

sudo service apache2 restart


อ่านรายละเอียดเพิ่มเติมได้จาก

  1. ติดตั้ง mysql server บน ubuntu 16.04 server
  2. ติดตั้ง nfs server บน ubuntu 16.04 server
  3. ติดตั้ง ssl-cert บน ubuntu 16.04 server
  4. ติดตั้ง haproxy บน ubuntu server 16.04