ลดความยุ่งยากในการใช้คลาวด์ พูดคุยกับเจ้าหน้าที่

Home สำรองข้อมูลไปยังเซิร์ฟเวอร์อื่นด้วย rsync และ Cronjob

สำรองข้อมูลไปยังเซิร์ฟเวอร์อื่นด้วย rsync และ Cronjob

การเก็บไฟล์สำรองไว้บนเซิร์ฟเวอร์เครื่องเดียวกับข้อมูลจริงไม่ช่วยอะไรเมื่อดิสก์เสีย เครื่องถูกลบ หรือถูกโจมตี วิธีที่ง่ายและใช้กันแพร่หลายคือใช้ rsync คัดลอกไฟล์ผ่าน SSH ไปเก็บที่เซิร์ฟเวอร์อีกเครื่อง rsync ส่งเฉพาะส่วนที่เปลี่ยนแปลง จึงเร็วและประหยัด Bandwidth หลังจากรอบแรก

คู่มือนี้เรียกเครื่องที่มีข้อมูลว่า เครื่องต้นทาง และเครื่องที่เก็บสำรองว่า เครื่องปลายทาง (ตัวอย่าง IP 203.0.113.20) ใช้ได้กับ Ubuntu, AlmaLinux และ Rocky Linux

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

  • สิทธิ์ sudo บนเครื่องต้นทาง และผู้ใช้สำหรับรับไฟล์บนเครื่องปลายทาง (ตัวอย่างใช้ชื่อ backup)
  • เครื่องต้นทางเชื่อมต่อ SSH ไปยังเครื่องปลายทางได้
  • พื้นที่บนเครื่องปลายทางมากกว่าขนาดข้อมูลที่จะสำรอง
  • ติดตั้ง rsync ทั้งสองเครื่อง: sudo apt install -y rsync หรือ sudo dnf install -y rsync

ตัวอย่างนี้สำรองโฟลเดอร์ /var/www หากต้องการสำรองฐานข้อมูลด้วย ให้ Dump ฐานข้อมูลเป็นไฟล์ก่อนตามคู่มือ สำรองและกู้คืนฐานข้อมูล MySQL/MariaDB ด้วย mysqldump แล้วให้ rsync ส่งโฟลเดอร์ไฟล์ Dump ไปด้วย

ขั้นตอนที่ 1: เตรียมผู้ใช้และโฟลเดอร์บนเครื่องปลายทาง

บนเครื่องปลายทาง สร้างผู้ใช้ backup และโฟลเดอร์รับไฟล์

sudo useradd -m -s /bin/bash backup
sudo mkdir -p /srv/backup/web01
sudo chown backup:backup /srv/backup/web01

บน Ubuntu อาจมีผู้ใช้ระบบชื่อ backup อยู่แล้ว หาก useradd แจ้งว่ามีผู้ใช้นี้ ให้ใช้ชื่ออื่น เช่น bkuser และเปลี่ยนชื่อในทุกคำสั่งให้ตรงกัน

ขั้นตอนที่ 2: สร้าง SSH Key สำหรับงานสำรองข้อมูล

Cronjob รันโดยไม่มีคนพิมพ์รหัสผ่าน จึงต้องใช้ SSH Key ที่ไม่มี Passphrase แยกไว้สำหรับงานนี้โดยเฉพาะ บนเครื่องต้นทาง ให้ทำในฐานะ root เพราะต้องอ่านไฟล์ได้ทุกไฟล์

sudo ssh-keygen -t ed25519 -f /root/.ssh/backup_ed25519 -N "" -C "backup web01"
sudo cat /root/.ssh/backup_ed25519.pub

คัดลอกข้อความ Public Key ที่ได้ แล้วนำไปใส่ในไฟล์ /home/backup/.ssh/authorized_keys บนเครื่องปลายทาง

sudo -u backup mkdir -p /home/backup/.ssh
sudo -u backup nano /home/backup/.ssh/authorized_keys
sudo chmod 700 /home/backup/.ssh
sudo chmod 600 /home/backup/.ssh/authorized_keys

