Podman, KVM และคอนเทนเนอร์: คู่มือภาคปฏิบัติเพื่อการจำลองเสมือนที่ปลอดภัย

การปรับปรุงครั้งล่าสุด: 9 เดือนมีนาคมของ 2026
  • คอนเทนเนอร์ใช้เคอร์เนลร่วมกับโฮสต์ ดังนั้นการแยกตัวของคอนเทนเนอร์จึงขึ้นอยู่กับเนมสเปซ ซีกรุ๊ป และการเสริมความปลอดภัยของระบบ
  • Podman มอบความปลอดภัยที่มากกว่า Docker แบบดั้งเดิม โดยหลีกเลี่ยงการใช้ daemon หลักส่วนกลาง และอำนวยความสะดวกในการเรียกใช้งานโดยไม่ต้องใช้สิทธิ์ root
  • เครือข่ายแบบบริดจ์ โฮสต์ และแบบไร้ราก (slirp4netns, paste) ใน Podman ช่วยให้คุณสามารถปรับสมดุลระหว่างการเชื่อมต่อและการแยกตัวได้
  • การผสานรวม KVM, คอนเทนเนอร์ และแนวทางปฏิบัติที่ดีที่สุด (rootless, MAC, seccomp, การสแกนอิมเมจ) เข้าด้วยกัน จะสร้างแพลตฟอร์มที่แข็งแกร่งสำหรับการใช้งานจริง

การจำลองเสมือนที่ปลอดภัยของ Podman KVM

เมื่อคุณเริ่มตั้งค่าสภาพแวดล้อมคอนเทนเนอร์อย่างจริงจังบนลินุกซ์ คำถามเดียวกันนี้ก็จะผุดขึ้นมาทันที: การพึ่งพาคอนเทนเนอร์เพียงอย่างเดียวมีความปลอดภัยมากน้อยเพียงใด และเมื่อใดจึงควรพิจารณาใช้ KVM หรือไมโคร VM ที่มีประสิทธิภาพสูงกว่า? ในสภาพแวดล้อมขององค์กรที่ใช้ Docker, Podman, LXC, เครื่องเสมือน KVM และไฮเปอร์ไวเซอร์ต่างๆ ผสมผสานกัน การทำความเข้าใจโมเดลการแยกส่วนอย่างดีจึงเป็นกุญแจสำคัญในการหลีกเลี่ยงข้อผิดพลาด

นอกจากนี้ สถานการณ์ที่ค่อนข้างซับซ้อนก็ไม่ใช่เรื่องแปลก เช่น ลองใช้ Docker Desktop หรือ Podman ภายในเครื่องเสมือนใน VirtualBox หรือ KVM ดูกระบวนการนี้เกี่ยวข้องกับการจำลองเสมือนหลายระดับ (แบบซ้อนกันหรือไม่ก็ได้) และอาจเกิดข้อผิดพลาดได้ง่าย เช่น "KVM ไม่ได้เปิดใช้งานบนโฮสต์" เรามาจัดระเบียบส่วนประกอบทั้งหมดเหล่านี้กัน: คอนเทนเนอร์, VM, Podman, KVM, เครือข่าย และความปลอดภัย แล้วดูวิธีการผสานรวมเข้าด้วยกันเพื่อให้ได้การจำลองเสมือนที่ปลอดภัยและใช้งานได้จริงอย่างแท้จริง

การจำลองเสมือนแบบคลาสสิกด้วย KVM และเครื่องเสมือน

รากฐานของระบบทั้งหมดนี้ยังคงอยู่ที่ การจำลองเสมือนของระบบปฏิบัติการ ดำเนินการให้เสร็จสมบูรณ์โดยใช้ไฮเปอร์ไวเซอร์ เช่น KVM, Xen หรือ ESXiในกรณีนี้ ฮาร์ดแวร์ทางกายภาพจะรันไฮเปอร์ไวเซอร์ซึ่งมีหน้าที่ "แบ่ง" เครื่องออกเป็นเครื่องเสมือนอิสระหลายเครื่อง

ในโมเดลนี้ เครื่องเสมือนแต่ละเครื่องจะเริ่มต้นขึ้น เคอร์เนลของตัวเองและระบบปฏิบัติการแขกของตัวเองแยกออกจากโฮสต์อย่างสิ้นเชิง ไฮเปอร์ไวเซอร์ (เช่น KVM ซึ่งรวมอยู่ในเคอร์เนลของลินุกซ์) ทำหน้าที่เป็นผู้พิทักษ์ระหว่างฮาร์ดแวร์และเครื่องเสมือน และรับผิดชอบในการแยกส่วนอย่างแน่นหนา ระหว่างกัน

โดยทั่วไปเราจะพูดถึงไฮเปอร์ไวเซอร์สองประเภท: ประเภทที่ 1 หรือแบบติดตั้งบนฮาร์ดแวร์โดยตรง และประเภทที่ 2 ซึ่งทำงานบนระบบปฏิบัติการที่มีอยู่แล้ว VirtualBox หรือ VMware Workstation จัดเป็นประเภทที่ 2ในขณะที่ KVM ที่จัดการโดย libvirt บนเซิร์ฟเวอร์ Linux นั้นใกล้เคียงกับสถานการณ์ประเภทที่ 1 มากกว่า แม้ว่าจะใช้พื้นที่ร่วมกับโฮสต์ก็ตาม

ข้อดีที่สำคัญที่สุดของแนวทางนี้คือ แต่ละ VM มีสแต็กที่สมบูรณ์เป็นของตัวเอง ได้แก่ เคอร์เนล พื้นที่ผู้ใช้ บริการ เครือข่าย และพื้นที่จัดเก็บข้อมูลสิ่งนี้ให้ความยืดหยุ่นสูงและความสามารถในการใช้งานระบบปฏิบัติการและเวอร์ชันเคอร์เนลที่แตกต่างกันบนเครื่องคอมพิวเตอร์เครื่องเดียวกัน

