HAProxy: กระจายโหลดเว็บไปสองเครื่องพร้อม Health Check

ตั้ง HAProxy เป็น Load Balancer หน้าเว็บเซิร์ฟเวอร์สองเครื่อง มี Health Check ตัดเครื่องที่ล่มออกอัตโนมัติ หน้า Stats ที่ปลอดภัย Sticky Session และ HTTPS

โดย ทีมงาน THAI DATA CLOUD อัปเดต อ่าน 11 นาที

แชร์FacebookXLINELinkedIn
HAProxy — HAProxy: กระจายโหลดเว็บไปสองเครื่องพร้อม Health Check
HAProxy: กระจายโหลดเว็บไปสองเครื่องพร้อม Health Check

คำตอบสั้น ๆ: ตั้ง HAProxy เป็น Load Balancer หน้าเว็บเซิร์ฟเวอร์สองเครื่อง มี Health Check ตัดเครื่องที่ล่มออกอัตโนมัติ หน้า Stats ที่ปลอดภัย Sticky Session และ HTTPS

คู่มือนี้อธิบาย HAProxy ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย

HAProxy คือซอฟต์แวร์ Load Balancer แบบโอเพนซอร์สที่รับคำขอจากผู้ใช้แล้วกระจายไปยังเว็บเซิร์ฟเวอร์หลายเครื่อง พร้อมตรวจสุขภาพ (Health Check) ของแต่ละเครื่องอยู่ตลอด ถ้าเครื่องไหนล่ม HAProxy จะหยุดส่งงานไปเครื่องนั้นเองภายในไม่กี่วินาที เหมาะกับเว็บที่โหลดเกินกว่าเครื่องเดียวรับไหว หรือเว็บที่ต้องอัปเดตระบบโดยไม่ปิดหน้าเว็บ

คู่มือนี้ตั้งเครื่อง lb01 ให้รับทราฟฟิกที่ 203.0.113.10 แล้วกระจายไป web01 (10.10.0.11) และ web02 (10.10.0.12) ผ่านเครือข่ายภายใน เมื่อจบคุณจะมี Health Check ที่ใช้งานได้จริง หน้า Stats ที่เปิดได้เฉพาะผู้ดูแล วิธีทำ Sticky Session และทางเลือกให้ HAProxy ถือใบรับรอง HTTPS

สิ่งที่ต้องเตรียม

  • Cloud Server สามเครื่องในเครือข่ายภายในเดียวกัน: lb01 ที่มี Public IP และเว็บเซิร์ฟเวอร์สองเครื่องที่ติดตั้ง Nginx และไฟล์เว็บชุดเดียวกัน (ดู ติดตั้ง LEMP)
  • ระบบปฏิบัติการ Ubuntu 22.04/24.04, Debian 12 หรือ AlmaLinux/Rocky Linux 9 และสิทธิ์ sudo
  • ข้อมูล Session ของแอปไม่ควรเก็บเป็นไฟล์ในเครื่อง ควรย้ายไป Redis หรือฐานข้อมูลกลาง ไม่เช่นนั้นผู้ใช้จะหลุดล็อกอินเมื่อถูกส่งไปอีกเครื่อง
  • DNS ของ www.example.com ชี้มาที่ 203.0.113.10
แผนภาพผู้ใช้เข้าเว็บผ่าน HAProxy บน lb01 ที่กระจายคำขอไป web01 และ web02 ผ่านเครือข่ายภายใน
ผู้ใช้เห็นเพียง 203.0.113.10 ส่วนเว็บเซิร์ฟเวอร์รับคำขอเฉพาะจาก lb01 ทางเครือข่ายภายใน

ขั้นตอนที่ 1: เตรียมเว็บเซิร์ฟเวอร์ให้มี /health

บน web01 และ web02 เพิ่ม location สำหรับ Health Check และ Header บอกชื่อเครื่องไว้ทดสอบ (เปลี่ยน web01 ให้ตรงกับแต่ละเครื่อง) ใน server block ของ Nginx แล้ว reload

location = /health {
    access_log off;
    default_type text/plain;
    return 200 "ok\n";
}
add_header X-Served-By web01 always;

# ให้ Log ของ Nginx เห็น IP จริงของผู้ใช้แทน IP ของ lb01
set_real_ip_from 10.10.0.5;
real_ip_header X-Forwarded-For;

จากนั้นจำกัดพอร์ต 80 ของเว็บเซิร์ฟเวอร์ให้รับเฉพาะจาก lb01 เช่น sudo ufw allow from 10.10.0.5 to any port 80 proto tcp เพื่อไม่ให้ใครข้าม Load Balancer มาตรงได้

ขั้นตอนที่ 2: ติดตั้ง HAProxy บน lb01

# Ubuntu / Debian
sudo apt update && sudo apt install -y haproxy
# AlmaLinux / Rocky Linux 9
sudo dnf install -y haproxy

