PVE প্রক্সমক্স বাংলা ডকুমেন্টেশন

বাস্তব কেস স্টাডি — দুই সার্ভারে VPS ব্যবসা#

এটি কোনো "কীভাবে করা উচিত" গাইড নয়। এটি একজন প্রকৌশলী আসলে যা করেছেন তার বিবরণ — ভুল কমান্ড, হারানো কনফিগ, মাঝরাতের বাগ এবং সেগুলোর সমাধান। সব কিছু দুইটি ফিজিক্যাল সার্ভারে, এক দিনে।

সার্ভার দুইটি#

নোড ১ — pveনোড ২ — SC305-S14
IP185.xxx.xxx.83185.xxx.xxx.117
CPU২× Xeon Gold 6140 (৭২ vCPU)২× Xeon Gold 6140 (৭২ vCPU)
RAM২৫১ GB২৫১ GB
খালি ডিস্ক২× NVMe ৮৯৪ GB২× SATA SSD ৯৩১ GB
OS ডিস্কSamsung SSD ৪৬৫ GB (OS + পুরনো VM)Samsung SSD ৪৬৫ GB (শুধু OS)

০১ · প্রথম SSH — সামনে কী আছে#

প্রথম কাজ: লগইন করে চারপাশ দেখা।

BASH
ssh root@185.xxx.xxx.83
uname -a          # Linux pve 6.8.12-9-pve
pveversion        # pve-manager/9.1.11 — সর্বশেষ
uptime            # ৫ দিন চালু, লোড কম

lscpu | grep -E 'Model name|Socket|Core|Thread|CPU\(s\)'
free -h           # ২৫১ GB, ব্যবহার হচ্ছে ৮.২ GB
lsblk
# sda      465.8G → Samsung SSD (Proxmox OS + সব VM)
# nvme0n1  894G   → খালি
# nvme1n1  894G   → খালি

qm list           # ৪টি VM চালু — সবগুলো ওই একটি SSD-তে

সমস্যা: ৮৯৪ GB-এর দুইটি NVMe একদম অব্যবহৃত। সব VM একটি ডিস্কে, কোনো রিডান্ডেন্সি নেই। ওই SSD মরলে সব শেষ। প্রথমেই এটি ঠিক করতে হবে।


০২ · স্টোরেজ — NVMe-তে ZFS মিরর#

প্রত্যাশা ছিল: RAID 10 আগে থেকেই সেট করা আছে। বাস্তবতা: ইনস্টলারের সময় শুধু একটি ডিস্ক দেখা গিয়েছিল, তাই এটি নীরবে single-disk LVM বানিয়ে ফেলেছিল। প্রক্সমক্সের ZFS RAID 10-এর জন্য কমপক্ষে ৪টি ডিস্ক লাগে। NVMe দুইটি MegaRAID কন্ট্রোলারের পেছনে আলাদা কাঁচা ডিভাইস হিসেবে পড়ে ছিল।

সমাধান: দুই NVMe দিয়ে ZFS মিরর (RAID 1)। ৮৯৪ GB ব্যবহারযোগ্য, যেকোনো একটি ডিস্ক মরলেও VM চলতে থাকবে।

BASH
lsblk /dev/nvme0n1 /dev/nvme1n1     # দুইটিই খালি কি না নিশ্চিত হন

zpool create -f \
  -o ashift=12 \
  -O compression=lz4 \
  -O atime=off \
  vm-storage mirror /dev/nvme0n1 /dev/nvme1n1

zpool status vm-storage             # ONLINE, errors: No known data errors

pvesm add zfspool nvme-mirror \
  --pool vm-storage \
  --content images,rootdir \
  --sparse 1

pvesm status                        # nvme-mirror  zfspool  active  902 GB

locale সংক্রান্ত একটি perl সতর্কবার্তা এসেছিল। এটি এরর নয়, তবু স্থায়ীভাবে ঠিক করা হয়:

BASH
echo 'LC_ALL=en_US.UTF-8' >> /etc/environment
locale-gen en_US.UTF-8

মনে রাখার বিষয়: ZFS পুলের নাম vm-storage, কিন্তু প্রক্সমক্স স্টোরেজ ID nvme-mirror। পরে রেপ্লিকেশনের সময় এই পার্থক্যটি অনেক বড় হয়ে দাঁড়ায়।


০৩ · চালু অবস্থায় VM ডিস্ক সরানো#

প্রক্সমক্স চালু VM-এর ডিস্ক এক স্টোরেজ থেকে আরেকটিতে সরাতে পারে। ৩২ GB সরাতে ২৫ সেকেন্ডের কম লেগেছে, VM কিছু টেরই পায়নি।

BASH
qm move_disk 100 scsi0 nvme-mirror --delete 1   # ৩২ GB — ২৩ সেকেন্ড
qm move_disk 101 scsi0 nvme-mirror --delete 1   # ৩২ GB — ১৮ সেকেন্ড
qm move_disk 102 scsi0 nvme-mirror --delete 1
qm move_disk 103 scsi0 nvme-mirror --delete 1   # ১০০ GB — ১ মিনিট ৪ সেকেন্ড
# কিন্তু: lvremove 'pve/vm-103-disk-1' error: LV is used by another device

