เมื่อปริมาณ traffic ของ web server เพิ่มมากขึ้น และไม่สามารถเพิ่มทรัพยากรหรือไม่สามารถขยาย web server ได้แล้ว เทคนิคที่มักนำมาใช้กันคือ การ scale out หรือ การเพิ่มจำนวน web server ออกตามแนวราบ (horizontal scaling) ซึ่งเมื่อมีการเพิ่มจำนวน web server ก็ต้องมีด่านหน้าที่ทำหน้าที่กระจาย traffic ไปยัง web server เครื่องต่างๆ

สำหรับในบทความนี้ จะนำเสนอการติดตั้ง haproxy เพื่อนำมาใช้เป็น load balancer หรือตัวกระจาย load ไปยัง web server หลายๆ เครื่อง ซึ่งแน่นอนว่า ทั้ง load balancer และ web server ทั้งหมด สามารถติดตั้งบน Cloud ของ HostPacific ได้

จากขั้นตอนตัวอย่างต่อไปนี้ จะประกอบด้วย Cloud จำนวน 3 ตัว (หรือ Server 3 เครื่อง) คือ

  • 1+2) www01:10.0.1.46 และ www02:10.0.1.47 ทำหน้าที่ web server ซึ่งมีการติดตั้ง Apache / PHP เรียบร้อยแล้ว 
  • 3) haproxy:10.0.1.45 สำหรับติดตั้ง haproxy ซึ่งเริ่มต้นจะมี Centos และ package พื้นฐานเท่านั้น

การติดตั้ง web server บน vm1 และ vm2

การติดตั้ง haproxy บน vm3

  • build Cloud โดยใช้ CentOS7
  • update package เบื้องต้นต่างๆ ให้เรียบร้อย โดยใช้คำสั่ง
# yum -y update
  • ติดตั้ง haproxy
# yum -y install haproxy
  • ตรวจสอบ version หลังจากที่ดำเนินการติดตั้งเรียบร้อย
# haproxy -v
HA-Proxy version 1.5.14 2015/07/02
Copyright 2000-2015 Willy Tarreau <willy@haproxy.org>

การ config haproxy

สำหรับ config ไฟล์ของ /etc/haproxy/haproxy.cfg จะแบ่งส่วน ออกเป็น

  • global: เป็นเหมือนค่า config กลาง ซึ่งบางส่วนเป็นค่า default ที่ไม่จำเป็นต้องเปลี่ยน แต่บางส่วนปรับเปลี่ยนได้ตามการใช้งาน

จากตัวอย่าง จะมีการทำงานด้วย user และ group ของ haproxy ซึ่งถูกสร้างเมื่อมีการติดตั้ง ทั้งนี้เพื่อความปลอดภัยในการใช้งาน ในส่วนนี้สามารถกำหนดสิทธ์ต่างๆ แยกจาก user อื่น ๆ ของระบบได้

  • defaults: เป็นค่า default สำหรับการใช้งานในส่วน section ต่างๆ ถัดจาก config ในส่วนนี้ไป
  • frontend: เป็นส่วนกำหนดการเปิด socket ซึ่งจะมีการรับค่าการเชื่อมต่อจากเครื่อง client
  • backend: เป็นส่วนกำหนดเครื่อง web server เพื่อให้ haproxy forward การเชื่อมต่อจาก client ไปยัง web server ที่อยู่ด้านหลัง
  • stats: เป็น option เพิ่มเติม โดยหน้า web tool จะเป็นการใช้งานสำหรับการตรวจสอบเครื่อง load balancer และ node ต่างๆ

เริ่มต้นการปรับไฟล์ configuration

ก่อนเริ่มดำเนินการแก้ไขไฟล์ config ควรมีการ backup ไว้เสมอๆ เพื่อป้องการความผิดพลาดที่อาจจะเกิดขึ้น

# cp -p /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.org
# vi /etc/haproxy/haproxy.cfg

global
   # ส่วนการเข้าสู่ระบบ
   log         127.0.0.1 local2
   chroot      /var/lib/haproxy
   pidfile     /var/run/haproxy.pid

   # จำนวนของ connection ที่รองรับ
   maxconn     512

   # user และ group สำหรับใช้ในการ run service
   user        haproxy
   group       haproxy

   # กำหนดให้ทำงานแบบ background mode
   daemon

defaults
  # mode การทำงาน เพื่อ forward http traffic
   mode                    http

   # การเก็บ log
   log                     global
   option                  httplog

   # การกำหนดค่า timeout
   timeout http-request    10s
   timeout queue           1m
   timeout connect         10s
   timeout client          1m
   timeout server          1m
   timeout http-keep-alive 10s
   timeout check           10s

   # การ monitor
   stats enable
   stats refresh 10s
   stats uri /stats
   stats realm Haproxy\ Statistics
   stats auth haproxy:HAPROXY

frontend http-web
   # เปิดรับ port 80
   bind *:80

   # กำหนดค่า header สำหรับ X-Forwarded-For
   option forwardfor
   reqadd X-Forwarded-Proto:\ http

   # กำหนด default backend
   default_backend http-backend

backend http-backend
   # กำหนดการทำงานแบบ roundrobin คือสลับเรียงทีละตัว
   balance            roundrobin
   option  httpclose

   # กำหนด server ที่จะทำงานในส่วน backend
   server             www01 10.0.1.46:80 check
   server             www02 10.0.1.47:80 check

