[TOC] # 什麼是虛擬化 虛擬化是一種技術,允許電腦與多個數位分隔的環境共用其硬體資源。每個虛擬化環境都在其設定的資源內執行,例如記憶體、處理能力和儲存空間。透過虛擬化,組織可以在同一伺服器上的不同作業系統之間切換而無需重新啟動。 # 虛擬化歷史 > 1950 年代,電腦還算是稀缺品,而虛擬化是為了解決在開發作業系統的時候如何 debug、分析新版的作業系統,當時 IBM 的 System/360 的開發過程就是在舊版的作業系統之上,去執行新的作業系統 ## 虛擬化的出現 - **1959: 分時共用與虛擬化概念** - Christopher Strachey 發表論文,提出「一虛多」的概念 - Director 建立隔離環境,控制程式分時運作 (time sharing),類似早期的 Hypervisor :::info ### Time Sharing - **分時概念** - 分時作業系統是多工技術的延伸。CPU 以極快的切換速度讓每個使用者都感覺到好像在獨占電腦 - **運作原理** - 同時讓多個使用者使用一台電腦,每個人都有自己的程式在記憶體中 - CPU 依序給予每個程式短暫的使用時間 (大約 10 至 100 毫秒),讓系統快速切換 ![截圖 2025-03-22 下午3.37.33](https://hackmd.io/_uploads/H1QROJ2n1x.png) ![ 2025-03-22 下午6.32.50](https://hackmd.io/_uploads/Hk8gffnh1l.png) [參考資料](https://www.geeksforgeeks.org/time-sharing-operating-system/) [圖片來源](https://www.geeksforgeeks.org/time-sharing-operating-system/) ::: ## 虛擬化技術普及 - **1960-80 年代** - 主要用於大型主機;隨著 x86 平台興起,Linux x86 伺服器逐漸取代大型主機和小型主機,促使 x86 虛擬化需求增長 :::info ### x86 是什麼 | 特性 | x86 | x86-64 | |:------------:|:------------------------------------------------ |:------------------------------------- | | CPU 體系結構 | 廣泛使用的 32 bit CPU 架構 | 基於 x86 架構,擴展為 64 bit | | 指令集 | 複雜指令集電腦(CISC),可在單一週期執行多條指令 | 保留 x86 指令集,同時支援 64 bit 運算 | | 記憶體處理 | 限制於 32 bit 記憶體空間 | 能更有效地處理大量記憶體與資料 | | 相容性 | — | 向後相容 32 bit x86 軟體 | [參考資料](https://www.lenovo.com/tw/zh/glossary/x86/) ### 指令集 Instruction Set Architecture (ISA) - ISA 是指電腦處理器可以理解和執行的指令集 - 指令集分為兩大類 #### CISC vs RISC | 特性 | RISC (精簡指令集) | CISC (複雜指令集) | |:--------:|:-------------------------------------- |:-------------------------------------- | | 全名 | Reduced instruction set computer | Complex Instruction Set Computer | | 指令數量 | 少且簡單 | 多且複雜 | | 設計重點 | 高效、快速執行 | 靈活、功能豐富 | | 執行效率 | 執行速度快 | 可直接完成複雜操作,速度較慢 | | 舉例 | 就像速食店廚師,菜單流程固定且快速出餐 | 就像大廚,多技能整合,獨立完成佳餚製作 | [參考資料](https://www.lenovo.com/tw/zh/glossary/instruction-set-architecture/) ::: <!-- - **1990年代:** - 1997年,斯坦福大學發表 DISCO,採用全虛擬化技術。 - 1998年 VMware 成立並發布了第一個支援 x86 架構的作業系統 - VMware Workstation。 - **2000年代初:** - 2003年,劍橋大學推出開源半虛擬化系統 Xen。 - QEMU 利用動態二進制翻譯實現跨平台模擬。 - **2005 年以後:** - x86 硬體廠商推出硬體輔助虛擬化(Intel VT、AMD-V),大幅提升效能。 - 2007年,Linux 核心加入 KVM,與 QEMU 搭配成為主流開源虛擬化方案。 ## 虛擬化蓬勃發展 - **新型硬體虛擬化:** 利用多核 GPU、RDMA、FPGA 等新硬體,硬體輔助虛擬化效能接近物理資源(如 gVirt、GPUvm)。 - **多虛一虛擬化:** 將多台機器資源整合成單一虛擬機,解決記憶體和運算瓶頸(如 GiantVM)。 - **輕量容器虛擬化:** 從 chroot、Jail 到 Docker 和 Kubernetes,實現快速且輕量的應用隔離。 [參考資料](https://developer.aliyun.com/article/1528282) --> # 為什麼虛擬化很重要? 想像這樣的情境:你可以同時運行多個不同服務或應用程式 (例如:Web 服務、資料庫服務、檔案伺服器等),且它們彼此獨立運行、不會互相干擾。這就是虛擬化能帶給你的彈性與效能優勢。 ## 虛擬化範例 以下是一個以「需要同時運行多個開發環境」的公司為例,來說明虛擬化的好處: - **需要同時執行不同作業系統** - 某些團隊需要在 Windows 環境開發,另一些團隊則需要 Linux 或 macOS 環境 - 虛擬化可以讓同一台實體伺服器同時運行多個 OS,彼此間互不干擾,且可以針對不同需求動態分配硬體資源 (CPU、RAM、硬碟空間) ## 傳統 vs. 虛擬化 | 項目 | 傳統實體 | 虛擬化 | |:------------:|:---------------------------------------------- |:------------------------------------------------ | | **資源配置** | 一台伺服器對應一個服務或系統,資源利用率較低 | 一台實體伺服器可同時執行多個虛擬機,資源彈性分配 | | **管理維護** | 新增或調整服務時,需購置或重新配置硬體 | 可以透過軟體快速部署、移轉與備份虛擬機 | | **可用性** | 若實體伺服器故障,該伺服器上的服務全部停擺 | 單一虛擬機故障不影響其他虛擬機,可快速啟動備援 | | **成本考量** | 需要為每個服務或系統預先採購並預留硬體資源 | 可集中管理與整合資源,減少硬體與能耗成本 | | **擴充性** | 擴充往往需要額外添購實體伺服器,時間與費用較高 | 透過虛擬化技術或雲端服務,能夠更快速且彈性地擴充 | [參考資料](https://aws.amazon.com/tw/what-is/virtualization/) ## 傳統、虛擬化架構差異 ### 傳統架構 ![截圖 2025-03-22 下午5.14.59](https://hackmd.io/_uploads/Syoj1Zh3Jx.png) [圖片來源](https://www.alibabacloud.com/tc/knowledge/what-is-virtualization?_p_lc=1) 1. **單一實體伺服器對應單一作業系統** - 在傳統模式下,一台實體伺服器(電腦)通常只安裝一個作業系統 (OS),並執行特定的應用程式或服務。 2. **硬體資源利用率較低** - 即使伺服器負載不高,也無法輕易地把閒置的 CPU、記憶體或儲存空間釋放給其他系統使用。 3. **當應用程式需要運算資源** - 應用程式 -> 作業系統 -> 主機 ![截圖 2025-03-22 下午5.30.24](https://hackmd.io/_uploads/rkLrQZn3Jl.png) [圖片來源](https://ithelp.ithome.com.tw/articles/10289701?sc=iThelpR) ### 虛擬化架構 ![截圖 2025-03-22 下午5.15.26](https://hackmd.io/_uploads/B1JRkW32ke.png) [圖片來源](https://www.alibabacloud.com/tc/knowledge/what-is-virtualization?_p_lc=1) 1. **單一實體伺服器可運行多個作業系統** - 透過虛擬化技術,能在一台硬體上同時執行多個虛擬機器(VM),每個 VM 都可安裝不同的作業系統 (Linux、Windows 等)。 2. **Hypervisor(虛擬化層)** - Hypervisor 以軟體的方式呈現,負責將硬體資源 (CPU、RAM、Storage、網路等) 動態分配給不同的虛擬機使用 - 虛擬化層可以被視為在硬體與作業系統之間多出的一層抽象層 3. **優點** - 提高資源利用率:系統負載不高時,閒置的硬體資源可立即釋放或分配給其他虛擬機,整體效能更佳 - 彈性部署與隔離:不同作業系統或應用程式間相互隔離,若某個虛擬機發生故障,不會影響其他虛擬機 4. **當應用程式需要運算資源** - Guest OS ➡️ hypervisor ➡️ 硬體 [參考資料](https://ithelp.ithome.com.tw/articles/10289701?sc=iThelpR) ### Hypervisor (VMM - virtual machine monitor) - **定義:** Hypervisor 是一種軟體,可集中管理處理器、記憶體和儲存裝置等資源,並將這些資源分配給多個虛擬機。 - **作用:** 它讓單一實體機器能同時運行多個虛擬機,就像一個主管分配資源給不同的部門。 - **名詞說明:** - 實體硬體稱為「主機」(Host) - 使用資源的虛擬機稱為「客戶機」(Guest) #### Hypervisor 類型 ![截圖 2025-03-22 下午5.43.02](https://hackmd.io/_uploads/ryUOUW33yx.png) [圖片來源](https://medium.com/@ravipatel.it/understanding-hypervisors-exploring-type-1-vs-type-2-and-full-vs-para-virtualization-71b4dad9abd9) ##### Type-1 Hypervisor (裸機式虛擬機監控程式) - **運作方式:** 直接安裝在實體硬體上,不需要宿主作業系統 - **優點:** 擁有更好的效能與資源使用效率,常用於企業資料中心與雲端環境 - **呼叫流程:** Guest OS ➡️ hypervisor (幫忙分配主機運算資源) ➡️ 硬體 ##### Type-2 Hypervisor (宿主式虛擬機監控程式) - **運作方式:** 安裝在已有的宿主作業系統上,再在其上執行虛擬機 - **特性:** 依賴宿主作業系統管理硬體與驅動程式,適合桌面或開發環境 - **呼叫流程:** Guest OS ➡️ Hypervisor ➡️ Host OS ➡️ 硬體 | 特性 | **Type 1** | **Type 2** | |:--------:|:------------------------------ |:-------------------------------------------------------- | | 安裝位置 | 直接在實體硬體上安裝 | 安裝在已有的作業系統上 | | 系統依賴 | 不需要宿主作業系統 | 依賴宿主作業系統管理硬體和驅動 | | 性能表現 | 效能較佳,資源使用效率高 | 相對效能較低,適合桌面與開發環境 | | 使用場景 | 企業資料中心、大型伺服器 | 個人電腦、輕量級測試或開發 | | 範例 | VMware ESXi、Microsoft Hyper-V | VMware Workstation、Oracle VirtualBox、Parallels Desktop | [參考資料 1](https://medium.com/@ravipatel.it/understanding-hypervisors-exploring-type-1-vs-type-2-and-full-vs-para-virtualization-71b4dad9abd9) [參考資料 2](https://www.redhat.com/en/topics/virtualization/what-is-a-hypervisor) # 什麼是虛擬機器 (VM)? 虛擬機器 (VM) 可視為「由軟體組成的電腦」,用來執行在實體電腦上運行的任何軟體。就像實體機器一樣,虛擬機器也有自己的作業系統 (Windows、Linux 等)、儲存、網路、組態設定及軟體,而且與在該主機上執行的其他虛擬機器完全隔離。 ## 虛擬機器如何運作? - 單一實體機透過虛擬化技術運行多個獨立環境 - 虛擬機管理程式建立資源池,按需分配 CPU、網路與儲存資源 - 資源需求增加時,管理程式會動態調整分配 - 虛擬機就像「電腦中的電腦」,可同時運行多個獨立系統 - 使用者可獨立更新系統設定和應用程式 [參考資料 ](https://www.nutanix.com/tw/info/virtual-machine#howworks) ## Container ![截圖 2025-03-22 晚上7.00.09](https://hackmd.io/_uploads/HJJIuznnyl.png) [圖片來源](https://www.oracle.com/tw/cloud/compute/virtual-machines/what-is-virtual-machine/) - Container 是一個封裝應用程式所需元件和功能的軟體單位 - 現代應用常由多個 container 組成,每個都負責特定任務 - Container 體積小 (以 MB 計),使用 container runtime 取代 hypervisor,提供更快、更靈活的隔離方式 <!-- :::info ### container runtime ![截圖 2025-03-27 下午3.18.13](https://hackmd.io/_uploads/HyXPnOMTJx.png) [圖片來源](https://zhuanlan.zhihu.com/p/338036211) - **定義:** Container Runtime 是在 Host OS 上執行容器所需的基礎軟體,負責從容器映像檔的下載、容器的建立與生命週期管理,到在系統上實際執行容器。 - **主要類型** - Low-Level Container Runtime - 這類工具直接實現了容器的基本功能(建立、啟動、停止)。 - containerd 雖然提供一個 API 介面,但它在底層依賴這些 Low-Level 工具來真正執行容器操作。 - 例如:runC、crun、runhcs。 - High-Level Container Runtime - 這類工具不僅負責容器的執行,還整合了映像檔管理、容器編排等更多功能。 - 它們提供一個完整的工具集,方便開發者和運維人員管理容器應用。 - 例如:Docker Engine、Podman、CRI-O。 [參考資料1](https://sysdig.com/learn-cloud-native/what-are-container-runtimes/) [參考資料2 ](https://ithelp.ithome.com.tw/m/articles/10322909) [參考資料3](https://www.wiz.io/academy/container-runtimes) ::: --> #### 方便遷移 - 就像 LEGO 組件,container 可以輕鬆在不同環境間移動 - 封裝後的應用及其依賴,可在開發者筆電、資料中心、雲端或邊緣裝置中一致運行 [參考資料 ](https://www.redhat.com/en/topics/containers/containers-vs-vms) | 項目 | 虛擬機 (VM) | 容器 (Container) | |:------:|:------------------ |:------------------ | | 定義 | 獨立虛擬電腦 | 封裝應用及其依賴 | | 隔離 | 完全隔離 | 輕量隔離,共用核心 | | 啟動 | 啟動較慢,資源較重 | 啟動迅速,資源輕巧 | | 管理 | 需獨立作業系統 | 運行在宿主 OS 上 | | 可攜性 | 較重但可跨平台 | 高度可攜,易轉移 | # 虛擬化類型 ![截圖 2025-03-24 晚上8.36.49](https://hackmd.io/_uploads/B1HgzR0hyl.png) [圖片來源](https://www.geeksforgeeks.org/virtualization-cloud-computing-types/) ## 網路虛擬化 (Network Virtualization) ![截圖 2025-03-24 晚上9.06.57](https://hackmd.io/_uploads/rJ9Zt003Je.png) [圖片來源](https://www.techtarget.com/searchnetworking/What-is-network-virtualization-Everything-you-need-to-know) - **定義** 將傳統由硬體提供的網路資源轉為軟體服務。可整合多個實體網路為一個虛擬網路,或將單一實體網路劃分為多個獨立虛擬網路 - **運作原理:** - 利用軟體建立網路覆蓋層(overlay),在現有的實體網路之上建立一層虛擬的網路結構 - 由 SDN 控制器管理,可隨時根據使用者需求更改虛擬網路的配置、分配和釋放網路資源,依據策略分配給不同工作運行 - **優點** - 部署速度快: 可從數週縮短至數分鐘 - 自動化管理: 提高運作效率,減少人為操作 - 靈活性高: 工作負載可獨立於實體外自由移動,且易於擴展 - **缺點** - 虛擬網路蔓延: 輕易建立虛擬網路可能導致資源浪費與網路複雜化 - 網路架構轉變: 轉型時需重新評估 CPU、儲存及安全需求 - 網路可視性下降: 多層虛擬化使傳統監控工具難以全面掌握流量 :::info ## SDN (Software Defined Network) <center> ![A-basic-SDN-architecture](https://hackmd.io/_uploads/S15mpRJTyg.png) </center> [圖片來源](https://www.techtarget.com/searchnetworking/What-is-network-virtualization-Everything-you-need-to-know) 為軟體定義網路,指透過軟體進行網路架構的調整與設定 - 重點: 將網路的**控制層**與**資料層**分離 > 傳統網路設備像是 switch 或是 router,控制層 (control plane) 和資料傳送層 (data plane) 是結合在同一台設備中,設備同時執行路由協定、規則決策 (控制層) 以及封包轉送 (資料層)。當這兩層分開後,網路設備就能夠專注在資料傳輸,並透過 SDN 控制器 (controller) 下的規則來設定封包如何轉送或丟棄。這種集中化的控制設計使得網路管理更靈活、可程式化,也更能自動化與快速地調整網路行為。 - 作用: SDN (就像網路的大腦) 集中管理所有網路設備,決定如何轉發封包 - 結果: 網路設備只負責執行封包轉發指令,提高整體網路管理效率 - 優點 - 可以有效規劃出最佳傳輸路徑 - 使用者可以彈性調整網路架構 [參考資料1](https://medium.com/@kenken880929/networking-essentials-sdn-58560e1e36c8) [參考資料2](https://medium.com/@RiverChan/sdn%E8%88%87nfv%E7%9A%84%E5%8D%80%E5%88%A5%E5%92%8C%E9%97%9C%E4%BF%82-3a15692bb3f6) ::: [參考資料1](https://www.vmware.com/topics/network-virtualization) [參考資料2](https://www.geeksforgeeks.org/virtualization-cloud-computing-types/) [參考資料3](https://www.techtarget.com/searchnetworking/What-is-network-virtualization-Everything-you-need-to-know) <!--## 桌面虛擬化(Desktop Virtualization) ![截圖 2025-03-24 晚上9.48.00](https://hackmd.io/_uploads/HJf3G11akg.png) [圖片來源](https://www.researchgate.net/figure/A-basic-SDN-architecture_fig1_323028955) - **定義:** - 將桌面環境(作業系統、應用程式、資料)從實體設備分離,集中在伺服器或雲端上運行。使用者可透過桌機、筆電、平板或手機遠端存取自己的桌面 - **運作原理:** - 虛擬化伺服器(Hypervisor)負責建立與管理多個虛擬桌面。使用者登入後,透過連線代理(Connection Broker)連接到各自的虛擬桌面。遠端虛擬化是桌面環境在資料中心或雲端運行,適合遠端辦公 - **優點:** - 安全性提升:資料集中管理,降低終端設備丟失或被竊風險 - 簡化管理:集中更新和維護,節省 IT 人力與時間 - 成本節省:延長舊設備使用期限,減少昂貴硬體投資 - 靈活性高:使用者可隨時隨地存取桌面,支援遠端與混合工作模式 - **挑戰:** - 可能出現性能與延遲問題,特別是在網路品質不穩時 - 初期投資(伺服器、軟體授權、網路設備)可能較高 - 授權、合規及安全性管理需要特別留意 [參考資料1](https://www.nutanix.com/info/virtualization/desktop-virtualization#software) [參考資料2](https://www.geeksforgeeks.org/virtualization-cloud-computing-types/) --> ## 儲存虛擬化 (Storage Virtualization) <center> ![What-is-Storage-Virtualization](https://hackmd.io/_uploads/BkdTRygT1g.jpg) </center> [圖片來源](https://www.storagetutorials.com/what-storage-virtualization/) - **定義:** - 將多個實體儲存裝置整合為一個虛擬儲存池,讓 IT 人員只需管理一個虛擬設備,而不用單獨管理各個實體裝置 - **運作原理:** 1. **建立虛擬化層** 在儲存虛擬化的流程中,首先透過虛擬化軟體建立一個虛擬化層 2. **劃分與映射硬碟區塊** 實體硬碟會被劃分成小資料區塊,這些區塊被映射後構成虛擬磁碟的內容 3. **建立映射表** 虛擬化軟體利用元資料 (關於資料的資訊) 建立映射表,使資料能夠快速定位並正確導向到相應的硬碟區塊,完成整個虛擬化存取的過程 - **優點:** - 降低成本: 減少傳統硬體冗餘需求,節省前期投資 - 彈性擴展: 可根據需求動態調整儲存容量,不需預先大規模投資 - 簡化管理: 統一管理虛擬儲存池,方便資料遷移與資源調度 - **挑戰:** - 虛擬化會破壞資料端到端的完整性,因此必須將虛擬儲存解決方案與現有工具和系統整合 - 資料安全問題依然存在,虛擬環境可能會吸引新型網路攻擊 :::info ### LVM (Logical Volume Management) ![截圖 2025-03-27 下午2.58.28](https://hackmd.io/_uploads/S1HXPufp1l.png) - **定義:** LVM 的重點在於**可以彈性的調整 filesystem 的容量**。使其可以更容易利用、管理硬碟。當磁區空間不足時,可透過 **VG** 和 **LV** 來做硬碟空間的調整,調整時不會影響到原先存放的資料 - **介紹:** 硬碟上可以切割多個實體 PV (physical volume),然後分配給抽象的 VG (volume group),最後則是由實際使用的 LV (logic volume) 掛載到 OS 內,讓作業系統能夠讀寫這個分區 - **優點:** 使用 LVM 就能將多顆硬碟整合成一個虛擬儲存池,再根據需要動態分配儲存空間,而不用逐一管理每顆硬碟 [參考資料1](https://sean22492249.medium.com/lvm-pv-vg-lv-1777a84a3ce8) [參考資料2](https://ithelp.ithome.com.tw/articles/10080861) [參考資料3](https://www.digitalocean.com/community/tutorials/an-introduction-to-lvm-concepts-terminology-and-operations) ::: [參考資料1](https://www.storagetutorials.com/what-storage-virtualization/) [參考資料2](https://www.hpe.com/tw/en/what-is/storage-virtualization.html) [參考資料3](https://www.geeksforgeeks.org/what-is-storage-virtualization/) [參考資料4](https://www.geeksforgeeks.org/virtualization-cloud-computing-types/) ## 伺服器虛擬化 (Server Virtualization) ![截圖 2025-03-25 下午5.27.39](https://hackmd.io/_uploads/B1nMvlg6yl.png) [圖片來源](https://www.energystar.gov/products/data_center_equipment/5-simple-ways-avoid-energy-waste-your-data-center/virtualize-servers) - **定義:** - 將一台實體伺服器分割成多個獨立的虛擬伺服器,每個虛擬伺服器可獨立運行自己的作業系統與應用程式,隱藏伺服器硬體細節,讓使用者看不到真實硬體配置 - **運作原理:** - 伺服器虛擬化利用 Hypervisor 將實體伺服器的 CPU、記憶體、儲存和網路等資源抽象化,並動態分配給多個虛擬機,使每台虛擬機都能獨立運行自己的作業系統與應用程式,就像獨立的實體伺服器一樣 - **優點:** - 強化災難復原: 硬體故障時可迅速將工作負載轉移至其他實體機,縮短停機時間 - 資源最佳化: 將多個虛擬伺服器整合於單一實體機器上,可最大化硬體利用率,減少實體伺服器數量 - 成本節省: 減少實體硬體採購,進而降低資本支出 - **挑戰:** - 硬體資源需求: 必須確保足夠的 CPU、記憶體與儲存資源,避免資源過度分配導致性能瓶頸 - 資源過度分配風險: 過度超額分配資源可能導致虛擬機間爭奪資源,進而降低整體性能 [參考資料1](https://www.nutanix.com/info/virtualization/server-virtualization#howitworks) [參考資料2](https://www.vmware.com/topics/server-virtualization) [參考資料3](https://www.geeksforgeeks.org/virtualization-cloud-computing-types/) ## 應用程式虛擬化 (Application Virtualization) ![67125735ef7b1d839ed6a749_63a0207a041f5fa536b03b9f_How%20it%20works](https://hackmd.io/_uploads/SJGAMdfTJg.jpg) [圖片來源](https://www.wallarm.com/what/what-is-application-virtualization-by-wallarm) - **定義** - 應用程式虛擬化允許使用者從與應用程式安裝所在的電腦不同的裝置上存取並使用該應用程式。意味著你可以遠端連線到伺服器上使用那個軟體,而無需在本地電腦上實際安裝該應用程式 - **運作原理** - IT 管理員會在資料中心或伺服器上部署應用程式,並透過網路將軟體傳送給使用者的裝置。虛擬化軟體確保應用程式的運作與通訊方式與本地端執行時一致,讓使用者操作時感覺流暢自然,並且伺服器能即時處理使用者指令 - **優點** - 安裝簡單:只需在伺服器上安裝一次,再分發可執行檔供使用者存取 - 高度可攜:虛擬應用程式可在各種裝置上運行 - 維護方便:中央更新或卸載即可同步應用至所有虛擬實例 - 安全強化:隔離運行降低惡意程式對主機及其他虛擬機的威脅 - **挑戰** - 與原生互動:例如防毒軟體需連結本地作業系統,無法完全虛擬化 - 伺服器依賴:使用體驗受伺服器穩定性影響 - 監控困難:虛擬化應用可能妨礙網路監控,難以快速發現瓶頸 [參考資料1](https://www.geeksforgeeks.org/virtualization-cloud-computing-types/) [參考資料2](https://www.nutanix.com/how-to/what-is-application-virtualization) [參考資料3](https://www.citrix.com/glossary/what-is-application-virtualization.html) [參考資料4](https://www.wallarm.com/what/what-is-application-virtualization-by-wallarm) # CPU 特權指令 ![截圖 2025-03-27 下午4.36.41](https://hackmd.io/_uploads/SyKQRKMTyx.png) [圖片來源](https://www.baeldung.com/cs/os-rings) :::info ## **基本概念** x86 指令集架構利用 **Ring** 來劃分不同的權限層級,每一層都有不同的資源存取權限 - **目的** 透過這種層級劃分,可以在同一台電腦上安全地共享資源,避免程式互相干擾,同時保護系統免受不受信任程式的影響 - **為什麼需要 Ring ?** - 防止系統崩潰 - 分層的權限結構確保即使應用程式崩潰,系統核心 (Ring 0) 依然安全,避免整個系統受到影響 - 資料安全與錯誤恢復: - 只有核心 (Ring 0) 能直接存取硬體資源,其他環層的錯誤可透過重啟應用程式來恢復,而不會導致資料丟失或影響 CPU 正常運作 - 提升安全性 - 當某個程序需要大量 CPU 資源時,必須向作業系統請求授權,作業系統可依據安全政策決定是否批准,防止惡意程式濫用資源 ::: ## Ring 等級 ### Ring 0 - 這是作業系統的核心層,由 Kernel 執行 - 在這一層的程式有最高權限,可直接存取 CPU 與系統記憶體 - 若核心層出現錯誤,可能導致整個系統崩潰 ### Ring 3 - 運行在 User mode 下,具有最低權限 - 大部分應用程式皆在此層執行,因此不具備直接存取 CPU 或記憶體的能力 - 所有需要硬體資源的操作,都必須通過請求轉交給 Ring 0 執行 ### Ring 1 and Ring 2 - **Ring 1** - 用於與硬體互動,例如處理與輸入裝置有關的操作 (例如從攝影機取得影像) - 提供比 Ring 3 更高的權限,但不及核心層 (Ring 0) - **Ring 2** - 用來處理與儲存裝置相關的操作,如讀取與寫入檔案 (例如從硬碟讀取 Excel 檔案) - 負責輸入輸出權限,即在 RAM 與儲存間傳輸資料 - **簡單說明** - Ring 1 與 Ring 2 都擁有比 Ring 3 更高的權限,專門用於處理與硬體直接互動的任務,但這些操作不涉及核心層的全面控制 - 例如,Ring 1 處理來自攝影機的即時影像傳輸,而 Ring 2 則處理檔案的讀寫作業,並與 Ring 3 配合完成資料編輯與保存 ## 全虛擬化/半虛擬化 :::info ## 完全虛擬化 vs. 半虛擬化 | 項目 | 完全虛擬化 (Full Virtualization) | 半虛擬化 (Para Virtualization) | |:------------:|:------------------------------------------------- |:------------------------------------------------------------- | | 作業系統意識 | 來 Guest OS 不知情,彷彿直接在實體硬體上運行 | Guest OS 知曉虛擬化環境,需透過特定驅動與 Hypervisor 互動 | | 運作原理 | Hypervisor 模擬完整硬體環境,不需修改來賓作業系統 | 直接透過 paravirtualized 驅動與 Hypervisor 溝通,省去硬體模擬 | | 優點 | 廣泛相容,適用於未修改的作業系統 | 效能較佳,降低虛擬化開銷 | | 缺點 | 硬體模擬可能帶來性能損耗 | 需修改 Guest OS 以支援驅動,兼容性較受限制 | ::: ### 全虛擬化 (Full Virtualization, FV) ![截圖 2025-03-27 下午6.37.53](https://hackmd.io/_uploads/BkiAqsfakx.png) [圖片來源](https://www.geeksforgeeks.org/difference-between-full-virtualization-and-paravirtualization/) 1. **Ring 3: 使用者應用程式 (User App)** - 權限最低的層級,應用程式在此層執行 - 一般非特權指令可直接在此層執行,不需要經過特別的翻譯 2. **Ring 1: 來賓作業系統 (Guest OS)** - 虛擬化環境中的 Guest OS 執行於此層,認為自己擁有完整硬體資源 - 實際上,所有特權指令都會被 VMM 攔截並做二進位轉譯或處理,避免 Guest OS 直接操作硬體 3. **Ring 0: VMM (Virtual Machine Monitor)** - 位於核心層,擁有最高特權,可直接存取實體硬體 - 當 Guest OS 執行需要硬體特權的指令時,VMM 會先攔截,再以安全方式與底層硬體互動 ### 半虛擬化 (Paravirtualization, PV) ![截圖 2025-03-27 下午6.39.41](https://hackmd.io/_uploads/rJ1bsjMT1l.png) [圖片來源](https://www.geeksforgeeks.org/difference-between-full-virtualization-and-paravirtualization/) 1. **Ring 3:使用者應用程式 (User App)** - 權限最低的層級,使用者端的應用程式在此層運行 - 一般的非特權指令可直接執行,不需要透過虛擬化層翻譯 2. **Ring 0:來賓作業系統 (Guest OS)** - Guest OS 位於 Ring 0,較 Ring 3 有更高的權限,但不直接存取硬體 - 在「半虛擬化」模式下,Guest OS 需要修改部分程式碼,使其能與虛擬化層 (Virtualization Layer) 溝通 3. **Virtualization Layer:** - 不同於「完全虛擬化」需要二進位轉譯,半虛擬化透過「Hypercall」(超呼叫) 讓 Guest OS 主動呼叫虛擬化層,進行特權指令或硬體操作 4. **Hypercalls to the Virtualization Layer** - 在半虛擬化中, Guest OS 知道自己在虛擬環境中,因此對特權指令進行修改或以 Hypercall 形式呼叫虛擬化層 - 這些 Hypercall 讓 Guest OS 不需透過二進位轉譯,效率較高,但需修改作業系統本身 :::info #### Hypercall - 直接將指令轉換成 hypervisor (kernel) 可以執行的指令,再由 hypervisor 去調度硬體資源 ::: ### 總結 - **半虛擬化**與**完全虛擬化**最大的差異在於: - **完全虛擬化**需靠**二進位轉譯**來攔截特權指令, Guest OS 無需修改 - **半虛擬化**需修改 Guest OS,使其以 Hypercall 呼叫虛擬化層,省去二進位轉譯的負擔,提高效能 - 由於需要修改 Guest OS 系統,因此**半虛擬化**在相容性上較弱,但效能通常較佳 ### 硬體輔助虛擬化 (Hardware Assisted Virtualization, HVM) ![截圖 2025-03-29 下午4.03.07](https://hackmd.io/_uploads/BJ1LKmSa1l.png) [圖片來源](https://silo.tips/download/full-and-para-virtualization) - 這是最新的方式需要有硬體的支援 - Intel VT-x 和 AMD-V 引入了**根模式 (Root Mode)** 和**非根模式 (Non-root Mode)** - **根模式 (Ring -1 or Ring0P)**: Hypervisor 在此運行,擁有最高特權,直接與硬體溝通 - **非根模式 (Ring0D)**: Guest OS 雖然看似在 Ring 0,實際上在非根模式中,特權指令會自動被 CPU 攔截 (trap) 並交由 Hypervisor 處理 :::info **Intel VT and AMD-V** **Intel VT (Intel Virtualization Technology)** - 一個支援 Intel 的虛擬化技術 - 為了解決 Intel 虛擬化的安全性及性能不足 - 讓一個 CPU 運作時像多個 CPU 同時運作 - 使一部電腦可同時運作多個作業系統 **AMD-V (AMD Virtualization)** - 是一種針對 x86 的硬體虛擬化輔助技術 - 為了使 Hypervisor 可以充分利用資源及提高虛擬化效率等 ::: - 這種硬體輔助的機制省去了使用二進位轉譯或修改 Guest OS (半虛擬化) 的需求,確保安全隔離與高效運作 :::info - **Trap 機制** - 當 Guest OS 或應用需要執行特權操作時,CPU 自動將指令交由 VMM 處理 - 這讓 VMM 在 Root Mode 下掌控所有特權,而 Guest OS 仍以為自己擁有完整硬體存取權 ::: [參考資料1](https://silo.tips/download/full-and-para-virtualization) [參考資料2](https://charleswan111.medium.com/understanding-hvm-hardware-virtual-machine-instances-in-aws-features-benefits-and-use-cases-697cb6354404) [參考資料3](https://www.geeksforgeeks.org/difference-between-full-virtualization-and-paravirtualization/) # 虛擬化層級 ![Bc1wszZ](https://hackmd.io/_uploads/SygInNSpyg.png) ## 硬體抽象層虛擬化 (Hardware Abstraction Level, HAL) - **概念** - 硬體抽象層 (HAL) 虛擬化讓虛擬化操作直接在硬體層面進行,透過 Hypervisor 來建立虛擬機 - **運作原理** - 利用 Hypervisor 直接管理硬體元件,如輸入輸出設備、記憶體與處理器 - 在這一層,虛擬機被建立出來,並可根據需求虛擬化各個硬體資源 - **應用場景** - 允許多個使用者在同一硬體上同時運行多個虛擬化實例 - 此技術通常用於雲端基礎架構,提升硬體資源的利用率與靈活性 - **缺點** - 能虛擬的硬體平台範圍有限,且可能需要硬體對虛擬化的支援 - **代表** - KVM(Kernel-based Virtual Machine) - 現在屬於 Linux 核心架構下的一部分,且具備虛擬化的功能,可將 Linux kernel 轉變為一個具 virtual machine monitor 功能的 kernel ## 指令集架構層虛擬化 (Instruction Set Architecture Level, ISA) - **概念:** 可以讓原本專門為某種硬體(例如舊的 x86 架構)編寫的程式碼,在虛擬機上運行,而不受硬體限制。這種方法使得虛擬機可以「看不出」底層硬體是什麼,無論是 x86 或 x64 平台,都能正常執行這些舊程式碼 - **運作原理:** 使用解譯器讀取原始二進位程式碼,將其轉換成目標硬體能識別的格式,從而使程式在虛擬機上正常執行 - **應用場景:** 特別適合執行大量遺留程式或舊版應用,讓它們不受原有硬體限制,並可在現代平台上繼續使用 - **缺點:** - 模擬與解譯過程可能帶來額外效能開銷,執行速度較慢 - 對於高效能要求的應用,可能不夠理想 - **代表** - QEMU(quick emulator) - 是模擬處理器的自由軟體,模擬一些不存在的硬體裝置 - 轉譯不同架構的指令集 - 因為 QEMU 是純軟體實現的,所有的指令都要經過 QEMU ,使得效能很差 (配合 KVM 則可以解決這一問題) ## 作業系統層虛擬化 - **概念:** - 在作業系統層級上建立一個抽象層,將應用程式與作業系統隔離開來,形成獨立的容器 - **運作原理:** - 在實體伺服器及其作業系統上,建立一個虛擬化的環境,每個容器相當於一個獨立的伺服器 - 每個使用者會獲得獨立的虛擬環境,並分配專屬的虛擬硬體資源,避免彼此衝突 - **應用場景:** - 適用於多使用者環境中,當使用者不願共享硬體資源時,可提供獨立而隔離的工作環境 - **缺點:** - 隔離程度低於硬體層級虛擬化,安全性可能較弱 - 當作業系統本身受到影響時,所有容器可能同時受波及 - **代表** - Docker - 可以自動化建立隔離環境,讓開發環境與作業系統隔離提升安全性 - 實現 container 的軟體,使用者可用簡單指令管理 container ## 函式庫層虛擬化 - **概念:** - 一般應用程式透過 API 與作業系統溝通,而函式庫層虛擬化則在呼叫前攔截這些 API,讓虛擬化軟體決定如何與系統互動 - **運作原理:** - 利用 API 鉤子 (API Hooks) 控制應用程式與作業系統之間的通訊,將這層虛擬化抽象化,簡化程序 - **優點:** - 簡化系統操作,減少作業系統本身的複雜性 - API 標準化、文件化,易於管理與整合 - **缺點:** - 依賴 API 的正確實作,若出現錯誤可能導致兼容性問題 - 虛擬化層級較薄弱,對系統整體影響有限 - **代表** - Wine(Wine Is Not an Emulator) - 在類 Unix 系統上執行 Windows 程式 - 可以在 Linux, BSD (UNIX like) , MacOS 中執行 windows 的執行檔(.exe) ## 應用程式層虛擬化 - **定義:** - 僅虛擬化單一應用程式,而非整個平台或環境 - **運作方式:** - 高階語言編譯的程式可以直接在應用層虛擬化環境中運行 - 應用程式運行在虛擬化層之上,與底層環境分離,確保其能無縫執行 - **優點:** - 只針對特定應用進行虛擬化,資源消耗較低 - 簡化管理與部署,避免虛擬化整個平台的複雜性 - **缺點:** - 只針對單一應用虛擬化,無法提供整個系統的完整隔離 - 對於需要全面環境虛擬化的需求,可能無法滿足 - **代表** - Java 程式 ![image](https://hackmd.io/_uploads/ryGl0C4Ckg.png) - JVM:將 bytecode 轉換成我們要用的作業系統可以讀懂的機器語言 - bytecode:JVM 的執行碼 [參考資料1](https://www.slideshare.net/slideshow/levels-of-virtualizationdocx/256172143) [參考資料2](https://u-next.com/blogs/cloud-computing/implementation-levels-of-virtualization-in-cloud-computing/) # 虛擬化安全 ## 什麼是虛擬化安全? - 傳統硬體安全保護實體設備 (如防火牆、路由器),而虛擬化安全則專注保護虛擬機、Hypervisor 及容器 - 虛擬化安全透過軟體實現,可根據需求動態配置,輕鬆部署於雲端,不受實體硬體限制 ## 虛擬化安全風險 - **複雜度提高:** 工作負載與應用頻繁遷移,難以維持一致的安全配置 - **VM 快速建立:** 虛擬機過量或閒置,可能造成潛在漏洞 - **注意事項:** 雲端或虛擬化環境既有風險 (如 VM Sprawl、過時系統),仍需嚴謹管理 ## 虛擬化常見安全脆弱點 - **虛擬機 (VM)** - **VM Escape**:駭客利用虛擬機漏洞,突破隔離限制,進而控制 hypervisor 和其他虛擬機 - **VM Poaching**:當某虛擬機佔用過多資源時,可能導致其他虛擬機資源被竊取或崩潰 - **Antivirus Storm**:多個虛擬機同時啟動防毒掃描,導致整個系統效能急速下降 - **Hypervisor** - **Hypervisor Hyper Jacking**:攻擊者利用漏洞劫持 hypervisor,進而掌控整個虛擬化環境 - **VM Migration**:在虛擬機遷移過程中,如無適當保護,資料可能被攔截或篡改 - **網路與外部威脅**:Hypervisor 漏洞可能被利用,發起網路攻擊或滲透內部系統 ## 虛擬化安全建議 1. **更新主機韌體與軟體**:確保所有系統元件都使用最新版本 2. **確保網路設備韌體亦為最新** 3. **自動更新 OS**:排程於非上班時段進行安裝與重啟 4. **安裝並維護防毒、反惡意程式軟體** 5. **權限區隔**:採最小權限原則 (PoLP),明確紀錄管理者操作 6. **網路流量加密**:防止攔截或竊聽 7. **安全意識訓練**:建立密碼強度與使用者政策 8. **移除無用 VM**:每台虛擬機都應有明確用途 9. **定期備份**:包含 VM 與實體伺服器,執行完整系統備份 [參考資料 1 ](https://www.cc.ntu.edu.tw/chinese/epaper/0057/20210620_5709.html) [參考資料 2 ](https://docs.redhat.com/zh-cn/documentation/red_hat_enterprise_linux/7/html/virtualization_security_guide/chap-virtualization_security_guide-host_security#chap-Securing_the_host_physical_machine_and_improving_performance) [參考資料 3 ](https://www.vmware.com/topics/virtualized-security) <!-- :::info ### 虛擬化攻擊範例 - VMware ESXi 攻擊 ![esxi-13-156](https://hackmd.io/_uploads/HkDrkua31x.jpg) [圖片來源 ](https://www.ithome.com.tw/news/167251) #### 攻擊方式與目的 勒索軟體駭客不僅僅鎖定虛擬機器進行勒索,還利用 VMware ESXi 平臺建立隱密的管道,持續存取受害企業的內部網路。攻擊者主要透過 SSH 加密存取,在 ESXi 系統中建立 SOCKS 隧道,與控制伺服器(C2)保持連線,藉此達到後門存取的目的。 --- #### 攻擊流程 - **入侵方式:** - 利用外流的管理員帳密或已知漏洞入侵 ESXi 系統。 - **建立通訊隧道:** - 透過 ESXi 系統內建的 SSH 功能建立加密連線,形成一個隱密的通訊隧道。 - **其他工具:** - 除了使用 SSH,攻擊者也可能部署其他工具以達成類似目的。 --- #### 為何 ESXi 平臺容易被忽略監控? - **事件記錄分散:** - ESXi 的事件記錄檔案分散,與一般集中在單一 Syslog 檔案的系統不同。 - **記錄檔不足:** - 只取得主要記錄檔(syslog.log)往往無法完整呈現安全事件的全貌,對鑑識工作不夠友善。 - **監控工具效能受限:** - 即使有第三方監控工具或遙測代理程式,但其可用性與效能常常受限。 --- #### 建議的防範措施 - **集中監控:** - 將 ESXi 伺服器的各類事件記錄檔案(如 shell.log、hostd.log、auth.log、vobd.log)轉送至外部事件記錄伺服器,進行集中監控與分析。 - **加強帳密與漏洞修補:** - 加強對管理員帳密的保護,並及時修補漏洞,避免駭客利用弱點入侵 ESXi 系統。 [參考資料](https://www.ithome.com.tw/news/167251) | 名詞 | 簡易說明 | | ---------------------------- | ------------------------------------------------------------ | | **VMware ESXi** | 裸機虛擬化平台,直接安裝在實體伺服器上,提供虛擬機運行環境 | | **SSH (Secure Shell)** | 加密遠端連線協定,用於安全登入與管理系統 | | **SOCKS 隧道** | 利用 SOCKS 代理協議建立的網路隧道,可轉發流量,隱藏真實來源 | | **C2 伺服器** | 指揮控制伺服器,攻擊者用來遠端控制受感染系統 | | **ESXi Shell** | ESXi 的命令行介面,供系統管理與故障排除使用 | | **Syslog / 事件記錄檔** | 記錄系統與安全事件的日誌,ESXi 記錄分散在多個檔案中 | | **hostd** | ESXi 平台的管理代理程式,記錄管理操作與系統事件 | | **vobd (VMware Observer Daemon)** | 監控 ESXi 系統效能與狀態的工具,記錄異常與效能數據 | | **寄生攻擊 (Living Off The Land)** | 利用系統內建工具進行攻擊,避免使用外來惡意軟體以降低被偵測風險| ::: --> # KVM 過去像是 Xen、VMware 還有 VirtualBox 有許多的虛擬化解決方案,但最終由 KVM 在 Linux 中取得主導的地位,因為 KVM 最初的設計目標清晰且巧妙: 聚焦於 Linux 核心 ## 定義與功能 KVM (**K**ernel-based **V**irtual **M**achine) 是 Linux kernel 中的一個開放原始碼虛擬化模組 (`kvm.ko`),對應的裝置為 `/dev/kvm`。它的作用是: - 讓 Linux Kernel 作為虛擬機器管理程式運作 - **讓虛擬機可以使用硬體虛擬化技術** (如 Intel VT / AMD-V),從而提升效能 [參考資料](https://en.wikipedia.org/wiki/Kernel-based_Virtual_Machine) [參考資料](https://www.yuanguohuo.com/2024/07/21/virtualization-1-qemu-and-kvm/) ## KVM 歷史故事 2006 年中期,以色列一家新創公司 **Qumranet** 的工程師 **Avi Kivity** 與團隊開始打造一個基於 Linux 的虛擬化基礎建設。他們的目標是讓 Linux 不僅僅是一個作業系統,能直接管理虛擬機,從而實現更有效率、更穩定的虛擬化運算環境。這個構想最終催生了 **KVM (Kernel-based Virtual Machine)** 的誕生。 :::info ### 初始階段與技術突破 - **2006 年 10 月**,KVM 正式問世。最初的 KVM 是為 **x86 處理器** 設計,利用當時新興的硬體虛擬化技術 (如 Intel VT-x 和 AMD-V) 來提升虛擬機效能。使得虛擬化可以達到接近裸機的效能,從而大幅降低虛擬機在運算上的負擔 - **2007 年 2 月 5 日**,KVM 被合併進 Linux 核心 mainline (2.6.20),正式成為 Linux 核心的一部分。為 Linux 社群帶來了一個高效且開放的虛擬化解決方案 ### 技術擴展與生態系統的建立 隨著 KVM 在 Linux 核心中的成功整合,它迅速被推向更廣泛的硬體平台: - **多架構支援** KVM 不僅僅侷限於 x86 架構,後來更被移植到 **ESA/390、PowerPC、IA-64** 和 **ARM** 等多種平台上。這一擴展,使 KVM 能夠應用在不同的系統環境中,滿足各種企業與科研領域的需求。 > Linux 核心中,虛擬化相關程式碼,x86 架構部分的程式碼數量是 S390 架構的 7 倍、PPC 架構的 8 倍、Arm 架構的 4 倍,其複雜度之高從中可見一斑 > 後續,由於市場與技術策略的改變,**IA-64 架構於 2014 年被刪除** - **生態系統的發展** 在 KVM 合併進 Linux 後,各大開源項目和商業產品開始圍繞它建立虛擬化解決方案。例如,**libvirt** 提供了一個統一的虛擬化 API,而 **virt-manager** 則為使用者提供直觀的圖形管理界面。這些工具使得 KVM 不僅在資料中心內被廣泛使用,也在雲端計算中扮演重要角色。 ### 商業與市場的變革 - **2008 年** Qumranet 被 **Red Hat** 收購,這一收購不僅鞏固了 KVM 在虛擬化領域的地位,也推動了其在企業級市場的迅速普及。Red Hat 利用自身在企業解決方案中的影響力,進一步完善並推廣 KVM 技術,讓它成為眾多企業部署虛擬化平台的首選。 - **2017 年** AWS 改採 KVM 作為虛擬化架構,自此 KVM 席捲 Linux 虛擬化技術生態。在 AWS 啟動的 2006 年,Xen 是當時最成熟、開放原始碼的 Linux 虛擬化引擎技術。因此,AWS 在早期採用 Xen,成為其 [EC2](https://aws.amazon.com/ec2/) 的底層基礎。 - **2011 年** 剛啟動的 Google Cloud 從一開始就採用 KVM 作為其虛擬化的基礎設施 - **虛擬化革命** 隨著雲端計算和虛擬化技術的快速發展,KVM 成為建立現代資料中心和雲端平台的基礎技術之一。許多大型開源與商業雲端平台,如 **OpenStack**、**ProxmoxVE** 等,都選擇 KVM 作為核心虛擬化引擎。這使得 KVM 的技術影響力日益擴大,並逐漸成為虛擬化領域的標準技術之一。 ::: ### 為什麼 KVM 能成功 - KVM 擁有一個更好、更靈活且具前瞻性的設計,這個設計是直接內建在 Linux 中,而不是作為其下層 - 它重用了 Linux 中已經存在的模組,並保留了對系統的控制權,這更能使 Linux 開發者關注 ## 核心觀念 KVM 是 Linux 核心提供的系統**虛擬機器基礎建設**,以核心模組的方式讓 Linux 系統成為一個 Hypervisor。一旦這個模組載入 Linux 中,KVM 把 Linux 變成了裸機虛擬機器管理程式。或者說,使用 KVM 產生虛擬機器時,KVM 變成主體,Linux 就變成 KVM 的一部分,KVM 透過 Linux 的能力管理記憶體、CPU 及其裝置。 :::info **核心模組 (Kernel Module)** 一段可以動態載入作業系統核心中的程式,通常用來擴充或修改核心功能 (例如驅動程式、網路協定等),而不需要重新編譯或重啟系統。這種模組化設計能讓系統在運作時依需求新增或移除功能,維持核心精簡並提升維護彈性 ::: ## KVM 的虛擬化層級定位 :::warning ### KVM 屬於 Type 1 or Type 2 Hypervisor ? KVM **不是獨立運行在硬體上的程式**,而是依附在 Linux 作業系統上 (Type 2 特性)。 但同時,因為 KVM 是 kernel module 運行於 kernel space,充分利用硬體虛擬化加速,效能非常接近裸機 (bare metal,Type 1 的特性)。 因此,KVM 應被歸類為一種**混合 (hybrid) Type 1 和 Type 2 特性的虛擬化技術**。 | 觀點 | 說明 | |:-------- |:------------------------------------- | | 結構定位 | 依賴 Linux 作業系統 → Type 2 | | 效能表現 | 直接運作在 kernel space → 接近 Type 1 | | 常見描述 | Type 2 with Type 1 performance | ::: ## KVM 架構跟原理 下圖顯示了 KVM Hypervisor 在 Linux 系統中的運作方式,從底層硬體到 Host OS,再到上層的 Guest OS。 ![xen-kvm(1).1d05f32a1acafb6d1e20094b327c823666f599fa](https://hackmd.io/_uploads/SkV1Qk46yl.png) [圖片連結](https://aws.amazon.com/tw/what-is/kvm/) :::info ### 架構層級說明 - **Bare Metal Server (實體硬體)** - 這是最底層的實體機器,包括 CPU、記憶體、網卡、硬碟等硬體資源 - KVM 能夠利用 CPU 的硬體虛擬化技術 (Intel VT 或 AMD-V),使虛擬機器的執行效率更接近原生速度 - **Linux Host Kernel (Linux 宿主核心)** - Linux 核心本身直接執行在硬體上,管理所有硬體資源 - KVM 是以**核心模組 (kernel module)** 的形式嵌入在此核心中,讓 Linux 同時具備 Hypervisor 的功能 - 一旦載入 KVM,使用者就能透過 `/dev/kvm` 這個檔案描述子 (file descriptor),使用檔案相關的系統呼叫 (像是 `open` 以及 `ioctl`) 對 KVM 進行操作,提供虛擬化能力 - **Hypervisor (KVM 模組)** - 在圖中以綠色標示,代表 **KVM 核心模組**。 - 它透過與 CPU 虛擬化指令配合,讓來自 Guest OS 的指令能直接或部分直接在實體 CPU 上執行,減少模擬 (emulation) 開銷 - KVM 本身只負責 CPU / memory 層面的虛擬化,加上 **QEMU** 或其他工具模擬 I/O 與週邊裝置,才能形成完整的虛擬機環境 - **Host OS (宿主作業系統)** - 這一層是 Linux 核心之上的使用者空間 (user space),提供管理與操作的環境 - 使用者可以在這裡安裝應用程式、管理工具 (如 `libvirt`, `virt-manager` 等),並透過它們建立、啟動、關閉或監控 Guest VM - **Guest OS (客體作業系統)** - 在圖的頂端看到多個方塊,代表多個獨立運行的虛擬機,每個 Guest 都有自己的 **Guest Kernel** (客體核心) 和上層的應用程式 - 因為 KVM 提供硬體虛擬化,這些 Guest OS 可以像在實體機上那樣運行 (安裝、開機、使用應用程式),而不會與其他 Guest 或 Host 互相干擾 - Guest OS 可以是各種 Linux 發行版、Windows、BSD、甚至其他架構 (搭配 QEMU 全模擬) 等 ::: ### 運作原理重點 1. **硬體虛擬化支援** - KVM 利用 Intel VT-x 或 AMD-V 指令集,使 Guest OS 的大部分指令能直接在 CPU 上執行,減少指令翻譯或模擬的負擔 2. **核心模組 vs. 使用者空間** - KVM 作為核心模組,負責 CPU 與記憶體的虛擬化 - QEMU 或其他使用者空間工具 (如 `libvirt`) 透過ioctl 呼叫 `/dev/kvm` 裝置檔案操作 KVM,並模擬網卡、硬碟、顯示卡等週邊設備 3. **高效能 + 安全隔離** - 每個 Guest OS 都在獨立的虛擬地址空間中運作,並受到 Linux 核心(Hypervisor) 保護,確保彼此之間互不影響 - 透過硬體輔助與核心級虛擬化,效能可接近原生主機速度,適合雲端環境或高負載的虛擬化部署 4. **靈活的管理工具** - 由於 KVM 已整合進 Linux 核心,許多管理工具、開源專案 (OpenStack、ProxmoxVE、oVirt 等) 都能輕鬆支援 KVM - 這讓 KVM 在企業級虛擬化、雲端平台上得到廣泛應用 ### 總結 > **KVM** 利用 Linux 核心 + CPU 硬體虛擬化,打造出一個高效、安全的虛擬化建設 > 其核心思想是 **讓 Linux 自身同時扮演作業系統與 Hypervisor 的角色** 在此架構下,Host 與 Guest 系統共存,卻彼此隔離,大幅提升硬體資源的利用率,並提供穩定且彈性的虛擬化服務。 :::info 下圖方便比對層級 ![](https://miro.medium.com/v2/resize:fit:1100/format:webp/1*iuW845pwRhd49KEUYvzsmg.png) ::: ::: info ### ❗ VirtualBox 內無法支援 KVM? - 即使開啟 nested-hw-virt,VirtualBox 無法提供 `/dev/kvm` 給 guest VM,這是因為 VirtualBox **不支援巢狀虛擬化**。 - 這是因為 KVM 是利用 CPU 的虛擬化擴展 (例如 Intel VT-x 或 AMD-V) 來進行虛擬化,而這些技術通常只會在主機上啟用。若要在虛擬機中運行 KVM,就必須透過巢狀虛擬化將這些硬體虛擬化功能提供給虛擬機。 #### **巢狀虛擬化** ![有巢狀的 Hyper-V](https://learn.microsoft.com/zh-tw/virtualization/hyper-v-on-windows/user-guide/media/hvnesting.png) 巢狀虛擬化是一項功能,像是讓 Hyper-V 虛擬機器內再執行 Hyper-V,巢狀虛擬化常用情況: - 在巢狀 VM 中執行應用程式或模擬器 - 在 VM 上測試軟體版本 - 減少定型環境的部署時間 - 針對容器使用 Hyper-V 隔離 [參考資料](https://learn.microsoft.com/zh-tw/virtualization/hyper-v-on-windows/user-guide/nested-virtualization) - 若要在 VM 中使用 KVM,可用方法有: - 使用 VMware + 開啟 nested virtualization - 在 ProxmoxVE / KVM Host 上建立 VM - 直接在實體機器安裝 Linux + KVM ::: ## KVM 的優缺點 <!-- - **整合虛擬化能力到核心** - Linux 核心同時扮演 Hypervisor 角色,管理硬體資源並分配給各虛擬機 - 減少中間層,提升效能並簡化系統架構 - **提供低延遲、高效能的虛擬化環境** - 運作在核心空間,直接控制 CPU 虛擬化指令,減少模擬開銷 - 透過 `/dev/kvm` 與 QEMU 溝通,效能可接近裸機 - **靈活且易於管理** - 依賴 Linux 的調度、記憶體管理與安全機制,整體系統穩定性高 - 豐富的管理工具 (如 `virt-manager`, `virsh`, `libvirt`),易於整合與自動化 - **開放性與生態系統** - 開源且整合進主線 Linux,支援多種硬體架構 (x86, ARM, PowerPC 等) - 有眾多開源專案 (ProxmoxVE、OpenStack、oVirt 等) 都基於 KVM ### 缺點 - **依賴 Linux 作業系統** - 屬於 Type 2 Hypervisor (理論分類),必須在 Linux 上運行 - 在非 Linux 系統 (如 Windows) 無法原生使用 - **管理介面相對分散** - 雖然有 `virt-manager`、`virsh` 等工具,但需要搭配 libvirt 等工具 - 若不熟悉 Linux 或 CLI,初期上手可能略顯複雜 - **Nested Virtualization 支援視平台而定** - 若要在虛擬機中再開啟 KVM,需要宿主機支援 Nested VT-x/AMD-V - 不同廠商或雲端平台對 Nested 虛擬化的支援程度不一 - **Windows 虛擬化生態較集中於 Hyper-V/VMware** - 雖然 KVM 能很好地支援 Windows Guest OS,但在 Windows 主機環境中並不支援 KVM - Windows 上常見的虛擬化選擇是 Hyper-V 或 VMware Workstation - **部分進階功能需要手動設定** - 例如高可用 (HA)、即時遷移 (Live Migration)、叢集管理等功能,在 KVM 環境中需要較多額外工具或平台整合 (如 ProxmoxVE、oVirt) - 商業化支援或服務 (如 Red Hat Virtualization) 通常需要付費或使用企業版 --> | 優點 | 缺點 | |:---------------------------------------------------------------------------------------- |:--------------------------------------------------------------------- | | **整合虛擬化能力**: Linux 核心直接扮演 Hypervisor,減少中間層、提升效能。 | **依賴 Linux**: 僅能在 Linux 上運行,無法原生支援 Windows。 | | **靈活易管理**: 利用 Linux 調度與安全機制,加上豐富的管理工具 (virt-manager、virsh 等)。 | **進階功能需整合**: 如高可用、即時遷移、叢集管理等需額外工具配合。 | | **開放生態系統**: 開源整合進主線 Linux,支援多種架構,眾多專案基於 KVM。 | **商業支援限制**: 企業級服務 (如 Red Hat Virtualization) 通常需付費。 | ### 結論 - **KVM** 優點在於效能、高度整合、與開源生態的豐富性,適合在 Linux 環境下部署大型或高效能虛擬化平台 - **缺點** 與 Linux 的深度綁定,對初學者或非 Linux 使用者來說,管理工具的學習門檻可能較高 # QEMU QEMU (**Q**uick **Emu**lator) 是一個[開放原始碼](https://github.com/qemu/qemu)模擬器,它透過軟體模擬 CPU 和周邊硬體設備,為虛擬機器提供執行環境;也可以模擬指令集,達成翻譯的效果。 QEMU 是 **Emulation (模擬)** 與上述的 **Virtualization (虛擬化)** 兩者是都是虛擬機器領域中常見的兩種技術,但其中運用的了不同的概念。 :::warning ## Emulation vs Virtualization ### 兩者差異 | 特性 | **Emulation 模擬** | **Virtualization 虛擬化** | |:-------- |:-------------------------------- |:--------------------------- | | 目標 | 模擬不同硬體架構 (跨平台) | 在相同硬體架構上執行虛擬機 | | CPU 架構 | 可以不同 (如 x86 上跑 ARM) | 必須相同 | | 運作方式 | 用**軟體**模擬 CPU 指令與設備 | 使用主機硬體 + 虛擬化指令集 | | 執行效能 | 慢 (需要轉譯與模擬) | 快 (接近原生) | | 技術範例 | QEMU、Bochs、Rosetta | KVM、VMware、VirtualBox | | 適用場景 | 跨平台測試、模擬嵌入式、教學用途 | 建立 VM、雲端平台、開發測試 | ### 具體例子 #### Emulation 模擬 - 用 QEMU 在 x86 筆電模擬一台 ARM 的 Raspberry Pi - **無中生有**: 假設一台電腦完全沒有顯示卡,正常情況下這台電腦就無法輸出圖形畫面。然而,透過一個模擬器,我們可以在軟體上「無中生有」創建一個虛擬顯示卡。這個虛擬顯示卡會模擬出實體顯示卡的所有功能,使 Guest OS 和應用程式認為電腦內部存在真正的顯示硬體,從而實現圖形輸出和顯示。 > ✅ 可跨架構執行 > ❗ 效能較慢 (因透過軟體模擬) #### Virtualization 虛擬化 - 在 VirtualBox 中執行 Ubuntu (x86 上跑 x86) - 使用 QEMU + KVM 建立高速 VM - 雲端平台如 AWS、GCP、Azure 的基礎技術 > ✅ 效能高、接近原生速度 > ❗ 架構必須與主機相同 ## 結論 | 問題 | Emulation | Virtualization | |:-------------------- |:-------------------- |:--------------------------- | | CPU 架構可以不同嗎? | 可以 | 不行,必須一樣 | | 效能怎麼樣? | 較慢 | 快很多 | | 用途偏向? | 開發、測試、模擬硬體 | 建立可用的 VM 系統 (如雲端) | | 常見工具? | QEMU | KVM、VMware、Xen、Hyper-V | [參考資料](https://github.com/vbaemulator/Visual-Boy-Advance) ::: ## 歷史發展 QEMU 最初於 2003 年發布,由法國程式設計師 Fabrice Bellard 發起,他也因建立 FFmpeg 和 LZEXE 等其他突破性工具而聞名。 Bellard 的起初想法是開發一種快速、便攜的動態翻譯器,使某台機器開發的軟體可以在另一台機器上執行。 雖然 QEMU 的初始版本僅支援 x86、ARM 和 SPARC 架構的模擬,但它逐漸擴展以適應 PowerPC、MIPS 等各種其他架構。在其歷史上,QEMU 不斷發展和改進,與 KVM (基於核心的虛擬機器) 和 libvirt 等其他專案整合,並將其支援擴展到系統和使用者模式 (user mode) 模擬。 [參考資料](https://tinycomputers.io/posts/the-history-use-and-technical-details-of-qemu.html) ## 架構與原理 ### QEMU 到底是什麼? 可以將 QEMU 算是一種虛擬機管理程式 (Hypervisor),但它與一般常見的 VMware 或 VirtualBox 有所不同。 - QEMU 屬於 **Type 2 Hypervisor** - 執行於作業系統之上 (user space) - 不直接存取硬體 - 通常使用軟體模擬完成虛擬化功能 - 搭配 KVM 使用時,QEMU 可透過 `ioctl` 去操作 `/dev/kvm` , 使用硬體虛擬化提升效能 :::info **`ioctl` (I/O Control)** **萬物皆檔案**這個概念背後,是為了讓所有 I/O 操作都可抽象為 `read`、`write`、`open`、`close` 等 system call,但這些操作難以描述較為複雜的操作,像光碟撥放時快轉 or 倒退等。 `ioctl` 就是為了彌補上述 system call 的不足而衍生。 在 Linux 可以透過引入以下標頭檔去使用 `ioctl` 操作 KVM ```c #include <fcntl.h> #include <sys/ioctl.h> #include <linux/kvm.h> #include <linux/kvm_para.h> ``` - `int kvm_fd = open("/dev/kvm", O_RDWR)`: 開啟 KVM 裝置。 KVM 是以裝置檔案及 fd(**f**ile **d**escriptor, 檔案描述子) 的方式與 User space 互動。並且都是用 `ioctl` 系統呼叫,傳入 KVM 相關的 fd 來操作 KVM。 - `int vm_fd = ioctl(kvm_fd, KVM_CREATE_VM, 0)`: 使用 KVM_CREATE_VM ioctl 來建立新的 VM 。此時 Linux 核心內的 KVM 模組會建立虛擬機器,並回傳此 VM 的 fd 。 > 建立 CPU 跟建立 memory 也是用這樣的方式。 [參考資料](https://man7.org/linux/man-pages/man2/ioctl.2.html) [參考資料](https://lwn.net/Articles/658511/) ::: > ✅ 單獨使用 QEMU = 純軟體模擬 → 效能較低 > ✅ 結合 KVM 使用 = 可啟用硬體加速 → 效能接近原生 ### 主要特點 - **完整軟體模擬** QEMU 單用的時候,可以透過軟體模擬來實現整台電腦的功能,模擬 CPU 執行指令以及各種設備 (如網路卡、硬碟、USB 等) 的讀寫操作,而不直接依賴硬體虛擬化技術 (如 Intel VT 或 AMD-V) - **API 支援** QEMU 提供了一系列 API 來輔助使用者管理與自動化虛擬機操作: - **QEMU Machine Protocol (QMP)**: 基於 JSON 的協定,可用來查詢狀態、控制虛擬機 (啟動、暫停、重置、停止) 及動態調整設備 - **QEMU Monitor Interface (Monitor)**: 互動式命令介面,讓使用者可以直接發送指令進行診斷、偵錯和管理 - 這些 API 使 QEMU 能與各種管理工具 (如 libvirt、virt-manager) 整合,從而自動化部署與控制虛擬機 > 💡 **簡單比喻** > 使用 QEMU 就像自己用積木一塊一塊 (自己模擬 CPU、記憶體、硬碟、網卡等所有元件) 搭建一台電腦,而不像其他虛擬機軟體 (VMware、VirtualBox) 那樣,是快速複製一台電腦來用。 ### QEMU 的模擬技術: DBT + TCG ```text Guest 指令(如 ARM 指令) ↓ ← QEMU 分析出基本區塊(Basic Block) 中間表示(IR) ← 類似中性語言,便於後續處理 ↓ Host 指令(如 x86 指令) ← 由 TCG 產生 ↓ 翻譯後的程式碼快取(Translation Cache) ← 可重複使用,提升效能 IR, Intermediate Representation) ↓ Host 指令 ``` [參考資料](https://zh.wikipedia.org/zh-tw/QEMU) #### DBT (Dynamic Binary Translation) - 一種**動態二進位翻譯**技術 - 將 Guest 的指令翻譯為 Host 能執行的指令 #### TCG (Tiny Code Generator) - TCG 是 QEMU 實作動態二進位翻譯 (DBT) 的核心技術,其主要流程如下: 1. **讀取 Basic Block** - 從 Guest 讀取一段連續指令,作為最小執行單位 2. **轉換為中間表示 (IR)** - 將 Basic Block 翻譯為一種與架構無關的中間表示,便於進一步最佳化 3. **生成 Host 指令** - 將最佳化後的 IR 轉換為 Host CPU 能執行的原生指令,並打包成 Translation Blocks (TBs) 4. **快取重用** - 快取已生成的 TBs,以便在後續執行相同區塊時直接重用,提高效率 | 名稱 | 中文 | 說明 | |:-----------:|:------------------------------------------- |:----------------------------------------------------------------------- | | DBT | 動態二進位翻譯 (Dynamic Binary Translation) | 執行時將 Guest 的機器碼 (例如 ARM 指令) 轉換成 Host(例如 x86)的機器碼 | | TCG | Tiny Code Generator | QEMU 裡的核心翻譯引擎,負責把中間表示 (IR) 轉成 host 指令 | | Basic Block | 基本區塊 | 一段連續不會跳轉的程式碼 (指令序列),是最小單位翻譯單元 | | IR | Intermediate Representation (中間表示) | 把 Guest 指令轉成一種中性格式,方便轉換成任何 host 架構的指令 | ## 優缺點 ### 優點 - **跨平台支援**: QEMU 能夠模擬多種 CPU 架構,使得在不同硬體平台上進行開發、測試或模擬變得更靈活 - **擴充性高**: 使用者只需要使用 QEMU 提供的 API,就能迅速模擬出多種裝置 - **彈性與多樣性**: 既可作為完整系統模擬器,也可作為 user mode 模擬器來執行單一程式 ### 缺點 - **執行速度相較緩慢**,QEMU 主要都是用軟體去模擬指令的執行,並沒有使用 Hardware-assisted virtualization - **部分硬體模擬的局限性**,雖然 QEMU 能夠模擬許多硬體設備,但在某些特殊硬體或最新技術上,可能存在支援不完善或模擬精度不足的情況 :::success ## DEMO - 先安裝 QEMU ```bash sudo apt update sudo apt install qemu ``` - 確認是否安裝成功,如果出現版本號就代表安裝成功 ```bash qemu-system-x86_64 --version ``` ![螢幕擷取畫面 2025-03-31 003723](https://hackmd.io/_uploads/HJStmlwpJx.png) 做完上面代表你的 QEMU 已經載好了,但要實際跑一台虛擬機還需要一個 **ISO 映像檔** > 🎯 為什麼需要 ISO 檔 ? > 我們要在 QEMU 裡「安裝一個作業系統」給虛擬機使用, > 而作業系統的安裝檔通常就是一個 ISO 檔。 - 我安裝的是 Alpine Linux ISO ```shell wget https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/x86_64/alpine-standard-3.21.3-x86_64.iso ``` - 下載好後,用指令查看這個檔案是否在你目前目錄裡 ```bash ls -lh *.iso ``` - 建立虛擬硬碟 ```shell qemu-img create -f qcow2 qemu.qcow2 10G ``` ![螢幕擷取畫面 2025-03-31 115710](https://hackmd.io/_uploads/ByxTGcw61l.png) - 完成後,就可以啟動 QEMU,進入安裝畫面 ```bash qemu-system-x86_64 \ -m 512 \ -cdrom alpine-standard-3.21.3-x86_64.iso \ -boot d \ -drive file=./qemu.qcow2,format=qcow2 \ -net nic -net user \ -display none \ -serial mon:stdio ``` >• -m 512:分配 512 MB 記憶體給虛擬機。 • -cdrom alpine-standard-3.21.3-x86_64.iso:指定我們下載的 Alpine Linux ISO 檔作為光碟映像。 • -boot d:設定虛擬機從光碟啟動,這樣系統就會讀取 ISO 中的引導程式。 • -drive file=./qemu.qcow2,format=qcow2:指定虛擬硬碟檔的檔案及格式。 • -net nic -net user:建立一個虛擬網卡並設定使用者網路模式,這讓虛擬機可以進行基本網路連線。 • -display none:關閉圖形化顯示(因為 Alpine Linux Server 通常只需要文字介面)。 • -serial mon:stdio:將虛擬機的序列介面映射到標準輸入/輸出,使我們可以在終端機中看到安裝介面並進行操作。 ![螢幕擷取畫面 2025-03-31 120134](https://hackmd.io/_uploads/H18w4cPp1g.png) - 進入 Alpine 安裝流程 (在 VM 裡操作),你會看到 "Welcome to Alpine Linux localhost login:" 輸入: ```bash root ``` ![螢幕擷取畫面 2025-03-31 120650](https://hackmd.io/_uploads/H1ZWBcvTJl.png) ::: # QEMU vs. KVM - **KVM**: 讓 Linux kernel 成為 Hypervisor 的關鍵元件,負責硬體虛擬化 - **QEMU**: 作為 VMM 提供完整的虛擬機環境和硬體模擬 ![image](https://hackmd.io/_uploads/rk2oWjya1l.png) [圖片來源](https://somaz.tistory.com/121) [參考資料](https://hosomikai317.blogspot.com/2018/07/qemu-kvm-qemu-kvm.html) <!-- ### 左邊:KVM 模式(QEMU + KVM) - 主機 OS: Linux Kernel - 使用 KVM 模組支援硬體虛擬化 - User space 部分交給 QEMU,作為其使用者層級的入口 - QEMU 負責虛擬機模擬 (如 I/O 裝置) - Guest VM 執行效率高,可接近原生速度 ### 右邊:純 QEMU 模式 - 主機 OS 核心不支援 KVM - QEMU 完全模擬 CPU、記憶體與裝置 - Guest Application 全部透過模擬執行 - 效能較差,但支援異架構模擬 (像是 x86 → ARM) --> ## ⚙️ 差異比較表 | 項目 | QEMU + KVM (有加速) | QEMU (無 KVM) | |:---------------------- |:--------------------------- |:------------------------ | | 虛擬化技術 | 硬體加速虛擬化 (VT-x/AMD-V) | 完全軟體模擬 | | 效能 | 快 (接近原生) | 慢 | | 使用情境 | 實際 VM 部署、生產環境 (不可異架構) | 模擬異架構、測試用 | | Nested Virtualization | 需支援 Nested 才能用 | 可以使用,但無法啟用 KVM | | 在 VirtualBox 支援情況 | ❌ (無法啟用 KVM) | ✅ (可跑,但慢) | ::: info - **KVM 是否必須搭配 QEMU? 為何講到 KVM 都會配著 QEMU 一起** ANS: 不一定 KVM 本身是一個 Linux 核心模組,僅實做 HVM (Hardware Virtual Machine) 功能,提供 **硬體** 虛擬化能力,只負責 CPU 和記憶體的虛擬化 (底層),並不提供完整的虛擬機模擬功能。因此,我們還需要一個使用者空間 (user space) 工具來建立和管理虛擬機。 QEMU 是最常用的選擇,但並不是唯一的方案。 ::: # QEMU + KVM ## 兩者如何協作 ![KVM QEMU](https://hackmd.io/_uploads/S1V53RQT1x.png) [圖片來源](https://cloud.tencent.com/developer/article/1850701) 在 QEMU 與 KVM 協作時, QEMU 作為使用者空間的管理工具,負責建立與管理虛擬機、模擬硬體 I/O (如磁碟、網卡等),但在只使用 QEMU 的情況下,它以 "**軟體**"方式模擬 CPU 指令,效能較低。 QEMU 將 KVM 整合進來,通過 `ioctl` 操作 `/dev/kvm`,把 vCPU 的執行交由 KVM 處理。KVM 是執行在 Linux 核心中的模組,能直接使用硬體虛擬化技術來執行 Guest 指令,實現高效能的 CPU 虛擬化。 但 KVM 不能虛擬其他硬體設備,因此 QEMU 還有模擬 IO 設備 (硬碟,網卡,顯卡等) 的作用,KVM 加上 QEMU 後就是完整意義上的伺服器虛擬化。 > QEMU: 處理高層管理與 I/O 模擬 > KVM: 處理底層虛擬 CPU 執行與記憶體管理 → 兩者分工合作,讓虛擬機兼具彈性與效能 [參考資料](https://hosomikai317.blogspot.com/2018/07/qemu-kvm-qemu-kvm.html) ## BIOS 從哪來? :::info BIOS(**B**asic **I**nput/**O**utput **S**ystem, 基本輸入/輸出系統) 的主要作用是在電腦啟動時進行硬體初始化、檢測系統硬體狀況,並負責啟動作業系統。簡單來說,它確保電腦的各個硬體裝置都正常運作,然後將控制權交給作業系統,使電腦能夠順利開機並運作。 ::: QEMU 跟 KVM 預設使用名為 **SeaBios** 的 BIOS ,SeaBIOS 是 16 位元 X86 BIOS 的開源軟體。它會在我們開啟一新虛擬機的時候,被 QEMU 自動載入,無須執行額外操作就可開機。 [參考資料](https://www.seabios.org/SeaBIOS) [參考資料](https://medium.com/@tunacici7/qemu-eli5-part-6-uefi-bios-ovmf-7919facf7e31) ### QEMU + KVM 相比原生 QEMU 的差異 QEMU + KVM 是在 QEMU 的基礎上,整合 KVM 模組來提升虛擬化效能,以下是它們的差異: #### CPU 虛擬化方式的不同 - **原生 QEMU**: - 採用 **DBT (Dynamic Binary Translation)** 技術 - 由 QEMU 自行以軟體方式模擬 CPU 行為,屬於 full virtualization - 效能較低,但相容性高 - **QEMU + KVM**: - 改為透過 `ioctl()` 呼叫 Linux 的 `/dev/kvm` 裝置 - 使用 KVM 模組提供的硬體虛擬化支援 (Intel VT-x / AMD-V) - 效能接近原生執行 #### 多執行緒支援 - 原生 QEMU 為 **單執行緒**,模擬多核心 CPU 時容易成為瓶頸 - QEMU + KVM 支援 **多執行緒**,可讓每個 Guest vCPU 對應到一個 Host 執行緒,提升多核處理能力 :::info ❗ **補充: `qemu-kvm` 已被 `qemu-system-x86_64 --enable-kvm` 取代** 原本 QEMU + KVM 要透過 `qemu-kvm` 這個指令去進行,但後來直接整合進 `qemu` 指令本身 ![image](https://hackmd.io/_uploads/r1pm-J2pJe.png) [資料來源](https://lists.gnu.org/archive/html/qemu-discuss/2016-04/msg00013.html) ::: :::success ## DEMO - 承接上面已經下載好的 QEMU 就好 ```bash sudo qemu-system-x86_64 \ -m 512 \ -cdrom alpine-standard-3.21.3-x86_64.iso \ -boot d \ -drive file=./qemu.qcow2,format=qcow2 \ -net nic -net user \ -display none \ -serial mon:stdio \ --enable-kvm ``` - 進入 Alpine 安裝流程 (在 VM 裡操作),你會看到 "Welcome to Alpine Linux localhost login: (看起來會跟剛剛長的一樣)" 輸入: ```bash root ``` 這樣就完成了,其實就跟 QEMU 的 DEMO 長的一模一樣但感覺比較快。 ::: # 虛擬化管理系統 ::: info ## libvirt ![DevTools Logo Banner Dark 800](https://hackmd.io/_uploads/SJbH8tU61x.png) libvirt 是一個通用的虛擬化 API 與管理工具,許多工具也透過它 (如 `virsh`、virt-manager) 來管理 KVM / QEMU 虛擬機器。 它提供統一介面、封裝底層虛擬化技術的函式庫,簡化 VM 的建立、啟動、快照、網路等操作。 ![libvirt](https://hackmd.io/_uploads/SySVHCQpye.png) [圖片來源](https://commons.wikimedia.org/wiki/File:Libvirt_support.svg#/media/File:Libvirt_support.svg) ::: ## virt-manager virt-manager 是**圖形化**的操作介面,讓使用者來建立、編輯、啟動與停止虛擬機。就像是一個「虛擬機司機」(API),你給他指令 (CLI) 他幫你開車 ![virt-manager](https://miro.medium.com/v2/resize:fit:1100/format:webp/1*uGB9x4qSpMFayUiwxglNdg.png) [參考資料](https://medium.com/codemonday/setup-virt-manager-qemu-libvert-and-kvm-on-ubuntu-20-04-fa448bdecde3) [參考資料](https://en.wikipedia.org/wiki/Virt-manager) | 比較項目 | libvirt | virt-manager | |:--------:|:------------------------------ |:-------------------------- | | 類型 | **後端** API / 服務 | **前端** 圖形工具 | | 功能 | 管理虛擬機、網路、磁碟、快照等 | 操作虛擬機、建立與設定資源 | | 操作方式 | CLI 或程式調用 (如 `virsh`) | GUI 介面 | | 彼此關係 | 底層引擎 | 使用 libvirt API 的前端 | ```text [ 使用者 ] ⬇ [ virt-manager (GUI 工具) ] ⬇ [ libvirt (中介層 / API 控制) ] ⬇ [ QEMU + KVM (實際執行虛擬機) ] ``` :::success ## virt-manager DEMO 1. 在終端機下 `sudo apt install virt-manager` 2. 然後可以看到 Virtual Machine Manager ![VirtualBox_eva_06_04_2025_04_30_13](https://hackmd.io/_uploads/r1xxXzyR1e.png) 3. 按左上角的圖示建立虛擬機,然後選第一個選項然後下一步 ![VirtualBox_eva_06_04_2025_05_00_09](https://hackmd.io/_uploads/ryjZcMJRkx.png) 4. 這裡要選擇要用甚麼 ISO 檔,這個檔案已經放好了,應該只會有一個選項可以選,然後下一步 ![VirtualBox_eva_06_04_2025_05_02_52](https://hackmd.io/_uploads/SyYKqG10Jx.png) ![VirtualBox_eva_06_04_2025_05_03_20](https://hackmd.io/_uploads/HJDo9f10yg.png) ![VirtualBox_eva_06_04_2025_05_04_07](https://hackmd.io/_uploads/SJ_R5MkR1g.png) 5. 記憶體給 512 CPU 給 1 個,然後下一步 ![VirtualBox_eva_06_04_2025_05_05_14](https://hackmd.io/_uploads/BJdzoMk0Je.png) 6. 硬碟給 10G,然後下一步 ![VirtualBox_eva_06_04_2025_05_05_57](https://hackmd.io/_uploads/SyFOizJCJx.png) 7. 然後 finish 就建立好了,等它一下就會跑出熟悉的畫面! ![VirtualBox_eva_06_04_2025_05_07_36](https://hackmd.io/_uploads/HycsjzkAkl.png) ![VirtualBox_eva_06_04_2025_05_08_38](https://hackmd.io/_uploads/SkTghfy0Jx.png) ::: ## PVE [**P**roxmox **V**irtual **E**nvironment](https://www.proxmox.com/en/) 是一套基於 Linux 的開放原始碼虛擬化平台。 - 主要使用兩種虛擬化技術 - 虛擬機器 (VM) - 容器 (Container) 的虛擬化 (LXC,**L**inu**X** **C**ontainer) 可在 **同一部主機上同時** 支援完整的 VM 和容器型虛擬化。以 KVM 和 QEMU 共同協作用於完整虛擬機器的虛擬化。QEMU 是開放原始碼機器模擬器和虛擬化程式、使用 KVM 核心模組直接在主機 CPU 上執行 Guest 程式碼。 Linux Container (LXC) 可讓容器像 VM 一樣進行管理、並在重新開機期間提供資料保存。除了可以在單個節點上使用,也可以組裝多個節點的 cluster,且所有的管理任務都可以使用 Web 介面來輕鬆管理與操作。 ![proxmox-overview-image01](https://hellogitlab.com/img/proxmox_introduction.svg) [圖片來源](https://hellogitlab.com/CM/proxmox/X1_Introduction) 從這張圖可以了解到 Proxmox 架在 Linux 上 - 支援 VM 和 Container - 提供 Web UI、CLI、API - 可做 Cluster ### 管理功能 PVE 提供了豐富且直觀的管理工具,使系統管理員能夠輕鬆地對虛擬機與容器進行監控與操作。主要功能包括: - **Web UI** - **直觀介面**: Proxmox VE 的 Web 介面設計簡潔,系統管理員可以通過瀏覽器進行大部分管理任務 - **資源監控**: 可以查看節點、虛擬機、容器的執行狀態、CPU、記憶體、磁碟與網路流量等視覺化圖表 - **方便操作**: 可以直接啟動、停止、備份、還原虛擬機和容器,支持批次操作與動態資源分配 - **CLI 與 API** - **命令列工具**: 提供如 `pvecm`、`qm` 等工具,適合自動化腳本或叢集管理 - **REST API**: 可整合其他工具或開發自動化管理解決方案,適用於大規模部署與系統整合 - **備份與還原** - **內建備份功能**: 支持線上備份虛擬機與容器 - **增量備份**: 節省備份時間與儲存空間 - **定時任務**: 可透過 Web UI 或使用指令設定定時備份,確保資料安全 ![image](https://hackmd.io/_uploads/HkjJx-xR1x.png) ![image](https://hackmd.io/_uploads/S1aMgZxRyx.png) ### 高可用性與即時遷移 PVE 支援高可用性 (High Availability, HA) 和即時遷移,這對企業級應用非常關鍵: - **高可用性 (HA)** - **叢集管理**: 多個節點可以組成 HA 叢集,當某個節點故障時,其他節點會自動接管該節點上的虛擬機與容器 - **自動故障轉移**: 配置 HA 後,故障節點上的虛擬機會自動遷移到其他可用節點,縮短服務中斷時間 - **監控與警報**: Web 介面可以監控節點狀態,一旦出現異常會發出警報,方便系統管理員及時干預 - **即時遷移 (Live Migration)** - **不中斷服務**: 支持在不中斷虛擬機運行的情況下,將虛擬機從一台實體主機遷移到另一台 - **動態資源調整**: 在負載不均或資源不足時,實現虛擬機的動態遷移,以達到資源最佳化 - **業務連續性**: 即時遷移可實現無停機遷移,確保使用者體驗不受影響 ### 案例與應用場景 PVE 在實際應用中有許多成功案例,以下是一些典型場景: - **企業資料中心整合** - **混合虛擬化管理**: 適用於中小企業,能夠整合傳統虛擬機與容器管理,簡化資料中心運維 - **資源共享**: 透過 HA 叢集管理,多台伺服器資源統一管理,提高資源利用率 - **開發與測試環境** - **靈活部署**: 開發團隊可以快速建立虛擬環境進行持續整合/持續部署(CI/CD)測試,並能輕鬆備份和回滾 - **環境隔離**: 開發環境與生產環境可以有效隔離,同時支持資源彈性擴展 - **雲原生與容器化轉型** - **逐步遷移**: 企業可以使用 Proxmox VE 作為過渡平台,將部分服務逐步遷移至容器化環境 - **統一管理**: 支援虛擬機和容器混合部署,提供單一管理介面,簡化運維工作 - **教育與實驗環境** - **低成本部署**: 學校和培訓機構可以利用 Proxmox VE 在有限硬體上建立虛擬化環境,用於教學和實驗 - **多租戶測試**: 可展示 HA 與熱遷移的實際應用,幫助學生理解企業級虛擬化技術 [參考資料](https://pve.proxmox.com/wiki/Main_Page) [參考資料](https://www.chirue.com/proxmox-install/) [參考資料](https://docs.netapp.com/zh-tw/netapp-solutions/proxmox/proxmox-overview.html#%E7%B8%BD%E8%A6%BD) # Container 容器技術的概念並不是近年才出現,它在作業系統發展過程中已逐步演進,主要目標是提供更輕量 (lightweight) 且可攜 (portable) 的**隔離環境**。 1. **早期雛形:`chroot`** - 在 1980 年代的 UNIX 系統中,就已出現了 `chroot` - 透過將程式的根目錄重新指定到特定目錄,實現最初的檔案系統隔離。雖然功能簡單,卻為後來的容器概念奠定基礎 2. **FreeBSD Jail、Solaris Zones 與其他容器技術** - **FreeBSD Jail (2000 年左右)**: 在 `chroot` 的基礎上加入更多資源限制與安全機制,提高隔離水準 - **Solaris Zones (2004 年)**: 在 Solaris 作業系統中提供類似容器的概念,可同時管理多個 Zone,彼此之間相互隔離又能共享核心資源 - **Linux VServer、OpenVZ 等**: 這些是早期 Linux 上對容器化及虛擬化技術的探索,透過核心機制 (如 namespaces、cgroups) 來達到隔離與資源管控 3. **LXC (Linux Containers) 與近代容器** - **LXC (2008 年左右)**: 將 Linux 上的多個核心功能(cgroups、namespaces 等)結合起來,提供一個更完整的容器化環境,是現代容器技術的重要里程碑 4. **Docker** - Docker 在 2013 年推出後,透過簡化的工具鏈與 image 管理方式,大幅降低了容器使用門檻 - **Build once, Run anywhere** 的理念開始廣為人知,並帶動整個生態系的發展,如 Kubernetes、CRI-O、containerd 等 5. **OCI 與 Container Runtime 的標準化** - 2015 年成立 **OCI (Open Container Initiative)**,推動容器映像與運行時的開放標準 - 使得 Docker、containerd、CRI-O、runc、crun 等多種實作能在同一套規範下協同工作 從早期的 `chroot` 到近代的 Docker/Kubernetes,逐步完善了資源隔離、部署與管理模式,解決了軟體佈署與執行環境不一致的痛點,並推動雲端原生 (cloud native) 應用架構的演進與普及。 :::info 過去 container 在改變行程的 root filesystem 時使用的系統呼叫是 `chroot`,現代會改為使用 `pivot_root` ::: ## Docker vs Container 觀念釐清 <center> | 元件 | 角色 | |:--------- |:------------------------------------- | | Docker | 平台與工具,用來管理 container | | Image | 模板,定義 container 的內容與環境設定 | | Container | 將 Image 啟動後才是 container | </center> > Docker 本身不等於 Container,但它是**實現 Container 技術的完整平台**是一種 container engine,幫助我們建立、部署與管理應用程式 :::info **container runtime** 在 Computer Science 或是軟體工程的語境下,runtime 通常指的是**程式執行階段**或在**程式執行期間所需的環境與支援**。 而在容器 (Container) 的領域中,runtime 比較偏向後者: **程式執行期間所需的環境與支援**。它所包含的是整個從**怎麼把容器真正跑起來**到**容器執行時和作業系統該怎麼協作**的細節與工具。因此,container runtime 就是***執行容器時的基礎支援系統*** **container engine** 包含一整套的工具鏈以及平台,包含 runtime、image 管理、網路以及 volume 其他更高階的管理功能,Docker 就是一種 container engine,而它使用的 runtime 是 containerd ::: # Container Isolation ## cgroups (Control Groups) Linux Kernel 中的功能,可以用來限制、控制與隔離 Process 所使用到的系統資源,例如 CPU, Memory, Disk I/O, Network…等。 ### 主要有以下四大功能 1. **Control**: 暫停或是重啟一整個 Group 的 Process。 2. **Resource Limiting**: Group 可以設定 Memory 的使用上限,其中也包含 File System 的 Cache。 3. **Prioritization**: 不同的 Group 可以擁有不同的 CPU 跟 Disk I/O 使用優先順序。 4. **Accounting**: 計算 Group 內的資源使用狀況,例如可以拿來當作計費的依據。 ### 由四元素組成 1. **Task**: 運行於作業系統內的 Process,在 cgroups 內被稱為 Task。 2. **Subsystem**: 一種資源控制器,一個 Subsystem 負責管理一種資源,例如 CPU 或是 Memory,不同的作業系統所提供的 Subsystem 種類可能不盡相同,以下列出一些常見的類型。 :::info #### Subsystem 常見類型 - **memory**: 限制 Task 可以使用的 Memory,並且自動產生 cgroup 內 Task 使用 Memory 資源的報告 - **cpu**: 透過 Scheduler 安排 cgroup 內 Task 存取 CPU 資源 - **cpuacct**: 自動產生 cgroup 內的 Task 使用 CPU 資源的報告 - **blkio**:限制 Task 對於儲存裝置的讀取,例如 Disk, SSD 和 USB…等 - **net_cls**: 對網路封包標記上 Class ID,進而讓 Linux Traffic Controller 根據這些 Class ID 得知網路封包是來自於哪一個 cgroup 中的 Task - **net_prio**: 為每一個 Network Interface 提供動態設定網路流量優先權的方法 - **freezer**: 暫停跟恢復位於 cgroup 內的 Task - **cpuset**: 為 cgroup 內的 Task 分配一組單獨的 CPU 核心 (多核心 的 CPU 系統) 跟 Memory - **devices**: 控制 cgroup 中 Task 可以存取的裝置有哪些 - **ns**: 有關於 Namespace 的 Subsystem - **perf_event**: 用來辨別 Task 屬於哪一個 cgroup,而且可以拿來做效能分析用途 ::: 3. **cgroup**: 資源控制單位,也就是 Task 與 Subsystem 的關係連結,用來定義 Task 的資源管理策略,例如把一個 Task 加入到某個 cgroup 內,那麼這個 Task 使用資源時就必須遵守該 cgroup 中所定義的規範。 4. **hierarchy**: 一群 cgroup 所組成的樹狀結構,每個節點都是一個 cgroup,一個 cgroup 可以有多個子節點,子節點預設繼承父節點的屬性;系統中可以有多個 hierarchy,換言之,就像一座森林一樣。 ### cgroup v1 v.s. cgroup v2 #### cgroup v1 - **多層級架構**: 允許將不同的控制器(如 CPU、記憶體)掛載到不同的層級(hierarchy),這使得配置具有靈活性,但也可能導致配置複雜且難以管理。 - **控制器獨立掛載**: 每個控制器可以獨立掛載,或與其他控制器聯合掛載到同一目錄,提供了高度的靈活性。 - **process 與 cgroup 的關係**: 允許將單個 process 分配到不同的 cgroup,可能導致資源管理上的問題。 #### cgroup v2 - **統一的單一層級架構**: 所有的控制器都掛載在同一個層級下,簡化了配置和管理,避免了 v1 中多層級可能帶來的混亂。 - **改進的資源管理**: 提供了更精細的資源分配和隔離能力,例如改進的記憶體分配管理和壓力監測資訊 (Pressure Stall Information) - **更安全的子樹委派**: 允許更安全地將子 cgroup 的控制權委派給非特權使用者,增強了系統的安全性和靈活性 - **統一的記憶體分配計算**: 對不同類型的記憶體分配 (如網路記憶體、核心記憶體) 進行統一的計算和管理,提升了資源使用的可預測性 ![image](https://hackmd.io/_uploads/BJfx5PdT1l.png) [圖片來源](https://medium.com/some-tldrs/tldr-understanding-the-new-control-groups-api-by-rami-rosen-980df476f633) > 在 cgroup v1 中,每個資源控制器 (像是 blkio、memory、pids) 都有獨立的階層樹 (hierarchy),每個控制器可以有自己的目錄結構 > cgroup v2 採用統一的階層樹 (unified hierarchy),所有的控制器 (memory, io, pids 等) 都掛載在同一棵樹上,且子 cgroup 必須服從父層的限制,使用 cgroup.subtree_control 來啟用子節點的資源控制器 ## Namespaces #### 傳統環境中的資源共享 在傳統的計算環境中,所有行程共享同一組系統資源,這可能導致資源競爭、安全漏洞等。例如,位於同一主機上的多個行程可能會互相干擾,造成系統行為的不穩定和不可預測。 #### Linux Namespace - 為了解決上述問題,Linux 核心引入了 Namespaces 的概念 - Namespaces將kernel資源進行劃分,限制 Container 所能看到的東西,不同 namespace 的程式互相看不見 - 當建立 Container 時,Container Engine 會為 container 建立一組 namespace #### Types of Namespaces - PID Namespace - 每個 namespace 中的 PID 互相獨立,在新的 namespace 中建立的第一個 process 其 PID 為 1 - 不同的 namespace 之間可以互相隔離,即使擁有相同PID也不會互相干擾 ![image](https://hackmd.io/_uploads/Sk5Ilm_p1g.png) [圖片來源](https://blog.nginx.org/blog/what-are-namespaces-cgroups-how-do-they-work) >圖中有三個 PID namespace:一個是parent,另外兩個是child。在parent namespace 裡有四個process,PID1 到 PID4。這些行程之間可以互相看到,也可以共享資源。 > 而 PID2 跟 PID3 這兩個行程,雖然在parent namespace 裡,但它們也各自屬於一個child namespace,外面的東西看不到。 比方說,在兩個 child namespace 裡的 PID1 都看不到 parent namespace 裡的 PID4。 - network namespace - 網路資源的隔離, 這樣每個 Container 就有獨立的網路資源可以用,例如 : 網路設備、IPv4、IPv6 、IP 路由表、防火牆等資源的隔離 - 如果你在 Container 內執行一個 apache ,Host 上也執行 apahce,你很可能會得到 80 Port 已經被佔用的錯誤 - Container 和 Host 都使用不同的 network namespace ,才可使用相同的行程相同的 Port 不互相干擾 :::success #### network namespace 小實作 - 輸入`ip link`及`ip route` - `ip link` : 列出所有網路裝置 (介面) 及其狀態 >- lo 是回送介面 (loopback) >- enp0s3 是主機的實體網卡 >- docker0 是 Docker 建立的虛擬網卡 - `ip route` : 顯示目前的路由表 (預設路由、特定網段的路由) >- default gateway (例如:default via 10.0.2.2) >- 各個內網的路由(例如:10.0.2.0/24、172.17.0.0/16) > ![image](https://hackmd.io/_uploads/B1DbuL_61e.png) - `sudo unshare -n` - 新增一個 network namespace :::info #### `unshare` - `unshare -[namespace]` - 例:`unshare -n`為新增一個network namespace - 同樣輸入`ip link`和`ip route` ![image](https://hackmd.io/_uploads/ry4VO8u6Jl.png) >- 只看到一個介面:lo,而且狀態是 DOWN,其他的實體網卡都消失了! >- 沒有任何路由資訊,因為新的 namespace 是乾淨的 ::: - mount namespace - 提供獨立的mount table,一個 mount namespace 中的 process 無法訪問掛載在另一個 mount namespace 中的 Filesystem :::info - **mount table** 記錄當前系統中所有已掛載檔案系統資訊的資料結構。它詳細列出了每個掛載點的來源設備、掛載位置、檔案系統類型以及掛載選項等資訊。 - **Filesystem** - **檔案儲存與組織**:把資料分成一個個檔案,並用資料夾(目錄)來分類,方便我們找到需要的東西 - **空間管理**:追蹤硬碟上哪些空間已被使用,哪些還是空的,確保新資料能正確地儲存在可用的地方 - **資料檢索**:提供方法讓我們快速找到檔案,無論是透過檔名、路徑,還是其他屬性 - **存取控制**:設定檔案的權限,確保只有被授權的人或程式才能讀取或修改特定檔案,保護資料的安全 - 總結來說,使用者不必知道資料實際存在硬碟的哪個位置,讓使用者更容易管理自己的檔案 ::: :::success ### mount namespace小實作 - `sudo unshare -m` - `mount -t tmpfs cchtest /mnt` - 將 tmpfs 這個檔案系統掛載至 /mnt 這個目錄,並將這個掛載的檔案系統取名叫 cchtest - `mount -t tmpfs` - 看有沒有被掛載進去 - `-t` : 指定要掛載的檔案系統類型 - `tmpfs` : Temporary File System,是一種基於記憶體的檔案系統,將檔案直接儲存在 RAM 中,而非磁碟上 ![image](https://hackmd.io/_uploads/SkWBVUOpyg.png) - `date > /mnt/time` - 將目前的日期和時間寫入到 /mnt/time 檔案中 - `cat /mnt/time` ![image](https://hackmd.io/_uploads/SJB5ELuaye.png) - 開新的terminal - `mount -t tmpfs` - `cat /mnt/time` - 在本機找不到剛剛創建的檔案系統及 time 這個檔案,因為他們不在同一個 mount namespace ![image](https://hackmd.io/_uploads/H1-ZrLdpkl.png) ::: - IPC namespace - process 只能和相同 Namespace 內的 process 溝通 - 假設你在容器 A 裡面使用 shared memory 開了一塊記憶體儲存資料,你一定不希望容器 B 也能存取它,這樣會有資安問題 - 有了 IPC Namespace,就能確保這種事情不會發生,每個容器的 IPC 資源都是獨立的 - UTS namespace - 每個 Namespace 有自己的 host name 和 domain name,讓每台 Namespace 都可以被看作一個獨立的網路節點。 ![image](https://hackmd.io/_uploads/Hk6GZEOpke.png) [圖片來源](https://i.imgur.com/NFNKTCw.png) :::success ### UTS namespace小實作 - `sudo unshare -u` - 建立一個新的 **UTS namespace** (隔離 hostname 與 domain name) - `hostname my-lab` - 更改當前 namespace 的主機名稱為 [your name] - `hostname` - 驗證是否變更成功 ![image](https://hackmd.io/_uploads/rkQ4gwO6Je.png) ::: - user namespace - 擁有自己的 UID 及 GID,每個 namespace 可以設定特定權限,不影響其他 namespace 與 host - 例如 : 讓本來在 container 是 root 權限,回去 host 變成一個普通的 user 身分,就算這個 container被駭了,它在 host 上也僅僅只是一個普通 user 的身份,大大提高了安全性 :::success ### user namespace小實作 - `unshare -Ur` - 新增一個 user namespace ,並用 root 的身分開啟,然後用 whoami 確認身分 ![image](https://hackmd.io/_uploads/HkZA3LOTke.png) - `date > /tmp/test` - `ls -l /tmp/test` - `cat /tmp/test` - 我們用 root 身分,所以會顯示 root 創建的 ![螢幕擷取畫面 2025-04-01 022447](https://hackmd.io/_uploads/ryAsALO61x.png) - 去 host 開新的 terminal , 輸入 `ls -l /tmp/test`,檢查文件 ![螢幕擷取畫面 2025-04-01 010120](https://hackmd.io/_uploads/ByqfJwOa1l.png) ::: ## 兩者比較 cgroups 提供一種機制,可以將一行程 (process) 及其所有子行程 (child process),整合或劃分成具備特定限制的階層式群組。 namespaces 將系統資源封裝成一個抽象層,使得處於該 namespace 內的行程看似擁有自己獨立隔離的全域系統資源。 簡而言之: cgroups = 限制行程能使用多少系統資源 namespaces = 限制行程能看到的系統視圖 (view) # [OCI (Open Container Initiative)](https://opencontainers.org/) 2015 由 Linux Foundation 所提出的計畫,它是一個由社群共同治理的組織,目的是建立一套統一的容器規範,以讓不同 container engine (如 Docker & Podman) 所打包的 images 可以互相溝通。 **標準的容器遵循以下五大原則** 1. **擁有標準運作流程**: container 能被建立、啟動、停止、複製、備份、下載和上傳 2. **內容無關性**: 無論 container 內的內容為何,執行方式應保持一致 3. **基礎架構無關性**: container 應能在任何支援 OCI 的環境中運作,無論是伺服器、桌上型電腦或筆記型電腦 4. **為自動化而設計**: 滿足以上三點原則,使 container 適用於自動化 5. **工業級別的應用**: 透過上述優點,開發者能以自動化方式部屬應用程式,以簡化流程 **OCI 制定兩個主要標準 (Runtime Specification & Image Specification)** - runtime-spec (Runtime Specification) 定義了如何控制 container - **檔案系統束 (FileSystem Bundle)** 將應用程式及其依賴的所有檔案和設定封裝成一個可獨立運作的資料夾,稱為「束」(bundle) - **設定檔 (Configuration)** 包含建立 container 所需的所有參數,如環境變數、執行流程等。不同作業系統的設定檔格式可能有所不同 - **runtime 與生命週期 (Lifecycle)** 規範了 container 的狀態查詢、操作方式及從啟動到關閉的整個過程,確保容器運行的一致性 ![image](https://hackmd.io/_uploads/rJVTAZKakg.png) [圖片來源](https://miro.medium.com/v2/resize:fit:1400/1*p2T79jQpvRm1b06dv4tbzA.jpeg) - image-spec (Image Specification): 定義了如何建立 image :::info ## image 的組成 ![image](https://hackmd.io/_uploads/ryWmfDEake.png) [圖片來源](https://github.com/opencontainers/image-spec/blob/main/spec.md) 1. Layer:相關的檔案系統配置,包含檔案的位置/內容/權限 2. Image Index:用來描述該 Image 的檔案 3. Configuration:應用程式相關設定檔案,包含使用的參數、用到的環境變數等 ::: - 當應用程式要包裝成 Image 時,要符合以下規範 - **轉換 (Conversion)**: 描述如何將image轉換成運行時的 FileSystem Bundle - **映像層檔案系統變更集 (Image Layer Filesystem Changeset)**: 定義如何序列化以及新增、刪除、修改檔案系統,形成稱為「層」(Layer) 的 Blob。image 透過層層堆疊的方式建構,每一層儲存該次建構所需的檔案及與上一層的變化 - **映像設定 (Image Configuration)**: 包含檔案系統所需的資訊,如參數、環境變數和工作目錄,並記錄每個層的順序及轉換成運行時檔案系統束的配置資訊 - **映像清單 (Image Manifest)**: 描述image的組成,包括哪些層和設定。每個Manifest文件對應一個平台 (架構或作業系統) - **映像索引 (Image Index)**: 包含一個列表,對應不同平台的 image Manifest,確保 image 可跨平台使用。下載 image 時,會根據平台在 Image Index 中找到對應的 Manifest,再下載相應的 Blob - **映像佈局 (Image Layout)**: 定義映像的目錄結構,包括 Blobs 資料夾、OCI-Layout 和 Image Index。Blobs 資料夾儲存實體文件,如 Manifest、設定。OCI-Layout 儲存 layout 的版本資訊 - **描述子 (Descriptor)**: 描述目標內容的位置,包括內容類型、ID(摘要)、大小。透過描述符,可從 image Manifest 中取得每個內容的 ID,再下載對應的 Blob。而 ID 採用安全雜湊演算法編碼,提升安全性 ![image](https://hackmd.io/_uploads/r1cXwS4a1e.png) [圖片來源](https://blog.tienyulin.com/open-container-initiative-oci/) :::info ### 什麼是 Blob 在 Docker 的架構中,Blob 是儲存 Image 和 Container 資料的基本單位。當拉取或建立 Docker Image 時,相關的檔案會被儲存為 Blobs,這些 Blobs 組成了 image 的各個層 (Layer)。 每個 Blob 都有一個唯一的 SHA-256 雜湊值作為其識別碼 (ID),確保內容的完整性和唯一性。這種設計允許 Docker 在不同 Image 之間共享相同的層,節省儲存空間並加速部署。 ::: <!-- - distribution-spec(Distribution Specification) --> # 🐳 Docker - Docker 是一個開源平台,用來建立、部署與管理被包裝成容器的應用 - 在 container 技術演進中,Docker 扮演了關鍵角色 - **簡化容器技術的使用**: 雖然容器概念早已存在,但 Docker 將其變得更易於使用,降低了技術門檻,使開發者能夠更方便地建構、部署和管理容器化應用程式。 - **提供一致的運行環境**: Docker 確保應用程式在不同環境中保持一致性,無論是在開發、測試還是生產環境,都能確保應用程式的行為相同,避免了「在我電腦上可以運行,但在其他人電腦上無法順利運行」的問題。 - **提高資源利用率**:相比傳統的虛擬機,Docker 容器更輕量,啟動速度快,資源佔用更少,能夠在同一硬體資源上運行更多的應用程式。 <center> ![image](https://hackmd.io/_uploads/Bkym3Pah1l.png) [圖片來源](https://i0.wp.com/tw.alphacamp.co/wp-content/uploads/2022/12/60e8284642b83301ff7fa05c_5eccb1e0fe9844687499ed40_docker20logo.jpeg?fit=1200%2C628&ssl=1) </center> :::info ### 安裝 Docker on Ubuntu ```bash sudo apt-get update -y sudo apt-get install -y curl curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" sudo apt-get install -y docker-ce sudo usermod -aG docker [username] newgrp docker ``` >安裝好後用`docker images`測試是否安裝成功 >![image](https://hackmd.io/_uploads/Sy5Mqsa6Jx.png) ::: ## Docker架構 ![7868545-060cc40d94102469](https://hackmd.io/_uploads/BJpjTvp3yg.jpg) [圖片來源](https://mrhelloworld.com/resources/articles/docker/7868545-060cc40d94102469.jpg) ### 1️⃣ Docker Objects - **Dockerfile**: 定義了 image 中應包含的作業系統、套件、原始碼、執行指令與環境設定等,用來建構 image > Dockerfile 就像「食譜」,可以讓 Docker 根據步驟自動「烹飪出」一份 image - **Image**: 由多個唯讀層組成,每層對應到Dockerfile中的一條指令 - **UnionFS (概念)**: 允許將多個唯讀 (read-only) 的映像層與一個可寫 (writable) 的容器層疊加,形成一個統一且完整的檔案系統,其中最頂層將取代檔案系統中找到的任何類似檔案,以執行給使用者看 ![image](https://hackmd.io/_uploads/SyEphoahke.png) [圖片來源](https://phoenixnap.com/kb/what-is-docker) > 每行 Dockerfile 指令都會在 image 中建立一個唯讀的層 (Image Layer)。當啟動容器時,Docker 會在這些唯讀層之上新增一個可寫的容器層 (Container Layer),使容器能夠在運行期間進行檔案的新增、修改或刪除,而不影響底層的映像檔 - **OverlayFS (實作)**: 允許使用者將 upperdir 覆蓋 lowerdir,且來源目錄可以位於不同資料夾,甚至是不同檔案系統,實現臨時修改唯獨層和資料夾。其包含: - **Base Layer (lowerdir)**: 儲存檔案系統基礎檔案的地方,可視為基礎 image,且為唯獨層 - **Overlay Layer (upperdir)**: 讓使用者能夠與 container 互動,若需要增加、修改甚至刪除 image,只能由該層進行,為可讀可寫層 - **Diff Layer (workdir)**: 利用 CoW (copy-on-write),讓在 Overlay layer 中所做的任何變更都會自動儲存於該層 - **mergeddir**: 最終呈現給使用者看到的目錄,這個目錄其實是上面三層合併後的結果。 > 1. 若要讀取的檔案不存在於 upperdir 則直接讀取 lowerdir 的 base image > 2. 相反的,若要讀取的檔案不存在 lowerdir 則直接讀取 upperdir 中的 image > 3. 當欲讀取檔案同時存在 upperdir 及 lowerdir,upperdir 會覆蓋掉 lowerdir 中同名的檔案 > ![image](https://hackmd.io/_uploads/Hk6IqsM61l.png) [圖片來源](https://docs.docker.com/engine/storage/drivers/overlayfs-driver/) :::info #### dir 說明 - lowerdir: OverlayFS中的唯讀層,無法被修改 - upperdir: 可讀寫的層,OverlayFS 中對檔案的新增、修改、刪除操作,都是在這一層進行 - mergeddir: 是掛載點 (mount point) 目錄,也是使用者最終看到的目錄 - workdir: 用來存放暫存檔,記錄檔案修改過程中的中介資料 ::: :::success ### Demo image - `docker --version` - 確認有安裝docker ![image](https://hackmd.io/_uploads/rJv1HFdakx.png) - `mkdir docker-demo` - `cd docker-demo` - `vim index.html` - 在目錄中建立一個名為 `index.html` 的檔案,並在其中新增以下內容: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Simple App</title> </head> <body> <h1>Hello World</h1> <p>This is running in a docker container</p> </body> </html> ``` - `vim Dockerfile` - 建立Dockerfile,開啟 Dockerfile 並新增以下行: ```dockerfile FROM nginx:stable-alpine3.17-slim #使用nginx:stable-alpine3.17-slim(官方 nginx image)作為基礎映像 COPY index.html /usr/share/nginx/html #將檔案複製到「/usr/share/nginx/html」目錄,這是 Nginx Web 伺服器中提供靜態檔案的預設位置。 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] #指定 container 啟動時執行的預設指令。 #nginx -g "daemon off;" 讓 nginx 以前景模式(foreground)啟動。 ``` - `docker build -t sampleapp:v1 .` - 建立 image 前,請確保位於包含 Dockerfile 的資料夾中 - 根據位於目前目錄 (.) 中的 Dockerfile 中指定的指令建立 Docker 映像 - `-t` : 標誌為 image 指定一個標籤 - `sampleapp:v1`: 映像將被標記為 "`sampleapp`",版本為 "`v1`" ![image](https://hackmd.io/_uploads/r1zHrt_aJe.png) - `docker images` - 列出 Docker 主機上所有可用的 image。 ![螢幕擷取畫面 2025-04-01 051248](https://hackmd.io/_uploads/HyntSKdTyx.png) ::: <!--:::info #### 什麼是 copy-on-write 寫時複製(Copy-On-Write,縮寫為 COW),當多個執行緒或進程共享相同的資源(例如記憶體頁面或檔案資料)且僅執行讀取操作時,系統允許它們共享同一份資源。只有在其中一個執行緒或進程嘗試修改該資源時,系統才會真正執行複製操作,為該修改者創建一個專屬的副本,確保其他共享者仍然訪問原始的未修改資源。 ::: --> - **Container**:Image 的執行實例 - 一個 image 可以啟動多個互相隔離的 Docker Container ![image](https://hackmd.io/_uploads/rkh3Y-hTJg.png) [圖片來源](https://www.docker.com/resources/what-container/) - **Volume**:允許容器將資料儲存在主機的特定位置,即使容器被刪除或重新啟動,資料仍然保留 - Volumes: 由 Docker 管理,儲存在主機的特定目錄中(例如,在 Linux 上為 /var/lib/docker/volumes/)。 - Bind Mounts: 可以儲存在主機系統的任何位置,(例如, /home/user/data)。 ![image](https://hackmd.io/_uploads/SJSUs_CnJe.png) [圖片來源](https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuwywtay58oa28odm0pmj.png) - **Network**:提供容器之間通訊的通道 1. bridge:預設的網路驅動程式 > 用於同一主機上需要互相通訊的容器 ![image](https://hackmd.io/_uploads/r1k3uc16yx.png) [圖片來源](https://miro.medium.com/v2/resize:fit:1400/1*6rANgRsFgLBfwax3n0nMUw.png) 2. host:移除容器和 Docker 主機之間的網路隔離,直接使用主機的網路 > 具高效能網路通訊,但可能導致 Docker 與本機的 port 發生衝突 ![image](https://hackmd.io/_uploads/BkDFccJaJg.png) [圖片來源](https://miro.medium.com/v2/resize:fit:1400/0*9Ag7iew3NVDcf-xs.) 3. none:將容器與主機和其他容器完全隔離。容器沒有網路介面 4. overlay:將多個 Docker Daemon程式連接在一起,可用Docker Swarm實現跨主機容器通訊 <!-- :::info #### 什麼是Docker Swarm? Docker Swarm 是 Docker 提供以實現分散式系統的一種工具,允許將多個Docker主機組成一個叢集,並以統一方式管理和部署容器化應用程式。它提供高可用性、可擴展性和容錯能力,使應用程式能在叢集中彈性運行和擴展。 ::: --> 5. ipvlan:所有容器共享宿主機的 MAC 位址,但擁有各自獨立的 IP 位址 - L2模式 :與宿主機位於相同的二層網路中 >可以直接透過 MAC 位址進行通訊。這種直接通訊不需要經過路由器,因為所有設備都在同一個廣播域內 - L3模式 :IP位址與宿主機不同的子網中 >設備之間的通訊需要透過路由器或三層交換機進行。這是因為不同子網路的設備無法直接透過 MAC 位址進行通訊,而需要依賴 IP 位址和路由功能來轉發資料封包 6. macvlan:每個容器都擁有自己的 MAC 和 IP 位址,能直接與其他網路裝置通訊,如同實體機器一般 | 模式 | 特點 | 適用場景 | | ------ | -------------------------------------------- | -------------------------- | | Bridge | 預設模式,容器彼此可通訊,透過 NAT 對外 | 單主機開發環境 | | Host | 共用主機網路介面,高效能但會有 port 衝突風險 | 對效能有極高要求的應用 | | None | 完全無網路 | 網路隔離測試、手動網路設定 | | Overlay | 可跨主機建立虛擬網路 |Swarm、分散式系統| | IPVLAN | 共用 MAC、有獨立 IP | 精密網路規劃| | MACVLAN |獨立 MAC 和 IP,如同實體主機|傳統網路架構、特殊設備通訊| ### 2️⃣ Docker Daemon (Dockerd) :::info 在 Linux,程式名字最後加個 d,通常是代表它是跑在**背景**、**提供服務**的 **d**aemon 程式。 這種命名方式是一種約定俗成的習慣,通常會這樣命名: **服務名 + d** → 表示它是該服務的 daemon,像是: - sshd (SSH Daemon) - httpd (HTTP Daemon) - crond (Cron Daemon) - systemd (System Daemon) ::: ![image](https://hackmd.io/_uploads/H1EL2uEpye.png) [圖片來源](https://dz2cdn1.dzone.com/storage/temp/16667754-docker.png) **為 Docker 的核心**,負責實際管理: - 映像檔 (Image) - 容器 (Container) - 虛擬網路 (Network) - 資料卷 (Volume) - 同時也能與其他 Docker Daemon 節點進行通訊 - Docker daemon 通過 Socket 來 listens for Docker API requests,也就是 Client 的請求 > 預設是使用 UNIX domain socket :::info ### 什麼是 Socket ? Socket 就是一個網路上的通訊端點,使用者或應用程式只要連接到 Socket 便可以和網路上任何一個通訊端點連線,Socket 之間通訊就如同作業系統內 Process 之間通訊一樣,而透過 Socket 通訊,使用者不用理會網路實體架構。通常使用 `socket()` 系統呼叫建立 Socket <center> ![image](https://hackmd.io/_uploads/rJ0SeuNpkg.png) [圖片來源](https://www.tsnien.idv.tw/Internet_WebBook/chap8/8-1%20Socket%20%E7%B0%A1%E4%BB%8B.html) </center> > 如以電話系統而言,只要將電話的插座設定好某一號碼,任何一部電話都可透過電話號碼 (插座) 和其它電話通訊。對使用者而言,不用理會電話系統是如何撥接、或是如何路由選擇到達目的,這些功能完全由電話公司負責。網路上的 Socket 也如同電話號碼一樣,任何一個 Socket 都給予一個特殊號碼 (IP number + TCP port),使用者之間只要記住對方的 Socket 號碼,便可以直接通訊,而不用考慮到底是經過何種網路、或主機放在什麼地方,這些尋找主機的工作是網路提供者所必須負責的。 [來自](https://www.tsnien.idv.tw/Internet_WebBook/chap8/8-1%20Socket%20%E7%B0%A1%E4%BB%8B.html) ::: ### 3️⃣ Docker Client (CLI) 使用者 Docker 互動的主要方式,讓使用者可以透過像 Docker Desktop 這樣的圖形介面或使用 Docker CLI 命令列工具 (像是利用 `docker push` 指令將 image 推送到 Docker Hub),透過 REST API 將請求傳給 Docker Daemon。 > 一個 Client 可以和一個以上的 Daemon 溝通。 ![image](https://hackmd.io/_uploads/rysAUuE6yl.png) [圖片來源](https://www.geeksforgeeks.org/what-is-docker-client/) ### 4️⃣ Docker Registry 專門儲存的倉庫,DockerHub 則是任何人都可以用的公共倉庫 ( 像是 Github ),使用 pull 可將 image下載,使用 push 時,image就會被推送到倉庫當中,沒有設定的情況下倉庫都預設為 DockerHub。也可以建立屬於自己的私人倉庫,來存放一些只屬於公司內部或是自己的 image <center> ![image](https://hackmd.io/_uploads/Bygua_phkg.png) [圖片來源](https://k21academy.com/wp-content/uploads/2024/04/2-9.webp) </center> ### Docker 執行過程 ![image](https://hackmd.io/_uploads/B1oXx4la1x.png) [圖片來源](https://www.netadmin.com.tw/netadmin/zh-tw/technology/4C812C79753542DA836AB855D8189F36?page=3) 1. **撰寫 Dockerfile**:開發者撰寫一個 Dockerfile,其中包含了建構Image所需的指令和設定,例如基礎映像、應用程式程式碼、所需的函式庫和環境變數等。 2. **構建image**:Client 使用 `docker build` 指令,並通過 UNIX Socket 向 Docker daemon 發出請求,Docker會根據Dockerfile 的內容,逐步執行其中的指令,並為每個步驟建立一個新的 Layer,最終生成一個完整的 image。 3. **執行image**:Client 透過 `docker run` 指令,並通過 UNIX Socket 向 Docker daemon 發出請求,Docker 使用指定的image 啟動一個新的 container。此時,Docker 會: - 檢查本地是否已有該 image;若無,則從預設的 Docker Registry(如 Docker Hub)拉取。 - 為 container 分配檔案系統(如 OverlayFS)和網路資源。 - 設定指定的環境變數和應用程式參數。 - 在 container 中執行應用程式。 4. **管理 container**:container 啟動後,您可以使用 `docker ps` 查看正在運行的 container,並透過 `docker stop`、`docker start`、`docker restart` 等指令管理 container 的生命週期。 5. **持久化與資料管理**:為了確保 container 中的資料在容器停止或刪除後仍能保留,Docker 提供了資料卷 (Volume) 功能,允許將資料儲存在宿主機上,並與 container 共享。 ## Container 與 VM 比較 | 面向 | Container | VM | |:------------:|:------------------------------------------------------ |:------------------------------------------------------- | | 安全性 | 使用主機 kernel,故隔離較弱 | 提供完整 OS 隔離,安全性較高,但資源耗用大 | | 便攜性 | 映像檔可跨主機運行,便攜性較高 | VM 映像檔較大,跨主機相對困難 | | 負載能力 | 較輕量,啟動快速,可在同樣硬體上運行多個 container | 較重,啟動慢,占用資源多 | | 作業系統支援 | 共享主機核心,只能運行在相同類型的作業系統 (如 Linux) | 每個 VM 可獨立運行不同的作業系統 (如 Windows on Linux) | :::success # Docker Demo ### pull docker image - 使用 `docker pull`,從 Docker Hub 下載 Ubuntu 作業系統的 Image - `docker pull ubuntu` : 若未指定版本,預設下載最新的。 - 查看本機已有的 image - `docker image list` ![image](https://hackmd.io/_uploads/H1Su-ctpkl.png) - REPOSITORY: 來自於哪個倉庫 - TAG: 映像檔的標記,可以指定版本,預設使用 latest:最新的版本 - IMAGE ID: ID (唯一) - CREATED: 建立時間 - SIZE: 映像檔大小 - 更改image名字 - `docker image tag [Repository:Tag] [想改的名字]` - `docker image tag ubuntu:latest ubuntu-0402test` ![image](https://hackmd.io/_uploads/Sk8hfcK61x.png) ### 啟動、顯示、連線 Container - 啟動 Image 產生 Container - `docker run -it --name [container Name or ID] [Repository:Tag]` - `docker run -it --name 0402test-con ubuntu:latest` - `-i`: 當需要與 Container 做互動 (輸入指令給 Container,Container 會回傳指令結果),沒有 `-i` 的話 container 就收不到你打的字。 - `-t`: 在 container 開啟一個虛擬終端 (tty) 透過 terminal 模式進入 Container。 - `--name`: 配置一個名稱給 container - `Repository:Tag`: 映像檔的名稱,若這個 image 不在本機, Docker 會自動幫你執行 `docker pull [image]` - 顯示目前啟動的 Container - 開一個新的 terminal - `docker ps` or `docker container ls` - 關閉 Container - 回到 container 的 terminal - 使用 `exit` 關閉 container,container 仍然存在 ![image](https://hackmd.io/_uploads/r1AzhctaJx.png) - 顯示已經存在但沒有啟用的 Container - `docker ps -a` or `docker container ls -a` ![螢幕擷取畫面 2025-04-02 010431](https://hackmd.io/_uploads/SyERn5Y6yg.png) - 啟動剛剛關閉的 Container - `docker start [container_name or id]` ![image](https://hackmd.io/_uploads/SJS_6cKakx.png) - 連線到已經啟動的 Container 裡 - (法一)`docker attach [container_name or id]` - 退出時, Container 也會跟著被關閉 - (法二)`docker exec -it [container_name or id] bash` - 以終端機模式進入 Container,且退出時也不會使 Container 關閉 - 在 host 向執行中的 Container 內部下指令 - `docker exec [container_name or id] [command]` - `docker exec 739882eab97c whoami` ![image](https://hackmd.io/_uploads/S1nagsYpJg.png) ### 關閉與刪除 Container 、 image - 刪除 Container - `docker rm -f [container_name or id]` - `-f`:強制刪除 Container ![image](https://hackmd.io/_uploads/HyhpfotaJg.png) - 檢查有沒有刪除成功 - `docker ps -a` ![image](https://hackmd.io/_uploads/BJKyQoKTyl.png) - 刪除 image - `docker rmi [image]` ![image](https://hackmd.io/_uploads/Bkfs7itTJg.png) - docker 常用指令 ![image](https://hackmd.io/_uploads/H1kK4iK61l.png) [圖片來源](https://cloud.tencent.com/developer/article/1772136) ### 限制 Container 資源 #### 限制memory資源 - 查看 Container 資源使用量 - `docker run --memory 512MB --name nginx1 -d nginx` - `docker stats [Container name]` ![image](https://hackmd.io/_uploads/SJVwyw6p1g.png) #### 限制cpu資源 - 利用 `while.sh` 比較有無限制的執行時間 ```bash #!/bin/bash x=1 while [ $x -le 1000000 ] do x=$(( $x + 1 )) done ``` - 沒限制 - `docker run --name cputest1 -it ubuntu bash` - `apt-get update` - `apt-get install vim` : 安裝vim - `vim while.sh` - `chmod +x while.sh` : 設定執行權限 - `time ./while.sh` ![image](https://hackmd.io/_uploads/Byzp7D06kl.png) - 有限制 - `docker run --cpu-period=1000000 --cpu-quota=500000 --name cputest2 -it ubuntu bash` - `--cpu-period=1000000`:設定 CPU 控制週期為 1 秒(單位為微秒)。 - `--cpu-quota=500000`:每個週期允許使用 500,000 微秒的 CPU 時間。 - 最多只能使用 50%(500000/1000000) 的 CPU 資源- - `apt update` - `apt install vim`: 安裝vim - `vim while.sh` - `chmod +x while.sh`: 設定執行權限 - `time ./while.sh` ![image](https://hackmd.io/_uploads/rkY0mwCakx.png) ### 使用 Dockerfile 建立 Nginx 環境 - 建立資料夾: `mkdir Docker`,並 `cd Docker` 建立以下三個檔案 - index.html - nginx.conf - dockerfile ```html= <!-- index.html --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Docker nginx</title> </head> <body> <h4>Hello LSAAA!</h4> </body> </html> ``` ```conf= #nginx.conf server{ listen 80 default_server; listen [::]:80 default_server; server_name localhost; root /usr/share/nginx/html; index index.html; charset utf-8; access_log /var/log/nginx/access_log; error_log /var/log/nginx/error_log; } ``` >`80 default_server`: 監聽在 80 埠 >`localhost`: server 會處理對 localhost 的請求 >`/usr/share/nginx/html`: 設定網站的根目錄,網頁檔案都放在這個目錄裡 >`index.html`: 預設首頁檔案為 index.html > `access_log`、`error_log`: 成功請求日誌及錯誤日誌的存放位置 ```dockerfile= #dockerfile FROM nginx COPY index.html /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf ``` >`FROM nginx`:要安裝的 image >`COPY index.html /usr/share/nginx/html`:將 index.html 複製到 nignx 內 `/var/www` 目錄下 >`COPY index.conf /etc/nginx/conf.d/default.conf`:複製 config 檔到 nginx 內 - 使用 dockerfile 建立 image - `docker build -t [image名字:image版本] .` - `docker build -t nginx:latest .` - `-t image 名字: image 版本`: 自訂 image 名字跟版本,若沒輸入版本則為預設值 latest - `.`: dockerfile 的路徑,因為我們的 terminal 已經移到 dockerfile 的路徑,所以只需打一個 . - 用 `docker images` 確認是否建立成功 ![image](https://hackmd.io/_uploads/Bk-BQHAa1e.png) - 建立並啟動 container - `docker run --name [container名字] -p 8080:80 -d [image名字]` - 瀏覽器搜尋 localhost:8080 ![image](https://hackmd.io/_uploads/ryW1DHCTJg.png) - 修改 nginx - `docker exec -it [container名字] bash` : 與 container 互動 - `cd /usr/share/nginx/html ` - ![image](https://hackmd.io/_uploads/HyfccrApJx.png) - `vim index.html` - 將 Hello LSAAA! 改為 Hello LSAAA-edited! > container 內安裝 vim : >- `apt update` >- `apt install -y vim` - `exit`: 回到host - `docker start [container名字]` - 將網頁 reload ![image](https://hackmd.io/_uploads/Sk493SCTJl.png) - 將更改過的 container 新建一個 image - `docker commit [container名字] [NewImage]` ![image](https://hackmd.io/_uploads/r1ci6S061l.png) - `docker stop [container名字]`: 停止原 container - `docker run -d -p [host port]:[container port] [NewImage]`: 用新的 image 建立 container ![image](https://hackmd.io/_uploads/HJLEkIRayx.png) - 打開剛剛設的 host port ,網頁會呈現剛才的頁面 ### 資料來源 :::spoiler [Docker Demo](https://medium.com/@xroms123/docker-%E5%BB%BA%E7%AB%8B-nginx-%E5%9F%BA%E7%A4%8E%E5%88%86%E4%BA%AB-68c0771457fb) [install Docker](https://cutejaneii.gitbook.io/docker/docker-installation/an-zhuang-docker-on-ubuntu) [Docker](https://phoenixnap.com/kb/what-is-docker) [client](https://www.geeksforgeeks.org/what-is-docker-client/) [Demo image](https://www.cherryservers.com/blog/docker-build-command) [socket](https://www.tsnien.idv.tw/Internet_WebBook/chap8/8-1%20Socket%20%E7%B0%A1%E4%BB%8B.html) [volume](https://docker.robertchang.me/volumes/dive-into-dockerhub) [OCI](https://opencontainers.org/about/overview/) [OCI](https://blog.tienyulin.com/open-container-initiative-oci/) [cgroup](https://medium.com/starbugs/%E7%AC%AC%E4%B8%80%E5%8D%83%E9%9B%B6%E4%B8%80%E7%AF%87%E7%9A%84-cgroups-%E4%BB%8B%E7%B4%B9-a1c5005be88c) [cgroup](https://kubernetes.io/docs/concepts/architecture/cgroups/?utm_source=chatgpt.com) [cgroup](https://medium.com/some-tldrs/tldr-understanding-the-new-control-groups-api-by-rami-rosen-980df476f633) [FS](https://www.terriblecode.com/blog/how-docker-images-work-union-file-systems-for-dummies/) [what's namespace](https://blog.nginx.org/blog/what-are-namespaces-cgroups-how-do-they-work) [namspace小實作-1](https://redhatgov.io/workshops/containers_the_hard_way/exercise3/) [namspace小實作-2](https://redhatgov.io/workshops/containers_the_hard_way/exercise4/) :::