বাগ: পুরনো device mapper এন্ট্রি#

আগের এক কাজে VM 103-এর ডিস্ক kpartx দিয়ে হাতে মাউন্ট করা হয়েছিল, পরে পরিষ্কার করা হয়নি। কার্নেল তখনো ওই ম্যাপিং ধরে ছিল।

BASH
dmsetup ls | grep 103
# pve-vm--103--disk--1    (252:10)  ← মূল LVM ভলিউম
# pve-vm--103--disk--1p3  (252:14)  ← kpartx-এর পার্টিশন ম্যাপিং

vgchange -an ubuntu-vg
dmsetup remove pve-vm--103--disk--1p3    # আগে সন্তান
dmsetup remove pve-vm--103--disk--1      # পরে মা
lvremove -f /dev/pve/vm-103-disk-1

শিক্ষা: ভেতরের পার্টিশন ম্যাপিং আগে মুছুন, তারপর মূল ভলিউম। ক্রম গুরুত্বপূর্ণ।

ZFS thin provisioning-এর কারণে ১৯৬ GB বরাদ্দ ডিস্ক আসলে মাত্র ৬.৭ GB দেখাচ্ছিল — ZFS শুধু সত্যিই লেখা ডাটা গোনে।


০৪ · নোড ২ — NVMe নয়, SATA SSD#

নোড ২-এর কথা ছিল নোড ১-এর মতোই হবে। প্রায় মিলেছে।

BASH
ssh root@185.xxx.xxx.117
pveversion       # একই প্রক্সমক্স সংস্করণ
lscpu            # ৭২ vCPU — একই
free -h          # ২৫১ GB — একই
lsblk
# sdb 931.5G → খালি   (NVMe নয়, SATA SSD)
# sdc 931.5G → খালি

zpool create -f vm-storage mirror sdb sdc
zpool status vm-storage

এখানেই একটি ছোট পার্থক্য চোখে পড়েছিল: নোড ২-এ QEMU ১০.১.২, নোড ১-এ QEMU ১১.x। তখন গুরুত্ব দেওয়া হয়নি। পরে লাইভ মাইগ্রেশনে এটি বড় সমস্যা হয়ে দাঁড়ায় (অধ্যায় ০৮)।


০৫ · সবচেয়ে বড় ভুল — ভুল নোডে ক্লাস্টার তৈরি#

পরিকল্পনা ছিল: নোড ১-এ (যেখানে সব VM) ক্লাস্টার বানিয়ে নোড ২-কে যোগ করা। কিন্তু কমান্ডটি চলে গেল নোড ২-এর টার্মিনালে।

BASH
# নোড ২-এ — ভুল নোড
pvecm create xcloud-cluster

যা ঘটল: নোড ২ খালি ছিল, তার ক্লাস্টার ডাটাবেসও খালি। নোড ১ যখন এই ক্লাস্টারে যোগ দিল, ক্লাস্টার ফাইল সিস্টেম (pmxcfs) নোড ১-এর ডাটাবেস মুছে নোড ২-এর খালি ডাটাবেস বসিয়ে দিল। ৭টি VM ও ১টি LXC-এর কনফিগ — সব উধাও।

BASH
qm stop 100 && qm stop 101 && qm stop 102 && qm stop 103
qm stop 104 && qm stop 105 && pct stop 200
pvecm add 185.xxx.xxx.117 --force
# backup old database to '/var/lib/pve-cluster/backup/config-1779344961.sql.gz'
# successfully added node 'pve' to cluster.
qm list      # খালি — সব কনফিগ নেই

উদ্ধার#

প্রক্সমক্স join করার আগে নিজে থেকেই পুরনো ডাটাবেস ব্যাকআপ করে রেখেছিল। ওই একটি লাইনই বাঁচিয়ে দিল।

BASH
zcat /var/lib/pve-cluster/backup/config-1779344961.sql.gz > /tmp/old-config.sql
sqlite3 /tmp/old_pve.db < /tmp/old-config.sql

এরপর একটি ছোট পাইথন স্ক্রিপ্ট পুরনো ডাটাবেস থেকে প্রতিটি .conf বের করে সঠিক জায়গায় লিখে দিল: VMID ২০০–২৯৯ হলে /etc/pve/nodes/pve/lxc/, অন্যথায় /etc/pve/nodes/pve/qemu-server/

PYTHON
import sqlite3
conn = sqlite3.connect('/tmp/old_pve.db')
cursor = conn.cursor()
cursor.execute("SELECT name, data FROM tree WHERE name LIKE '%.conf'")
for name, data in cursor.fetchall():
    vmid = int(name.replace('.conf', ''))
    if 200 <= vmid <= 299:
        path = f'/etc/pve/nodes/pve/lxc/{name}'
    else:
        path = f'/etc/pve/nodes/pve/qemu-server/{name}'
    with open(path, 'wb') as f:
        f.write(data)
    print(f'Restored: {path}')
conn.close()

৮টি কনফিগই ফিরে এল (9000, 100–105, 200)। VM-গুলো ঠিকঠাক চালু হলো — কারণ আসল ডিস্ক ডাটা ZFS-এ ছিল, ক্লাস্টার ডাটাবেসে নয়। শুধু কনফিগ ফাইল গিয়েছিল, VM নয়।

