ตั้งค่า Keepalived High Availability บน VPS ด้วย VRRP

16 กันยายน 2026 · อ่าน 12 นาที · Linux, Networking, HA

Keepalived High Availability VRRP บน Linux VPS

Keepalived คือซอฟต์แวร์ Open Source สำหรับทำ High Availability (HA) บน Linux โดยใช้โปรโตคอล VRRP (Virtual Router Redundancy Protocol) — สร้าง Virtual IP ที่จะย้ายตัวเองไปยังเซิร์ฟเวอร์ตัวสำรองโดยอัตโนมัติภายในไม่กี่วินาที หากเซิร์ฟเวอร์หลักล้มเหลว

บทความนี้จะพาคุณตั้งค่า Keepalived แบบ Master/Backup บน VPS 2 ตัว พร้อม health check สำหรับ Nginx หรือ HAProxy เพื่อให้ระบบมี uptime สูงสุด

Keepalived คืออะไร และทำงานอย่างไร

VRRP เป็นมาตรฐาน RFC 3768/5798 ที่กำหนดให้กลุ่มเราเตอร์/เซิร์ฟเวอร์แชร์ Virtual IP (VIP) ตัวเดียวกัน โดยมีเพียงหนึ่งตัว (Master) ที่รับ traffic จริงในขณะใดขณะหนึ่ง ตัวอื่น (Backup) คอยฟัง heartbeat — ถ้า Master เงียบไปนานเกิน threshold, Backup จะ promote ตัวเองขึ้นเป็น Master ทันที

บทบาทคำอธิบายPriority
Masterรับ traffic ผ่าน Virtual IPสูงกว่า (เช่น 101)
BackupStandby, คอยรับ VIP หาก Master ล่มต่ำกว่า (เช่น 100)

เตรียม VPS ก่อนติดตั้ง

ต้องการ VPS อย่างน้อย 2 ตัวที่อยู่ใน Network เดียวกัน (same subnet หรือ private network):

Note: บน Cloud VPS (Vultr, DigitalOcean, Hetzner) ที่ใช้ shared network ต้องเปิดใช้ IP Floating / Allowed IPs เพื่อให้ VIP assign ได้ — ดูในเอกสารของ provider แต่ละราย

ติดตั้ง Keepalived

ทำทั้งสองเซิร์ฟเวอร์ (node1 และ node2):

Ubuntu / Debian

sudo apt update
sudo apt install -y keepalived

CentOS / AlmaLinux / Rocky Linux

sudo dnf install -y keepalived

เปิดใช้ IP nonlocal bind (สำคัญมาก)

Keepalived ต้องการ bind บน Virtual IP ซึ่งยังไม่ได้ assign บน interface — ต้องเปิด kernel parameter นี้ก่อน:

# เพิ่มใน /etc/sysctl.conf
echo "net.ipv4.ip_nonlocal_bind = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

ตั้งค่า Keepalived บน Master (node1)

sudo nano /etc/keepalived/keepalived.conf
global_defs {
   router_id node1
   script_user root
   enable_script_security
}

vrrp_script chk_nginx {
    script "/usr/bin/systemctl is-active nginx"
    interval 2       # ตรวจทุก 2 วินาที
    weight -20       # ลด priority 20 เมื่อ nginx ล้มเหลว
    fall 2           # ต้องล้มเหลว 2 ครั้งติดกันก่อน failover
    rise 2           # ต้องสำเร็จ 2 ครั้งติดกันก่อน recovery
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0           # ชื่อ interface ของเซิร์ฟเวอร์ (ตรวจด้วย ip a)
    virtual_router_id 51     # ต้องตรงกันทั้งสองเซิร์ฟเวอร์ (1-255)
    priority 101             # Master ต้องสูงกว่า Backup
    advert_int 1             # ส่ง heartbeat ทุก 1 วินาที

    authentication {
        auth_type PASS
        auth_pass MySecretPass2026   # รหัสผ่านต้องตรงกันทั้งสองฝั่ง
    }

    virtual_ipaddress {
        192.168.1.100/24 dev eth0    # Virtual IP
    }

    track_script {
        chk_nginx
    }
}