ในการจัดการแพลตฟอร์มเสมือนเหล่านี้ใน GNU/Linux นั้น โดยทั่วไปแล้วจะใช้ libvirt ในฐานะ API สำหรับการจัดการระบบนอกจากนี้ยังรองรับเครื่องมือแบบกราฟิกและแบบบรรทัดคำสั่ง หรือโครงการขนาดใหญ่อย่าง OpenStack ซึ่งสร้างระบบคลาวด์ทั้งหมดโดยการรวม VM, เซิร์ฟเวอร์แบบไม่มีฮาร์ดแวร์ และคอนเทนเนอร์เข้าด้วยกัน

ข้อกำหนดด้านฮาร์ดแวร์และปัญหาทั่วไปของ KVM

ก่อนที่จะใช้งาน KVM หรือโซลูชันที่ขึ้นอยู่กับ KVM (เช่น Docker Desktop หรือการกำหนดค่า micro-VM บางอย่าง) คุณต้องตรวจสอบให้แน่ใจว่า... โปรเซสเซอร์รองรับการจำลองเสมือนด้วยฮาร์ดแวร์ (VT-x บน Intel หรือ SVM/AMD-V บน AMD) และคืออะไร เปิดใช้งานใน BIOS/UEFI.

ใน Linux เรามีวิธีตรวจสอบอย่างรวดเร็ว: ถ้าคำสั่งนั้นถูกต้อง grep -E 'svm|vmx' /proc/cpuinfo หากไม่มีการส่งค่าใดๆ กลับมา หรือตัวเลือกนั้นยังคงถูกปิดใช้งานในเฟิร์มแวร์ KVM ก็จะใช้งานไม่ได้ ยิ่งไปกว่านั้น ในสถานการณ์ที่เราจะเรียกใช้ VM ภายใน VM อื่น (การจำลองเสมือนแบบซ้อนกัน) ไฮเปอร์ไวเซอร์ระดับบนสุดจะต้องเปิดเผยส่วนขยายเหล่านั้นให้แก่ระบบปฏิบัติการแขกอย่างชัดเจน

เมื่อมีสิ่งผิดปกติเกิดขึ้น ข้อความแจ้งเตือนทั่วไปจะปรากฏขึ้น เช่น ป๊อปอัพ Docker Desktop ที่คุ้นเคยใน RHEL 9 ภายใน VirtualBox: “KVM ไม่ได้เปิดใช้งานบนโฮสต์”ปัญหาในที่นี้ไม่ได้อยู่ที่ Docker หรือ RHEL โดยตรง แต่เป็นเพราะ VM ของ VirtualBox ไม่ได้รับส่วนขยายการจำลองเสมือนที่จำเป็นสำหรับการเรียกใช้ KVM ภายในนั้น

คำสั่งเช่น modprobe kvm o modprobe kvm_amd / kvm_intel โมดูลเคอร์เนลควรโหลดโดยไม่มีข้อความแสดงข้อผิดพลาด หากไม่มีสิ่งใดที่เกี่ยวข้องปรากฏใน dmesg หรือ lsmod | grep kvm มันแสดงแค่ KVM และ IRQ BYPASS แบบ "พื้นฐาน" เท่านั้น และโมดูล CPU เฉพาะนั้นหายไป มีความเป็นไปได้สูงมากว่า... การจำลองเสมือนฮาร์ดแวร์ไม่ได้ถูกเปิดเผย ไปยังระบบของแขกหรือถูกปิดใช้งานในเฟิร์มแวร์

ในสถานการณ์เหล่านี้ แม้ว่าจะเปิดใช้งานทุกอย่างที่เป็นไปได้ภายในโฮสต์แล้วก็ตาม หาก VirtualBox ไม่รองรับการจำลองเสมือนแบบซ้อนกัน หรือมีการตั้งค่าที่ไม่ถูกต้อง KVM ก็จะไม่สามารถใช้งานได้วิธีแก้ปัญหานี้เกี่ยวข้องกับการตรวจสอบการตั้งค่าของไฮเปอร์ไวเซอร์โฮสต์ (VirtualBox, VMware เป็นต้น) และเปิดใช้งานการจำลองเสมือนแบบซ้อนกันหากมีให้ใช้งาน

คอนเทนเนอร์: การจำลองเสมือนแบบน้ำหนักเบาในระดับระบบปฏิบัติการ

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

ตู้คอนเทนเนอร์ยังคงอยู่ ชุดของกระบวนการที่ถูกห่อหุ้มไว้โดยใช้เนมสเปซและซีกรุ๊ปภายใน “สภาพแวดล้อม” นั้น แอปพลิเคชันเชื่อว่าตนเองกำลังทำงานอยู่บนเครื่องของตนเอง โดยมีระบบไฟล์ อินเทอร์เฟซเครือข่าย และ PID เป็นของตนเอง แต่ในความเป็นจริงแล้ว แอปพลิเคชันใช้เคอร์เนลร่วมกับเครื่องโฮสต์

คอนเทนเนอร์ให้ประสิทธิภาพใกล้เคียงกับอุปกรณ์ดั้งเดิม เนื่องจาก ไม่มีเคอร์เนลตัวที่สองเข้ามาเกี่ยวข้อง และไม่มีการจำลองฮาร์ดแวร์อย่างสมบูรณ์ค่าใช้จ่ายเพิ่มเติมมีน้อยมาก: เพียงพอสำหรับการตั้งค่าเนมสเปซ จำกัดทรัพยากรด้วย cgroups และใช้มาตรการรักษาความปลอดภัย (seccomp, AppArmor, SELinux เป็นต้น)