স্টোরেজ কনফিগও মুছে গিয়েছিল (নোড ২-এ শুধু locallocal-lvm ছিল), তাই আবার যোগ করতে হলো:

BASH
pvesm add zfspool nvme-mirror --pool vm-storage --content rootdir,images

দুইটি শিক্ষা

  1. যেখানে VM আছে, সেই নোডেই ক্লাস্টার তৈরি করুন। খালি নোড যোগ করুন।

উল্টো করলে খালি ডাটাবেস জিতে যায়।

  1. join-এর আগের ব্যাকআপ থাকে /var/lib/pve-cluster/backup/config-*.sql.gz-এ।

এটি একটি SQLite ডাটাবেস — সেখান থেকে আলাদা আলাদা VM কনফিগ ফেরানো যায়।


০৬ · quorum ঠিক করা — QDevice#

BASH
pvecm status
# Expected votes: 2
# Quorum: 2       ← সব নোড চালু থাকতে হবে

সমস্যা: ২ নোড আর quorum ২ মানে — যেকোনো একটি নোড বন্ধ হলে অন্যটিও quorum হারায় এবং সব VM থামিয়ে দেয়। এটি হাই অ্যাভেইলেবিলিটির ঠিক উল্টো।

সমাধান: QDevice — তৃতীয় একটি ভোটার, যে VM চালায় না, শুধু ভোট দেয়। PBS কন্টেইনার (CT 200, 185.xxx.xxx.115) এই কাজের জন্য উপযুক্ত ছিল।

BASH
apt install corosync-qdevice -y                                  # নোড ১
ssh root@185.xxx.xxx.117 "apt install corosync-qdevice -y"       # নোড ২
pct exec 200 -- apt install -y corosync-qnetd                    # কন্টেইনারে

# setup SSH ব্যবহার করে — কন্টেইনারে কী বসান
pct exec 200 -- mkdir -p /root/.ssh
cat /root/.ssh/id_rsa.pub | pct exec 200 -- tee -a /root/.ssh/authorized_keys
pct exec 200 -- chmod 600 /root/.ssh/authorized_keys

pvecm qdevice setup 185.xxx.xxx.115

pvecm status
# Expected votes: 3      ← আগে ছিল ২
# Quorum: 2              ← এখন ৩-এর মধ্যে ২ হলেই চলে
# Flags: Quorate Qdevice

ফলাফল:

  • নোড ১ মরলে → নোড ২ + QDevice = ২/৩ ভোট → quorum আছে
  • নোড ২ মরলে → নোড ১ + QDevice = ২/৩ ভোট → quorum আছে
  • QDevice মরলে → নোড ১ + নোড ২ = ২/৩ ভোট → quorum আছে

তিনটিই একসাথে মরলে তবেই quorum যায়। সেটাই উদ্দেশ্য।


০৭ · এই পর্যন্ত কী দাঁড়াল#

ক্লাস্টার হয়েছে, quorum স্থিতিশীল। কিন্তু নোড ১ এখন মরে গেলে কী হবে?

BASH
ha-manager status
# quorum OK
# (no services registered)    ← কোনো VM-এ HA চালু নেই

সৎ উত্তর: VM গুলো শুধু বন্ধ হয়ে যাবে। কেউ চালু করবে না। তার জন্য HA লাগে।

সুরক্ষার ছয় স্তর#

স্তরকী থেকে বাঁচায়ফল
১. ZFS মিররNVMe ডিস্ক নষ্টকোনো ডাউনটাইম নেই
২. স্ন্যাপশটখারাপ পরিবর্তন, ভাঙা আপগ্রেড৩০ সেকেন্ডে রোলব্যাক
৩. PBS ব্যাকআপVM মুছে যাওয়া, ransomwareকয়েক মিনিটে রিস্টোর
৪. ক্লাস্টার + QDeviceভিত্তিquorum, লাইভ মাইগ্রেশন, HA সম্ভব হয়
৫. HAনোড মরে যাওয়াঅন্য নোডে VM চালু (~৬০ সেকেন্ড)
৬. রেপ্লিকেশনHA-এর জন্য ডিস্ক দরকারপ্রতি ১৫ মিনিটে ডিস্ক সিঙ্ক

এই পর্যায়ে ১–৪ স্তর হয়েছিল। ৫ ও ৬ বাকি — এবং সেখানেই বাগগুলো অপেক্ষা করছিল।


০৮ · কঠিন অংশ — রেপ্লিকেশন, HA ও তিনটি বাগ#

বাগ ১: স্টোরেজ সীমিত করায় রেপ্লিকেশন ভেঙে গেল#

দুই নোডেই ZFS পুলের নাম vm-storage। বিভ্রান্তি থেকে nvme-mirror স্টোরেজটি শুধু নোড ১-এ সীমাবদ্ধ করা হলো:

BASH
pvesm set nvme-mirror --nodes pve      # ভুল
# pvesr রেপ্লিকেশন সাথে সাথে ভেঙে গেল

কারণ: pvesr চায় একই স্টোরেজ ID উৎস ও গন্তব্য — দুই নোডেই থাকুক।