เมื่อกำหนดค่าแล้ว ให้ดำเนินการบันทึกไฟล์

ส่วนต่อไปจะเป็นการกำหนดค่าการเก็บ log ที่ /var/log/haproxy.log  

1)  เปิดการใช้งานค่า ModLoad และ UDPServerRun ตามตัวอย่างด้านล่างนี้

#  vi /etc/rsyslog.conf
...

# Provides UDP syslog reception

$ModLoad imudp
$UDPServerRun 514
...

เมื่อกำหนดค่าแล้ว ให้เซฟไฟล์

2) สร้างไฟล์ ชื่อ haproxy.conf

#  vi /etc/rsyslog.d/haproxy.conf
local2.* /var/log/haproxy.log

เมื่อกำหนดค่าแล้ว ให้เซฟไฟล์

ตรวจสอบความถูกต้องของไฟล์ config อีกครั้ง และ restart service ที่เกี่ยวข้องหลังจากที่มีการแก้ไข

# haproxy -f /etc/haproxy/haproxy.cfg
# systemctl restart rsyslog
# systemctl restart haproxy

การปรับ config เพิ่มเติมที่ web server

เนื่องจาก web server แต่ละตัวจะเห็น IP ที่เรียกเข้ามา จาก haproxy ข้างหน้า ทำให้ไม่สามารถดูที่มาของ traffic ที่แท้จริงใน access_log ได้ จึงต้องแก้ไข config การเก็บ log บน web server ให้แสดงที่มา IP ต้นทางที่แท้จริงด้วย โดยแก้ไขจากบรรทัด LogFormat

# vi /etc/httpd/conf/httpd.conf
...
LogFormat "%{X-Fo
rwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
...

# systemctl restart httpd

เมื่อกำหนดค่าแล้ว ให้เซฟไฟล์ และ restart service httpd

เมื่อทดสอบใช้งาน โดยเรียก IP ของ haproxy คือ 10.0.1.45 จะแสดง ตามตัวอย่างด้านล่างนี้ ซึ่งมาจาก web server 2 ตัว สลับกันไป

เราสามารถตรวจสอบ access_log ได้จาก /var/log/httpd/access_log ของ web server ทั้ง 2 เครื่อง (จากกรณีนี้ IP เครื่อง client คือ 10.0.1.35)

Web server: Site1

# tail /var/log/httpd/access_log

10.0.1.35 - - [01/Mar/2016:14:19:28 +0700] "GET / HTTP/1.1" 200 23 "-" "Mozilla/5.0 
(Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 
Safari/537.36"

10.0.1.35 - - [01/Mar/2016:14:19:50 +0700] "GET / HTTP/1.1" 200 23 "-" "Mozilla/5.0 
(Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 
Safari/537.36"

Web server: Site2

# tail /var/log/httpd/access_log

10.0.1.35 - - [01/Mar/2016:14:19:42 +0700] "GET / HTTP/1.1" 200 23 "-" "Mozilla/5.0 
(Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 
Safari/537.36"

10.0.1.35 - - [01/Mar/2016:14:19:55 +0700] "GET / HTTP/1.1" 200 23 "-" "Mozilla/5.0 
(Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 
Safari/537.36"

ซึ่งจะเห็น IP ของ client ที่แท้จริง ใน web server ทั้ง 2 ตัว

และสามารถตรวจสอบ haproxy log ได้จาก /var/log/haproxy.log ในเครื่อง load balancer

# tail /var/log/haproxy.log

Mar  1 14:19:28 localhost haproxy[4751]: 10.0.1.35:61569 [01/Mar/2016:14:19:28.949] 
http-web http-backend/www01 5/0/0/1/6 200 226 - - ---- 0/0/0/0/0 0/0 "GET / HTTP/1.1"

Mar  1 14:19:42 localhost haproxy[4751]: 10.0.1.35:61571 [01/Mar/2016:14:19:42.301] 
http-web http-backend/www02 5/0/1/1/7 200 226 - - ---- 0/0/0/0/0 0/0 "GET / HTTP/1.1"

Mar  1 14:19:50 localhost haproxy[4751]: 10.0.1.35:61573 [01/Mar/2016:14:19:50.133] 
http-web http-backend/www01 5/0/0/1/6 200 226 - - ---- 0/0/0/0/0 0/0 "GET / HTTP/1.1"

Mar  1 14:19:55 localhost haproxy[4751]: 10.0.1.35:61576 [01/Mar/2016:14:19:55.579] 
http-web http-backend/www02 5/0/0/1/6 200 226 - - ---- 0/0/0/0/0 0/0 "GET / HTTP/1.1"

ซึ่งจะสังเกตเห็นบันทึกว่า traffic แต่ละครั้ง ถูก forward ไปยัง backend ตัวไหน (www01 หรือ www02)

การตรวจสอบ stats ของ haproxy

สามารถตรวจสอบได้จาก http://10.0.1.45/stats

Default Username: haproxy
Default Password: HAPROXY

ข้อควรทราบเพิ่มเติม

  • เพื่อประสิทธิที่เพิ่มขึ้น ควรเชื่อมต่อ haproxy และ web server ต่างๆ ผ่านทาง private network
  • ข้อมูลเพิ่มเติม http://www.haproxy.org และ http://haproxy.com/

Reference เพิ่มเติม:

การแก้ไข haproxy ไม่ยอม auto-start ผ่าน systemd