6 คะแนน โดย GN⁺ 2025-03-15 | 2 ความคิดเห็น | แชร์ทาง WhatsApp
  • แซนด์บ็อกซ์แบบโปรเซสเดี่ยวที่อิง KVM
    • สามารถรันโปรแกรม Linux ทั่วไป หรือโปรแกรมที่ใช้ API เฉพาะภายในแซนด์บ็อกซ์ได้
  • ใช้ฮาร์ดแวร์เวอร์ชวลไลเซชันเพื่อมอบ ประสิทธิภาพระดับเนทีฟ
  • ใช้เพียงบางส่วนของ KVM API → ทำให้โค้ดเบสมีขนาดเล็กและมีประสิทธิภาพ

การออกแบบของ TinyKVM

  • รองรับการรันโปรแกรม Linux ELF แบบสแตติก
    • มีแผนจะเพิ่มการรองรับไฟล์ปฏิบัติการแบบไดนามิกในภายหลัง
    • สามารถขยายเป็น API เพื่อให้เข้าถึงเซิร์ฟเวอร์ HTTP ภายนอกหรือแคชได้
    • ปัจจุบันทำงานบน AMD64(x86_64) และมีแผนพอร์ตไปยัง AArch64(ARM 64 บิต)
  • รองรับ Hugepage
    • สามารถสร้าง hugepage สำหรับ guest page ได้
    • โฮสต์ก็สามารถใช้ hugepage ได้เช่นกัน → ช่วยเพิ่มประสิทธิภาพ
    • ตัวอย่าง: เมื่อจัดสรรเพจขนาด 2MB พบว่าประสิทธิภาพการคอมไพล์ LLVM เพิ่มขึ้น 5%
  • การเรียกฟังก์ชันที่รวดเร็ว
    • โอเวอร์เฮดเมื่อเรียกฟังก์ชันจาก guest อยู่ที่ 2μs
    • หากรันโดยไม่ใช้ตัวจับเวลา โอเวอร์เฮดจะลดลงเหลือ 1.2μs
  • รองรับการดีบักระยะไกล
    • สามารถดีบักระยะไกลด้วย GDB ได้
    • หลังดีบักแล้วสามารถกลับมารันโปรแกรมต่อได้ตามปกติ
  • รองรับ Copy-on-Write
    • รองรับความสามารถ fork ของตัวเอง → ช่วยลดการคัดลอกหน่วยความจำให้เหลือน้อยที่สุด
    • ตัวอย่าง: หากโคลนโมเดลขนาด 6GB จะใช้หน่วยความจำเพียง 260MB ต่ออินสแตนซ์
  • การรีเซ็ตสถานะที่รวดเร็ว
    • สามารถรีเซ็ตสถานะของ guest ได้อย่างรวดเร็ว → เสริมความปลอดภัย
    • หากรีเซ็ตทุกคำขอจะช่วยลดความเสี่ยงจากการเปิดเผยสถานะ
  • โค้ดเบสที่เรียบง่าย
    • ใช้งานประมาณ 42k LOC จาก KVM API
    • โค้ดเบสของ TinyKVM เองมีประมาณ 9k LOC → เล็กกว่าคู่แข่งมาก
    • ตัวอย่าง: Wasmtime 350k LOC, FireCracker 165k LOC
  • การสร้างตารางเพจแบบคงที่
    • ไม่สามารถแก้ไขตารางเพจระหว่างรันไทม์ได้ → เสริมความปลอดภัย
    • มีการตรวจสอบความถูกต้องสมบูรณ์ของตารางเพจ
  • คอนเท็กซ์ของโปรเซสที่แยกจากกัน
    • KVM guest ใช้ PCID/ASID แยกต่างหาก → ทนทานต่อการโจมตีแบบ speculative execution เช่น Spectre
  • เคอร์เนลที่เสริมความปลอดภัย
    • เปิดใช้งาน SMEP และ SMAP
    • สามารถจัดการ CPU exception ได้ในโหมดผู้ใช้

การจัดการ system call

  • การเชื่อมต่อ API กับโฮสต์
    • ดำเนิน system call ผ่านคำสั่ง SYSCALL/SYSRET หรือ OUT
    • เมื่อดำเนิน system call จะเกิด VM exit → ใช้เวลาประมาณ 1μs
    • แนะนำให้ออกแบบ API ที่ลดการเรียกขนาดเล็กและใช้หน่วย I/O ขนาดใหญ่

เบนช์มาร์ก

  • โอเวอร์เฮดของการเรียก VM
    • วัด tail latency ตอนรีเซ็ต VM
    • หากเป็นการเรียกธรรมดาโดยไม่รีเซ็ต โอเวอร์เฮดจะต่ำ
  • ประสิทธิภาพหน่วยความจำ
    • ประสิทธิภาพหน่วยความจำอยู่ในระดับปกติ
    • ตัวอย่าง: ใน HTTP เบนช์มาร์ก สามารถเข้ารหัส AVIF ได้ 1500 รายการต่อวินาที
  • ประสิทธิภาพการแปลง JPEG → AVIF
    • สามารถแปลงภาพได้ประมาณ 1582 ภาพต่อวินาที
    • สามารถแปลงแบบไม่สูญเสียข้อมูลได้โดยใช้เส้นทางการแปลง YUV

เหตุผลที่แซนด์บ็อกซ์นี้ทำงานได้รวดเร็ว

  • ไม่ใช้ I/O และไดรเวอร์
    • ไม่มี I/O, ไดรเวอร์ หรืออุปกรณ์เสมือน → ป้องกันการลดลงของประสิทธิภาพ
    • ใช้เฉพาะทรัพยากร CPU → ความเร็วใกล้เคียงเนทีฟ
  • การปรับแต่ง Hugepage
    • การใช้ hugepage ช่วยลด page walk → เพิ่มประสิทธิภาพ
    • ในเวิร์กโหลด LLM ขนาดใหญ่ ทำประสิทธิภาพได้ 99.7% ของเนทีฟ
  • การเรียก VM ที่รวดเร็ว
    • ลดโอเวอร์เฮดของการเรียกฟังก์ชันจาก guest ให้ต่ำที่สุด
    • ประมวลผลข้อมูลได้ด้วยความเร็วระดับ CPU เนทีฟ

ข้อจำกัด

  • ไม่สามารถลดจำนวน vCPU ได้
    • KVM API ไม่สามารถลดจำนวน vCPU ได้
    • งานแบบหลายโปรเซสสามารถแก้ได้ด้วยการรันหลาย VM แบบขนาน
  • ปัญหาประสิทธิภาพลดลงขณะรีเซ็ต
    • อาจเกิดประสิทธิภาพลดลงเมื่อรีเซ็ตสถานะ VM
    • แต่สามารถแก้ได้ด้วยการแชร์และโคลนสถานะ

งานในอนาคต

  • เพิ่มการรองรับ Intel TDX และ AMD SEV
  • พอร์ตไปยัง AArch64
  • เพิ่มความสามารถ memory lock (KVM_MEM_READONLY) → เสริมความปลอดภัย
  • ปรับปรุง API ให้ใช้งานง่ายขึ้น
  • เพิ่มการรองรับการโหลด dynamic link → เสริมการผสานรวมกับ Varnish

บทสรุป

  • TinyKVM เป็นหนึ่งในโซลูชันแซนด์บ็อกซ์ที่เล็กและเร็วที่สุด
  • บรรลุทั้งการเสริมความปลอดภัยและการปรับแต่งประสิทธิภาพ
  • โค้ดเบสมีขนาดเล็กจึงดูแลรักษาได้ง่าย
  • เปิดให้ใช้งานในรูปแบบไลบรารีโอเพนซอร์ส → หากสนใจสามารถดูได้ที่ที่เก็บโค้ด

คลังเก็บ TinyKVM

2 ความคิดเห็น

 
xcutz 2025-03-16