haproxy -v
sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.orig

Ubuntu 24.04 ได้รุ่น 2.8 ส่วน Ubuntu 22.04 และ AlmaLinux/Rocky 9 ได้รุ่น 2.4 การตั้งค่าในคู่มือนี้ใช้ได้กับทุกรุ่นดังกล่าว บน AlmaLinux/Rocky ไฟล์ตั้งต้นมีตัวอย่าง frontend main ที่พอร์ต 5000 และ backend static, app ให้ลบออก เหลือไว้เฉพาะ global และ defaults

ขั้นตอนที่ 3: เขียน frontend และ backend พร้อม Health Check

เพิ่มท้ายไฟล์ /etc/haproxy/haproxy.cfg โดย frontend คือฝั่งที่รับคำขอ ส่วน backend คือกลุ่มเซิร์ฟเวอร์ที่รับงานต่อ

frontend web_front
    bind *:80
    mode http
    option forwardfor
    default_backend web_servers

backend web_servers
    mode http
    balance roundrobin
    option httpchk
    http-check send meth GET uri /health ver HTTP/1.1 hdr Host www.example.com
    http-check expect status 200
    default-server inter 3s fall 3 rise 2
    server web01 10.10.0.11:80 check
    server web02 10.10.0.12:80 check
  • balance roundrobin ส่งงานสลับกันทีละเครื่อง ถ้าคำขอใช้เวลานานไม่เท่ากัน เช่น รายงานหรืออัปโหลดไฟล์ ให้ใช้ leastconn ซึ่งส่งไปเครื่องที่มีการเชื่อมต่อค้างน้อยที่สุด
  • inter 3s fall 3 rise 2 ตรวจทุก 3 วินาที พลาด 3 ครั้งติดถือว่าล่ม ผ่าน 2 ครั้งติดจึงรับกลับ
  • option forwardfor ส่ง IP จริงของผู้ใช้ไปใน Header X-Forwarded-For
ลำดับการทำงานของ Health Check ใน HAProxy ตั้งแต่ตรวจ /health จนตัดเครื่องออกและรับกลับ
ค่า inter 3s fall 3 rise 2 ทำให้เครื่องที่ล่มถูกตัดออกภายในประมาณ 9 วินาที

ขั้นตอนที่ 4: ตรวจไฟล์ เปิด Firewall และ reload

ตรวจไวยากรณ์ก่อนทุกครั้ง ถ้าถูกต้องจะขึ้น Configuration file is valid แล้วจึงเปิดบริการ การ reload ไม่ตัดการเชื่อมต่อที่กำลังใช้งานอยู่

sudo haproxy -c -f /etc/haproxy/haproxy.cfg
sudo systemctl enable --now haproxy
sudo systemctl reload haproxy

# Ubuntu / Debian
sudo ufw allow 80,443/tcp
# AlmaLinux / Rocky Linux 9
sudo firewall-cmd --permanent --add-service=http --add-service=https
sudo firewall-cmd --reload

ทดสอบจากเครื่องของคุณ แล้วลองหยุด Nginx บน web02 ภายในประมาณ 9 วินาทีทุกคำขอจะไปที่ web01 และ journalctl -u haproxy จะบันทึกว่า web02 เป็น DOWN

for i in 1 2 3 4; do curl -s -o /dev/null -D - http://203.0.113.10/ | grep -i x-served-by; done
หน้าจอทดสอบ HAProxy ด้วย curl เห็นคำขอสลับไป web01 และ web02 และ Log เมื่อ web02 ถูกตัดออก
Header X-Served-By สลับกันแปลว่า roundrobin ทำงาน และ Log บอกเหตุผลที่เครื่องถูกตัด

ขั้นตอนที่ 5: เปิดหน้า Stats ให้เข้าได้เฉพาะผู้ดูแล

หน้า Stats แสดงสถานะทุกเครื่อง จำนวนการเชื่อมต่อ และ Error ห้ามเปิดสู่อินเทอร์เน็ต ให้ผูกไว้ที่ 127.0.0.1 พร้อมรหัสผ่าน แล้วเข้าผ่าน SSH Tunnel

frontend stats
    bind 127.0.0.1:8404
    mode http
    stats enable
    stats uri /stats
    stats refresh 10s
    stats auth admin:Ch4nge-This-Long-Passw0rd
# รันบนเครื่องของคุณ แล้วเปิด http://localhost:8404/stats
ssh -L 8404:127.0.0.1:8404 [email protected]

ขั้นตอนที่ 6: Sticky Session เมื่อแอปยังเก็บ Session ในเครื่อง

ถ้ายังย้าย Session ไป Redis ไม่ได้ ให้ HAProxy ใส่ Cookie จดว่าผู้ใช้คนนี้เคยไปเครื่องไหน แล้วส่งไปเครื่องเดิมทุกครั้ง แก้ backend ดังนี้

