摘要:本章內容將講解虛擬化虛擬化本質。在中限制容器能夠使用的資源量參數示例是的縮寫,是內核提供的一種可以進程所使用的物理資源的機制。
本章內容將講解 Docker 虛擬化、虛擬化本質、namespace、cgroups。
本小節將介紹 Docker 虛擬化的一些特點。
?
在接觸 Docker 的過程中,或多或少會了解到 Docker 的虛擬化,最常見的介紹方式是對比 Docker 和虛擬機之間的差別,筆者這里也給出兩者的對比表格,以便后面詳細地展開來講。
? | 虛擬機 | Docker 容器 |
---|---|---|
隔離程度 | 硬件級進程隔離 | 操作系統級進程隔離 |
系統 | 每個虛擬機都有一個多帶帶的操作系統 | 每個容器可以共享操作系統(共享操作系統內核) |
啟動時間 | 需要幾分鐘 | 幾秒 |
體積大小 | 虛擬機鏡像GB級別 | 容器是輕量級的(KB/MB) |
啟動鏡像 | 虛擬機鏡像比較難找到 | 預建的 docker 容器很容易獲得 |
遷移 | 虛擬機可以輕松遷移到新主機 | 容器被銷毀并重新創建而不是移動 |
創建速度 | 創建 VM 需要相對較長的時間 | 可以在幾秒鐘內創建容器 |
資源使用 | GB級別 | MB級別 |
Docker 中的虛擬化是依賴于 Windows 和 Linux 內核的,在 Windows 上會要求開啟 Hyper-V,在 Linux 上需要依賴 namespace 和 cgroups 等,因此這里就不過多介紹 Docker 了,后面主要介紹 Linux 上的虛擬化技術。
傳統虛擬化方式是在硬件抽象級別虛擬化,其特點是 虛擬化程度高。
![traditional_kvm ](./images/traditional_kvm .jpg)
傳統虛擬化方式的優點是:
1,虛擬機之間通過虛擬化技術隔離互不影響 2,物理機上可部署多臺虛擬機,提升資源利用率 3,應用資源分配、擴容通過虛擬管理器直接可配置 4,支持快照、虛擬機克隆多種技術,快速部署、容災減災
傳統虛擬化部署方式的缺點:
1, 資源占用高,需要額外的操作系統鏡像,需要占用GB級別的內存以及數十GB存儲空間。 2,啟動速度慢,虛擬機啟動需要先啟動虛擬機內操作系統,然后才能啟動應用。 3,性能影響大,應用 => 虛擬機操作系統=> 物理機操作系統=> 硬件資源
本節簡單地講解 Docker 的實現原理,讀者可以從中了解 Linux 是如何隔離資源的、Docker 又是如何隔離的。
我們知道,操作系統是以一個進程為單位進行資源調度的,現代操作系統為進程設置了資源邊界,每個進程使用自己的內存區域等,進程之間不會出現內存混用。Linux 內核中,有 cgroups 和 namespaces 可以為進程定義邊界,使得進程彼此隔離。
在容器中,當我們使用 top 命令或 ps 命令查看機器的進程時,可以看到進程的 Pid,每個進程都有一個 Pid,而機器的所有容器都具有一個 Pid = 1 的基礎,但是為什么不會發生沖突?容器中的進程可以任意使用所有端口,而不同容器可以使用相同的端口,為什么不會發生沖突?這些都是資源可以設定邊界的表現。
在 Linux 中,namespace 是 Linux 內核提供的一種資源隔離技術,可以將系統中的網絡、進程環境等進行隔離,使得每個 namespace 中的系統資源不再是全局性的。目前有以下 6 種資源隔離,Docker 也基本在這 6 種資源上對容器環境進行隔離。
讀者可以稍微記憶一下這個表格,后面會使用到。
namespace | 系統調用參數 | 隔離內容 |
---|---|---|
UTS | CLONE_NEWUTS | 主機名和域名 |
IPC | CLONE_NEWIPC | 信號量、消息隊列、共享內存 |
PID | CLONE_NEWPID | 進程編號 |
Network | CLONE_NEWNET | 網絡設備、網絡棧、端口 |
Mount | CLONE_NEWNS | 文件系統掛載 |
User | CLONE_NEWUSER | 用戶和用戶組 |
[info] 關于 Mount
namespace 的 Mount 可以實現將子目錄掛載為根目錄。
Linux 中,unshare 命令行程序可以創建一個 namespace,并且根據參數創建在 namespace 中隔離各種資源,在這里我們可以用使用這個工具簡單地創建一個 namespace。
為了深刻理解 Linux 中的 namespace,我們可以在 Linux 中執行:
unshare --pid /bin/sh
--pid
?僅隔離進程。
這命令類似于?docker run -it {image}:{tag} /bin/sh
?。當我們執行命令后,終端會進入一個 namespace 中,執行 top 命令查看進程列表。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 160188 8276 5488 S 0.0 0.4 9:35.58 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.08 kthreadd 3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp 4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp
可以看到,進程 PID 是從 1 開始的,說明在這個 namespace 中,與主機的進程是隔離開來的。
這個命令中,只隔離了進程,因為并沒有隔離網絡,因此當我們執行?netstat --tlap
?命令時,這個命名空間的網絡跟其它命名空間的網絡是相通的。
在執行 unshare 命令前,使用 pstree 命令查看進程樹:
init─┬─2*[init───init───bash] ├─init───init───bash───pstree ├─init───init───fsnotifier-wsl ├─init───init───server───14*[{server}] └─2*[{init}]
為了方便比較,我們使用?unshare --pid top
?創建一個 namespace,對比執行了 unshare 命令后:
$> pstree -lhainit ├─init │ └─init │ └─bash │ └─sudo unshare --pid top │ └─top ├─init │ └─init │ └─bash │ └─pstree -lha ├─init │ └─init │ └─fsnotifier-wsl ├─init │ └─init │ └─bash ├─init │ └─init │ └─server --port 29687 --instance WSL-Ubuntu │ └─14*[{server}] └─2*[{init}]
而在 namespace 中,查看 top 顯示的內容,發現:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 1904 1136 1020 S 0.0 0.0 0:08.38 init
通過進程樹可以看到,不同 namespace 內的進程處于不同的樹支,他們的進程 PID 也是相互獨立的。其功能類似于 Docker 中的 runc。
由于筆者對 Linux 了解不深,這部分內容就不深入探究了。
在?unshare
?命令中,--pid
?參數創建 隔離進程的命名空間,此外,還可以隔離多種系統資源:
在前面我們使用了 unshare 創建命名空間,在這里我們可以嘗試使用 Go 調用 Linux 內核的 namespace,通過編程代碼創建隔離的資源空間。
Go 代碼示例如下:
package mainimport ( "log" "os" "os/exec" "syscall")func main() { cmd := exec.Command("sh") cmd.SysProcAttr = &syscall.SysProcAttr{ Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWNS | syscall.CLONE_NEWNET | syscall.CLONE_NEWPID | syscall.CLONE_NEWUSER, } cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { log.Fatalln(err) }}
[info] 提示
前面已經提到過 UTS 等資源隔離,讀者可以參考表格中的說明,對照代碼理解 Cloneflags 的作用。
代碼示例參考 陳顯鷺《自己動手寫 Docker》一書。
在這個代碼中,我們啟動了 Linux 中的 sh 命令,開啟一個新的進程,這個進程將會使用新的 IPC、PID 等隔離。
讀者可以在 Linux 中,執行?go run main.go
?,即可進入新的命名空間。
限于個人水平和篇幅有限,關于 namespace 的介紹就到這里。
前面提到的 namepace 是邏輯形式使得進程之間相互不可見,形成環境隔離,這跟 Docker 容器的日常使用是一樣的,隔離根目錄,隔離網絡,隔離進程 PID 等。
當然,Docker 處理環境隔離外,還能限制每個容器使用的物理資源,如 CPU 、內存等,這種硬件資源的限制是基于 Linux 內核的 cgroups 的。
在 Docker 中限制容器能夠使用的資源量參數示例:
-m 4G --memory-swap 0 --cpu-period=1000000 --cpu-quota=8000000
cgroups 是 control groups 的縮寫,是 Linux 內核提供的一種可以進程所使用的物理資源的機制。
cgroups 可以控制多種資源,在 cgroups 中每種資源限制功能對應一個子系統,可以使用命令查看:
mount | grep cgroup
[info] 提示
每種子系統的功能概要如下:
blkio
?— 該子系統對進出塊設備的輸入/輸出訪問設置限制,如 USB 等。cpu
?— 該子系統使用調度程序來提供對 CPU 的 cgroup 任務訪問。cpuacct
?— 該子系統生成有關 cgroup 中任務使用的 CPU 資源的自動報告。cpuset
?— 該子系統將單個 CPU和內存節點分配給 cgroup 中的任務。devices
?— 該子系統允許或拒絕 cgroup 中的任務訪問設備。freezer
?— 該子系統在 cgroup 中掛起或恢復任務。memory
?— 該子系統對 cgroup 中的任務使用的內存設置限制,并生成有關自動報告。net_cls
— 允許 Linux 流量控制器 (?tc
) 識別源自特定 cgroup 任務的數據包。net_prio
?— 該子系統提供了一種動態設置每個網絡接口的網絡流量優先級的方法。ns
—命名空間子系統。perf_event
?— 該子系統識別任務的 cgroup 成員資格,可用于性能分析。詳細內容請參考:redhat 文檔
我們也可以使用?lssubsys
?命令,查看內核支持的子系統。
$> lssubsys -acpusetcpucpuacctblkiomemorydevicesfreezernet_clsperf_eventnet_priohugetlbpidsrdma
[info] 提示
Ubuntu 可以使用?
apt install cgroup-tools
?安裝工具。
為了避免篇幅過大,讀者只需要知道 Docker 限制容器資源使用量、CPU 核數等操作,其原理是 Linux 內核中的 cgroups 即可,筆者這里不再贅述。
本節內容將從底層角度,聊聊虛擬化。
從語言角度,一臺由軟硬件組成的通用計算機系統可以看作是按功能劃分的多層機器級組成的層次結構。
如果從語言角度來看,計算機系統的層次結構可用下圖所示。
?
?
【圖來源:《計算機組成原理》天勤考研 1.2.5 計算機系統的層次結構】
我們平時使用的筆記本、安卓手機、平板電腦、Linux 服務器等,雖然不同機器的系統和部分硬件差異很大,但是其系統結構是一致的。從 CPU 中晶體管、寄存器 到 CPU 指令集,再到操作系統、匯編,現在使用的通用計算機基本上這種結構。
下面講解一下不同層次的主要特點。
計算機的最底層是硬聯邏輯級,由門電路,觸發器等邏輯電路組成,特征是使用極小的元件構成,表示了計算機中的 0、1。
微程序是使用微指令編寫的,一個微程序即一個機器指令,一般直接由硬件執行,它可以表示一個最簡單的操作。例如一個加法指令,由多個邏輯元件構成一個加法器,其元件組成如下圖所示(圖中為一個 8 位全加器)。
傳統機器語言機器級是處理器的指令集所在,我們熟知的 X86、ARM、MIPS、RISC-V 等指令集,便是在這個層次。程序員使用指令集中的指令編寫的程序,由低一層微程序解釋。
操作系統機器層是從操作系統基本功能來看的,操作系統需要負責管理計算機中的軟硬件資源,如內存、設備、文件等,它是軟硬件的交互界面。常用的操作系統有 Windows、Linux、Unix 等。這個層次使用的語言是機器語言,即 0、1 組成的二進制代碼,能夠由計算機直接識別和執行。
匯編語言機器層顧名思義是匯編語言所在的位置,匯編語言與處理器有關,相同類型的處理器使用的匯編語言集是一致的。匯編語言需要被匯編語言程序變換為等效的二進制代碼目標程序。由于計算機中的資源被操作系統所管理,因此匯編語言需要在操作系統的控制下進行。
到了高級語言機器層,便是我們使用的 C、C++ 等編程語言,高級語言是與人類思維相接近的語言。
?
一個功能使用硬件來實現還是使用軟件來實現?
硬件實現:速度快、成本高;靈活性差、占用內存少。
軟件實現:速度低、復制費用低;靈活性好、占用內存多。
虛擬化技術是將原本 硬件實現的功能,使用軟件來實現,它們在性能、價格、實現的難易程度是不同的。一個功能既可以使用硬件實現,也可以使用軟件實現,也可以兩者結合實現,可能要根據各種人力成本、研發難度、研發周期等考慮。
?
我們應該在很多書籍、文章中,了解到虛擬機跟 Docker 的比較,了解到 Docker 的優點,通過 Docker 打包鏡像后可以隨時在別的地方運行而不需要擔心機器的兼容問題。但是 Docker 的虛擬化并不能讓 Linux 跑 Windows 容器,也不能讓 Windows 跑 Linux 容器,更不可能讓 x86 機器跑 arm 指令集的二進制程序。但是 VMware 可以在 Windows 運行 Linux 、Mac 的鏡像,但 WMWare 也不能由 MIPS 指令構建的 Linux 系統。
Docker 和 VMware 都可以實現不同程度的虛擬化,但也不是隨心所欲的,它們虛擬化的程度相差很大,因為它們是在不同層次進行虛擬化的。
[Info] 提示
許多虛擬化軟件不單單是在一個層面上,可能具有多種層次的虛擬化能力。
在指令集級別虛擬化中,從指令系統上看,就是要在一種機器上實現另一種機器的指令系統。例如,QEMU 可以實現在 X64 機器上模擬 ARM32/64、龍芯、MIPS 等處理器。
虛擬化程度在于使用硬件實現與軟件實現的比例,硬件部分比例越多一般來說性能就會越強,軟件部分比例越多靈活性會更強,但是性能會下降,不同層次的實現也會影響性能、兼容性等。隨著現在計算機性能越來越猛,很大程度上產生了性能過剩;加之硬件研發的難度越來越高,越來越難突破,非硬件程度的虛擬化將會越來越廣泛。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/123757.html
摘要:我們現在來看二分搜索算法的兩種變形插值搜索和指數搜索。插值搜索是對二分搜索算法的改進,插值搜索可以基于搜索的值選擇到達不同的位置。 預警 在本篇文章中,將為各位老鐵介紹不同的搜索算法以及它們的復雜度。因為力求通俗易懂,所以篇幅可能較長,大伙可以先Mark下來,每天抽時間看一點理解一點。本文配套的Github Repo,歡迎各位老鐵star,會一直更新的。 開篇 和排序類似,搜索或者叫做...
摘要:在上運行使用系統要求開啟虛擬化的硬件支持可以通過命令來檢查或者更高版本至少內存安裝最新點擊下載安裝下載的文件安裝完成后,啟動使用鏡像加速地址使用自帶的使用的系統要求運行或者以上版本支持硬件虛擬化技術并且已啟用虛擬化安裝點擊下載運行在上運行使 在Mac上運行Docker 使用Docker for Mac 系統要求 開啟虛擬化的硬件支持,可以通過命令來檢查:sysctl kern.hv_...
摘要:虛擬化就是表示計算機資源的一種抽象方式,它是一系列虛擬技術的集合,如硬件虛擬化技術,處理器虛擬化技術,指令虛擬化技術,軟件虛擬化技術等。對于計算機領域,虛擬化技術主要分為兩類,一類是硬件虛擬化,一類是軟件虛擬化,容器技術屬于軟件虛擬化。 容器技術并不是什么新概念,只不過最近幾年隨著云計算的火熱,變得被大家所熟知。最早于1979年誕生的chroot技術,容器技術又稱為容器虛擬化。 虛擬化...
摘要:虛擬化就是表示計算機資源的一種抽象方式,它是一系列虛擬技術的集合,如硬件虛擬化技術,處理器虛擬化技術,指令虛擬化技術,軟件虛擬化技術等。對于計算機領域,虛擬化技術主要分為兩類,一類是硬件虛擬化,一類是軟件虛擬化,容器技術屬于軟件虛擬化。 容器技術并不是什么新概念,只不過最近幾年隨著云計算的火熱,變得被大家所熟知。最早于1979年誕生的chroot技術,容器技術又稱為容器虛擬化。 虛擬化...
摘要:分別進行配置和測試。也就是說對于開發和部署來說,使用可以更快速的交付和部署應用環境。更便捷的應用更新管理。使用鏡像創建并啟動一個容器。執行用戶指定的應用程序。執行完畢后,容器被終止。 Docker是為應用的開發和部署提供的一站式容器解決方案,它能幫助開發者高效快速的構建應用,實現Build,Ship and Run Any App, Anywhere,從而達到一次構建,到處運行的目的。...
閱讀 3215·2021-11-24 09:39
閱讀 2944·2021-11-23 09:51
閱讀 900·2021-11-18 10:07
閱讀 3550·2021-10-11 10:57
閱讀 2757·2021-10-08 10:04
閱讀 3010·2021-09-26 10:11
閱讀 1056·2021-09-23 11:21
閱讀 2798·2019-08-29 17:28