แปลกดีนะ

 
GN⁺ 2025-03-15
ความคิดเห็นบน Hacker News
  • ชอบสิ่งนี้มากจริงๆ หวังว่าจะไม่หยุดทำสิ่งที่กำลังทำอยู่ต่อไป

    • รู้ว่าเป็นผู้มีส่วนร่วมหลักของ IncludeOS นั่นเป็นโปรเจ็กต์แรกที่นึกถึงตอนอ่านบล็อกโพสต์นี้
    • หมกมุ่นกับ network function virtualization มานานแล้ว มันเป็นขอบเขตที่เป็นธรรมชาติที่สุดในการแยกหน่วยงานใน distributed systems และให้ทั้ง abstraction ที่สะอาดกับกลไกการขยายระบบที่มีประสิทธิภาพ
    • ใช้ Varnish ในโปรดักชันด้วยความพึงพอใจอย่างมาก มันน่าเชื่อถือยิ่งกว่า nginx เสียอีก ปกติแทบจะลืมไปเลยว่ามีมันอยู่ ตั้งค่าถูกต้องแล้วก็ไม่เคยเป็นสาเหตุของบั๊กเลย
  • คล้าย Firecracker แต่เร็วกว่ามาก

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

    • หาโพสต์ที่เกี่ยวกับหัวข้อนี้ได้อีกมาก
  • น่าสนใจมาก ประสิทธิภาพการกู้คืนสแนปช็อต 2.5us อยู่ในระดับเดียวกับ Wasmtime แต่มีข้อได้เปรียบใหญ่ว่าสามารถรัน native code ได้ อย่างไรก็ตาม มันช้ากว่ามาก แต่ก็ยังมีการทำงานร่วมกันได้ในระดับไมโครวินาที

    • ในรีโพ tinykvm_examples มีเดโม QuickJS อยู่แล้ว แต่ถ้าลองดูว่าสามารถรัน JavaScript runtime ที่มี JIT ได้หรือไม่ ก็น่าจะเร็วขึ้นมาก
    • ในการทดลอง server-render React app, native QuickJS ใช้เวลาประมาณ 12-20ms ส่วน v8 หลัง JIT วอร์มอัปแล้วอยู่ที่ 2-4ms
    • ยังต้องศึกษาเพิ่ม แต่ก็อยากสร้าง single executable แบบ Deno ที่รันภายใน sandbox และจัดการทุก HTTP request ผ่าน Varnish
    • ดึง JS URL ที่กำหนดมา จากนั้นถ่ายสแนปช็อต แล้วให้แต่ละคำขอไปรันในสแนปช็อตที่แยกกัน
    • น่าจะต้องมีกลไกสำหรับรีเซ็ต random seed ต่อคำขอ
  • โดยพื้นฐานแล้วมันไม่ใช่อะไรประมาณ libkrun หรอกหรือ? ลิงก์

  • แม้นี่จะไม่ใช่ use case ที่ตั้งใจไว้โดยตรง แต่มีใครเคยลองรัน X server (หรือ Wayland) ไหม?

    • กำลังพัฒนาสำหรับ RDP server บน Mac และบางครั้งก็มีความต้องการอื่นสำหรับไคลเอนต์ ตอนนี้ใช้ UTM (ฟรอนต์เอนด์ QEMU บน Mac) กับ VM ของ DietPi (Debian แบบลดทอนอย่างมาก)
    • คุ้นกับ Docker แต่ก็รู้ดีว่าต้องมีขั้นตอนอะไรบ้างในการรัน graphical server แค่อยากรู้ว่ามีวิธีที่ง่ายกว่านี้ไหม
  • น่าสนใจ แต่กำลังลำบากในการทำความเข้าใจภาพรวมใหญ่ มันคือการรัน user process ใน VM โดยไม่มีเคอร์เนลหรือ? system call ทั้งหมดจะทำให้ VM จบการทำงานแล้วพร็อกซีไปยังโฮสต์หรือ? หรือว่าไม่มี system call เลย?

  • ถ้าเหมาะกับ use case ก็เจ๋งมากจริงๆ

    • โน้ตบางอย่างจากโพสต์
    • พบว่า TinyKVM รันได้ที่ความเร็ว 99.7% ของ native
    • ถ้าไม่ต้องการการเข้าถึงไฟล์หรือเครือข่ายและเป็นแบบ static ก็สามารถรันได้ตรงๆ เลย
    • guest ของ TinyKVM มีเคอร์เนลขนาดเล็กที่แก้ไขไม่ได้
  • เจ๋งมาก

    • กำลังสำรวจ micro-VM สำหรับ self-hosted PaaS และสิ่งนี้ดูเหมือนจะเป็นตัวเลือกที่น่าสนใจมากเพราะมีโอเวอร์เฮดต่ำ
  • ในบทความไม่ได้บอกว่ามันรันอยู่บน Varnish และจริงๆ แล้วผู้เขียนก็บอกด้วยว่ามันไม่ได้มีไว้เพื่อให้ Varnish รันบนมัน