SiamCafe · Blog
Proxmox VE Cluster Troubleshooting แก้ปัญหา —
บทความ

Proxmox VE Cluster Troubleshooting แก้ปัญหา —

เผยแพร่ 28 พฤษภาคม 2569

Proxmox VE Cluster คืออะไรและปัญหาที่พบบ่อย

Proxmox VE (Virtual Environment) เป็น open source virtualization platform ที่รองรับทั้ง KVM virtual machines และ LXC containers Proxmox Cluster ช่วยให้หลาย nodes ทำงานร่วมกันเป็นระบบเดียว รองรับ High Availability, Live Migration และ Shared Storage ผ่าน Ceph หรือ NFS

Proxmox Cluster ใช้ Corosync สำหรับ cluster communication และ quorum management ใช้ pmxcfs (Proxmox Cluster File System) สำหรับ synchronize configuration ระหว่าง nodes และใช้ HA Manager สำหรับ automatic failover ของ VMs/Containers

ปัญหาที่พบบ่อยใน Proxmox Cluster ได้แก่ Quorum loss เมื่อ node ล่มจนเหลือน้อยกว่ากึ่งหนึ่ง Split-brain เมื่อ network แบ่ง cluster เป็นสองส่วน Corosync timeout จาก network latency สูง Ceph degraded/unhealthy จาก disk failure Storage replication failures และ VM migration failures

การแก้ปัญหา Proxmox Cluster ต้องเข้าใจหลักการทำงานของ Corosync, Quorum, RAFT consensus และ Ceph architecture รวมถึงการใช้ command line tools เพื่อวินิจฉัยและแก้ไขปัญหาอย่างถูกต้อง

วินิจฉัยปัญหา Cluster ด้วย Command Line

คำสั่งสำหรับตรวจสอบสถานะ cluster

=== ตรวจสอบสถานะ Cluster ===

ดูสถานะ cluster overview

pvecm status

Output ที่ดี:

Cluster information

-------------------

Name: my-cluster

Config Version: 3

Transport: knet

Secure auth: on

Quorum information

------------------

Date: Mon Jan 15 10:30:00 2024

Quorum provider: corosync_votequorum

Nodes: 3

Node ID: 1

Ring ID: 1/3

Quorate: Yes <-- สำคัญ! ต้องเป็น Yes

ดูรายชื่อ nodes

pvecm nodes

ตรวจสอบ quorum

pvecm expected 1 # กรณีฉุกเฉิน: บังคับ quorum ด้วย 1 vote

ดูสถานะ Corosync

systemctl status corosync

journalctl -u corosync --since "1 hour ago" --no-pager

ดูสถานะ pve-cluster

systemctl status pve-cluster

journalctl -u pve-cluster --since "1 hour ago" --no-pager

ตรวจสอบ HA status

ha-manager status

pvesh get /cluster/ha/status/current

ดู VM/Container status ทุก nodes

pvesh get /cluster/resources --type vm

ตรวจสอบ storage

pvesm status

ตรวจสอบ Ceph status (ถ้าใช้ Ceph)

ceph status

ceph health detail

ceph osd tree

ceph osd df

ceph pg stat

ตรวจสอบ network connectivity ระหว่าง nodes

ping -c 5 node2

ping -c 5 node3

ตรวจสอบ Corosync rings

corosync-cfgtool -s

ดู cluster configuration

cat /etc/pve/corosync.conf

ดู firewall rules

pve-firewall status

iptables -L -n | grep -E "(8006|5405|5404)"

ตรวจสอบ time sync (สำคัญมากสำหรับ cluster)

timedatectl status

chronyc sources

nodes ต้อง sync time ภายใน 1 วินาที

แก้ปัญหา Quorum และ Split-brain

วิธีแก้ปัญหา quorum loss และ split-brain

=== Quorum Loss ===

เกิดเมื่อ nodes ที่ online น้อยกว่ากึ่งหนึ่ง

Cluster 3 nodes: ต้องมีอย่างน้อย 2 nodes online

Cluster 5 nodes: ต้องมีอย่างน้อย 3 nodes online

ตรวจสอบ quorum

pvecm status | grep -i quor

Quorate: No <-- ปัญหา!

วิธีแก้ 1: บังคับ quorum (กรณีฉุกเฉิน)

ใช้เมื่อ node อื่นไม่สามารถกลับมาได้ชั่วคราว

pvecm expected 1

วิธีแก้ 2: เพิ่ม node กลับเข้า cluster

บน node ที่ล่ม: restart services

systemctl restart corosync

systemctl restart pve-cluster

วิธีแก้ 3: ถ้า node ถูกถอดออกจาก cluster