ตั้งค่า Keepalived บน Backup (node2)

sudo nano /etc/keepalived/keepalived.conf
global_defs {
   router_id node2
   script_user root
   enable_script_security
}

vrrp_script chk_nginx {
    script "/usr/bin/systemctl is-active nginx"
    interval 2
    weight -20
    fall 2
    rise 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51     # ต้องตรงกับ Master
    priority 100             # Backup ต้องต่ำกว่า Master
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass MySecretPass2026   # ต้องตรงกัน
    }

    virtual_ipaddress {
        192.168.1.100/24 dev eth0
    }

    track_script {
        chk_nginx
    }
}

เริ่มต้นและเปิดใช้ Keepalived

รันบนทั้งสองเซิร์ฟเวอร์:

sudo systemctl enable --now keepalived
sudo systemctl status keepalived

ตั้งค่า Notify Script (แจ้งเตือนเมื่อ Failover)

สร้าง script เพื่อรับการแจ้งเตือนเมื่อ state เปลี่ยน (ส่ง email หรือ log):

sudo nano /etc/keepalived/notify.sh
#!/bin/bash
TYPE=$1
NAME=$2
STATE=$3

case $STATE in
    "MASTER")
        echo "[$(date)] ${NAME} became MASTER" >> /var/log/keepalived-notify.log
        ;;
    "BACKUP")
        echo "[$(date)] ${NAME} became BACKUP" >> /var/log/keepalived-notify.log
        ;;
    "FAULT")
        echo "[$(date)] ${NAME} entered FAULT state" >> /var/log/keepalived-notify.log
        ;;
esac
sudo chmod +x /etc/keepalived/notify.sh

เพิ่มใน vrrp_instance ทั้งสองฝั่ง:

    notify /etc/keepalived/notify.sh

Health Check สำหรับ HAProxy แทน Nginx

หากใช้ HAProxy แทน Nginx ให้เปลี่ยน script เป็น:

vrrp_script chk_haproxy {
    script "/usr/bin/systemctl is-active haproxy"
    interval 2
    weight -20
    fall 2
    rise 2
}

หรือตรวจด้วย TCP port แทน (ยืดหยุ่นกว่า):

vrrp_script chk_port {
    script "/bin/bash -c 'echo > /dev/tcp/127.0.0.1/80'"
    interval 3
    weight -20
    fall 3
    rise 2
    timeout 2
}

ตั้งค่า Firewall สำหรับ VRRP

VRRP ใช้ IP Protocol 112 (multicast 224.0.0.18) — ต้องเปิด firewall:

UFW

sudo ufw allow proto vrrp
# หรือกำหนด IP เฉพาะ
sudo ufw allow from 192.168.1.11 proto vrrp

iptables

sudo iptables -A INPUT -p vrrp -j ACCEPT
sudo iptables -A OUTPUT -p vrrp -j ACCEPT

firewalld (CentOS/AlmaLinux)

sudo firewall-cmd --add-protocol=vrrp --permanent
sudo firewall-cmd --reload

ตรวจสอบว่า Keepalived ทำงานถูกต้อง

# ดูว่า Virtual IP อยู่บน interface ไหน (ควรอยู่บน node1/Master)
ip addr show eth0 | grep 192.168.1.100

# ดู log ของ keepalived
journalctl -u keepalived -f

# ดู state ปัจจุบัน
sudo cat /tmp/keepalived.pid  # หรือดูจาก systemctl
sudo systemctl status keepalived

# ทดสอบ failover — หยุด keepalived บน Master
sudo systemctl stop keepalived   # บน node1
# แล้วตรวจว่า VIP ย้ายไป node2
ip addr show eth0 | grep 192.168.1.100  # บน node2 (ควรปรากฏ)