อย่างไรก็ตาม การออกแบบนี้มีผลกระทบที่สำคัญอย่างหนึ่งคือ: เพย์โหลดทั้งหมดใช้เคอร์เนลทางกายภาพเดียวกันช่องโหว่ร้ายแรงในเคอร์เนลนั้นอาจกลายเป็นช่องทางหลบหนีสำหรับคอนเทนเนอร์ทั้งหมดที่ทำงานอยู่บนโหนดนั้นได้โดยฉับพลัน

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

เนมสเปซและซีกรุ๊ป: รากฐานของการแยกคอนเทนเนอร์

ใน Linux การแยกคอนเทนเนอร์นั้นสร้างขึ้นบนหลักการสำคัญสองประการ: เนมสเปซเพื่อแยกมุมมองของระบบ y ใช้ cgroups เพื่อจำกัดและตรวจสอบการใช้ทรัพยากร.

  การกู้คืนเครื่องอย่างรวดเร็วใน Windows 11: คืออะไร ทำงานอย่างไร และจะตั้งค่าอย่างไร

เนมสเปซจะแยกสิ่งต่างๆ ออกจากกัน เช่น PID, เครือข่าย, จุดเชื่อมต่อ, IPC, ชื่อโฮสต์ (UTS) และผู้ใช้ด้วยวิธีนี้ กระบวนการจะ "มองเห็น" เฉพาะกระบวนการ อินเทอร์เฟซเครือข่าย ระบบไฟล์ และชื่อโฮสต์ของเนมสเปซของตนเองเท่านั้น ทำให้รู้สึกเหมือนกำลังทำงานอยู่บนระบบอื่น

ในส่วนของ cgroups นั้นอนุญาตให้... ระบุว่าคอนเทนเนอร์สามารถใช้ CPU, หน่วยความจำ, การอ่าน/เขียนดิสก์, จำนวนกระบวนการ ฯลฯ ได้มากน้อยเพียงใดวิธีนี้จะช่วยป้องกันไม่ให้โหลดที่ไม่สามารถควบคุมได้ไปทับซ้อนกับระบบโฮสต์ทั้งหมด ซึ่งเป็นสิ่งสำคัญอย่างยิ่งเมื่อมีการใช้โหนดร่วมกันระหว่างทีมหรือโครงการต่างๆ

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

วิธีที่เหมาะสมในการเสริมสร้างความแข็งแกร่งให้กับสภาพแวดล้อมคือการผสมผสานกัน ตัวกรอง syscall ร่วมกับ seccomp, นโยบาย MAC (AppArmor หรือ SELinux) และการลดความสามารถลงอย่างมาก โดยควรมีการกำหนดกระบวนการต่างๆ ควบคู่ไปกับเนมสเปซของผู้ใช้และโหมดไร้สิทธิ์รูท เพื่อลดความเสียหายหากมีผู้ใดสามารถออกจากคอนเทนเนอร์ได้

ภัยคุกคามด้านความปลอดภัยบนแพลตฟอร์มคอนเทนเนอร์

ในแพลตฟอร์มคอนเทนเนอร์จริง พื้นที่เสี่ยงต่อการโจมตีจะกระจายอยู่หลายชั้น: เคอร์เนลและรันไทม์ (runc, containerd, CRI-O), ห่วงโซ่อุปทานของอิมเมจ, การกำหนดค่าคอนเทนเนอร์/ออร์เชสเตรเตอร์ และโครงสร้างพื้นฐานที่อยู่เบื้องหลัง (คลาวด์, พื้นที่จัดเก็บข้อมูล, IAM, เครือข่าย)

รูปแบบการโจมตีทั่วไป ได้แก่ ช่องโหว่ของซอฟต์แวร์ ในเคอร์เนลหรือรันไทม์คอนเทนเนอร์ การใช้ภาพที่ไม่ปลอดภัยหรือไม่ได้รับการดูแลรักษา การกำหนดค่าผิดพลาดใน Kubernetes หรือ Docker (คอนเทนเนอร์ที่มีสิทธิ์พิเศษ การเมานต์โฮสต์ที่เป็นอันตราย โหมดเครือข่ายที่เปิดมากเกินไป) และช่องโหว่ด้านความปลอดภัยในรีจิสทรีหรือไปป์ไลน์ CI/CD

ในเหตุการณ์จริงหลายๆ ครั้ง ไม่ได้มีแค่ "แมลงประหลาด" ตัวเดียวเท่านั้น แต่... การรวมกันของช่องโหว่ที่ทราบแล้วและการตั้งค่าที่ไม่รัดกุม: คอนเทนเนอร์ที่ทำงานในฐานะ root, การใช้แฟล็ก –privileged, การเมานต์ระบบไฟล์ของโฮสต์ภายในคอนเทนเนอร์ และการไม่มี seccomp หรือ MAC

นอกเหนือจากปัญหาทั้งหมดนี้แล้ว ยังมีประเด็นเรื่องห่วงโซ่อุปทานอีกด้วย: อิมเมจพื้นฐานสาธารณะมักมีช่องโหว่ด้านความปลอดภัย (CVE) แพ็กเกจที่ล้าสมัย และการจัดการการพึ่งพาที่ไม่ดีมัลแวร์สามารถแทรกซึมเข้ามาได้ค่อนข้างง่าย หรือไลบรารีที่ถูกบุกรุกอาจแฝงตัวอยู่เฉยๆ จนกว่าจะมีเงื่อนไขเหมาะสมสำหรับการเรียกใช้งาน