pvecm add NODE_IP

=== Split-brain Recovery ===

เกิดเมื่อ network แบ่ง cluster เป็น 2 ส่วน

ทั้ง 2 ส่วนคิดว่าตัวเองเป็น active cluster

Step 1: หยุด VMs ที่ run ซ้ำกัน (ถ้ามี)

ตรวจสอบว่า VM run อยู่บน node ไหน

qm list # บน node 1

qm list # บน node 2

Step 2: เลือก side ที่จะเป็น primary

Side ที่มี data ล่าสุดควรเป็น primary

Step 3: Stop cluster services บน secondary side

systemctl stop pve-cluster

systemctl stop corosync

Step 4: ลบ cluster config บน secondary nodes

*** อันตราย! ทำเฉพาะ secondary side ***

systemctl stop pve-cluster corosync

pmxcfs -l # mount local mode

rm /etc/corosync/corosync.conf

rm /etc/pve/corosync.conf

rm -rf /etc/corosync/uidgid.d/*

rm /var/lib/corosync/*

Step 5: Rejoin cluster

pvecm add PRIMARY_NODE_IP

Step 6: Verify

pvecm status

pvecm nodes

=== ป้องกัน Split-brain ===

1. ใช้ redundant network สำหรับ Corosync

corosync.conf:

totem {

interface {

linknumber: 0

knet_transport: udp

}

interface {

linknumber: 1

knet_transport: udp

}

}

2. ใช้ fencing/STONITH

HA Manager settings:

ha: shutdown_policy=conditional

3. ใช้ QDevice (external quorum device)

เพิ่ม vote จาก external server

apt install corosync-qdevice

pvecm qdevice setup QDEVICE_IP

แก้ปัญหา Storage และ Ceph

วิธีแก้ปัญหา storage ที่พบบ่อยใน Proxmox

# === Ceph Troubleshooting ===

# ตรวจสอบ Ceph health
ceph health detail

# HEALTH_WARN: 1 osds down
# แก้: restart OSD ที่ down
systemctl restart ceph-osd@OSD_ID

# ถ้า OSD ไม่ start:
journalctl -u ceph-osd@OSD_ID --since "30 min ago"

# ตรวจสอบ disk health
smartctl -a /dev/sdX
# ถ้า disk เสีย: replace OSD
ceph osd out OSD_ID
ceph osd purge OSD_ID --yes-i-really-mean-it

# เพิ่ม OSD ใหม่
pveceph osd create /dev/sdY

# HEALTH_WARN: Degraded data redundancy
ceph pg stat
# ดู PGs ที่ degraded
ceph pg dump_stuck degraded

# รอ recovery (อาจใช้เวลาหลายชั่วโมง)
ceph -w  # watch recovery progress

# ปรับ recovery speed
ceph tell osd.* injectargs '--osd-recovery-max-active 3'
ceph tell osd.* injectargs '--osd-max-backfills 1'

# HEALTH_WARN: clock skew detected
# แก้ time sync
apt install chrony
systemctl enable chrony
systemctl restart chrony
chronyc makestep

# HEALTH_WARN: pool has too few PGs
ceph osd pool set POOL_NAME pg_num 128
ceph osd pool set POOL_NAME pgp_num 128

# === NFS/CIFS Storage Issues ===

# ตรวจสอบ NFS mount
showmount -e NFS_SERVER
mount | grep nfs

# ถ้า NFS hang:
umount -f /mnt/pve/nfs_storage
mount -t nfs NFS_SERVER:/export /mnt/pve/nfs_storage

# ตรวจสอบ NFS performance
nfsstat -c
dd if=/dev/zero of=/mnt/pve/nfs_storage/test bs=1M count=1024
rm /mnt/pve/nfs_storage/test

# === ZFS Issues ===
zpool status
zpool list
# ถ้ามี DEGRADED:
zpool replace POOL /dev/old_disk /dev/new_disk

# Scrub เพื่อตรวจสอบ data integrity
zpool scrub POOL_NAME

# === VM Disk Issues ===
# ตรวจสอบ disk ของ VM
qm config VMID | grep -i disk
qm rescan
lvs  # ถ้าใช้ LVM

แก้ปัญหา Network และ Corosync

วิธีแก้ปัญหา network ที่กระทบ cluster

=== Corosync Network Issues ===

ตรวจสอบ Corosync communication

corosync-cfgtool -s

Output:

Printing link status.

Local node ID 1

LINK ID 0

addr = 10.0.0.1

status:

nodeid 2: connected <-- ต้องเป็น connected

nodeid 3: connected

ถ้า disconnected:

1. ตรวจสอบ firewall

iptables -L -n | grep 5405

Corosync ports: UDP 5405-5412

เปิด firewall สำหรับ Corosync

iptables -A INPUT -p udp --dport 5405:5412 -j ACCEPT

iptables -A INPUT -p tcp --dport 8006 -j ACCEPT

2. ตรวจสอบ network interface

ip addr show

ip route show

ตรวจสอบว่า Corosync bind กับ interface ที่ถูกต้อง

3. ตรวจสอบ MTU

ip link show | grep mtu

ทุก nodes ต้องใช้ MTU เดียวกัน

4. ทดสอบ multicast (ถ้าใช้)

omping -m 239.192.1.1 -p 5405 NODE1_IP NODE2_IP NODE3_IP

=== Network Performance ===

ทดสอบ bandwidth ระหว่าง nodes

Node 1 (server):

iperf3 -s

Node 2 (client):

iperf3 -c NODE1_IP

ทดสอบ latency

ping -c 100 NODE2_IP | tail -1

ค่าที่ดี: < 1ms สำหรับ local network, < 5ms สำหรับ dedicated link

=== VM Migration Issues ===

Live migration failed

ตรวจสอบ:

1. Network bandwidth เพียงพอ

2. Storage accessible จากทั้ง source และ target

3. CPU compatibility

qm migrate VMID TARGET_NODE --online

ถ้า fail เพราะ CPU:

qm set VMID -cpu host # หรือเปลี่ยนเป็น compatible CPU type

Migration timeout

เพิ่ม timeout สำหรับ VM ที่มี memory มาก

qm migrate VMID TARGET_NODE --online --with-local-disks

=== Bridge Network Issues ===

ตรวจสอบ bridge configuration

brctl show

ip link show vmbr0

สร้าง bridge ใหม่ (ถ้าจำเป็น)

cat /etc/network/interfaces

auto vmbr0

iface vmbr0 inet static

address 10.0.0.1/24

gateway 10.0.0.254

bridge-ports eno1

bridge-stp off

bridge-fd 0

Apply network changes

ifreload -a

=== Bonding Issues ===

cat /proc/net/bonding/bond0

ตรวจสอบว่า slaves ทั้งหมด active

Mode ที่แนะนำ: 802.3ad (LACP) หรือ balance-alb

สร้าง Monitoring Script สำหรับ Cluster Health

Script อัตโนมัติสำหรับตรวจสอบ cluster health

#!/bin/bash
# pve_health_check.sh — Proxmox VE Cluster Health Monitor
set -euo pipefail

LOG_FILE="/var/log/pve_health.log"
ALERT_WEBHOOK=""
HOSTNAME=$(hostname)
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

log() { echo "[$TIMESTAMP] $1" | tee -a "$LOG_FILE"; }
alert() {
    log "ALERT: $1"
    if [ -n "$ALERT_WEBHOOK" ]; then
        curl -s -X POST "$ALERT_WEBHOOK" \
            -H "Content-Type: application/json" \
            -d "{\"text\":\"[$HOSTNAME] $1\"}" > /dev/null 2>&1
    fi
}

ISSUES=0

# 1. Check Quorum
log "Checking quorum..."
QUORATE=$(pvecm status 2>/dev/null | grep "Quorate:" | awk '{print $2}')
if [ "$QUORATE" != "Yes" ]; then
    alert "Quorum LOST! Cluster is not quorate"
    ISSUES=$((ISSUES + 1))
fi

# 2. Check Node Status
log "Checking nodes..."
TOTAL_NODES=$(pvecm nodes 2>/dev/null | grep -c "^[[:space:]]*[0-9]" || echo 0)
ONLINE_NODES=$(pvecm status 2>/dev/null | grep "Nodes:" | awk '{print $2}')
if [ "$TOTAL_NODES" != "$ONLINE_NODES" ]; then
    alert "Node(s) offline: $ONLINE_NODES/$TOTAL_NODES online"
    ISSUES=$((ISSUES + 1))
fi

# 3. Check Corosync
log "Checking corosync..."
if ! systemctl is-active --quiet corosync; then
    alert "Corosync service is NOT running"
    ISSUES=$((ISSUES + 1))
fi

# 4. Check Ceph (if installed)
if command -v ceph &> /dev/null; then
    log "Checking Ceph..."
    CEPH_HEALTH=$(ceph health 2>/dev/null | head -1)
    if [[ "$CEPH_HEALTH" == *"HEALTH_ERR"* ]]; then
        alert "Ceph HEALTH_ERR: $CEPH_HEALTH"
        ISSUES=$((ISSUES + 1))
    elif [[ "$CEPH_HEALTH" == *"HEALTH_WARN"* ]]; then
        log "WARNING: Ceph $CEPH_HEALTH"
    fi
    
    # Check OSD status
    OSD_DOWN=$(ceph osd tree 2>/dev/null | grep -c "down" || echo 0)
    if [ "$OSD_DOWN" -gt 0 ]; then
        alert "Ceph: $OSD_DOWN OSD(s) down"
        ISSUES=$((ISSUES + 1))
    fi
fi

# 5. Check Storage
log "Checking storage..."
pvesm status 2>/dev/null | tail -n +2 | while read -r line; do
    STORE=$(echo "$line" | awk '{print $1}')
    STATUS=$(echo "$line" | awk '{print $2}')
    USAGE=$(echo "$line" | awk '{print $7}' | tr -d '%')
    
    if [ "$STATUS" != "active" ]; then
        alert "Storage '$STORE' is $STATUS"
        ISSUES=$((ISSUES + 1))
    fi
    
    if [ -n "$USAGE" ] && [ "$USAGE" -gt 90 ]; then
        alert "Storage '$STORE' usage at %"
    fi
done

# 6. Check HA Services
log "Checking HA..."
HA_ERRORS=$(ha-manager status 2>/dev/null | grep -c "error" || echo 0)
if [ "$HA_ERRORS" -gt 0 ]; then
    alert "HA Manager: $HA_ERRORS error(s) detected"
    ISSUES=$((ISSUES + 1))
fi

# 7. Check Disk Health
log "Checking disks..."
for disk in /dev/sd[a-z] /dev/nvme[0-9]n1; do
    [ -b "$disk" ] || continue
    SMART=$(smartctl -H "$disk" 2>/dev/null | grep "SMART overall" | awk '{print $NF}')
    if [ "$SMART" = "FAILED!" ]; then
        alert "Disk $disk SMART check FAILED!"
        ISSUES=$((ISSUES + 1))
    fi
done

# 8. Check Time Sync
log "Checking time sync..."
if command -v chronyc &> /dev/null; then
    OFFSET=$(chronyc tracking 2>/dev/null | grep "System time" | awk '{print $4}')
    # ตรวจสอบว่า offset ไม่เกิน 1 วินาที
fi

# Summary
if [ "$ISSUES" -eq 0 ]; then
    log "Health check PASSED: All checks OK"
else
    log "Health check: $ISSUES issue(s) found"
fi

# Cron: ทุก 5 นาที
# */5 * * * * /opt/scripts/pve_health_check.sh

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