BASH
pvesm set nvme-mirror --nodes ''
# নোড ২-এও একই ID-তে নিবন্ধন করুন (সেখানকার নিজস্ব vm-storage পুল দেখিয়ে)
pvesm add zfspool nvme-mirror --pool vm-storage --content rootdir,images

বাগ ২: PVE 9-এ pvesr-এর সিনট্যাক্স বদলেছে#

BASH
# ভুল — এই ফ্ল্যাগগুলো PVE 9-এ নেই
pvesr create-local-job 104-0 SC305-S14 --guest 104 --target_storages nvme-mirror=ssd-mirror
# Error: Unknown option: guest

# সঠিক — শুধু job ID আর টার্গেট নোড
pvesr create-local-job 104-0 SC305-S14 --schedule "*/15"
pvesr run --id 104-0

# নোড ২-এ যাচাই
zfs list -t all | grep 104
# vm-storage/vm-104-disk-0
# vm-storage/vm-104-disk-0@__replicate_104-0_...   ← ইনক্রিমেন্টাল সিঙ্কের স্ন্যাপশট

বাগ ৩: QEMU সংস্করণের অমিলে লাইভ মাইগ্রেশন ব্যর্থ#

BASH
ha-manager add vm:104 --state started
qm migrate 104 SC305-S14 --online
# [SC305-S14] Installed QEMU version '10.1.2' is too old to run machine type
# 'pc-q35-11.0+pve0', please upgrade

কারণ: VM তৈরির সময় প্রক্সমক্স হোস্টের সর্বোচ্চ machine type দেয়। নোড ১-এ QEMU ১১.x ছিল, তাই VM 104 পেয়েছিল pc-q35-11.0+pve0। নোড ২-এর QEMU ১০.১.২ সেটি চালাতে পারে না।

BASH
qm set 104 --machine pc-q35-10.1+pve0     # দুই নোডেই চলে এমন সংস্করণ
qm reboot 104
qm migrate 104 SC305-S14 --online         # সফল
qm migrate 104 pve --online               # ফেরতও সফল

শিক্ষা: ক্লাস্টারের সব নোডে একই QEMU সংস্করণ রাখুন, নয়তো machine type সবচেয়ে পুরনো নোডের সাথে মিলিয়ে দিন। টেমপ্লেটে --machine pc-q35-10.1+pve0 বসিয়ে দিলে ভবিষ্যতের সব ক্লোন এমনিতেই সামঞ্জস্যপূর্ণ হবে।

IPMI fencing ছাড়া HA#

corosync বন্ধ করে নোড ১-এর ব্যর্থতা নকল করা হলো। watchdog কাজ করল — নোড ১ রিবুট হলো। নোড ২ + QDevice quorum ধরে রাখল। কিন্তু নোড ২ VM 104 চালু করল না — অপেক্ষা করল।

কারণ: হার্ডওয়্যার fencing (IPMI/iDRAC) ছাড়া নোড ২ নিশ্চিত হতে পারে না যে নোড ১ সত্যিই মরেছে — শুধু জানে corosync সাড়া দিচ্ছে না। দুই জায়গায় একই VM চালু হয়ে গেলে (split-brain) ডাটা নষ্ট হবে, তাই সে ঝুঁকি নেয় না।

সফটওয়্যার fencing (watchdog) split-brain ঠেকায়, কিন্তু নিজে থেকে VM ফিরিয়ে আনে না। সত্যিকারের অটো-ফেইলওভারের জন্য IPMI fencing লাগে, যাতে বেঁচে থাকা নোড মরা নোডের বিদ্যুৎ কেটে নিশ্চিত হতে পারে।


০৯ · ব্যাকআপ — LXC-তে PBS, আর curl নেই#

PBS বসল CT 200-এ (Debian 12 কন্টেইনার, 185.xxx.xxx.115)। ন্যূনতম Debian টেমপ্লেটে curl থাকে না, অথচ PBS ইনস্টলে সেটি লাগে।

BASH
pct enter 200
curl -o ... https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg
# bash: curl: command not found

apt update && apt install -y curl        # আগে এটি
curl -o /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg \
  https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg
echo "deb http://download.proxmox.com/debian/pbs bookworm pbs-no-subscription" \
  > /etc/apt/sources.list.d/pbs.list
apt update && apt install -y proxmox-backup-server

retention ফ্ল্যাগ বদলে গেছে#

BASH
# ভুল — PBS 3.x-এ --datastore ফ্ল্যাগ নেই
proxmox-backup-manager datastore set vps-backups --keep-daily 7

# সঠিক — prune-job ব্যবহার করুন
proxmox-backup-manager prune-job create nightly \
  --store vps-backups \
  --keep-daily 7 --keep-weekly 4 --keep-monthly 3 \
  --schedule daily

প্রক্সমক্সে PBS যুক্ত করা#

BASH
proxmox-backup-manager cert info | grep Fingerprint   # fingerprint লাগবে
exit

pvesm add pbs pbs-backups \
  --server 185.xxx.xxx.115 \
  --datastore vps-backups \
  --username root@pam \
  --password ******** \
  --fingerprint 6f:a7:04:21:...

vzdump 100 --storage pbs-backups --mode snapshot
# INFO: 100% (32.0 GiB) in 25s (1.3 GiB/s)
# INFO: backup is sparse: 87% total zero data