ดังนั้น ในกระบวนการผลิตจึงไม่ใช่ทางเลือก: จำเป็นต้องสแกนภาพเพื่อหาช่องโหว่โดยใช้เครื่องมือต่างๆ เช่น Trivy, Clair หรือ Grypeควบคุมการใช้รีจิสทรี (Harbor, Quay, GHCR พร้อมนโยบาย) และลงนาม/ตรวจสอบความถูกต้องของอิมเมจก่อนที่จะนำไปใช้งานในคลัสเตอร์

Docker กับ Podman: ผลกระทบต่อแบบจำลองภัยคุกคาม

ในโลกของคอนเทนเนอร์แอปพลิเคชัน Docker และ Podman ทำหน้าที่คล้ายคลึงกัน แต่ โครงสร้างทางสถาปัตยกรรมแตกต่างกันอย่างมาก และนั่นทำให้รูปแบบการรักษาความปลอดภัยเปลี่ยนไป ซึ่งเราใช้ในการทำงานบนโฮสต์

Docker ในโหมด rootful แบบดั้งเดิมนั้นอาศัย... โปรแกรมจัดการส่วนกลาง (dockerd) ที่ทำงานในฐานะผู้ใช้ rootCLI สื่อสารกับ daemon นี้ผ่านทาง /var/run/docker.sock หรือผ่านทาง TCP และกระบวนการที่มีสิทธิ์พิเศษนี้เองที่สร้างและทำลายคอนเทนเนอร์ จัดการอิมเมจ เครือข่าย และวอลุ่ม รวมถึงสื่อสารกับรีจิสทรีต่างๆ

ซึ่งหมายความว่า ใครก็ตามที่สามารถเข้าถึง Docker socket ได้ ก็จะมีสิทธิ์เข้าถึงระดับ root บนโฮสต์นั้นโดยปริยายเนื่องจากสามารถเรียกใช้คอนเทนเนอร์ที่มีสิทธิ์พิเศษ ติดตั้งระบบไฟล์ตามอำเภอใจ และแก้ไขการกำหนดค่าที่สำคัญได้ ทำให้ดีมอนกลายเป็นจุดล้มเหลวเพียงจุดเดียวอย่างแท้จริง

ในทางกลับกัน พอดแมนเกิดมาพร้อมกับแนวคิดที่ว่า เพื่อเป็นเอนจินคอนเทนเนอร์ที่ไม่มีเดมอน และมีความ "ดั้งเดิม" มากที่สุดเท่าที่จะเป็นไปได้บนลินุกซ์ไม่มีกระบวนการส่วนกลางที่ถาวร คอนเทนเนอร์ขึ้นอยู่กับผู้ใช้หรือ systemd และการบูรณาการกับ systemd ช่วยให้สามารถควบคุมคอนเทนเนอร์ผ่านหน่วยบริการได้

แนวทางนี้สอดคล้องกับโมเดลของ Unix ที่ว่า "แต่ละกระบวนการเป็นของผู้ใช้ที่เริ่มกระบวนการนั้น" ได้ดีกว่า จงหลีกเลี่ยงการพึ่งพาปีศาจที่มีอภิสิทธิ์สูงนอกจากนี้ Podman ยังรองรับคำสั่ง Docker ทำให้การย้ายระบบง่ายขึ้น (คุณสามารถสร้างชื่อย่อ docker=podman ในสภาพแวดล้อมที่คุณไม่ต้องการติดตั้ง Docker CE ได้ด้วยซ้ำ)

โหมดไร้รากและเนมสเปซของผู้ใช้

หนึ่งในความก้าวหน้าทางปฏิบัติที่สำคัญในการลดผลกระทบจากการรั่วไหลของภาชนะบรรจุที่อาจเกิดขึ้นได้คือ โหมดไร้รากเมื่อใช้งานร่วมกับเนมสเปซของผู้ใช้คำถามที่กำลังกล่าวถึงในที่นี้คือ "จะเกิดอะไรขึ้นหากภาชนะบรรจุหลุดออกไปในที่สุด?"

เนมสเปซของผู้ใช้ช่วยให้ กำหนดค่า UID ของคอนเทนเนอร์ 0 ใหม่ให้เป็น UID ที่ไม่มีสิทธิ์พิเศษบนโฮสต์กล่าวอีกนัยหนึ่ง ภายในคอนเทนเนอร์ แอปพลิเคชันเข้าใจว่าตนเองเป็นผู้ใช้ระดับรูท แต่จากมุมมองของโฮสต์ กระบวนการนั้นแท้จริงแล้วเป็นผู้ใช้ทั่วไปที่มีการกำหนดช่วง subuid/subgid ไว้

ด้วยวิธีนี้ แม้ว่าผู้โจมตีจะได้รับสิทธิ์ระดับรูทภายในคอนเทนเนอร์และสามารถเชื่อมโยงการโจมตีในระดับเคอร์เนลหรือรันไทม์เข้าด้วยกันได้ก็ตาม เมื่อกลับไปยังเครื่องโฮสต์ ระบบจะกลับในฐานะผู้ใช้ที่ไม่มีสิทธิ์พิเศษคุณไม่สามารถเขียนทับไฟล์ไบนารีของรูท ติดตั้งระบบไฟล์ที่มีความสำคัญ หรือจัดการอุปกรณ์ที่คุณไม่มีสิทธิ์ที่จำเป็นได้

Podman ได้รับการออกแบบตั้งแต่เริ่มต้นโดยคำนึงถึงโมเดลนี้เป็นหลัก: โดยค่าเริ่มต้นควรใช้คอนเทนเนอร์แบบไร้รากทุกครั้งที่เป็นไปได้รวมถึงการใช้งาน SELinux/AppArmor และ cgroups แม้ไม่มีสิทธิ์ root และการให้ความสำคัญอย่างมากกับการลดสิทธิ์เชิงโครงสร้างให้น้อยที่สุด

