วิธีติดตั้ง Incus system container บน VPS อย่างละเอียด
เรียนรู้วิธีติดตั้ง Incus บน VPS เพื่อรัน system container ที่มี init และผู้ใช้แยกอิสระ ครอบคลุมการตั้งค่า storage pool ระบบเครือข่าย และวิธีแก้ปัญหาเมื่อเกิดข้อผิดพลาด
Incus system container คืออะไร
Incus system container บน VPS มอบสภาพแวดล้อมเสมือนเครื่องคอมพิวเตอร์ทั้งเครื่องที่มีระบบ init และบัญชีผู้ใช้เป็นของตนเอง ไม่ใช่เพียงแค่กระบวนการเดียวที่ผูกกับระบบไฟล์ Container จะทำการบูต รัน init เป็น PID 1 และตอบสนองต่อตัวจัดการบริการของระบบนั้นๆ ซึ่งในอิมเมจที่ใช้ systemd อย่าง Debian และ Ubuntu จะเป็น systemctl ส่วนใน Alpine ที่ใช้ OpenRC จะเป็น rc-service โดย container จะใช้ kernel ร่วมกับโฮสต์ จึงไม่ใช่ virtual machine แต่ทุกอย่างที่อยู่เหนือระดับ kernel จะทำงานเสมือนเป็นเครื่องแยกอิสระ
Incus เป็นโครงการ fork ของ LXD ที่ดูแลโดยชุมชนภายใต้โปรเจกต์ Linux Containers โดยมีคำสั่งสำหรับฝั่งไคลเอนต์คือ incus นอกจากนี้ Incus ยังสามารถรัน virtual machine จริงผ่าน QEMU ได้เมื่อคุณระบุแฟล็ก --vm อย่างไรก็ตาม system container คือเหตุผลหลักที่คนส่วนใหญ่ติดตั้ง Incus และเป็นสิ่งที่เนื้อหาในคู่มือนี้จะกล่าวถึงต่อไป
เหตุใดการเปรียบเทียบ Docker จึงทำให้ผู้คนเข้าใจผิด
Docker บรรจุเพียงหนึ่งกระบวนการ (process) ในขณะที่ Incus บรรจุหนึ่งระบบปฏิบัติการ เอกสารของ Incus ระบุความแตกต่างนี้ไว้อย่างชัดเจนว่า: "Application container (เช่นที่ Docker จัดหาให้) จะบรรจุเพียงกระบวนการหรือแอปพลิเคชันเดียว ในทางกลับกัน System container จะจำลองระบบปฏิบัติการเต็มรูปแบบคล้ายกับสิ่งที่คุณใช้งานบนโฮสต์หรือในเครื่องเสมือน (virtual machine)"
ความแตกต่างนี้เปลี่ยนวิธีการที่คุณใช้งานสิ่งเหล่านี้ในแต่ละวัน
- Docker image ไม่มีระบบ init ดังนั้น
systemctlภายในจึงทำงานล้มเหลว ในขณะที่ Incus container รันระบบ init ทำให้บริการและตัวตั้งเวลา (timer) ทำงานได้เช่นเดียวกับบนเซิร์ฟเวอร์ทั่วไป - Docker container ถูกออกแบบมาให้ทำลายและสร้างใหม่จาก Dockerfile ส่วน Incus container ถูกออกแบบมาให้คงอยู่ อัปเดตแพตช์ และทำ snapshot
- Docker image เป็นผลลัพธ์จากการ build ที่คุณต้อง push ไปยัง registry ส่วน Incus instance คือสถานะบนดิสก์ใน storage pool และคุณสามารถย้ายมันได้ด้วย
incus export - Docker แยกส่วนเฉพาะภาระงาน (workload) แต่ Incus แยกส่วนทั้งเครื่อง ดังนั้นหนึ่ง container จึงสามารถรองรับหลายภาระงานและหลายบัญชีผู้ใช้ได้
คุณสามารถรัน Docker ภายใน Incus system container ได้ แต่คุณไม่สามารถรัน Incus ภายใน Docker application container หากสิ่งที่คุณต้องการจริงๆ คือหนึ่งกระบวนการต่อหนึ่ง container พร้อมขั้นตอนการ build image Podman และ Docker บน VPS คือการเปรียบเทียบที่คุณควรอ่านเป็นอันดับแรก หากคุณต้องการ kernel แยกสำหรับแต่ละภาระงานแทนการใช้ kernel ร่วมกัน Firecracker microVMs บน VPS คือแนวทางในทิศทางตรงกันข้าม
Incus จะทำงานบน VPS ได้หรือไม่?
ขึ้นอยู่กับประเภทการทำ Virtualization ของ VPS และ Kernel ที่ใช้งาน ดังนั้นควรตรวจสอบทั้งสองส่วนก่อนเริ่มติดตั้ง อย่าเชื่อข้อมูลจากหน้าเว็บไซต์โฆษณาของผู้ให้บริการ ให้รันคำสั่ง 4 คำสั่งต่อไปนี้บนเซิร์ฟเวอร์
systemd-detect-virt
uname -r
stat -fc %T /sys/fs/cgroup
cat /sys/fs/cgroup/cgroup.controllerssystemd-detect-virt หากแสดงผลเป็น kvm หรือ qemu หมายความว่า VPS ของคุณเป็น Virtual Machine ที่มี Kernel เป็นของตัวเอง กรณีนี้จะจัดการได้ง่ายเพราะ Incus จะทำงานเหมือนกับบน Hardware จริง หากแสดงผลเป็น lxc, lxc-libvirt หรือ openvz หมายความว่า VPS ของคุณเป็น Container ที่แชร์ Kernel ร่วมกับผู้ให้บริการ การรัน Incus ภายในนั้นจะเป็นการทำ Nested Container ซึ่งจะทำงานได้ก็ต่อเมื่อผู้ให้บริการเปิดใช้งานฟีเจอร์นี้ไว้ให้คุณเท่านั้น คุณไม่สามารถเปิดใช้งานเองจากภายในได้เนื่องจากการตั้งค่านี้อยู่ที่ฝั่ง Host ซึ่งคุณไม่มีสิทธิ์ควบคุม
stat -fc %T /sys/fs/cgroup ควรแสดงผลเป็น cgroup2fs หากเป็นค่าอื่นแสดงว่าเซิร์ฟเวอร์ใช้ cgroup (control group) แบบ v1 หรือแบบผสม ซึ่ง Incus เวอร์ชันปัจจุบันไม่รองรับ
cat /sys/fs/cgroup/cgroup.controllers จะแสดงรายการ control-group controller ที่ถูกส่งต่อมาให้คุณ Incus ระบุในเอกสารว่าจำเป็นต้องใช้ blkio, cpuset, devices, freezer, memory และ pids สำหรับ VPS แบบ Nested รายการนี้มักจะสั้นกว่าบน KVM เนื่องจากผู้ให้บริการเป็นผู้กำหนดว่าจะส่งต่อส่วนใดมาให้บ้าง หาก controller ใดหายไปจากไฟล์นี้ Incus จะไม่สามารถใช้งาน controller นั้นได้ ส่งผลให้ขีดจำกัดของ Instance ที่ต้องพึ่งพา controller ดังกล่าวไม่สามารถใช้งานได้
เวอร์ชันของ Kernel มีความสำคัญมากกว่าในอดีต ณ เดือนตุลาคม 2026 ทางต้นน้ำดูแล LTS (long term support) อยู่ 2 ซีรีส์ คือ 6.0 และ 7.0 ควบคู่ไปกับรุ่น Feature release ปัจจุบัน ซึ่งทั้งสองรุ่นมีข้อกำหนดขั้นต่ำไม่เท่ากัน เอกสารของ 6.0 LTS ระบุว่า "เวอร์ชัน Kernel ขั้นต่ำที่รองรับคือ 5.4" ส่วนเอกสารปัจจุบันระบุว่า "เวอร์ชัน Kernel ขั้นต่ำที่รองรับคือ 6.12" และประกาศของ 7.0 LTS ในเดือนพฤษภาคม 2026 ได้ระบุ Linux 6.12 ไว้ในข้อกำหนดขั้นต่ำด้วย ประกาศเดียวกันนี้ยังปรับให้ 6.0 LTS เข้าสู่สถานะดูแลเฉพาะความปลอดภัยเท่านั้น Ubuntu 24.04 จัดเตรียมซีรีส์ 6.0 LTS ไว้ใน Repository ของตนเองและใช้งานคู่กับ Kernel 6.8 ซึ่งเป็นชุดที่รองรับ การติดตั้งรุ่น Stable หรือ 7.0 LTS จาก Repository ต้นน้ำลงบน Kernel 6.8 จะทำให้คุณมีเวอร์ชันต่ำกว่าเกณฑ์ขั้นต่ำที่ระบุไว้ ดังนั้นโปรดอ่าน uname -r ก่อนเลือก Repository
หากเป้าหมายของคุณคือการรัน Virtual Machine เต็มรูปแบบแทนที่จะเป็น Container ข้อจำกัดจะแตกต่างออกไปและทำได้ยากกว่า ดูข้อมูลเพิ่มเติมที่ การทำ nested virtualisation บน VPS เพื่อตรวจสอบว่า VPS ของคุณสามารถเปิดใช้งาน /dev/kvm ได้หรือไม่ และดู Proxmox กับ VPS ที่เช่ามา สำหรับกรณีที่คุณเป็นเจ้าของ Hardware เอง
การติดตั้ง Incus บน Ubuntu หรือ Debian
Debian 13 และ Ubuntu 24.04 ขึ้นไปมี Incus รวมอยู่ใน repository หลักของระบบแล้ว
sudo apt update
sudo apt install -y incusบน Debian คำสั่ง incus-base จะติดตั้งการรองรับ container โดยไม่รวมส่วนประกอบของ virtual machine สำหรับ Ubuntu ให้เพิ่ม qemu-system หากคุณต้องการใช้งาน instance แบบ --vm ด้วย
หากต้องการรุ่นที่ใหม่กว่าที่มาพร้อมกับ distribution ของคุณ แพ็กเกจจากผู้พัฒนาโดยตรงจะอยู่ที่ pkgs.zabbly.com repository ดังกล่าวมีช่องทาง lts-6.0, lts-7.0 และ stable ให้เลือกใช้ โดยคำสั่งด้านล่างนี้อ้างอิงมาจากไฟล์ README ของโปรเจกต์โดยตรงและใช้ stable ให้เปลี่ยนชื่อช่องทางในชื่อไฟล์และบรรทัด URIs: หาก kernel ของคุณต้องการใช้รุ่น LTS
sudo apt update && sudo apt install -y curl
sudo mkdir -p /etc/apt/keyrings/
sudo curl -fsSL https://pkgs.zabbly.com/key.asc -o /etc/apt/keyrings/zabbly.asc
sudo sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
Enabled: yes
Types: deb
URIs: https://pkgs.zabbly.com/incus/stable
Suites: $(. /etc/os-release && echo ${VERSION_CODENAME})
Components: main
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/zabbly.asc
EOF'
sudo apt-get update
sudo apt-get install -y incusจากนั้นให้สิทธิ์ผู้ใช้ของคุณในการเข้าถึง daemon socket
sudo usermod -aG incus-admin "$USER"
newgrp incus-admin
incus infoการใช้ incus info เพื่อแสดงการตั้งค่าของเซิร์ฟเวอร์หมายความว่า socket ทำงานได้ปกติ หากเกิดข้อผิดพลาดด้านสิทธิ์ แสดงว่าการเปลี่ยนแปลงกลุ่มผู้ใช้ยังไม่มีผลกับ shell ปัจจุบัน ซึ่ง newgrp incus-admin จะช่วยแก้ไขได้สำหรับ shell ปัจจุบัน และการล็อกอินใหม่จะช่วยแก้ไขได้อย่างสมบูรณ์ ให้ถือว่าการเป็นสมาชิกของ incus-admin มีสิทธิ์เทียบเท่า root บนโฮสต์ เนื่องจากการเข้าถึง socket ดังกล่าวคือการควบคุม daemon ที่รันด้วยสิทธิ์ root อย่างเต็มรูปแบบ บาง distribution อาจสร้างกลุ่ม incus แยกต่างหากสำหรับการเข้าถึงของผู้ใช้แบบจำกัดสิทธิ์
จากนั้นให้เริ่มต้นการทำงานของ daemon
sudo incus admin initให้ตอบคำถามตามขั้นตอนแทนการใช้ incus admin init --minimal เส้นทางที่ง่ายที่สุดคือการเลือก storage driver แบบ dir ซึ่งส่วนถัดไปจะอธิบายว่าเหตุใดตัวเลือกนี้จึงส่งผลต่อการใช้งานในระยะยาว
ทดสอบเปิดใช้งาน instance เพื่อยืนยันว่าทุกอย่างทำงานได้ปกติ
incus launch images:debian/13 web
incus list
incus exec web -- bashincus list ควรแสดงสถานะ web เป็น RUNNING พร้อมกับที่อยู่ IPv4 บน subnet incusbr0 หากไม่มีที่อยู่แสดงขึ้นมา หมายความว่า DHCP (dynamic host configuration protocol) ทำงานไม่สำเร็จ ซึ่งจะอธิบายไว้ในส่วนของระบบเครือข่าย หาก container ไม่สามารถเริ่มทำงานได้ ระบบจะแสดงสาเหตุไว้ใน incus info web --show-log และความผิดพลาดในระดับ daemon จะถูกบันทึกไว้ใน sudo journalctl -u incus -n 50 บน VPS ที่คำสั่ง systemd-detect-virt ส่งค่ากลับเป็น lxc หรือ openvz การทดสอบเปิดใช้งานนี้จะเป็นตัวชี้วัดที่ชัดเจนว่าระบบของคุณรองรับการทำ nesting หรือไม่
เหตุใด storage backend จึงมีความสำคัญ
Storage backend เป็นตัวกำหนดว่า snapshot จะทำงานได้ทันทีหรือต้องคัดลอกข้อมูลดิสก์ของ container ทั้งหมด นี่คือการตัดสินใจเพียงอย่างเดียวในขั้นตอนติดตั้งที่คุณไม่สามารถเปลี่ยนภายหลังได้โดยง่ายโดยไม่เสียค่าใช้จ่ายสูง
Incus รองรับ dir, btrfs, lvm, zfs, Ceph และไดรเวอร์ระยะไกลอื่นๆ อีกหลายตัว สำหรับ VPS ที่มีดิสก์ลูกเดียว ตัวเลือกที่แท้จริงคือระหว่าง dir และ btrfs
ไดรเวอร์ dir จะเก็บ container แต่ละตัวไว้เป็นไฟล์และไดเรกทอรีปกติภายใต้ /var/lib/incus ซึ่ง Incus ระบุไว้ในเอกสารว่าเป็นไดรเวอร์ที่ "ช้ากว่าไดรเวอร์อื่นๆ ทั้งหมดอย่างมาก" เนื่องจากต้องแตกไฟล์ image ทุกครั้งและทำการคัดลอกข้อมูลจริงแทนการอ้างอิงบล็อกที่ใช้ร่วมกัน การทำ snapshot ของ container ขนาด 4 GiB จะต้องเขียนข้อมูล 4 GiB และใช้เวลานานเท่ากับที่ cp -a ใช้ Disk quota จะทำงานได้เฉพาะบน ext4 หรือ XFS ที่เปิดใช้งาน project quotas ในระดับไฟล์ระบบเท่านั้น ซึ่งโดยปกติแล้วไม่ได้เปิดใช้งานมาให้ใน VPS image ส่วนใหญ่ ดังนั้นการจำกัดขนาดดิสก์บน pool แบบ dir จึงมักไม่มีผล
btrfs และ zfs เป็นแบบ copy-on-write ดังนั้น snapshot จะบันทึกเฉพาะบล็อกที่มีการเปลี่ยนแปลงหลังจากนั้น Incus แนะนำให้ใช้ backend สองตัวนี้เป็นหลัก ซึ่งจะทำให้การทำ snapshot ทำได้เกือบจะทันที และ disk quota จะทำงานผ่านการรองรับ quota ของตัวไฟล์ระบบเอง
VPS ส่วนใหญ่ให้ดิสก์มาหนึ่งลูกโดยไม่มี partition สำรอง ดังนั้นให้สร้าง pool ไว้บนไฟล์แบบ loop ซึ่ง Incus จะจัดการให้คุณหากคุณไม่ได้ระบุ source=
sudo apt install -y btrfs-progs
incus storage create fast btrfs size=30GiB
incus profile device set default root pool=fast
incus launch images:debian/13 web2 -s fastหากไม่มี size= pool ที่ใช้ loop จะกินพื้นที่ดิสก์ว่างไป 20% โดยมีขนาดขั้นต่ำที่ 5 GiB และสูงสุดที่ 30 GiB คุณควรตั้งค่าขนาดให้ชัดเจน Pool จะหยุดขยายเมื่อถึงขนาดที่กำหนดไว้ ดังนั้นมันจึงเต็มได้ในขณะที่โฮสต์ยังมีพื้นที่ว่างเหลืออยู่ และนั่นเป็นสาเหตุปกติที่ทำให้ pool แบบ loop เต็ม อย่างไรก็ตาม ตัวไฟล์ loop เองก็เป็นไฟล์หนึ่งบนไฟล์ระบบของโฮสต์ ดังนั้นควรคำนึงถึงความต้องการของโฮสต์เองในการกำหนดขนาด pool แทนที่จะยกพื้นที่ว่างทั้งหมดที่มีให้
ZFS บน Debian และ Ubuntu เป็นโมดูลแบบ DKMS ไม่ใช่โมดูลที่รวมอยู่ใน kernel โดยตรง ดังนั้นมันจะถูกสร้างใหม่ทุกครั้งที่มีการอัปเกรด kernel และอาจล้มเหลวในการ build ได้หลังจากอัปเกรด สำหรับเซิร์ฟเวอร์ที่คุณไม่ได้ตรวจสอบทุกวัน btrfs จะเป็นตัวเลือกที่ต้องการการดูแลรักษาน้อยกว่าเมื่อเทียบกับทั้งสองตัวนี้
โหมดเครือข่ายทั้งสามรูปแบบและสิ่งที่แต่ละโหมดเปิดเผยออกมา
เมื่อคุณยอมรับคำตอบที่แนะนำ incus admin init จะสร้าง managed bridge ที่ชื่อว่า incusbr0 และเชื่อมต่อเข้ากับโปรไฟล์ default เพื่อให้ทุกอินสแตนซ์ใหม่ที่ใช้โปรไฟล์นี้ถูกจัดให้อยู่บน bridge ดังกล่าว คุณสามารถกำหนดให้มันชี้ไปยัง bridge หรืออินเทอร์เฟซที่มีอยู่เดิมแทนได้ Managed bridge เป็นหนึ่งในสามวิธีในการเชื่อมต่อคอนเทนเนอร์ ส่วนอีกสองวิธีที่เหลือมีไว้เพื่อแก้ปัญหาที่วิธีแรกซ่อนคอนเทนเนอร์ของคุณไว้หลัง NAT (network address translation)
Managed bridge. incusbr0 จะได้รับ private subnet โดยโฮสต์จะถือครองแอดเดรสแรกและทำหน้าที่เป็นเกตเวย์ ส่วน Incus จะรัน DHCP และ DNS (domain name system) บนนั้น และทราฟฟิกขาออกจะถูกส่งผ่าน public address ของโฮสต์โดยมีการทำ source NAT กำกับไว้ ไม่มีสิ่งใดจากภายนอกเข้าถึงคอนเทนเนอร์ได้จนกว่าคุณจะอนุญาต โดยคุณสามารถทำ port forwarding ได้ด้วยอุปกรณ์ประเภท proxy
incus config device add web http proxy listen=tcp:0.0.0.0:8080 connect=tcp:127.0.0.1:80 nat=truenat=true จะทำการส่งต่อด้วยกฎของ netfilter แทนการทำ proxy ผ่านการเชื่อมต่อใน userspace แยกต่างหาก ดังนั้นแอดเดรสจริงของไคลเอนต์จึงยังคงปรากฏอยู่ใน log ของคอนเทนเนอร์ Incus รองรับโหมดนี้เฉพาะในกรณีที่โฮสต์เป็นเกตเวย์ของอินสแตนซ์เท่านั้น ซึ่งก็คือกรณีของ incusbr0
macvlan. คอนเทนเนอร์จะได้รับ MAC (media access control) address ของตัวเองบนเครือข่ายกายภาพของโฮสต์ บนแพลตฟอร์ม VPS ส่วนใหญ่วิธีนี้จะล้มเหลวเนื่องจากพอร์ตของ virtual switch ถูกผูกไว้กับ MAC address ของ VM ของคุณ ทำให้มันปฏิเสธเฟรมที่มาจาก MAC address อื่น นอกจากนี้ยังมีข้อจำกัดประการที่สองที่มักพบแม้ในกรณีที่ใช้งานได้ Incus ระบุไว้ว่า "อุปกรณ์ macvlan แม้จะสามารถสื่อสารระหว่างกันเองและกับภายนอกได้ แต่ไม่สามารถสื่อสารกับอุปกรณ์แม่ (parent device) ของมันเองได้ ซึ่งหมายความว่าคุณไม่สามารถใช้ macvlan ได้หากต้องการให้อินสแตนซ์สื่อสารกับตัวโฮสต์โดยตรง"
Routed. นี่คือโหมดที่มักจะใช้งานได้บน VPS ที่มีแอดเดรสเพิ่มเติม Incus ระบุว่าอุปกรณ์นี้ "สร้างคู่ของอุปกรณ์เสมือนเพื่อเชื่อมต่อโฮสต์เข้ากับอินสแตนซ์ และตั้งค่า static routes รวมถึงรายการ proxy ARP/NDP เพื่อให้อินสแตนซ์สามารถเข้าร่วมเครือข่ายของอินเทอร์เฟซแม่ที่กำหนดไว้ได้" ARP คือ address resolution protocol คอนเทนเนอร์จะยังคงใช้ public address โดยโฮสต์จะตอบกลับ ARP แทนให้ ดังนั้นผู้ให้บริการจึงยังคงเห็นเพียง MAC address ของโฮสต์เท่านั้น
incus config device add web eth0 nic nictype=routed parent=enp1s0 ipv4.address=203.0.113.20ให้ใช้ชื่ออินเทอร์เฟซแม่จาก ip route show default อิมเมจปัจจุบันมักใช้ชื่ออย่าง enp1s0 หรือ ens3 และพบน้อยมากที่จะเป็น eth0 การตั้งชื่ออุปกรณ์เป็น eth0 จะเป็นการแทนที่ค่าที่โปรไฟล์ default กำหนดไว้ ส่งผลให้อินสแตนซ์ไปอยู่บน routed interface แทนที่จะเป็น bridge ให้ตรวจสอบผลลัพธ์จากภายในด้วย ip a และ ip route
เหตุใดคอนเทนเนอร์จึงเข้าถึงบริการบนโฮสต์ได้
คอนเทนเนอร์บน incusbr0 มี network namespace เป็นของตนเอง แต่นั่นไม่ใช่ขอบเขตของไฟร์วอลล์ที่จะกั้นออกจากโฮสต์ กฎไฟร์วอลล์ที่ Incus bridge จัดการนั้นถูกเพิ่มเข้ามาตามที่ระบุไว้ในเอกสารประกอบว่า "เพื่อให้มั่นใจถึงการทำงานที่สมบูรณ์" ไม่ใช่เพื่อปิดกั้นโฮสต์ โฮสต์ตั้งอยู่บน bridge นั้นที่ที่อยู่ gateway ดังนั้นจากภายในคอนเทนเนอร์ โฮสต์จึงเป็นเพื่อนบ้านที่เข้าถึงได้โดยตรง และทุกบริการบนโฮสต์ที่ผูกไว้กับ 0.0.0.0 จะตอบสนองที่นั่น เว้นแต่จะมีกฎไฟร์วอลล์ของโฮสต์คอยดรอปแพ็กเก็ตเหล่านั้น
คุณสามารถตรวจสอบได้ด้วยตนเอง บนโฮสต์ ให้แสดงรายการสิ่งที่กำลังรอรับการเชื่อมต่ออยู่
sudo ss -tlnpจากนั้น จากภายในคอนเทนเนอร์ ให้ชี้ไปที่ gateway ที่ ip route รายงานไว้
ip route show default
nc -zv 10.0.0.1 6379หากฐานข้อมูล, metrics endpoint หรือแผงควบคุมของผู้ดูแลระบบบนโฮสต์ถูกผูกไว้กับ 0.0.0.0 และไม่มีกฎไฟร์วอลล์ของโฮสต์บล็อก bridge ไว้ การตรวจสอบนั้นจะสำเร็จ ไฟร์วอลล์เครือข่ายของผู้ให้บริการของคุณจะไม่เห็นแพ็กเก็ตนั้นเลย เพราะแพ็กเก็ตไม่เคยออกจากเครื่อง นี่คือสิ่งที่น่าประหลาดใจเบื้องหลังคำถามส่วนใหญ่ที่ว่า "มันเข้าถึงสิ่งนั้นได้อย่างไร": คอนเทนเนอร์ถูกแยกออกจากอินเทอร์เน็ตด้วย NAT และถูกแยกออกจากโฮสต์ด้วยสิ่งที่ไฟร์วอลล์ของโฮสต์คุณบังคับใช้เท่านั้น
ผูกบริการบนโฮสต์ไว้กับ 127.0.0.1 ทุกครั้งที่ทำได้ จากนั้นจึงกรอง bridge บนโฮสต์ สำหรับเครื่องที่ใช้ ufw นโยบาย default deny จะบล็อกการรับส่งข้อมูลจากคอนเทนเนอร์ไปยังโฮสต์อยู่แล้ว ซึ่งจะทำให้ Incus DNS และ DHCP ใช้งานไม่ได้ และวิธีแก้ไขที่เอกสารของ Incus แนะนำคือ sudo ufw allow in on incusbr0 คำสั่งเดียวนั้นจะเปิดพอร์ตทุกพอร์ตของโฮสต์ให้คอนเทนเนอร์ทุกตัวเข้าถึงได้ คุณควรอนุญาตเฉพาะสิ่งที่คอนเทนเนอร์จำเป็นต้องใช้จริงๆ เท่านั้น
sudo ufw allow in on incusbr0 to any port 53 proto udp
sudo ufw allow in on incusbr0 to any port 53 proto tcp
sudo ufw allow in on incusbr0 to any port 67 proto udp
sudo ufw route allow in on incusbr0
sudo ufw route allow out on incusbr0กฎ ufw route สองข้อนี้คือสิ่งที่อนุญาตให้ทราฟฟิกของอินสแตนซ์ผ่านโฮสต์ออกไปยังอินเทอร์เน็ตได้ หากไม่มีกฎเหล่านี้ นโยบายการ routing ของ ufw จะดรอปแพ็กเก็ตที่ส่งต่อ ทำให้คอนเทนเนอร์ได้รับที่อยู่แต่ไม่สามารถเข้าถึงสิ่งใดได้เลย
Snapshots และ profiles
Snapshot คือสำเนาของ instance ณ จุดเวลาใดเวลาหนึ่งที่เก็บไว้ภายใน storage pool ของคุณ
incus snapshot create web pre-upgrade
incus info web
incus snapshot restore web pre-upgrade
incus snapshot delete web pre-upgradeincus info web ใช้สำหรับแสดงรายการ snapshot ทั้งหมดที่ instance นั้นถือครองอยู่ คุณสามารถตั้งตารางเวลาการทำ snapshot แยกตามราย instance ได้
incus config set web snapshots.schedule=@daily
incus config set web snapshots.expiry=4wSnapshot จะถูกเก็บไว้ใน pool เดียวกัน บนดิสก์ลูกเดียวกัน และบนเซิร์ฟเวอร์เครื่องเดียวกัน มันช่วยป้องกันคุณจากความผิดพลาดในการอัปเกรด แต่ไม่สามารถป้องกันคุณจากกรณีดิสก์เสียหรือการลบ instance ทิ้งได้ การสำรองข้อมูลที่แท้จริงคือ incus export ซึ่งไฟล์ข้อมูลจะต้องถูกย้ายออกจากเครื่องเซิร์ฟเวอร์นั้น
incus export web /root/web-backup.tar.gz
incus import /root/web-backup.tar.gzProfile คือชุดของ config keys และอุปกรณ์ที่ถูกตั้งชื่อไว้เพื่อนำไปปรับใช้กับ instance ต่างๆ ทุก instance จะได้รับ profile ชื่อ default เว้นแต่คุณจะกำหนดเป็นอย่างอื่น และ profile ดังกล่าวคือสิ่งที่จัดเตรียม root disk และ network interface ให้กับ instance นั้น การแก้ไข default จะส่งผลกระทบต่อทุก instance ที่ใช้งาน profile นี้ ซึ่งเป็นประโยชน์และเป็นวิธีที่ใช้ในการปลดการเชื่อมต่อเครือข่ายออกจาก container จำนวน 20 ตัวพร้อมกัน
incus profile create small
incus profile set small limits.memory=512MiB
incus profile set small limits.cpu=1
incus launch images:debian/13 api -p default -p smallProfile จะถูกนำไปปรับใช้ตามลำดับ ดังนั้นค่า key ที่ถูกกำหนดไว้ใน profile ลำดับสุดท้ายจะเป็นค่าที่มีผลใช้งานจริง คุณสามารถตรวจสอบค่าคอนฟิกูเรชันที่ instance ใช้งานอยู่จริงได้โดยใช้ incus config show api --expanded
การรัน Docker ภายใน Incus container
การรัน Docker ภายใน Incus system container จำเป็นต้องเปิดใช้งาน nesting เนื่องจาก Docker จะสร้าง namespace และ mount ของตนเองขึ้นมา ซึ่งโดยปกติแล้ว container จะไม่ได้รับอนุญาตให้ทำเช่นนั้น
incus config set web security.nesting=true
incus restart webเอกสารของ Incus ระบุว่า security.nesting คือ "การอนุญาตให้ทำ nesting ภายใน instance" โดยค่าเริ่มต้นสำหรับ container คือ false นอกจากนี้ยังมีอีกสองประเด็นที่ระบุไว้ใน FAQ ของ Incus คือ container ไม่สามารถโหลด kernel module ได้ ดังนั้น module ที่ Docker จำเป็นต้องใช้จะต้องถูกโหลดที่ฝั่ง host และระบุไว้ใน incus config set web linux.kernel_modules overlay,br_netfilter และการสร้างไฟล์ /.dockerenv ภายใน container จะช่วยให้ Docker ข้ามการตรวจสอบบางอย่างที่มักจะล้มเหลวในสภาพแวดล้อมแบบ nested
บน host ที่ใช้ Ubuntu 24.04 ข้อจำกัดเรื่อง unprivileged user namespace ของ AppArmor อาจขัดขวางการทำงานของ pivot_root ที่ runc เรียกใช้ ซึ่งจะทำให้ Docker ภายใน container แสดงข้อความ:
failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error jailing process inside rootfs: pivot_root .: permission deniedและใน dmesg ของ host จะแสดงบรรทัดที่มีข้อความ apparmor="DENIED" operation="pivotroot" class="mount" การตั้งค่าที่ผู้คนมักเลือกใช้คือ kernel.apparmor_restrict_unprivileged_userns แต่การปิดใช้งานนั้นไม่ใช่การแก้ไขที่เชื่อถือได้ โดยรายงานบั๊กของ Incus ที่เกี่ยวข้องกับกรณีนี้ระบุว่าการตั้งค่าเป็น 0 ไม่สามารถแก้ไขปัญหาได้ โปรดอ่าน dmesg เพื่อตรวจสอบการปฏิเสธการเข้าถึงก่อน เพื่อให้แน่ใจว่า AppArmor เป็นสาเหตุของปัญหาจริงก่อนที่จะเปลี่ยนค่าความปลอดภัยเริ่มต้น
หากคุณต้องการรัน container บน VPS โดยตรงเพื่อลดความซับซ้อนของเลเยอร์ การรัน Docker บน VPS จะอธิบายถึงการตั้งค่าดังกล่าวไว้โดยเฉพาะ
รูปแบบความล้มเหลวและข้อความที่คุณจะพบ
อินสแตนซ์สูญเสียการเชื่อมต่อเครือข่ายทั้งหมดหลังจากติดตั้ง Docker บนโฮสต์ เอกสารของ Incus ระบุสาเหตุไว้ว่า "Docker ตั้งค่า FORWARD policy ส่วนกลางเป็น drop ซึ่งขัดขวางไม่ให้ Incus ส่งต่อทราฟฟิก จึงทำให้อินสแตนซ์สูญเสียการเชื่อมต่อเครือข่าย" อินสแตนซ์ยังคงมีที่อยู่ IP แต่ไม่สามารถติดต่อปลายทางใดได้ ให้ตั้งค่า ip-forward-no-drop เป็น true ใน /etc/docker/daemon.json จากนั้นทำให้การส่งต่อข้อมูลคงอยู่ถาวรและอนุญาตให้ bridge ผ่าน chain ของ Docker ได้
echo "net.ipv4.conf.all.forwarding=1" | sudo tee /etc/sysctl.d/99-forwarding.conf
sudo systemctl restart systemd-sysctl
sudo iptables -I DOCKER-USER -i incusbr0 -j ACCEPT
sudo iptables -I DOCKER-USER -o incusbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPTกฎ iptables เหล่านั้นจะไม่คงอยู่หลังจากการรีบูตด้วยตัวมันเอง คุณต้องทำให้มันคงอยู่ถาวร
คอนเทนเนอร์หยุดทำงานพร้อมข้อผิดพลาดเกี่ยวกับ cgroup FAQ ของ Incus ได้บันทึกปัญหานี้ไว้ ข้อความเกี่ยวกับ Failed to mount "/sys/fs/cgroup" มักหมายความว่าไคลเอ็นต์ VPN บนโฮสต์ได้ mount ตัวควบคุม net_cls cgroup v1 ทับ cgroup v2 ซึ่งเป็นสิ่งที่ Incus ใช้งานอยู่ การใช้ sudo umount /sys/fs/cgroup/net_cls จะช่วยแก้ไขปัญหานี้
อินสแตนซ์ไม่ได้รับที่อยู่ IPv4 incus list แสดงสถานะว่ากำลังทำงานอยู่แต่คอลัมน์ที่อยู่ว่างเปล่า การตอบกลับ DHCP จากโฮสต์ถูกทิ้ง ซึ่งมักเกิดจากไฟร์วอลล์ของโฮสต์ที่ไม่รู้จัก bridge ดังกล่าว หากใช้ ufw การใช้ sudo ufw allow in on incusbr0 to any port 67 proto udp จะช่วยกู้คืนการทำงานได้ ให้ตรวจสอบการมาถึงของคำขอด้วย sudo tcpdump -ni incusbr0 port 67
อินสแตนซ์ปฏิเสธที่จะเริ่มทำงานบน VPS แบบ nested โปรดอ่าน incus info <name> --show-log ก่อน แล้วตามด้วย sudo journalctl -u incus -n 50 หาก systemd-detect-virt แจ้งว่า lxc หรือ openvz แสดงว่าส่วนที่ขาดหายไปอยู่ที่ฝั่งผู้ให้บริการ และไม่มีการตั้งค่าใดภายใน VPS ของคุณที่จะเปลี่ยนแปลงสิ่งนี้ได้
Snapshot ทำงานช้าและดิสก์เต็มอยู่ตลอด คุณกำลังใช้งาน pool แบบ dir อยู่ คำสั่ง incus storage list จะแสดงไดรเวอร์สำหรับแต่ละ pool การย้ายไปยัง pool แบบ copy-on-write หมายถึงการสร้าง pool ใหม่ คัดลอกอินสแตนซ์เข้าไปด้วย incus copy web web-new -s fast จากนั้นจึงลบข้อมูลต้นฉบับทิ้งหลังจากที่คุณตรวจสอบแล้วว่าสำเนาสามารถเริ่มทำงานได้ตามปกติ
FAQ
Incus container เหมือนกับ Docker container หรือไม่?
ไม่เหมือนกัน Docker บรรจุเพียงกระบวนการหรือแอปพลิเคชันเดียว แต่ Incus system container จำลองระบบปฏิบัติการเต็มรูปแบบ ซึ่งมี init, ผู้ใช้, บริการ และตัวจัดการแพ็กเกจของตนเอง คุณสามารถดูแลและแพตช์ Incus container ได้เหมือนกับเซิร์ฟเวอร์ทั่วไป ในขณะที่ Docker container นั้นถูกออกแบบมาให้ลบทิ้งและสร้างใหม่จาก image คุณสามารถรัน Docker ภายใน Incus container ได้โดยการตั้งค่า security.nesting=true บน container นั้น แต่ไม่สามารถทำในทางกลับกันได้
ฉันสามารถรัน Incus บน VPS ได้หรือไม่?
หากเป็น KVM VPS สามารถทำได้ หาก systemd-detect-virt แสดงผลเป็น kvm หรือ qemu แสดงว่าคุณมี kernel ของตนเองและ Incus จะทำงานได้เหมือนบนฮาร์ดแวร์จริง แต่ถ้าแสดงผลเป็น lxc, lxc-libvirt หรือ openvz แสดงว่า VPS ของคุณเป็น container อยู่แล้ว ดังนั้น Incus container ที่อยู่ภายในจะเป็นการซ้อนทับ (nested) ซึ่งจะทำงานได้ก็ต่อเมื่อผู้ให้บริการเปิดใช้งานฟีเจอร์ nesting ไว้ให้ นอกจากนี้ควรตรวจสอบ uname -r ด้วย เนื่องจาก ณ เดือนตุลาคม 2026 รุ่นปัจจุบันของ Incus และซีรีส์ 7.0 LTS ต้องการ kernel เวอร์ชัน 6.12 ขึ้นไป ในขณะที่ซีรีส์ 6.0 LTS ระบุไว้ที่ 5.4
ฉันควรเลือก storage backend แบบใดสำหรับ Incus บน VPS?
ควรเลือก btrfs บนไฟล์ loop เว้นแต่คุณจะมี block device สำรองไว้ใช้งาน ไดรเวอร์ dir มีเอกสารระบุว่าทำงานช้ากว่าตัวเลือกอื่นมาก เนื่องจากใช้วิธีคัดลอกไฟล์แทนการใช้ copy-on-write ทำให้ทุกครั้งที่ทำ snapshot จะต้องเขียนข้อมูล container ใหม่ทั้งหมด incus admin init --minimal จะเลือก dir ให้โดยอัตโนมัติ ซึ่งเป็นเหตุผลว่าทำไมการตอบคำถามในโหมด interactive จึงคุ้มค่ากับเวลาที่เสียไปเพียงสองนาที คุณสามารถสร้าง pool ได้ด้วยคำสั่ง incus storage create fast btrfs size=30GiB
ทำไม Incus container ของฉันถึงเข้าถึงบริการที่รันอยู่บน host ได้?
เพราะ bridge แบบ incusbr0 ที่เป็นค่าเริ่มต้นจะวาง host ไว้ใน subnet เดียวกับ container ที่ตำแหน่ง gateway และกฎ firewall ที่ Incus เพิ่มเข้าไปใน bridge นั้นมีไว้เพื่อให้ระบบเครือข่ายทำงานได้ ไม่ใช่เพื่อบล็อก host บริการใดๆ บน host ที่ผูกไว้กับ 0.0.0.0 จะตอบสนองต่อคำขอเหล่านั้น เว้นแต่จะมีกฎ firewall บน host มาดร็อปแพ็กเก็ตทิ้ง และ firewall ของผู้ให้บริการจะไม่เห็นแพ็กเก็ตเหล่านี้เพราะมันไม่ได้ออกจากเครื่อง ดังนั้นควรผูกบริการบน host ไว้กับ 127.0.0.1 และหากใช้ ufw บน host ให้ยอมรับเฉพาะ DNS และ DHCP บน incusbr0 แทนการเปิดกว้างทั้งหมดด้วย sudo ufw allow in on incusbr0
ฉันจะสำรองข้อมูล Incus container ได้อย่างไร?
incus export web /root/web-backup.tar.gz จะเขียนข้อมูล instance และ snapshot ลงในไฟล์เดียว และ incus import จะใช้สำหรับกู้คืนข้อมูลบนเซิร์ฟเวอร์เดิมหรือเซิร์ฟเวอร์อื่น การทำ snapshot ด้วย incus snapshot create ไม่ถือเป็นการสำรองข้อมูล เพราะมันถูกเก็บไว้ใน storage pool เดียวกันบนดิสก์ลูกเดียวกัน ซึ่งช่วยป้องกันได้เพียงความผิดพลาดจากการอัปเกรด แต่ไม่สามารถป้องกันกรณีเซิร์ฟเวอร์เสียหายได้ ควรตั้งเวลาสำรองข้อมูลด้วย incus config set web snapshots.schedule=@daily และคัดลอกไฟล์ที่ export ออกไปเก็บไว้นอกเครื่องเสมอ