৮৭% ফাঁকা — প্রক্সমক্স শূন্য ব্লক বাদ দেয়। ৩২ GB ডিস্ক আসলে ~৪ GB ডাটা হিসেবে গেল।

BASH
pvesh create /cluster/backup \
  --id nightly-backup \
  --storage pbs-backups \
  --schedule "02:00" \
  --mode snapshot \
  --vmid 100,101,102,103 \
  --compress zstd

১০ · টেমপ্লেট বানানো — cloud image থেকে ক্লোনযোগ্য VM#

৩ মিনিটে কাস্টমার VM দিতে হলে আগে টেমপ্লেট লাগে।

BASH
cd /var/lib/vz/template/iso/
wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img   # ৬৯ MB

qm create 9000 \
  --name ubuntu-24-template \
  --memory 2048 --cores 2 \
  --net0 virtio,bridge=vmbr0,firewall=1 \
  --scsihw virtio-scsi-single \
  --agent enabled=1 \
  --machine q35 --bios ovmf --ostype l26 --onboot 0

qm set 9000 --efidisk0 nvme-mirror:0,efitype=4m,pre-enrolled-keys=0

qm set 9000 --scsi0 nvme-mirror:0,\
import-from=/var/lib/vz/template/iso/noble-server-cloudimg-amd64.img,\
discard=on,iothread=1,cache=none
# ৬৯ MB কম্প্রেসড ইমেজ খুলে ৩.৫ GB হয়

qm disk resize 9000 scsi0 32G          # cloud-init প্রথম বুটে ফাইল সিস্টেম বড় করবে
qm set 9000 --ide0 nvme-mirror:cloudinit
qm set 9000 --boot order=scsi0
qm set 9000 --ciuser ubuntu
qm set 9000 --nameserver "8.8.8.8 1.1.1.1"

qm template 9000                       # এখন আর চালু করা যাবে না, শুধু ক্লোন

প্রথম ক্লোন ও SSH সমস্যা#

BASH
qm clone 9000 104 --name customer-1 --full 1 --storage nvme-mirror
qm set 104 --memory 2048 --cores 2
qm set 104 --ipconfig0 ip=185.xxx.xxx.112/24,gw=185.xxx.xxx.1
qm set 104 --cipassword "**********"
qm start 104

ssh ubuntu@185.xxx.xxx.112
# Permission denied (publickey)

কারণ: Ubuntu 24.04 cloud image-এ /etc/ssh/sshd_config.d/60-cloudimg-settings.conf ফাইলে PasswordAuthentication no থাকে। cloud-init পাসওয়ার্ড বসায়, কিন্তু SSH সেটি মানে না।

তাৎক্ষণিক সমাধান — SSH কী ঢোকানো:

BASH
cat ~/.ssh/id_ed25519.pub | ssh root@185.xxx.xxx.83 \
  "cat > /tmp/customer_key.pub && \
   qm set 104 --sshkeys /tmp/customer_key.pub && \
   qm cloudinit update 104 && \
   qm reset 104"

ssh-keygen -R 185.xxx.xxx.112    # রিসেটের পর হোস্ট কী বদলায়
ssh ubuntu@185.xxx.xxx.112       # সফল

স্থায়ী সমাধান (টেমপ্লেটের ডিস্কেই ঠিক করা) আছে অধ্যায় ১৬-তে।


১১ · স্ন্যাপশট — ঝুঁকিপূর্ণ কাজের আগে ৩০ সেকেন্ডের বীমা#

ZFS-এ স্ন্যাপশট প্রায় তাৎক্ষণিক ও প্রায় বিনামূল্যে। ইচ্ছা করে VM নষ্ট করে পরীক্ষা করা হলো — পুরো পুনরুদ্ধারে ৩০ সেকেন্ডের কম লেগেছে।

BASH
qm snapshot 104 clean-install --description "Fresh Ubuntu 24.04, guest agent installed"
qm listsnapshot 104

# ইচ্ছা করে ভাঙা
ssh ubuntu@185.xxx.xxx.112
sudo rm -rf /etc/ssh/sshd_config
echo "I broke this VM on purpose" | sudo tee /BROKEN
exit

qm stop 104 && qm rollback 104 clean-install && qm start 104

ssh ubuntu@185.xxx.xxx.112
ls /etc/ssh/sshd_config    # ফিরে এসেছে
ls /BROKEN                 # নেই

qm delsnapshot 104 clean-install

স্ন্যাপশট বনাম ব্যাকআপ: স্ন্যাপশট দ্রুত ও সস্তা, কিন্তু একই ডিস্কে থাকে — ঝুঁকিপূর্ণ পরিবর্তনের আগে ব্যবহার করুন। PBS ব্যাকআপ আসল দুর্যোগের জন্য: হার্ডওয়্যার নষ্ট, ভুলে VM মুছে ফেলা, ডাটাসেন্টারে আগুন। মরা ডিস্কের স্ন্যাপশট কোনো কাজে আসে না। দুইটাই দরকার।


১২ · ফায়ারওয়াল ফাঁদ — রুল ডিফল্টে নিষ্ক্রিয়#

BASH
qm config 104 | grep net0      # firewall=1 আছে