Docker ยังมีอีกด้วย โหมดไร้ราก "แท้จริง"ในสภาพแวดล้อมนี้ Dockerd และคอนเทนเนอร์ของมันจะอยู่ในเนมสเปซของผู้ใช้ ซึ่งแตกต่างจาก userns-remap แบบเก่าที่เดมอนยังคงเป็น root จากมุมมองด้านความปลอดภัย วิธีนี้จะป้องกันการโจมตี Dockerd ที่ทำให้สามารถเข้าถึงโฮสต์ในฐานะ root ได้โดยอัตโนมัติ

เครือข่ายคอนเทนเนอร์ด้วย Podman: อินเทอร์เฟซแบบบริดจ์, โฮสต์, macvlan และ rootless

อีกหนึ่งองค์ประกอบที่สำคัญของความปลอดภัยและการใช้งานจริงคือ... เลเยอร์เครือข่ายคอนเทนเนอร์Podman มีกลไกหลากหลายในการเชื่อมต่อ โดยให้ความสำคัญเป็นพิเศษกับสถานการณ์ที่ไม่มีไดเร็กทอรีราก (rootless)

  Linux จาก Scratch: Linux จาก Scratch สำหรับผู้เริ่มต้น

Podman 4 เปิดตัวแล้ว Netavark คือไดรเวอร์เครือข่ายที่ใช้โมเดล CNI เพื่อกำหนดที่อยู่ IP ให้กับคอนเทนเนอร์บนเครือข่ายบริดจ์, macvlan เป็นต้น โดยปกติแล้ว ใน NetAvark คอนเทนเนอร์ที่มีสิทธิ์ root จะเชื่อมต่อกับเครือข่ายที่เรียกว่า "podman" ซึ่งเชื่อมโยงกับบริดจ์ Linux (podman0) บนโฮสต์ โดยมีที่อยู่ 10.88.0.0/16

เครือข่ายบริดจ์เริ่มต้นนี้จัดเตรียมไว้ให้ การเชื่อมต่ออินเทอร์เน็ตขั้นพื้นฐานผ่านกฎ SNAT วิธีนี้ช่วยให้คุณเปิดพอร์ตคอนเทนเนอร์ไปยังโฮสต์โดยใช้ `-po --publish` ซึ่งจะสร้างกฎ DNAT ใน iptables/nftables เพื่อความเข้ากันได้กับ Docker เครือข่ายนี้จะไม่เปิดใช้งานเซิร์ฟเวอร์ DNS ภายใน

เรายังสามารถสร้างไฟล์ เครือข่ายบริดจ์ที่ผู้ใช้กำหนดเองโซลูชันเหล่านี้จะแยกกลุ่มคอนเทนเนอร์ออกจากกันและให้บริการ DNS ภายใน ทำให้คอนเทนเนอร์สามารถระบุชื่อภายในเครือข่ายส่วนตัวของตนเองได้ง่ายขึ้น ช่วยให้แยกบริการที่ไม่ควรเห็นกันได้ง่ายขึ้น และให้การควบคุม MTU ไฟร์วอลล์ และการตั้งค่าอื่นๆ ได้มากขึ้น

ในสภาพแวดล้อมที่มีความก้าวหน้ามากขึ้น สามารถใช้งานได้ ใช้เครือข่าย macvlan หรือ ipvlan เพื่อเชื่อมต่อคอนเทนเนอร์เข้ากับเครือข่ายทางกายภาพโดยตรง Macvlan ช่วยให้คอนเทนเนอร์สามารถสื่อสารกันได้ ในขณะที่ ipvlan มักจะแยกคอนเทนเนอร์ออกจากกันมากกว่า ซึ่งตัวเลือกเหล่านี้มีประโยชน์ในการใช้งานที่แต่ละคอนเทนเนอร์จำเป็นต้องถูกมองว่าเป็นโฮสต์จริงโดยส่วนที่เหลือของเครือข่าย

เครือข่ายไร้ราก: slirp4netns และ pasta

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

นั่นคือจุดที่มันเข้ามาเล่น slirp4netns กลไกคลาสสิกที่ Podman rootless ใช้โปรเจกต์นี้สร้างสภาพแวดล้อมเครือข่ายที่แยกต่างหากภายในคอนเทนเนอร์ และใช้โมดูล slirp ของเคอร์เนลในการแปลงที่อยู่ (NAT) และอนุญาตให้คอนเทนเนอร์เข้าถึงอินเทอร์เน็ตผ่านเครือข่ายของโฮสต์

ในทางปฏิบัติ slirp4netns สร้างอินเทอร์เฟซ TAP ภายในเน็ตเวิร์กเนมสเปซของคอนเทนเนอร์ (ตัวอย่างเช่น tap0 ที่มี IP 10.0.2.100 และเกตเวย์ 10.0.2.2) และกำหนดเส้นทางการรับส่งข้อมูลผ่านสแต็ก TCP/IP ที่ใช้งานในพื้นที่ผู้ใช้ วิธีการนี้ใช้งานได้ แต่เพิ่มภาระและข้อจำกัดบางประการ

ข้อจำกัดประการหนึ่งก็คือ ผู้ใช้ที่ไม่ได้รับสิทธิ์พิเศษไม่สามารถใช้พอร์ตที่มีหมายเลขต่ำกว่า 1024 ได้พารามิเตอร์ sysctl net.ipv4.ip_unprivileged_port_start จะระบุว่าพอร์ตใดถือเป็น "พอร์ตที่ไม่ได้รับสิทธิ์พิเศษ" (โดยค่าเริ่มต้นคือ 1024) แต่สามารถปรับเปลี่ยนได้อย่างระมัดระวังหากรูปแบบความปลอดภัยอนุญาต