จากนั้นทดสอบการเชื่อมต่อจากเครื่องต้นทาง ครั้งแรกต้องทำด้วยมือ เพื่อตอบ yes ยืนยัน Host Key ของเครื่องปลายทาง ไม่เช่นนั้น Cronjob จะล้มเหลว

sudo ssh -i /root/.ssh/backup_ed25519 [email protected] 'echo connected'

ถ้าได้คำว่า connected โดยไม่ถามรหัสผ่าน แสดงว่าพร้อมแล้ว หากเครื่องปลายทางเปลี่ยน SSH Port ไว้ ให้เติม -p 2222 (ใช้พอร์ตจริง) ต่อจาก ssh ดูรายละเอียดเรื่อง SSH Key เพิ่มเติมได้ที่ ตั้งค่า SSH Key และปิดการเข้าสู่ระบบด้วยรหัสผ่านบน Linux

ขั้นตอนที่ 3: ทดลองรัน rsync แบบจำลองก่อน

sudo rsync -aHz --delete --dry-run --itemize-changes \
  -e "ssh -i /root/.ssh/backup_ed25519" \
  /var/www/ [email protected]:/srv/backup/web01/www/

ความหมายของตัวเลือก

  • -a คัดลอกแบบเก็บสิทธิ์ เจ้าของ เวลา และ Symlink ครบ
  • -H รักษา Hard Link
  • -z บีบอัดข้อมูลระหว่างส่ง
  • --delete ลบไฟล์ฝั่งปลายทางที่ไม่มีแล้วในต้นทาง ให้สองฝั่งตรงกัน
  • --dry-run แสดงว่าจะทำอะไรโดยยังไม่ทำจริง

หมายเหตุ: เครื่องหมาย / ท้าย Path ต้นทางมีผล /var/www/ หมายถึงคัดลอก เนื้อหาใน โฟลเดอร์ ส่วน /var/www จะสร้างโฟลเดอร์ www ซ้อนเข้าไปอีกชั้น และเมื่อใช้ --delete ถ้าระบุ Path ปลายทางผิด ไฟล์ในโฟลเดอร์นั้นจะถูกลบ จึงต้องตรวจผลจาก --dry-run ทุกครั้งก่อนรันจริง

เมื่อตรวจรายการแล้วถูกต้อง ให้รันซ้ำโดยตัด --dry-run ออก รอบแรกจะใช้เวลานานตามขนาดข้อมูล รอบต่อไปจะเร็วขึ้นมาก

ขั้นตอนที่ 4: เขียนสคริปต์สำรองข้อมูล

sudo nano /usr/local/bin/backup-web.sh
#!/bin/bash
set -euo pipefail

DEST="[email protected]:/srv/backup/web01"
SSH="ssh -i /root/.ssh/backup_ed25519 -o BatchMode=yes"

echo "=== $(date '+%F %T') start"
rsync -aHz --delete --exclude 'cache/' -e "$SSH" /var/www/ "$DEST/www/"
rsync -aHz --delete -e "$SSH" /etc/nginx/ "$DEST/nginx/"
echo "=== $(date '+%F %T') done"
sudo chmod 700 /usr/local/bin/backup-web.sh
sudo /usr/local/bin/backup-web.sh

set -euo pipefail ทำให้สคริปต์หยุดทันทีเมื่อคำสั่งใดล้มเหลว และ BatchMode=yes ทำให้ SSH ไม่ค้างรอรหัสผ่านหากใช้ Key ไม่ได้ ปรับ --exclude และรายการโฟลเดอร์ให้ตรงกับเซิร์ฟเวอร์ของคุณ

ขั้นตอนที่ 5: ตั้ง Cronjob ให้รันอัตโนมัติ

sudo crontab -e

เพิ่มบรรทัดนี้ เพื่อรันทุกวันเวลา 02:30 ตามเวลาของเซิร์ฟเวอร์

30 2 * * * /usr/bin/flock -n /run/backup-web.lock /usr/local/bin/backup-web.sh >> /var/log/backup-web.log 2>&1