pvesh create /nodes/pve/qemu/104/firewall/rules \
  --action ACCEPT --type in --proto tcp --dport 22 --comment "SSH"
# (৮০ ও ৪৪৩ পোর্টেও একই)
pvesh set /nodes/pve/qemu/104/firewall/options --enable 1

# ssh: connect to host 185.xxx.xxx.112 port 22: Connection refused

কারণ: pvesh create দিয়ে বানানো রুলে enable ডিফল্টে ০ থাকে। ফায়ারওয়াল চালু, রুলগুলো আছে, কিন্তু প্রতিটি রুল আলাদাভাবে নিষ্ক্রিয় — তাই সব কিছু ব্লক, SSH সহ।

BASH
pvesh get /nodes/pve/qemu/104/firewall/rules
# action: ACCEPT  pos: 0  enable: 0   ← নিষ্ক্রিয়

pvesh set /nodes/pve/qemu/104/firewall/rules/0 --enable 1
pvesh set /nodes/pve/qemu/104/firewall/rules/1 --enable 1
pvesh set /nodes/pve/qemu/104/firewall/rules/2 --enable 1

নিয়ম: রুল বানানোর সময়ই --enable 1 দিন।

BASH
pvesh create /nodes/pve/qemu/$VMID/firewall/rules \
  --action ACCEPT --type in --proto tcp --dport 22 --comment "SSH" --enable 1

১৩ · প্রথম আসল কাস্টমার VM — প্রায় ৩ মিনিট#

টেমপ্লেট কাজ করার পর প্রতিটি VM মানে ছয়টি কমান্ড।

BASH
# ১. পরবর্তী খালি VMID
pvesh get /cluster/nextid            # 105

# ২. টেমপ্লেট ক্লোন
qm clone 9000 105 --name customer-2 --full 1 --storage nvme-mirror

# ৩. IP, রিসোর্স, পাসওয়ার্ড
qm set 105 --ipconfig0 ip=185.xxx.xxx.113/24,gw=185.xxx.xxx.1
qm set 105 --memory 2048 --cores 2
qm set 105 --cipassword "**********"

# ৪. ফায়ারওয়াল (--enable 1 ভুলবেন না)
pvesh create /nodes/pve/qemu/105/firewall/rules --action ACCEPT --type in --proto tcp --dport 22  --comment "SSH"   --enable 1
pvesh create /nodes/pve/qemu/105/firewall/rules --action ACCEPT --type in --proto tcp --dport 80  --comment "HTTP"  --enable 1
pvesh create /nodes/pve/qemu/105/firewall/rules --action ACCEPT --type in --proto tcp --dport 443 --comment "HTTPS" --enable 1
pvesh set /nodes/pve/qemu/105/firewall/options --enable 1

# ৫. চালু
qm start 105

# ৬. যাচাই
ssh ubuntu@185.xxx.xxx.113

cloud-init নিজেই হোস্টনেম, IP ও SSH কী বসিয়ে দেয়। হোস্টনেম আসে --name থেকে, আর প্রথম বুটে ফাইল সিস্টেম ডিস্কের পুরো আকারে ছড়িয়ে যায়। VM-এর ভেতরে হাতে কিছু করতে হয় না।


১৪ · ওয়েব UI থেকে তিনটি আবিষ্কার#