ใน Podman 5 ฟังก์ชัน slirp4netns ถูกแทนที่ด้วย โดยค่าเริ่มต้น การวางจะเป็นกลไกที่ไม่ต้องพึ่งพารากPasta ทำงานในพื้นที่ผู้ใช้โดยสมบูรณ์เช่นกัน แต่ด้วยอินเทอร์เฟซ tap และเทคนิค zero-copy ทำให้ได้ประสิทธิภาพเครือข่ายที่ใกล้เคียงกับแบบเนทีฟ ลดผลกระทบต่อความหน่วงและปริมาณงานเมื่อเทียบกับ slirp4netns

เชื่อมต่อและโฮสต์เครือข่ายในคอนเทนเนอร์แบบ rootless

แม้จะทำงานในโหมดที่ไม่ต้องใช้สิทธิ์ root เราก็สามารถทำได้ เชื่อมต่อคอนเทนเนอร์แบบ rootless เข้ากับเครือข่ายบริดจ์ "podman" ตามค่าเริ่มต้น โดยใช้ –network=podman วิธีนี้จะใช้ประโยชน์จากความสามารถของ netavark และแมปพอร์ตไปยังโฮสต์ด้วย -p เช่นเดียวกับในโหมด rootful

ก็สามารถสร้างได้เช่นกัน เครือข่ายบริดจ์ที่ผู้ใช้กำหนดเองในสภาพแวดล้อมแบบไร้รากในกรณีนี้ บริดจ์และอุปกรณ์ที่เกี่ยวข้องไม่ได้ถูกสร้างขึ้นในเน็ตเวิร์กเนมสเปซส่วนกลางของโฮสต์ แต่จะอยู่ในเนมสเปซของผู้ใช้ ดังนั้นจากโฮสต์เราจะไม่สามารถมองเห็นอินเทอร์เฟซเหล่านั้นได้ด้วยคำสั่ง sudo ip a ง่ายๆ

เพื่อตรวจสอบสะพานที่ไร้รากเหล่านี้ พอดแมนจึงเสนอคำสั่ง podman unshare –rootless-netnsการดำเนินการนี้จะเปิดเชลล์ในเน็ตเวิร์กเนมสเปซของผู้ใช้ จากนั้นจึงสามารถสังเกตบริดจ์ภายในและตรวจสอบการเชื่อมต่อโดยตรงไปยังคอนเทนเนอร์ได้

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

อีกด้านหนึ่งคือ เครือข่ายโฮสต์ (–network=host)ในโหมดนี้ คอนเทนเนอร์จะใช้สแต็กเครือข่ายร่วมกับโฮสต์โดยไม่มีที่อยู่ IP ของตัวเอง หากคอนเทนเนอร์แบบ rootless เริ่มเซิร์ฟเวอร์บนพอร์ต 8080/tcp บริการนั้นจะพร้อมใช้งานโดยตรงบนพอร์ต 8080 ของโฮสต์ ซึ่งจะช่วยประหยัดการแมปพอร์ต แต่ลดระดับการแยกตัวลง

Podman Desktop, เครื่องมือสร้างภาพ และการจัดการระบบภายในเครื่อง

สำหรับผู้ที่ชื่นชอบภาพประกอบมากกว่า Podman Desktop เป็นสภาพแวดล้อมแบบกราฟิก เพื่อจัดการคอนเทนเนอร์ พอด อิมเมจ และการกำหนดค่าเครือข่ายบนเครื่องพัฒนา โดยทำหน้าที่เป็นทางเลือกโดยตรงแทน Docker Desktop แต่ใช้กลไกแบบไร้เดมอน (daemonless engine)

การเก็บภาพทำได้ด้วย คำสั่ง `podman pull` จะดาวน์โหลดข้อมูลจากรีจิสทรีที่กำหนดไว้ในไฟล์ `/etc/containers/registries.conf`หากเราระบุรูปภาพโดยไม่ระบุชื่อระเบียน Podman จะพยายามค้นหารูปภาพนั้นตามลำดับระเบียนที่กำหนดค่าไว้ โดยใช้แท็กใหม่ล่าสุดเป็นค่าเริ่มต้น

นอกเหนือจาก CLI ของ Podman แล้ว เรายังสามารถใช้... skopeo เป็นเครื่องมือเฉพาะสำหรับการจัดการ ตรวจสอบ และคัดลอกรูปภาพ ระหว่างรีจิสทรีและที่เก็บข้อมูลในเครื่อง คำสั่งต่างๆ เช่น คัดลอก ลบ หรือซิงค์ ช่วยให้คุณสามารถทำการซิงค์ข้อมูลระหว่างที่เก็บข้อมูลโดยอัตโนมัติ ทำเครื่องหมายรูปภาพสำหรับการเก็บกวาดขยะ หรือย้ายอาร์ติแฟกต์ระหว่างสภาพแวดล้อมต่างๆ ได้

เมื่อดาวน์โหลดภาพแล้ว คำสั่ง `podman run` อนุญาตให้เริ่มต้นคอนเทนเนอร์โดยระบุการขนส่งและเส้นทาง (โดยค่าเริ่มต้น Docker จะขนส่งและค้นหาในรีจิสทรีที่กำหนดค่าไว้) ตัวเลือกทั่วไป (-d, -p, --name, --pod เป็นต้น) ครอบคลุมทั้งสถานการณ์ในห้องปฏิบัติการและการใช้งานจริงที่จริงจังมากขึ้น