# Ping VIP ต่อเนื่องระหว่างทดสอบ
ping 192.168.1.100
Tip: ใช้ tcpdump -i eth0 -p vrrp เพื่อดู VRRP heartbeat packets ระหว่าง node1 และ node2 — ช่วย debug เมื่อ VIP ไม่ย้ายตามที่คาด

แก้ปัญหาที่พบบ่อย

Error: "VRRP_Script(chk_nginx) timed_out"

Script ที่ใช้ตรวจสอบ service ทำงานช้าเกินกำหนด timeout เริ่มต้น (5 วินาที)

# เพิ่ม timeout ใน vrrp_script
vrrp_script chk_nginx {
    script "/usr/bin/systemctl is-active nginx"
    interval 2
    weight -20
    timeout 5   # เพิ่มบรรทัดนี้
    fall 2
    rise 2
}

Error: "Keepalived_vrrp: ip address associated with VRID not present in MASTER advert"

virtual_router_id ของทั้งสองเซิร์ฟเวอร์ไม่ตรงกัน หรือมี Keepalived instance อื่นใน subnet ที่ใช้ VRID เดียวกัน

# ตรวจสอบ VRID ทั้งสองฝั่ง
sudo grep virtual_router_id /etc/keepalived/keepalived.conf
# ต้องตรงกันเสมอ และเปลี่ยนเป็นตัวเลขที่ไม่ซ้ำกับระบบอื่น (1-255)

Error: "Keepalived_vrrp: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.1.100" แต่ client ยังต่อไม่ได้

ARP cache ของ client ยังเก่าอยู่ — ทำ ARP flush:

# บน client หรือ router
arp -d 192.168.1.100

# บน Linux ทำ ARP request ใหม่
arping -c 3 192.168.1.100

Error: "Can't open PID file /run/keepalived.pid"

Permission issue หรือ Keepalived ไม่มีสิทธิ์เขียน /run/

# แก้ไข service unit
sudo systemctl edit keepalived --force
# เพิ่ม:
[Service]
RuntimeDirectory=keepalived
RuntimeDirectoryMode=0755

sudo systemctl daemon-reload
sudo systemctl restart keepalived

Error: VIP ไม่ย้ายกลับมาที่ Master หลังจาก Master กลับมาออนไลน์ (Preemption)

โดยค่าเริ่มต้น Keepalived จะ preempt (ย้าย VIP กลับ Master) เมื่อ Master กลับมา ถ้าไม่ต้องการพฤติกรรมนี้:

# เพิ่มใน vrrp_instance บน Master
nopreempt   # VIP จะไม่ย้ายกลับอัตโนมัติ

# หรือกำหนด delay
preempt_delay 30   # รอ 30 วินาทีก่อน preempt

คำถามที่พบบ่อย

Keepalived ต่างจาก HAProxy อย่างไร?

Keepalived ทำ IP-level failover — ย้าย Virtual IP จาก node หนึ่งไปอีก node เมื่อล้มเหลว ส่วน HAProxy ทำ application-level load balancing — กระจาย request ไปยัง backend หลายตัว ทั้งสองมักถูกใช้ร่วมกัน: Keepalived ดูแล VIP ของ HAProxy และ HAProxy กระจาย traffic ไปยัง web server

Keepalived รองรับกี่ Virtual IP ต่อ instance?

รองรับได้หลาย VIP ต่อหนึ่ง vrrp_instance เพียงแค่ระบุหลายบรรทัดใน virtual_ipaddress {}:

virtual_ipaddress {
    192.168.1.100/24
    192.168.1.101/24
    10.0.0.50/24
}

ใช้ Keepalived กับ Cloud VPS ทั่วไปได้ไหม?

ได้ แต่มีข้อจำกัดสำหรับ Public IP — Cloud provider ส่วนใหญ่ไม่ให้ broadcast VRRP multicast บน Public Network เพราะ security policy จึงต้องใช้ VIP บน Private Network แทน แล้วให้ Load Balancer ของ Cloud รับ Public IP มาชี้ที่ VIP อีกที หรือใช้ Floating IP ของ provider ร่วมกับ API script