flock -n ป้องกันไม่ให้สคริปต์รอบใหม่เริ่มขณะที่รอบก่อนยังไม่เสร็จ และ Log ทั้งหมดถูกเก็บที่ /var/log/backup-web.log ตรวจว่าเวลาของเซิร์ฟเวอร์ถูกต้องได้ที่ ตั้งค่า Timezone และซิงก์เวลาอัตโนมัติบน Linux Server และอ่านพื้นฐาน Cronjob เพิ่มได้ที่ วิธีตั้ง Cronjob หรือ Crontab เพื่อให้ Script ทำงานอัตโนมัติบน Linux

เก็บหลายเวอร์ชันย้อนหลัง (ทางเลือก)

การใช้ --delete ทำให้ปลายทางเป็นสำเนาล่าสุดเพียงชุดเดียว หากไฟล์ถูกลบหรือถูกเข้ารหัสโดยมัลแวร์ก่อนรอบสำรอง ความเสียหายจะถูกคัดลอกไปด้วย หากต้องการเก็บย้อนหลังหลายวัน ให้ใช้ Snapshot บนเครื่องปลายทางหรือบริการสำรองข้อมูลของเซิร์ฟเวอร์ (ดู การ Backup Server บน Cloud ของ TDC) ร่วมด้วย หรือใช้ตัวเลือก --link-dest ของ rsync สร้างโฟลเดอร์แยกตามวันที่ ซึ่งไฟล์ที่ไม่เปลี่ยนจะเป็น Hard Link ไม่เปลืองพื้นที่เพิ่ม

ตรวจสอบผลลัพธ์

  • ดู Log หลังเวลาที่ตั้งไว้: sudo tail -n 20 /var/log/backup-web.log ต้องเห็นบรรทัด start และ done
  • บนเครื่องปลายทาง ตรวจขนาดและเวลาไฟล์: du -sh /srv/backup/web01/* และ ls -la /srv/backup/web01/www
  • ทดสอบกู้คืนจริง อย่างน้อยเป็นระยะ เช่น ดึงไฟล์กลับมาไว้ในโฟลเดอร์ชั่วคราวแล้วเปิดดู
sudo rsync -a -e "ssh -i /root/.ssh/backup_ed25519" \
  [email protected]:/srv/backup/web01/www/ /tmp/restore-test/

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

Host key verification failed

root บนเครื่องต้นทางยังไม่เคยยืนยัน Host Key ของเครื่องปลายทาง ให้รันคำสั่งทดสอบในขั้นตอนที่ 2 ด้วย sudo หนึ่งครั้งแล้วตอบ yes หากเครื่องปลายทางเพิ่งติดตั้งใหม่ ให้ลบ Key เก่าด้วย sudo ssh-keygen -R 203.0.113.20 ก่อน

Permission denied (publickey)

Public Key ไม่อยู่ใน authorized_keys ของผู้ใช้ที่ถูกต้อง หรือสิทธิ์ไฟล์กว้างเกินไป ตรวจว่า .ssh เป็น 700 และ authorized_keys เป็น 600 และเป็นเจ้าของโดยผู้ใช้ backup

รันด้วยมือได้ แต่ใน Cron ไม่ทำงาน

Cron มี PATH น้อยกว่า Shell ปกติ ให้ใช้ Path เต็มของโปรแกรมและสคริปต์ทุกตัว และตรวจ Log ของ Cron ด้วย grep CRON /var/log/syslog บน Ubuntu หรือ sudo journalctl -u crond บน AlmaLinux และ Rocky Linux

rsync: command not found หรือ connection unexpectedly closed

เครื่องปลายทางยังไม่ได้ติดตั้ง rsync ต้องติดตั้งทั้งสองฝั่ง

หากทำตามขั้นตอนแล้วยังติดปัญหา สามารถติดต่อทีมงาน Support ของ THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/ โดยแจ้งชื่อเซิร์ฟเวอร์ ระบบปฏิบัติการ ขั้นตอนที่ทำไปแล้ว และข้อความ Error ที่พบ เพื่อให้ตรวจสอบได้รวดเร็วขึ้น

ผู้ให้บริการคลาวด์ไทย
เพื่อธุรกิจของคนไทย

"มุ่งมั่น" และ "มั่นคง"
พร้อมรับมือทุกการเติบโต
Trust Cloud
คลาว์ที่ปลอดภัย
คือรากฐานที่มั่นคง
cloud security