การบริหารจัดการประจำวันเสร็จสมบูรณ์ด้วย ใช้คำสั่ง `podman ps` เพื่อแสดงรายการคอนเทนเนอร์ ใช้คำสั่ง `podman stop / start` เพื่อหยุดหรือเริ่มอินสแตนซ์ที่มีอยู่ และใช้คำสั่ง `podman rm` เพื่อลบคอนเทนเนอร์ที่หยุดทำงานแล้วหากคอนเทนเนอร์ถูกแก้ไข และเราต้องการแปลงเป็นอิมเมจใหม่ คำสั่ง podman commit จะบันทึกการเปลี่ยนแปลงเหล่านั้นภายใต้ชื่อใหม่

  ระบบไฟล์แบบกระจาย: 8 สิ่งสำคัญที่ต้องจำ

Pods และโมเดลการดำเนินการขั้นสูงด้วย Podman

Podman ได้รับแรงบันดาลใจจาก Kubernetes และช่วยให้ จัดกลุ่มคอนเทนเนอร์เข้าเป็นพ็อดที่ใช้สแต็กเครือข่ายและทรัพยากรบางอย่างร่วมกันนี่เป็นรูปแบบที่สมบูรณ์แบบสำหรับสิ่งต่างๆ เช่น ฐานข้อมูลและไคลเอนต์ หรือไมโครเซอร์วิสหลายตัวที่ต้องการสื่อสารกันด้วยความหน่วงต่ำ

คำสั่ง `podman pod create` สร้างพ็อดใหม่ และส่งคืน ID ของมัน แต่โดยค่าเริ่มต้น พอดจะยังคงหยุดทำงานจนกว่าคอนเทนเนอร์ที่เกี่ยวข้องจะเริ่มต้น หรือถูกเรียกใช้งานอย่างชัดเจนด้วยคำสั่ง podman pod start

หากต้องการดูว่ามีพ็อดใดบ้างในระบบ คุณใช้คำสั่งต่อไปนี้ พอดแมน พอด แอลเอสนอกจากนี้ ยังจะแสดงรายการคอนเทนเนอร์ INFRA ที่เชื่อมโยงกับแต่ละพ็อดด้วย คอนเทนเนอร์พิเศษนี้ทำหน้าที่รักษาเครือข่ายและทรัพยากรที่ใช้ร่วมกันอื่นๆ ของพ็อดให้ทำงานได้ ดังนั้นจำนวนคอนเทนเนอร์จึงไม่เป็นศูนย์

Podman มีคำสั่งเฉพาะสำหรับ เริ่ม หยุด หรือรีสตาร์ทพ็อดทั้งหมด (podman pod start/stop/restart)แต่เรายังสามารถดำเนินการเฉพาะกับคอนเทนเนอร์ที่ระบุภายในพ็อดโดยไม่ต้องแก้ไขส่วนที่เหลือ ซึ่งจะช่วยรักษาการแยกกระบวนการในระดับแอปพลิเคชันได้

หากต้องการเพิ่มคอนเทนเนอร์เพิ่มเติมลงในพ็อดที่มีอยู่แล้ว คุณจะใช้ podman run –pod POD_NAMEใช้ไวยากรณ์เดียวกันกับคอนเทนเนอร์แต่ละตัว ไม่สามารถ "ลบ" คอนเทนเนอร์ออกจากพอดได้โดยไม่ทำลายพอดนั้นก่อน เนื่องจากสถานะการเป็นสมาชิกของพอดนั้นเชื่อมโยงกับวงจรชีวิตของมัน

การกำกับดูแลเสร็จสิ้นลงด้วย ใช้คำสั่ง `podman ps --pod` หรือคำสั่งเฉพาะอื่นๆ เพื่อตรวจสอบกระบวนการทำงานของคอนเทนเนอร์ทั้งหมดในพอดทั้งหมดโดยสามารถระบุได้อย่างรวดเร็วว่าสิ่งใดอยู่ในกลุ่มใด และมีการจัดสรรบริการอย่างไร

คอนเทนเนอร์, LXC และการจำลองเสมือนแอปพลิเคชัน

แม้ว่า Docker และ Podman จะเป็นหัวข้อหลักในการพูดคุย แต่... นี่ไม่ใช่ตัวเลือกการสร้างคอนเทนเนอร์เพียงอย่างเดียวใน GNU/Linuxมีโซลูชันต่างๆ เช่น LXC/LXD, systemd-nspawn หรือ Kata Containers ที่เข้าถึงปัญหาจากมุมมองที่แตกต่างกันบ้าง

LXC ให้บริการ คอนเทนเนอร์ระบบที่มีน้ำหนักเบามาก โดยมีชื่อโฮสต์ ที่อยู่ IP ระบบไฟล์ และกระบวนการเริ่มต้น (init) ที่สมบูรณ์เป็นของตัวเองเมื่อใช้งานร่วมกับ LXD ซึ่งทำหน้าที่เป็นไฮเปอร์ไวเซอร์สำหรับคอนเทนเนอร์และเครื่องเสมือน คุณจะได้รับประสบการณ์ที่ใกล้เคียงกับการมีเครื่องขนาดเล็กหลายเครื่องพร้อมประสิทธิภาพเกือบเทียบเท่ากับเครื่องจริง

ในขณะที่ Docker/Podman มุ่งเน้นไปที่... คอนเทนเนอร์แอปพลิเคชันที่เข้ากันได้กับ OCILXC โดดเด่นเมื่อต้องการสภาพแวดล้อมแบบถาวรที่มีบริการและกระบวนการหลายอย่าง ซึ่งทำงานคล้ายกับเครื่องเสมือน (VM) แต่ใช้ทรัพยากรน้อยกว่า และผสานรวมเข้ากับเคอร์เนลของ Linux ได้อย่างเป็นธรรมชาติ

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

