林科佑
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    ###### tags: `1092LSA` # 虛擬化技術<br> 各位你學會了嗎 我們學廢了 - Book mode https://hackmd.io/@ncnu-opensource/book [TOC] ## 小小歷史 - 在1979年 version 7 Unix 的開發過程中引入 chroot system call。 :::info **chroot** 改變 Process 的 根目錄,讓這個 Process 只能在這個目錄裡面執行,並且不能對目錄之外的檔案執行存取動作。 ::: - 在2000年 FreeBSD 4.0版本中引入 jail mechanism 有了第一個完整的 OS level 的虛擬化技術,是因為 R&D Associates 這家 shared environmental services 供應商希望在自己的服務和客戶的服務之間建立清晰、明確的分離。 - 2006年,Linux 開發出 cgroups 。 - 2008年,Linux 基於 cgroups,開發出 LXC,並且開始使用 "容器" 這個術語。 - 2012年,dotcloud 啟動了 Docker 項目。 - 2013年,Docker 發佈,Docker 使用 LXC 作為預設執行環境,dotcloud 公司名改為 Docker 。 - 2014年,Docker 使用 libcontainer 來取代 LXC ,而 libcontainer 是由 Go 語言所編碼的。 :::info Linux vserver 為os level 的虛擬化 ,利用 chroot 來隔離資源( CPU time, network addresses , memory ), ::: :::info FreeBSD FreeBSD 的系統管理者可以創造出幾個小型的軟體系統分成幾個獨立的小系統叫做 jail。 ::: ## 為什麼要虛擬化 ### 早期伺服器, 機房 一台伺服器就是一個網站。 但是只有一個網站在一台功能強大的伺服器上跑好浪費。 而且一台伺服器,又貴又大又重。 除了機台都是錢, 放機台的房間要錢,這些機台的冷氣也要錢,管機台的人還是要錢。 - 🤔兩個網站分別在兩台伺服器 - 😱使用量不均 - 😭一台滿載另一台空轉 - 🤩兩個網站在同一台伺服器 - 🤗解決空轉問題 - 🤔有可用性問題 - 😭伺服器故障,導致兩個服務一起下去 - 🤔有安全性問題 - 😭一個網站被攻擊的時候,兩個服務一起下去 - 🤩在一台伺服器上開兩台 VM - 🤗解決安全性問題 - 一個網站被入侵,另一個網站不會被影響 - 🤔還是有可用性問題 - 😭如果伺服器直接壞了,那我的虛擬機還不是得下去 - 🤩兩台伺服器分別開兩台 VM - 🤗解決可用性問題 - 若一台伺服器壞掉,還有一台伺服器撐著 - 🤔管理問題 - 因為每台伺服器都要留一個空位給壞掉的時候做準備,資源沒辦法彈性運用 - 🤔靈活性問題 - 😭若要新增一個網站在伺服器,那我要放在哪台伺服器比較好 - 🤩兩台伺服器一起建立虛擬平台,在平台上開多台 VM - 🤗解決管理問題 - 不用留空位給壞掉的時候用,因為大家一起共用資源 - 🤗解決靈活性問題 - 因為這兩台伺服器用同一個平台運作,我就不用管要裝在哪台了 ### 虛擬化的效益 | 效益 | 特點 | 原因 | | -------- | -------- | -------- | | **減少成本** | 伺服器成本、電力成本跟空間成本等都降低 | 因為我不需要太多台伺服器 | | **管理彈性高** | 管理人員負擔降低 | 虛擬化可以減少實體伺服器的數量 | | **可用性高** | 系統的運作時間長 | 如果實體機壞了,其運行中的虛擬機不會跟著壞掉 | | **靈活性高** | 可以解決臨時需求 | 因為可以馬上建一台出來 | | **可以賺更多錢** | 減少硬體閒置的時間 | 因為可以把硬體資源切出來租給別人 | ### 但是! | 壞處 | 特點 | 原因 | | -------- | -------- | -------- | | **複雜度更高** | 伺服器除了要處理硬體的分配,還要確認關機前,VM 有沒有已經正常關機 | 因為 VM 數量龐大,如果一台一台檢查會累死阿... | | **會有性能損耗** | 做同一件事情時,CPU 需要更多的步驟才能完成 | 因為虛擬化的關係,以資源的請求為例,需要多走幾個步驟才能達到資源上的傳遞 | ## 甚麼是虛擬化 - 我有一台六核心的電腦 - 建一台配置有 六核心 的 VM_A - 再建一台配置有 六核心 的 VM_B - 把 VM_A 跟 VM_B 開機 - 我就可以在 六核心 的電腦,運作 十二核心 的電腦 虛擬化是將電腦的各種實體資源(CPU、記憶體、磁碟空間、網路卡等),予以抽象、轉換後呈現出來並可供分割、組合為一個或多個電腦組態環境。 ## 虛擬化的分類 ### 抽象等級分類 ![](https://i.imgur.com/XKkszDx.png =500x) #### 程式語言等級的虛擬化 - 此等級的虛擬化會將高階語言轉譯成一種名為位元組碼的語言,透過虛擬機器轉譯成為可以直接執行的命令。 - ex. Oracle Java ![](https://i.imgur.com/Mr8HvBb.png) - 對於 Java 而言,其實它只認識一種作業系統,這個系統叫作**JVM** - 對於 JVM 而言,位元碼檔案就是它的可執行檔案 #### 函式庫等級的虛擬化 - 每種系統的函式庫都不同,編譯後的結果也不同 - getpid vs GetProcessId - 可以使用 不同系統編譯的檔案 - ex. Wine, WSL - Wine ![](https://i.imgur.com/awnkloo.png =50x) - 可以在 Linux, BSD (UNIX like) , MacOS 中執行 windows 的執行檔(.exe) - Wine 不對 Windows 的執行檔本身進行反組譯,而是利用黑箱測試法並參照開發文件,來實做所有的 Win32 APIs。 #### 作業系統等級的虛擬化 - 資源和性能損耗比較小,不需要有多層轉譯 - 不需要虛擬整個底層,只要將執行環境包起來就好 - OS 的 kernel 可以提供多個互相隔離的 Container #### Container ![](https://i.imgur.com/PaJe3AR.png) ![](https://i.imgur.com/qNDIkTQ.png) - 將執行環境打包。 - 應用程式 (App) 為單位的虛擬化技術。 - 裝了相依性資源與 App 的執行環境。 - 容器間彼此獨立運行,互不干擾。 :::info **相依性資源(Dependency)**:官方是以 bins/libs 稱之,也就是二進位執行檔(binaries)與函數庫(libraries),它們可能是Nodejs、.Net Framework、程式庫、DLL(Dynamic-Link Library 具有函式功能的可執行檔)、編譯器等運行App所需要的執行環境。 ::: #### 指令集架構等級的虛擬化 - 透過軟體來模擬不同架構的硬體 (處理器、記憶體晶片、匯流排等) :::spoiler 筆記 若主機處理器可以執行由虛擬機轉換出來的指令,或是使用相同的指令集來完成任務,那就表示除了處理器以外的作業系統、I/O設備皆可不受特定平台所綁定,但由於虛擬機的每條指令都必須透過軟體來模擬,所以在效能會有較大程度的耗損。 ::: - ex. QEMU, Bochs - QEMU - 由軟體模擬 CPU,處理 Guest 的硬體請求,並由其轉譯給真正的硬體。 - 因為 QEMU 是純軟體實現的,所有的指令都要經過 QEMU ,使得效能很差 (配合 KVM 則可以解決這一問題。) - Bochs - 開源軟體,模擬的是整台 PC,包括 I/O 設備、記憶體和 BIOS - 能模擬大部分的作業系統 - Bochs 也是純軟體實作,所以效能也很差 #### 硬體抽象層等級的虛擬化 - ex. KVM、Xen、VMware ESXi、Hyper-V、Citrix - KVM - 可將 Linux kernel 轉化為一個 virtual machine monitor - guest OS 的 CPU 指令不用再經過 QEMU 來轉譯便可直接運行,大大提高了執行速度 - 但 KVM 本身只提供了 CPU 和記憶體的虛擬化,所以它必須結合 QEMU 才能構成一個完整的虛擬化技術 - QEMU / KVM 的搭配 ![](https://i.imgur.com/mltCVwF.png) - KVM 運作在 kernel mode,QEMU 運作在 user mode - 提供對 cpu、記憶體(KVM 負責),IO 設備(QEMU 負責)的虛擬 - 對各種虛擬設備的創建,調用進行管理(QEMU負責) - 如 Network, Disk - libvirt - 一套開源的虛擬化的管理工具 - 功能:虛擬機器管理、支援遠端連線、存儲管理 - 現在的 linux 上大多是使用結合 QEMU、KVM 核心模組和 libvirt 的虛擬解決方案 ## 硬體抽象層等級的分類 ### CPU 的四個特權模式(補充) ![](https://i.imgur.com/ONIUkRr.png =400x) - CPU 本身有支援 - 用來**保護資料**和**避免惡意行為**的機制 - CPU 運作架構上共有 Ring 0~Ring 3 四個特權等級 - Ring 0 (權限最大) - 通常為 Kernel - 控制實體主機硬體資源的使用 - CPU、Memory、Device I/O - Ring 3 (權限最小) - 使用者所碰觸的應用程式 - 幾乎所有的用戶程序都在這一級別 :::info **Call gate** - 當外環向內環請求資源或功能時,可以透過 Call gate 進行溝通 - 可以提升安全性 ::: - PV & FV - PV - ![](https://i.imgur.com/tZxN3P3.png =300x) - 不必為了虛擬化而將 CPU 特權等級被調降到 Ring 1(保持在Ring 0) - 透過 Hypercall 來存取硬體資源。 :::info **hypercall (PV)** - 直接將指令轉換成 hypervisor 可以執行的指令,再由 hypervisor 去要硬體資源 - hypercall 是 hypervisor 對 kernel 發出的 syscall ::: ### Full-Virtualization (全虛擬化) > 跟 OS 之間的關係 (Ring 3 ~ 1) - ![](https://i.imgur.com/8dys4hw.png =400x) - guest OS 運作在 Ring 1 - 在 Ring 0 才能執行特權/敏感指令 - Hypervisor 偵測到 Guest OS 要做他不能做的事(執行特權/敏感指令) - 用 **binary translation** 幫 Guest OS 執行他不能執行的指令 - Guest OS 認為自己的特權/敏感指令工作正常 - 但實際上是別人 (hypervisor) 幫他做了 - 性能差 - 要通過複雜的 trap 處理過程 - ex. - Adeos、Mac-on-Linux、Parallels Desktop for Mac、Parallels Workstation、VMware Workstation、VMware Server、**VirtualBox**、Win4BSD、Win4Lin Pro、**KVM** :::info **application 怎麼執行特權指令** - 透過 Software interrupt 讓 application 叫 kernel 幫他做事 ![](https://i.imgur.com/tJaPULJ.png) - OS 會把影響重大的指令設為**特權指令 (Privileged Instruction)**,以保護重要的資源,需要 Kernel mode 才能執行。 - 用一個 Mode Bit 記錄權限 - User Mode (Mode Bit==1):一般模式 - Kernel Mode (Mode Bit==0):在此模式下才有權利執行特權指令 - 目的為**保護系統安全** ::: :::spoiler Guest OS 跟 hypervisor 怎麼溝通 來補充一下,既然每次都只提到 Guest OS 怎麼跟 hypervisor 溝通,這次來講一下 application 怎麼跟 Guest OS 交流吧~當我們的 user process 執行時需要 OS 的服務,他就可以透過 system call 來完成這個動作,但是要怎麼做才能讓 kernel 幫我執行這個指令呢 ? 以 linux 的 kernel 為例,他有兩種 mode (kernel & user) 進入 kernel mode 之後,因為 Guest OS 在 Ring 1 的關係,執行特權指令又會發生 trap 這就接回我們上次說的, hypervisor 會偵測 Guest OS 有沒有發生 trap,偵測到幫他做完他原本要做的事之後就將結果回傳回 kernel ,然後再回傳回 user mode ::: :::info ## Binary Translation ![](https://i.imgur.com/rdOluBK.png) - hypervisor 會把他的請求轉換成硬體可以執行的 code,再來向硬體提出要求。 - hypervisor 可以在運行之前檢查一段 guest code,找到"敏感"但無"特權"的指令,將它們轉換為特權代碼,然後運行轉換後的代碼。 - "不安全" 指令也稱為 "敏感" 指令 - 導致 trap 的指令稱為 "特權" :::success **敏感指令** - 所有 I/O 指令 - 企圖訪問或者修改 VM mode 或者機器狀態的指令 - 企圖訪問或者修改敏感暫存器 / 儲存單元的指令 - 企圖訪問儲存保護系統或記憶體 / 地址分配系統的指令 ::: - direct execution - 一般性的指令不需要在 Ring0 才能執行就直接可以向硬體提出請求 ::: ### Para-Virtualization (半虛擬化) - ![](https://i.imgur.com/wSW8jR8.png =400x) - 以 Xen 為例 - 為何要修改 Kernel - 有些 Non-Virtualizable OS 指令不會被 hypervisor trap - 所以 Guest OS 利用 Hypercall 呼叫 Hypervisor 對缺少的指令進行更換。 :::info **Non-Virtualizable OS 指令** - 敏感但不是特權的指令 (17 個) - 舉例 - ![](https://i.imgur.com/r8AGWMK.png) - [What are “non-virtualizable” instructions in x86 architecture?](https://stackoverflow.com/questions/32794361/what-are-non-virtualizable-instructions-in-x86-architecture) ::: - 而在 Hypervisor 之上,還跑著一個 Host OS (Dom0 in Xen) - 用來管理 Hypervisor,並且利用 native OS 的方法管理硬體上的所有 device driver - Guest OS 不需要 device driver,可以直接找 Host OS - ex. Xen - 提供效能佳、可支援不同作業系統的系統環境。 - 原本有跟早期的 Linux Kernel 中包裝在一起,後因版權問題被移出 Kernel ### HVM (Hardware Virtual Machine) - 為了克服 VM 的 Kernel 無法置於 Ring 0 權限層級的問題 - ![](https://i.imgur.com/wUakw4W.png =400x) - 讓 Guest OS 發出的特權指令被 hypervisor 攔截到 - 需要硬體的支援虛擬化 - intel VT-x ![](https://i.imgur.com/rarUhLZ.png =400x) - VMX (Virtual-Machine Extensions) 是 Intel 所定義的架構 - Hypervisor 扮演 Host - VM 扮演 Guest - VMX 有兩種模式 - Hypervisor 運作在 VMX root operation - VM 運作在 VMX non-root operation - root 跟 non-root 都有對應的 Ring 0 ~ 3 - Hypervisor 運作在 root 模式下的 Ring 0,Guest OS 運作在 non-root 模式下的 Ring 0 - 切換 root 模式 - VMEntry : 從 root 切換到 non-root - 執行 Guest OS 的指令 - VMExit : 從 non-root 切換到 root - 若在 Non-Root Mode 執行了敏感指令時發生中斷等情況 - AMD SVM - 跟 intel VT-x 其實差不多啦 - 差別在功能的名稱可能不同 :::info **名稱不同的舉例** - 存放 VM 狀態和控制信息的數據結構 - Intel VT-x : VMCS - AMD-V : VMCB - TLB 紀錄中用於標記 VM 地址空間的字串 - Intel VT-x : VPID - AMD-V : ASID - 二級位置轉譯 - Intel VT-x : EPT - AMD : NPT ::: - Intel VT 及 AMD-V 增加 Ring -1 並提供 Hypervisor x86 虛擬化指令 - 使 Hypervisor 可以存取硬體,並把 Guest OS 放在Ring 0 - Guest OS 能在不影響其他 guest 或 host OS 的情況下,直接執行 Ring 0 的指令,所以不需要作 Binary Translation 也不需要修改 Kernel ### HVM 與其他虛擬化技術的混合 - ![](https://i.imgur.com/yFbAkPy.png =500x) - 改善原本那個虛擬化的缺失,讓他進化 ### FV vs PV vs HVM | | FV | PV | HVM | |:------------------:|:------------------:|:----------------------------------------------------:|:---------------------------:| | **怎麼處理特權指令** | Binary translation | 修改 kernel 及使用 hypercall,取代無法被虛擬化的指令 | 新增一個 root mode 特權等級 | | **怎麼執行 CPU 指令** | 軟體 | 軟體 | 硬體 | | **效能** | 👎🏿 | 👍 | 👍 | | **OS 相容性** | 👍 | 👎🏿 | 👍 | ## Hypervisor :::spoiler 筆記 Hypervisor 的作用就像是一位交通警察,指揮主機的資源並配置給每個虛擬機器 或者 將虛擬機要的硬體資源只會到對應的硬體來處理 ::: - 又稱虛擬機器監視器(virtual machine monitor) - 負責管理與分配硬體資源 - 提供動態的硬體資源配置及彈性設定。 - 介於軟體與硬體之間一層極小的程式碼,作為實體資源與虛擬機器間的控制介面 - 所以他算軟體喔~ - hypervisor 用來執行一個或多個虛擬機器的電腦稱為 `host machine` - 這些虛擬機器 (VM) 則稱為 `guest machine`。 ### 類型 - Type 1 : Bare-Metal hypervisor (裸機型) ![](https://i.imgur.com/R9peKa3.jpg =500x) - Hypersivor 直接安裝在 Host Machine 的硬體上 - Host Machine 的硬體不需先有 OS 就可安裝 - 特點 - 需要硬體支援 - Intel (Intel Virtualization Technology, Intel VT-x) - AMD (AMD Secure Virtual Machine, AMD SVM) - Virtual Machine Monitor 作為 Host OS - 執行效率高 - 舉例 - VMware ESX 伺服器版本 - Xen 3.0 及以後版本 - Type 2 : Hosted hypervisor (主機型) ![](https://i.imgur.com/XQVCKoF.jpg =500x) - 這些虛擬機器管理程式執行在傳統的 OS 上,就像其他電腦程式那樣執行。 - 特點 - Virtual Machine Monitor 作為應用程式執行在 Host OS 環境內 - 執行效率一般較 type I 低 - 舉例 - VMware workstation - Xen 3.0 以前版本 - **Virtual Box** - **QEMU** - 比較 | Bare-Metal hypervisor | | Hosted hypervisor | |:------------------: | ----- |:-----------------:| | 👍 | 效能 | 👎 | | 👍 | 穩定度 | 👎 | | 👍 | 安全性 | 👎 | | 👎 | 易用性 | 👍 | ## 來重新整理一下呦 避免大家混淆 - 這是偶們 VM 和 Container 的架構 ![](https://i.imgur.com/E00FKIf.jpg) - 而 VM 這個咚咚是由 VMM 建構出來的,VM 和 Container 互補互生 ![](https://i.imgur.com/YcGw6Ni.jpg) - Hypervisor | | Bare-Metal hypervisor | Hosted hypervisor | | -------- | -------- | -------- | | **效能** | 高 | 低 | | **特點** | 直接安裝在 Host Machine 的硬體上 | 執行在 OS 上 | | | 作為 Host OS | 作為應用程式執行在 Host OS 環境內 | | | 需要硬體支援 | 因為底下有 Host OS 的幫助,hypervisor 不用親自跟硬體溝通 | - 硬體抽象層等級的分類 | | 全虛擬化 | 半虛擬化 | | --------------- | -------- | -------- | |技術|Binary translation、Direct excution|Hypercalls| |消耗資源 | 多,因為二進位轉譯| 少,因為 Hypercall | |不需修改 Kernel | ✔️ |❌| |執行速度 | ..🐌 | 🐇~~ | |kernel 跑在哪個特權層級 | Ring | Ring 0 | - VM 跟 Container 的差異 | 功能平台 | Container | Virtual Machine | | -------- | -------- | -------- | | **技術** | 不需要安裝 OS,以 app 為中心 | 需要安裝 OS(Guest OS),以 OS 為中心 | | **開機載入時間** | 秒為單位 | 分鐘為單位(因為須等待作業系統開機時間) | | **硬碟容量** | MB 為單位 | GB 為單位 | | **異質 guest** | ❌ | ✔️ | | **單一主機同時運行** | 最高可到數千個 | 最多可到數十個 | | **隔離性** | 不完全隔離(共用 Kernel) | 完全隔離(用自己的 Kernel) | ### 象限表做不出來,不過找到一個不錯的圖 ![](https://i.imgur.com/Ct126Jb.png) # 容器 - Container picture from : https://twitter.com/martinbuberl/status/915184348558712833 ## Container 介紹 - **安全性:** **將 Applications 與 Host OS 彼此隔離**,提高了安全性。將 Application 容器化 ,從根本上防止入侵者進一步擴展影響到其他的 Container 或 Host OS。此外,可以定義安全權限,以自動阻止不想要的 Component 進入 Container ,或是限制不必要資源的訪問。 BUT 有一點很重要因為 **Container 使用的是 Host OS kernel** :::info 例如: Linux 的 Namespace 幫每個容器提供隔離的功能,被隔離的資源其中包括 Network、PID、User ID、Inter-Process communication 和 Hostname setting。 ::: - **輕量級:** **和 VM 相比** Container 所需要的檔案更少,**因為只需要準備可以讓 Process 運作的檔案**,代表著 Image 的檔案更小。而**在啟動時,需要呼叫、載入記憶體的檔案更少**,意味著它可以快速啟動。 - **可移植性:** Container 裡面已經**有要軟體的 dependency** ,而無需重新設定即可執行。 - **支援現代的開發模式和架構:** 由於其跨平台的可移植性/一致性以及體積小巧的優點,非常適合現代開發和應用模式,例如 DevOps 、Microservices 等。 :::info devops 讓開發和維運兩個團隊共同參與設計 → 開發 → 運行服務的一個生命週期。 ::: - **易於管理:** 使用容器管理平台( container orchestration platform )可以自動安裝、增加容器化的服務。容器管理平台可以簡化管理任務,例如: 提供監視、記錄 log 和 debug 等功能。 :::info 例如: Kubernetes 是一個由 Google 開發並開源的系統,專門用以自動化部屬、彈性擴充及容器應用管理 ::: - **提高硬體資源使用率:** 和 VM 一樣,Container 使開發人員可以提高 Physical machine 的 CPU 和 記憶體使用率。 - **隔離性**: 每個 Containerized App 都是**被互相隔離的,並且獨立運作**。**一個 Container 出現了 BUG 並不會影響到其他 Container 的運作**。開發團隊修復這個 Container 中的問題時,不需要讓其他的 Container 停止運作。 Source from: https://www.ibm.com/cloud/learn/containers 、 https://www.ibm.com/cloud/learn/containerization#toc-benefits-1bZ7yTDN # LXC ## 簡介 **Linux container** (LXC) 是一種 OS-level 的虛擬化技術,透過 **Namespace** 和 **cgroup** 來分配不同 Container 的可用硬體資源,創造出 Application 的**獨立沙盒且互相隔離的執行環境**,使得 Linux 使用者可以容易的建立、管理、應用 Container。 :::info 沙盒可以說是一個生態觀察箱,觀察生物在裡面的活動還有造成的影響。在裡面造成的影響並不影響到外面的世界。 ::: ### Cgroups ( Control groups ) ![](https://i.imgur.com/dO625IB.png) - 概念 - **cgroup** : 是一組 process 的行為控制群組,而 cgroup 可以有很多個 process 。 - **hierarchy** : 按照樹狀結構進行排列。 - **subsystem** : cgroup 中可添加或刪除的 module。 - 功能: - 限制可用的 CPU time 和 Memory available。 - 紀錄使用的 CPU time 。 - freezing、resuming cgroup 中 Process 的執行。 ![](https://i.imgur.com/igWmju7.png) - Demo - 輸入`mount | grep cgroup` ![](https://i.imgur.com/EO13lpy.png) 第一行的`tmpfs`說明`/ sys / fs / cgroup`目錄下的檔案是臨時儲存在 Memory 中。 - 輸入`ls /sys/fs/cgroup ` ![](https://i.imgur.com/jh8CB0A.png) - 輸入`cd /sys/fs/cgroup `,再用`ls -l`,看一下這個目錄有什麼檔案。 ![](https://i.imgur.com/gufKLPp.png) - 我們來看看 memory 裡面有什麼檔案 輸入`ls -l memory` ![](https://i.imgur.com/2e0EF4O.png) 裡面有一個檔案叫`memory.limit_in_bytes` ![](https://i.imgur.com/JR62qqJ.png) 設定 User Memory 的最大用量,單位為 `bytes`。 - 輸入 `ps -a` ![](https://i.imgur.com/xFlHTTW.png) - 輸入`cat /proc/[pid]/cgroup` ![](https://i.imgur.com/IuxEzrs.png) - 下載工具 `sudo apt install cgroup-bin` - 限制 Memory 的可用容量 ``` sudo mkdir jack_memory sudo su ls -l jack_memory/ echo 314572800 > jack_memory/memory.limit_in_bytes echo 0 > jack_memory/memory.swappiness ``` ![](https://i.imgur.com/HZuP5Ih.png) - 創建一個不斷分配 Memory 的程式,它分五次分配內存,每次分配100MB。(程式碼在下面) ![](https://i.imgur.com/QtCKB0t.png) - 執行 `cgexec -g memory:jack_memory ./mem` ![](https://i.imgur.com/JjuNqcB.png) cgexec 把要執行的任務綁定到這個cgroup ``` #include<stdio.h> #include<stdlib.h> #include<string.h> #define CHUNK_SIZE 1024 * 1024 * 100 void main() { char *p; int i; for(i = 0; i < 5; i ++) { p = malloc(sizeof(char) * CHUNK_SIZE); if(p == NULL) { printf("fail to malloc!"); return ; } // memset() 函數用來指定 memory 的前n個 bytes 設置為特定的值 memset(p, 0, CHUNK_SIZE); printf("malloc memory %d MB\n", (i + 1) * 100); } } ``` :::info 任務( task ): processes or thread ::: source from : https://www.cnblogs.com/sparkdev/p/8296063.html ### Namespace | Namespace| 被隔離的資源 | | -------- | -------- | | **PID Namespace** | Process ID| |**Network Namespace**|網卡、 iptables、routing table| |**UTS Namespace** |hostname、NIS domain name| |**IPC Namespace**|IPC resources、namely、System V IPC objects、POSIX message queues| |**Cgroup Namespace**|Cgroup root directory| |**User Namespace**|User & group ID| |**Time Namespace**|Boot & monotonic clocks| |**Mount Namespace**|Mount point| - PID Namespace ![](https://i.imgur.com/0h18SKj.png) :::info process 的樹,不一定長這樣有線連起來,有線連起來會 Parent process & child process ::: - Mount Namespace - **/mnt** : 讓 user 臨時掛載別的 file system,例如: 接上光碟機,放入光碟後,透過該目錄進去查內光碟裡面的內容 - subtree 有四種類型: | TYPE| 作用| | -------- | -------- | | MS_SHARED | 大家同時安裝或卸載。 | |MS_PRIVATE|我裝我的,你裝你的,不會影響 subtree。| |MS_SLAVE |同時安裝或卸載,只會發生在父子關係中,同階層的不會發生。| |MS_UNBINDABLE|這個 subtree 的都不給你安裝。| - [subtree Demo](https://lwn.net/Articles/689856/) ![](https://i.imgur.com/NFEHtPn.png) - unshare demo - 開啟兩個 terminal 左邊輸入 `sudo unshare -m /bin/bash` - 左邊繼續輸入 ```mount -t tmpfs tmpfs /mnt mount | grep mnt``` - 右邊輸入 ```date | sudo tee /mnt/test cat /mnt/test``` - 左邊輸入`cat /mnt/test` ![](https://i.imgur.com/7VQA2sf.png) source from : https://www.redhat.com/sysadmin/mount-namespaces :::info ### 補充 ![](https://i.imgur.com/3utU0oG.png) - `sudo unshare -m /bin/bash` - `mount -t tmpfs tmpf123 /mnt` - `cat /mnt/test` - `df -h` ![](https://i.imgur.com/5ar6pOU.png) ![](https://i.imgur.com/hmfEtw9.png) ![](https://i.imgur.com/e4cLStm.png) ------------------------- ![](https://i.imgur.com/ynXC1Xc.png) ![](https://i.imgur.com/G3Noa8z.png) ![](https://i.imgur.com/T6c6L36.png) ![](https://i.imgur.com/3CGTkQt.png) ![](https://i.imgur.com/SDgjKhN.png) ![](https://i.imgur.com/RzO9k1p.png) ::: :::info NIS, an abbreviation of Network Information Service ::: :::info - System V : Process 之間的 communication - IPC resource: Amount of shared memory Number of semaphores Size of message queues and messages ::: source from : https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt picture from : https://www.toptal.com/linux/separation-anxiety-isolating-your-system-with-linux-namespaces https://www.schutzwerk.com/en/43/posts/namespaces_02_mnt/ # Docker ## 簡介 使用 Docker 可標準化流程、快速部署、統一開發與執行環境,以及透過提高資源使用率節省成本。 ## 主要核心 ### Image Docker 映像檔可以把它想成是 VM 的 Guest OS ,是 read only。涵蓋 Container 內的所有程式(包括應用程式、函式庫、環境設定檔) :::info 蛋糕模具 ::: ### Dockerfile 說明 Docker Image 如何安裝、更新等,例如:要安裝...套件。 :::info 規格書 ::: ### Container 容器是利用映像檔 Image 所創造出來的,一個 Image 可以創造出多個不同的 Container , Container 可以被啟動、停止、刪除。而 Container 被刪除的時候,資料會全部不見,所以才會有 Volume 來儲存 Container 的資料。 :::info 蛋糕模具烤出來的蛋糕本體 ::: ### Volume Container 永久保存 Data 的地方,**因為 Container 被刪除時,所儲存的 data 都會消失**。 ### Network - bridge - host ![](https://i.imgur.com/w8M6yDr.png) - overlay - 注意事項: - 啟用port | Port Number | 作用 | | -------- | -------- | | 2377(TCP) | 管理群集的溝通 | |7946(TCP & UDP)|nodes 間的溝通| |4789(UDP)| overlay network traffic| - 初始化 swarm `docker swarm init` or 加入現有的 swarm `docker swarm join` - none ![](https://i.imgur.com/4EQdw1S.png) - macvlan ![](https://i.imgur.com/bPOKbYF.png) ![](https://i.imgur.com/XDLDmUJ.png) ![](https://i.imgur.com/ERxasMI.png) ![](https://i.imgur.com/Ea7A3Qv.png) ### Repository 倉庫是**集中存放映像檔檔案**的場所,Registry 是存放著多個倉庫,最大的公開 Registry 是 Docker Hub。Docker Registry的概念跟 Github 類似,可以在上面建立多個倉庫,然後透過 push、pull 的方式上傳、存取 image 。 ## Docker - Swarmkit 將執行 Swarmkit 的機器,形成 Swarm。而機器則會成這個 Swarm 裡的 Node。 | Name| 比喻 | | -------- | -------- | |Swarm | 作品 | |Swarm mode|模式| |Docker swarm|舊的工具| |Swarmkit|新的工具|| ### Node (節點) |TYPE| 作用 | | -------- | -------- | | Worker | **執行**工作 | | Manager| 接收和回應用戶的請求,**協調**工作| Node 是 Manager 的時候,可以像 Woker 一樣執行工作 。 ![](https://blog.toright.com/wp-content/uploads/2017/10/swarm-diagram-1-640x300.png) :::info Node 是 Cluster 組成的基本單位。 工作(Task): Worker 執行的基本單位,它是**容器**。 服務(Service): 由**工作**,所組成的。 叢集(Cluster):由節點所組成的一個群組。 ![](https://i.imgur.com/eNyD0BU.png) ::: ### 特點 - **協同運作(Orchestration)** - **狀態協調** : 當 Node1 掛掉了,Swarmkit 會把 Node1 執行的任務,安排到 Node2 上執行。 - **重啟策略** : User 可以**制定重啟的條件、延遲和最大嘗試次數**。SwarmKit會檢測任務狀態,並按照 User 定義的條件進行重啟,同時SwarmKit會決定是否在不同節點啟動任務,避免失效節點對服務產生影響。 - **服務類型** : - **Replicated Services** : 按照 User 預計要啟動任務的數量,在不同的節點上啟動任務。 - **Global Services** : 在叢集裡每台可以使用的 Worker 執行一個任務。 - **設定更新** : - **平行更新** : 可以設定同時更新多少個工作。 - **延遲更新** : 設定每次更新之間的最短延遲時間。 - **排程(Scheduling)** - Swarmkit 知道 Node 上可用的資源,並照著現有的資源分配任務。 - 利用條件式來尋找符合的 Node | node attribute | matches | example | |------------- |-------------| -------------| | node.id | node's ID | `node.id == 2ivku8v2gvtg4`| | node.hostname | node's hostname | `node.hostname != node-2`| | node.ip | node's IP address | `node.ip != 172.19.17.0/24`| | node.role | node's manager or worker role | `node.role == manager`| | node.platform.os | node's operating system | `node.platform.os == linux`| | node.platform.arch | node's architecture | `node.platform.arch == x86_64`| | node.labels | node's labels added by cluster admins | `node.labels.security == high`| | engine.labels | Docker Engine's labels | `engine.labels.operatingsystem == ubuntu 14.04`| - **管理叢集** - **狀態儲存** : SwarmKit 基於 Raft 演算法 和 in-Memory read 維護叢集的狀態一致性,並能夠在叢集狀態發生異常時迅速作出調度調整。 - **拓撲管理** : User 可以利用 API/CLI 來調整節點類型。 - **節點管理** : 更改節點狀態為已暫停,防止其他任務分配到該節點上。 - **安全** - 節點互相**使用TLS**來加密通訊。 - **TLS憑證**需要進行更換,更換時間可由 User 設定,預設為 3 個月,最短時間為 30 minutes 。 - 節點加入集群可以通過自動允許、手動允許或通過一個密鑰來加入叢集。 :::info [**Raft**](http://thesecretlivesofdata.com/raft/) : : 每台機器會投票,把其中一台機器選為 leader, 其他則為 follower ,當 leader 掛掉了,則會再重新投票出leader。Raft [**TLS**](https://zh.wikipedia.org/zh-tw/%E5%82%B3%E8%BC%B8%E5%B1%A4%E5%AE%89%E5%85%A8%E6%80%A7%E5%8D%94%E5%AE%9A) : : 為網路通訊提供安全及資料完整性保障。 用於在兩個應用程式間透過網路建立起安全的連線,**防止在交換資料時受到竊聽及篡改**。 ::: source from : https://github.com/docker/swarmkit/ ## Docker 應用 ### Microservices Microservices,和 Monolithic service 差別 ![](https://i.imgur.com/RoNNFkR.jpg) - 特性: - **模組化**: 讓架構更清楚 - **易擴展**: 使用量高的模組,可以很容易地增加它的數量。 - **分散式開發**: 可以針對不同的服務選擇最適合的工具進行開發。 - 開發注意事項: - **訊息格式不一致** - 如果不一致,管理跟開發上會很雜亂 - 缺點: - 當服務串接越多服務**複雜度提升** - 服務呼叫服務的時候,會有 **Network delay** ### Docker swarm demo - 首先建立三個節點,點左邊 ADD NEW INSTANCE,執行三次。 ![](https://i.imgur.com/gE33JdQ.png) - 在 node1 輸入 `docekr swarm init --advertise-addr [node's ip]` ,而這個節點會成為 manager - 輸入 `docker info` 查看 docker 現在的訊息。 ![](https://i.imgur.com/wa4bVCO.png) - 輸入 `docker node ls` 查看 swarm node 的訊息 ![](https://i.imgur.com/W8G1PX5.png) - 在node2 、 node3 的節點上,輸入下面第一張圖片的那長串,那 node2 、 node3 會以工人的類型進入這個 swarm。 ![](https://i.imgur.com/CxVtzcO.png) ![](https://i.imgur.com/DiSLjpo.png) ![](https://i.imgur.com/s6qzjCm.png) - 回到節點1上,再次輸入 `docker node ls`,來看看偶們的節點訊息。欸!!! 多了,兩個出來好酷喔。 ![](https://i.imgur.com/PnkfXaY.png) - 在節點1上,開始創造我們的服務,請輸入`docker service create --replicas 1 --name helloworld alpine ping docker.com` - **replicas** 我們要運行幾個 task - **name** 命名服務名稱 - name `alpine ping docker.com`後面接的是,你要用的 image ![](https://i.imgur.com/nMAlIMz.png) - 輸入 `docker service inspect --pretty helloworld`,來查看剛剛創建的服務訊息 - **pretty** 讓輸出格式能讓使用者,更容易讀懂。 ![](https://i.imgur.com/xgI0bq4.png) - 再測試一下,創建其他的服務,而 Swarmkit 自動把它分配到其他節點上運行,讚讚。 ![](https://i.imgur.com/gxSxx0C.png) - 去 node2 、 node3,看一下是不是真的在跑這個 task 。輸入`docker ps` ![](https://i.imgur.com/wFJFN20.png) - `docker service scale helloworld=5`,把 task 增加到 5 個。 ![](https://i.imgur.com/E23PQT5.png) ![](https://i.imgur.com/5GgAdan.png) ![](https://i.imgur.com/Fvllq4M.png) - 刪除服務,輸入`docker service rm helloworld`。用`docker service inspect helloworld` 和 `docker ps`,檢查是否真的停止了。 ![](https://i.imgur.com/BgWi1Vg.png) ![](https://i.imgur.com/31qes8D.png) - `docker service create --replicas 3 --name redis --update-paralleism 2 --update-delay 10s redis:3.0.6` ![](https://i.imgur.com/piDaKnf.png) - `docker service inspect --pretty redis` ![](https://i.imgur.com/FdbMImu.png) - `docker service update --image redis:3.0.7 redis` ![](https://i.imgur.com/knUG6lK.png) ![](https://i.imgur.com/cTvSeq9.png) - `docker service inspect --pretty redis` ![](https://i.imgur.com/5DQ3M47.png) - `docker service ps redis` ![](https://i.imgur.com/Rn4RqQM.png) - `docker node update --availability drain node2` ![](https://i.imgur.com/hAk6cXF.png) ![](https://i.imgur.com/FdC7Jo5.png) - `docker serivce ps redis` ![](https://i.imgur.com/OKSly1g.png) - `docker service create \ --name my-web \ --publish published=8080,target=80 \ --replicas2 \ nginx` ![](https://i.imgur.com/fBeP7QE.png) ![](https://i.imgur.com/rrHYIAX.png) - 點節點有顆亮亮的8080進來 node1 ![](https://i.imgur.com/4UMRf9N.png) node2 ![](https://i.imgur.com/dK9qQ1x.png) node3 - 看一下它們的網路 ![](https://i.imgur.com/uHUjZdC.png) ![](https://i.imgur.com/zx7TLke.png) ![](https://i.imgur.com/CHaIshy.png) ![](https://i.imgur.com/atPtvFU.png) ![](https://i.imgur.com/8EEl98T.png) - `docker node demote [node's name]` - `docker node promote [node's name]` :::info **docker_gwbridge** : - 初始化或者加入一個 swarm 時會創建的 bridge ,用在 container 之間的通訊。 - 在容器的所有網絡都不能訪問外部時,Docker 會將docker_gwbridge 網絡加入到容器中,用來訪問外部網絡或者其他的 cluster 的節點。 **ingress**: - 它是 overlay,當外網要使用該服務時,可以從任意一個節點去使用,即使這個節點並沒有執行服務的 task 。 :::

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully