<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本章內容將講解 Docker 虛擬化、虛擬化本質、namespace、cgroups。
本小節將介紹 Docker 虛擬化的一些特點。
Docker 是一個開放原始碼軟體專案,自動化進行應用程式容器化部署,藉此在Linux作業系統上,提供一個額外的軟體抽象層,以及作業系統層虛擬化的自動管理機制。 -From wiki
在接觸 Docker 的過程中,或多或少會了解到 Docker 的虛擬化,最常見的介紹方式是對比 Docker 和虛擬機器器之間的差別,筆者這裡也給出兩者的對比表格,以便後面詳細地展開來講。
虛擬機器器 | Docker 容器 | |
---|---|---|
隔離程度 | 硬體級程序隔離 | 作業系統級程序隔離 |
系統 | 每個虛擬機器器都有一個單獨的作業系統 | 每個容器可以共用作業系統(共用作業系統核心) |
啟動時間 | 需要幾分鐘 | 幾秒 |
體積大小 | 虛擬機器器映象GB級別 | 容器是輕量級的(KB/MB) |
啟動映象 | 虛擬機器器映象比較難找到 | 預建的 docker 容器很容易獲得 |
遷移 | 虛擬機器器可以輕鬆遷移到新主機 | 容器被銷燬並重新建立而不是移動 |
建立速度 | 建立 VM 需要相對較長的時間 | 可以在幾秒鐘內建立容器 |
資源使用 | GB級別 | MB級別 |
Docker 中的虛擬化是依賴於 Windows 和 Linux 核心的,在 Windows 上會要求開啟 Hyper-V,在 Linux 上需要依賴 namespace 和 cgroups 等,因此這裡就不過多介紹 Docker 了,後面主要介紹 Linux 上的虛擬化技術。
傳統虛擬化方式是在硬體抽象級別虛擬化,其特點是 虛擬化程度高。
傳統虛擬化方式的優點是:
傳統虛擬化部署方式的缺點:
本節簡單地講解 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 -lha init ├─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。
在 unshare
命令中,--pid
引數建立 隔離程序的名稱空間,此外,還可以隔離多種系統資源:
在前面我們使用了 unshare 建立名稱空間,在這裡我們可以嘗試使用 Go 呼叫 Linux 核心的 namespace,通過程式設計程式碼建立隔離的資源空間。
Go 程式碼範例如下:
package main import ( "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 的作用。
在這個程式碼中,我們啟動了 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 -a cpuset cpu cpuacct blkio memory devices freezer net_cls perf_event net_prio hugetlb pids rdma
[info] 提示
Ubuntu 可以使用
apt install cgroup-tools
安裝工具。
為了避免篇幅過大,讀者只需要知道 Docker 限制容器資源使用量、CPU 核數等操作,其原理是 Linux 核心中的 cgroups 即可,筆者這裡不再贅述。
本節內容將從底層角度,聊聊虛擬化。
從語言角度,一臺由軟硬體組成的通用計算機系統可以看作是按功能劃分的多層機器級組成的層次結構。
如果從語言角度來看,計算機系統的層次結構可用下圖所示。
我們平時使用的筆電、安卓手機、平板電腦、Linux 伺服器等,雖然不同機器的系統和部分硬體差異很大,但是其系統結構是一致的。從 CPU 中電晶體、暫存器 到 CPU 指令集,再到作業系統、組合,現在使用的通用計算機基本上這種結構。
下面講解一下不同層次的主要特點。
計算機的最底層是硬聯邏輯級,由閘電路,觸發器等邏輯電路組成,特徵是使用極小的元件構成,表示了計算機中的 0、1。
微程式是使用微指令編寫的,一個微程式即一個機器指令,一般直接由硬體執行,它可以表示一個最簡單的操作。例如一個加法指令,由多個邏輯元件構成一個加法器,其元件組成如下圖所示(圖中為一個 8 位全加器)。
傳統機器語言機器級是處理器的指令集所在,我們熟知的 X86、ARM、MIPS、RISC-V 等指令集,便是在這個層次。程式設計師使用指令集中的指令編寫的程式,由低一層微程式解釋。
作業系統機器層是從作業系統基本功能來看的,作業系統需要負責管理計算機中的軟硬體資源,如記憶體、裝置、檔案等,它是軟硬體的互動介面。常用的作業系統有 Windows、Linux、Unix 等。這個層次使用的語言是機器語言,即 0、1 組成的二進位制程式碼,能夠由計算機直接識別和執行。
組合語言機器層顧名思義是組合語言所在的位置,組合語言與處理器有關,相同型別的處理器使用的組合語言集是一致的。組合語言需要被組合語言程式變換為等效的二進位制程式碼目標程式。由於計算機中的資源被作業系統所管理,因此組合語言需要在作業系統的控制下進行。
到了高階語言機器層,便是我們使用的 C、C++ 等程式語言,高階語言是與人類思維相接近的語言。
計算機的某些功能即可以由硬體實現,也可以由軟體來實現。即軟體和硬體在功能意義上是等效的。
一個功能使用硬體來實現還是使用軟體來實現?
硬體實現:速度快、成本高;靈活性差、佔用記憶體少。
軟體實現:速度低、複製費用低;靈活性好、佔用記憶體多。
虛擬化技術是將原本 硬體實現的功能,使用軟體來實現,它們在效能、價格、實現的難易程度是不同的。一個功能既可以使用硬體實現,也可以使用軟體實現,也可以兩者結合實現,可能要根據各種人力成本、研發難度、研發週期等考慮。
虛擬化(技術)或虛擬技術是一種資源管理技術,將計算機的各種實體資源(CPU、記憶體、磁碟空間、網路介面卡等),予以抽象、轉換後呈現出來並可供分割、組合為一個或多個計算機設定環境。
我們應該在很多書籍、文章中,瞭解到虛擬機器器跟 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 等處理器。
虛擬化程度在於使用硬體實現與軟體實現的比例,硬體部分比例越多一般來說效能就會越強,軟體部分比例越多靈活性會更強,但是效能會下降,不同層次的實現也會影響效能、相容性等。隨著現在計算機效能越來越猛,很大程度上產生了效能過剩;加之硬體研發的難度越來越高,越來越難突破,非硬體程度的虛擬化將會越來越廣泛。
到此這篇關於Docker虛擬化的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45