นอกจากนี้ พวกเขายังได้รับความแข็งแกร่งเพิ่มขึ้นอีกด้วย เทคโนโลยีที่มุ่งเน้นไปที่ไมโคร VM และการแยกส่วนที่แข็งแกร่ง เช่น Kata Containersตัวเลือกเหล่านี้จะเรียกใช้งานแต่ละพอดภายในเครื่องเสมือนขนาดเล็กที่มีเคอร์เนลเป็นของตัวเอง ในขณะที่ gVisor จะแทรก "แซนด์บ็อกซ์เคอร์เนล" ที่เขียนด้วยภาษา Go ระหว่างแอปพลิเคชันและ Linux ทั้งสองวิธีนี้ช่วยลดการพึ่งพาเคอร์เนลที่ใช้ร่วมกันและเข้าใกล้โมเดลความปลอดภัยของเครื่องเสมือน (VM) ในขณะที่ยังคงรักษาความสะดวกในการใช้งานของคอนเทนเนอร์ไว้

แนวทางปฏิบัติที่ดีที่สุดสำหรับการเสริมความปลอดภัยให้กับ Docker และ Podman

จากที่กล่าวมาทั้งหมด แนวทางที่เหมาะสมสำหรับแพลตฟอร์มคอนเทนเนอร์ที่แข็งแกร่งคือการทำงานเป็นชั้นๆ: การแบ่งส่วนด้วยเนมสเปซ/cgroups, นโยบายการกรองด้วย seccomp และ MAC และการจำกัดสิทธิ์เชิงโครงสร้างโดยใช้โหมด rootless.

ในทางปฏิบัติ แนะนำให้ยึดถือมาตรฐานดังต่อไปนี้ ควรเรียกใช้คอนเทนเนอร์ในโหมดที่ไม่ใช้สิทธิ์ root ทุกครั้งที่เป็นไปได้โดยเฉพาะในสภาพแวดล้อมที่มีผู้เช่าหลายรายหรือภายในระบบคลาวด์แบบใช้ร่วมกัน Podman ช่วยอำนวยความสะดวกในเรื่องนี้ได้ทันที และ Docker rootless ก็ยึดหลักการเดียวกันเมื่อต้องการความเข้ากันได้

เคอร์เนลของโฮสต์จะต้อง หมั่นอัปเดตแพทช์รักษาความปลอดภัยอยู่เสมอช่องโหว่ต่างๆ เช่น Dirty COW, Dirty Pipe และอื่นๆ จะได้รับการแก้ไขด้วยการอัปเดต ซึ่งต้องดำเนินการอย่างรวดเร็วหากเราไม่ต้องการเปิดช่องโหว่ให้ศัตรูหลุดออกจากคอนเทนเนอร์ได้

มาตรการที่มีประสิทธิภาพมากอีกอย่างหนึ่งคือการใช้ ระบบปฏิบัติการแบบคอนเทนเนอร์ที่ไม่สามารถเปลี่ยนแปลงได้ เช่น openSUSE MicroOS หรือ Flatcar Linuxระบบรูทแบบอ่านอย่างเดียวและระบบอัปเดตแบบอะตอมิกช่วยลดช่องโหว่ด้านความปลอดภัยได้อย่างมาก และอำนวยความสะดวกในการย้อนกลับหากเกิดข้อผิดพลาดหลังจากการอัปเดตแพทช์

เกี่ยวกับการตั้งค่า: ไม่มีคอนเทนเนอร์ที่มีสิทธิพิเศษใดๆ ในการใช้งานจริง ยกเว้นในกรณีที่มีการควบคุมอย่างเข้มงวดเป็นพิเศษอย่าเรียกใช้แอปพลิเคชันในฐานะผู้ใช้ root ภายในคอนเทนเนอร์ ใช้ระบบไฟล์แบบอ่านอย่างเดียวเมื่อทำได้ และจำกัดความสามารถให้น้อยที่สุดเท่าที่จะเป็นไปได้ โปรไฟล์ SELinux/AppArmor และ seccomp ที่ปรับแต่งให้เหมาะสมกับการเรียกใช้งานจริงของแอปพลิเคชันนั้นแทบจะเป็นสิ่งที่จำเป็น

สุดท้ายนี้เราต้องไม่ลืมส่วนที่เกี่ยวกับ การตรวจสอบเวลาในการดำเนินการเครื่องมืออย่าง Falco, Sysdig Secure หรือ Aqua ช่วยตรวจจับความผิดปกติ ความพยายามหลบหนี (เช่น การเข้าถึง /proc หรือ /sys ที่ผิดปกติ) การรับส่งข้อมูลเครือข่ายที่ผิดปกติ หรือคำสั่งที่น่าสงสัย ทำให้มีเวลาในการตอบสนองก่อนที่การโจมตีจะเกิดขึ้น

ด้วยการผสมผสานการจำลองเสมือนแบบคลาสสิกเข้ากับ KVM, คอนเทนเนอร์ที่จัดการโดย Podman (โดยเฉพาะอย่างยิ่งในโหมด rootless), เครือข่ายที่มีการแบ่งส่วนอย่างดี และแนวทางการรักษาความปลอดภัยที่ดี จะสามารถสร้างแพลตฟอร์มการจำลองเสมือนที่มีความยืดหยุ่นสูงและปลอดภัยมากได้ การเข้าใจว่าเคอร์เนลที่ใช้ร่วมกันเป็นจุดสำคัญที่สุด การใช้ VM หรือ micro-VM เมื่อความเสี่ยงหรือข้อกำหนดด้านกฎระเบียบกำหนด และการจัดการห่วงโซ่อุปทานของอิมเมจอย่างรอบคอบ จะทำให้เกิดความแตกต่างระหว่างสภาพแวดล้อมในห้องปฏิบัติการและโครงสร้างพื้นฐานที่พร้อมใช้งานจริง

ประเภทของการจำลองเสมือนเซิร์ฟเวอร์
บทความที่เกี่ยวข้อง:
ประเภทของการจำลองเสมือนเซิร์ฟเวอร์

สารบัญ