Q: Proxmox Cluster ต้องใช้กี่ nodes?

A: แนะนำอย่างน้อย 3 nodes สำหรับ HA cluster เพื่อรักษา quorum เมื่อ 1 node ล่ม 2 nodes ก็ยังมี quorum ถ้ามี 2 nodes ต้องใช้ QDevice เป็น tie-breaker สำหรับ Ceph storage แนะนำอย่างน้อย 3 nodes เพราะ Ceph ต้องการ minimum replication factor 3

Q: Corosync timeout เท่าไหร่ดี?

A: Default token timeout คือ 1000ms (1 วินาที) สำหรับ local network ที่มี latency ต่ำค่านี้เหมาะสม สำหรับ remote sites หรือ network ที่ไม่เสถียรอาจเพิ่มเป็น 5000-10000ms แต่ค่ายิ่งสูง failover ยิ่งช้า ถ้า token timeout สูงเกินไป HA จะตรวจจับ failure ช้า ควร balance ระหว่าง sensitivity กับ false positives

Q: ควรใช้ Ceph หรือ NFS สำหรับ shared storage?

A: Ceph เหมาะสำหรับ cluster ที่ต้องการ performance สูงและ self-healing storage ไม่ต้องมี external storage server แต่ต้องการ SSD/NVMe และ RAM มากขึ้น NFS เหมาะสำหรับ setup ที่ง่ายกว่า ใช้ NAS ที่มีอยู่ หรือมี dedicated storage server แต่เป็น single point of failure ถ้า NAS ล่ม ถ้ามี 3 nodes ขึ้นไปแนะนำ Ceph

Q: VM migration failed ทำอย่างไร?

A: สาเหตุที่พบบ่อยคือ storage ไม่ accessible จาก target node (ตรวจด้วย pvesm status), CPU incompatible ระหว่าง nodes (ใช้ cpu type เป็น kvm64 หรือ x86-64-v2 แทน host), network bandwidth ไม่พอสำหรับ VM ที่มี memory มาก (ใช้ dedicated migration network), VM มี local disk ที่ไม่ได้อยู่บน shared storage (ใช้ --with-local-disks option)