backend web_servers
    cookie SRV insert indirect nocache
    server web01 10.10.0.11:80 check cookie web01
    server web02 10.10.0.12:80 check cookie web02

ข้อเสียคือโหลดอาจไม่เท่ากัน และเมื่อเครื่องหนึ่งล่ม ผู้ใช้ที่ผูกอยู่จะถูกย้ายไปอีกเครื่องและหลุด Session อยู่ดี จึงควรใช้เป็นทางชั่วคราว

ขั้นตอนที่ 7: ให้ HAProxy ถือใบรับรอง HTTPS (TLS Termination)

HAProxy ต้องการไฟล์ PEM ที่รวมใบรับรองกับ Private Key ไว้ในไฟล์เดียว ขอใบรับรองด้วย Certbot แบบ DNS-01 เพราะพอร์ต 80 ถูก HAProxy ใช้อยู่ แล้วรวมไฟล์

sudo mkdir -p /etc/haproxy/certs
sudo sh -c 'cat /etc/letsencrypt/live/www.example.com/fullchain.pem \
  /etc/letsencrypt/live/www.example.com/privkey.pem > /etc/haproxy/certs/www.example.com.pem'
sudo chmod 600 /etc/haproxy/certs/www.example.com.pem

แก้ frontend ให้ฟัง 443 และบังคับ HTTPS แล้วตรวจไฟล์และ reload ตามขั้นตอนที่ 4

frontend web_front
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/www.example.com.pem alpn h2,http/1.1
    mode http
    http-request redirect scheme https code 301 unless { ssl_fc }
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    option forwardfor
    default_backend web_servers

Certbot ต่ออายุใบรับรองเองแต่ไม่รู้จัก HAProxy ให้สร้างสคริปต์ /etc/letsencrypt/renewal-hooks/deploy/haproxy.sh แล้ว sudo chmod +x สคริปต์นี้จะรวมไฟล์ใหม่และ reload ทุกครั้งที่ต่ออายุสำเร็จ

#!/bin/sh
cat "$RENEWED_LINEAGE/fullchain.pem" "$RENEWED_LINEAGE/privkey.pem" \
  > /etc/haproxy/certs/www.example.com.pem
systemctl reload haproxy

ปัญหาที่พบบ่อยเกี่ยวกับ HAProxy

ทุกเครื่องขึ้น DOWN ทั้งที่เปิดเว็บตรงได้ เกิดจากอะไร?

ดูเหตุผลใน journalctl -u haproxy ถ้าเป็น Layer7 wrong status แปลว่า /health ไม่ตอบ 200 เช่น Nginx Redirect ไป HTTPS หรือ Host ไม่ตรง server block ถ้าเป็น Layer4 connection problem ให้ตรวจ Firewall ของเว็บเซิร์ฟเวอร์ว่าอนุญาต 10.10.0.5 แล้ว

HAProxy บน AlmaLinux หรือ Rocky Linux แจ้ง cannot bind socket ต้องทำอย่างไร?

SELinux ไม่อนุญาตให้ HAProxy ใช้พอร์ตที่ไม่ใช่พอร์ตเว็บมาตรฐาน เช่น 8404 ให้เปิดด้วย sudo setsebool -P haproxy_connect_any 1 แทนการปิด SELinux (ดู ใช้งาน SELinux โดยไม่ต้องปิด)

เว็บหลังเปิด HTTPS วน Redirect ไม่จบ แก้อย่างไร?

แอปเห็นคำขอจาก HAProxy เป็น HTTP จึง Redirect ไป HTTPS ซ้ำ ให้ตั้งแอปให้เชื่อ Header X-Forwarded-Proto จาก 10.10.0.5 เช่น ตั้ง Trusted Proxies ใน Laravel หรือเช็ก Header นี้ใน wp-config.php ของ WordPress

ถ้า lb01 ล่ม เว็บจะล่มทั้งหมดหรือไม่?

ใช่ Load Balancer เครื่องเดียวคือจุดเสี่ยงจุดเดียว (Single Point of Failure) ระบบที่ต้องการความพร้อมสูงควรมี HAProxy สองเครื่องใช้ Virtual IP ร่วมกันด้วย keepalived หรือใช้บริการ Load Balancer ของแพลตฟอร์ม

ถ้าต้องการออกแบบระบบเว็บหลายเครื่องบน Cloud Server ให้รองรับโหลดและไม่มีจุดล่มจุดเดียว ติดต่อทีมงาน THAI DATA CLOUD ตัวเลือกทั้งหมดของ HAProxy ดูได้ที่ HAProxy Documentation

อ่านเพิ่มเติมเกี่ยวกับ HAProxy

แชร์FacebookXLINELinkedIn

มีคำถามเรื่องบริการ? ติดต่อทีมงาน