CLI-তে বানানো সব কিছু ওয়েব UI-তে (https://185.xxx.xxx.83:8006) দেখতে গিয়ে তিনটি বিষয় ধরা পড়ল।

১. ডুপ্লিকেট SSH রুল — VM 104-এর ফায়ারওয়াল ট্যাবে তিনটির বদলে চারটি রুল। পজিশন ৩-এ আগের পরীক্ষার সময়ের বাড়তি SSH রুল।

BASH
pvesh delete /nodes/pve/qemu/104/firewall/rules/3

২. Cloud-Init ট্যাব সরাসরি এডিট করা যায় — CLI দিয়ে বসানো সব (IP, ইউজার, পাসওয়ার্ড, DNS) ব্রাউজারেই বদলানো যায়। কাস্টমারের IP বদলাতে: IP এডিট → Regenerate Image → VM রিবুট।

৩. Console ট্যাব জরুরি প্রবেশপথ — হাইপারভাইজারের মাধ্যমে সরাসরি VM-এর টার্মিনাল। SSH ভাঙা থাকলে, ফায়ারওয়াল ২২ পোর্ট আটকে থাকলে বা VM-এর IP না থাকলেও কাজ করে। এই কনসোল দুইবার বাঁচিয়েছে — একবার ফায়ারওয়ালে নিজেকে আটকে ফেলার পর, আরেকবার cloud-init-এর IP সংঘাতে VM অচেনা হয়ে যাওয়ার পর।


১৫ · প্রভিশনিং অটোমেশন — আর ভুল IP-এর বাগ#

একটি bash স্ক্রিপ্ট লেখা হলো। সাথে সাথেই তিনটি সমস্যা।

BASH
#!/bin/bash
set -e
NAME=$1
RAM=${2:-2048}
IP=$3
PASSWORD=$(openssl rand -base64 12)
VMID=$(pvesh get /cluster/nextid)
TEMPLATE=9000
STORAGE="nvme-mirror"

echo "==> Provisioning VM: $NAME (ID: $VMID)"
qm clone $TEMPLATE $VMID --name "$NAME" --full --storage $STORAGE
qm set $VMID --memory $RAM --cores 2
qm set $VMID --ipconfig0 "ip=$IP/24,gw=185.xxx.xxx.1"
qm set $VMID --nameserver "8.8.8.8 1.1.1.1"
qm set $VMID --cipassword "$PASSWORD"
qm start $VMID
echo "==> VM $VMID ($NAME) ready."

বাগ ১: ZFS-এ linked clone হয় না#

BASH
qm clone $TEMPLATE $VMID --name "$NAME" --storage $STORAGE
# Error: parameter 'storage' not allowed for linked clones

linked clone শুধু LVM-thin ও Ceph-এ চলে। ZFS-এ প্রতিটি ক্লোন সবসময় full clone। স্ক্রিপ্টে --full রাখতেই হবে। তবু দ্রুত হয়, কারণ আসলে লেখা ডাটা (~১–২ GB) কপি হয়।

বাগ ২: ভুল IP — VM নীরবে অচেনা#

BASH
ping 185.xxx.xxx.120        # Request timeout
qm guest exec 106 -- ip addr show eth0         # IP ঠিকই বসেছে
qm guest exec 106 -- ping -c 3 185.xxx.xxx.1   # গেটওয়েও পাচ্ছে না

কারণ: হোস্টিং প্রোভাইডার প্রতিটি ফিজিক্যাল সার্ভারে ARP ফিল্টারিং করে। প্রতিটি সার্ভারের জন্য নির্দিষ্ট IP বরাদ্দ। অন্য সার্ভারের IP ব্যবহার করলে সুইচ নীরবে সব প্যাকেট ফেলে দেয় — VM কিছুই টের পায় না।

CODE
নোড ১-এর পুল: .99 .108 .109 .111 .112 .113 .114 .115 .116
নোড ২-এর পুল: .120 .121 .122 .123 .124 .125 .127 .128 .129

নোড ১-এর VM-এ নোড ২-এর .120 বসানো হয়েছিল।

BASH
qm set 106 --ipconfig0 "ip=185.xxx.xxx.108/24,gw=185.xxx.xxx.1"
qm guest exec 106 -- cloud-init clean       # নতুন IP নিতে বাধ্য করা
qm reboot 106
ping 185.xxx.xxx.108                        # সফল

শিক্ষা: কোন IP কোন ফিজিক্যাল নোডের, সেটি লিখে রাখুন। ভুল রেঞ্জ ব্যবহার করলে কোনো এরর মেসেজ আসে না, কোনো লগ থাকে না — শুধু নীরবতা।


১৬ · টেমপ্লেট উন্নতি — গেস্ট এজেন্ট ও SSH#

প্রতিটি রেপ্লিকেশন ও ব্যাকআপে একই সতর্কবার্তা আসছিল:

CODE
skipping guest filesystem freeze - agent configured but not running?

qemu-guest-agent ছাড়া প্রক্সমক্স স্ন্যাপশটের আগে ফাইল সিস্টেম থামাতে পারে না — ফলে স্ন্যাপশট অসম্পূর্ণ হতে পারে।

BASH
qm set 9000 --template 0                     # টেমপ্লেট আবার সাধারণ VM
qm set 9000 --serial0 socket --vga serial0   # জরুরি সিরিয়াল কনসোল

apt install -y libguestfs-tools
qm config 9000 | grep disk
# scsi0: nvme-mirror:base-9000-disk-1,size=32G     ← টেমপ্লেটে "base-" উপসর্গ

# VM চালু না করেই ডিস্কের ভেতরে সফটওয়্যার বসানো
virt-customize -a /dev/zvol/vm-storage/base-9000-disk-1 \
  --install qemu-guest-agent \
  --run-command 'systemctl enable qemu-guest-agent'

# একই সুযোগে SSH পাসওয়ার্ড লগইন চালু
virt-customize -a /dev/zvol/vm-storage/base-9000-disk-1 \
  --run-command "sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/' \
  /etc/ssh/sshd_config.d/60-cloudimg-settings.conf"

qm set 9000 --machine pc-q35-10.1+pve0       # দুই নোডেই চলবে
qm template 9000

virt-customize টেমপ্লেট ডিস্ক বদলানোর সঠিক উপায় — VM চালু করা, IP দেওয়া বা SSH করা লাগে না। ZFS-এ টেমপ্লেট ডিস্কের নামে base- উপসর্গ বসে, তাই আগে qm config 9000zfs list | grep 9000 দেখে নিন।


১৭ · পর্যবেক্ষণ — CT 201-এ Prometheus + Grafana#

BASH
pct create 201 local:vztmpl/debian-12-standard_12.12-1_amd64.tar.zst \
  --hostname monitoring \
  --memory 2048 --cores 2 \
  --rootfs nvme-mirror:20 \
  --net0 name=eth0,bridge=vmbr0,ip=185.xxx.xxx.113/24,gw=185.xxx.xxx.1 \
  --nameserver "8.8.8.8 1.1.1.1" \
  --unprivileged 1 --start 1

pct set 201 --features nesting=1      # ছাড়া systemd ঠিকমতো চলে না
pct reboot 201
pct exec 201 -- systemctl is-system-running    # running
BASH
pct exec 201 -- apt update && pct exec 201 -- apt install -y prometheus

# দুই নোডেই node_exporter
apt install -y prometheus-node-exporter
systemctl enable --now prometheus-node-exporter
ssh root@185.xxx.xxx.117 "apt install -y prometheus-node-exporter && \
  systemctl enable --now prometheus-node-exporter"

Grafana সরকারি রিপো থেকে নিন — Debian-এর রিপোতে পুরনো ৯.x সংস্করণ থাকে, সরকারি রিপোতে ১৩.x।

Prometheus-এর /etc/prometheus/prometheus.yml:

YAML
global:
  scrape_interval: 15s
scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets:
          - '185.xxx.xxx.113:9100'   # CT 201 নিজে
          - '185.xxx.xxx.83:9100'    # নোড ১
          - '185.xxx.xxx.117:9100'   # নোড ২
        labels:
          cluster: 'xcloud'
BASH
pct exec 201 -- systemctl reload prometheus
pct exec 201 -- curl -s http://localhost:9090/api/v1/targets | grep -o '"health":"[^"]*"'
# সবগুলো "up"

Grafana: http://185.xxx.xxx.113:3000 → ডাটা সোর্স Prometheus (http://localhost:9090) → ড্যাশবোর্ড ID 1860 (Node Exporter Full) ইমপোর্ট করুন। তিন হোস্টের CPU, মেমরি, ডিস্ক ও নেটওয়ার্ক লাইভ দেখা যাবে।

টিপ: Debian 12 LXC-তে systemd ঠিকমতো চালাতে --features nesting=1 লাগে। না দিলে Prometheus ও Grafana পরিষ্কারভাবে চালু হয় না।


শেষ অবস্থা#

অংশযা দাঁড়াল
ক্লাস্টারxcloud-cluster — ২ নোড + QDevice (৩ ভোট, quorum ২)
নোড ১185.xxx.xxx.83 — ZFS NVMe মিররে ৬টি VM, HA সুরক্ষিত
নোড ২185.xxx.xxx.117 — প্রতি ১৫ মিনিটে রেপ্লিকেটেড ডিস্ক পায়
স্টোরেজদুই নোডেই nvme-mirror (ZFS) — একই ID, আলাদা ফিজিক্যাল ডিস্ক
ব্যাকআপCT 200-এ PBS — রাত ২টায়, ৭ দিন / ৪ সপ্তাহ / ৩ মাস
মনিটরিংCT 201-এ Prometheus + Grafana — ১৫ সেকেন্ড scrape, ড্যাশবোর্ড 1860
টেমপ্লেটVM 9000 — Ubuntu 24.04, গেস্ট এজেন্ট, সিরিয়াল কনসোল, SSH পাসওয়ার্ড চালু, machine type 10.1
প্রভিশনিংক্লোন → কনফিগ → ফায়ারওয়াল → স্টার্ট — প্রতি VM ~৩ মিনিট

যা এখনো বাকি#

  • IPMI/iDRAC fencing — নোড মরলে সত্যিকারের স্বয়ংক্রিয় ফেইলওভারের জন্য
  • নোড ২-এর QEMU আপগ্রেড — তাহলে machine type সীমাবদ্ধ রাখতে হবে না
  • সব VM-এ HA ও রেপ্লিকেশন — এখন শুধু VM 104-এ
  • বিলিং ও কাস্টমার পোর্টাল — এখনো হাতে

সবচেয়ে দামি ১০টি শিক্ষা#

  1. যে নোডে VM আছে, সেখানেই ক্লাস্টার তৈরি করুন — খালি নোডকে যোগ করুন।
  2. ক্লাস্টার join-এর আগের ব্যাকআপ থাকে /var/lib/pve-cluster/backup/config-*.sql.gz-এ।
  3. দুই নোডের ক্লাস্টারে QDevice বাধ্যতামূলক, নয়তো এক নোড পড়লেই সব বন্ধ।
  4. ZFS রেপ্লিকেশনে দুই নোডে একই স্টোরেজ ID থাকতে হয় — --nodes দিয়ে সীমিত করবেন না।
  5. সব নোডে একই QEMU সংস্করণ রাখুন, নয়তো machine type সবচেয়ে পুরনোটির সাথে মেলান।
  6. IPMI fencing ছাড়া HA নিজে থেকে VM ফেরাবে না — এটি ইচ্ছাকৃত নিরাপত্তা।
  7. pvesh দিয়ে ফায়ারওয়াল রুল বানালে সবসময় --enable 1 দিন।
  8. Ubuntu 24.04 cloud image-এ পাসওয়ার্ড SSH বন্ধ — virt-customize দিয়ে টেমপ্লেটেই ঠিক করুন।
  9. কোন IP কোন ফিজিক্যাল নোডের তা লিখে রাখুন — ARP ফিল্টারিং কোনো এরর দেয় না, শুধু নীরবতা।
  10. Debian LXC-তে systemd সার্ভিসের জন্য --features nesting=1 দরকার।

আগের অংশ: ফেজ ৬ — আসল প্রক্সমক্স VE · সূচিপত্র