日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Docker技術(shù)三大要點(diǎn):cgroup, namespace和unionFS的理解

 汪子熙 2019-04-05

www.的網(wǎng)頁(yè)有這樣一張有意思的動(dòng)畫:

從這張gif圖片,我們不難看出Docker網(wǎng)站想傳達(dá)這樣一條信息, 使用Docker加速了build,ship和run的過(guò)程。

Docker最早問(wèn)世是2013年,以一個(gè)開(kāi)源項(xiàng)目的方式被大家熟知。

Docker的奠基者是dotcloud,一家開(kāi)發(fā)PaaS平臺(tái)的技術(shù)公司。

不過(guò)可惜的是,這家公司把Docker開(kāi)源之后,于2016年倒閉了,因?yàn)槠渲鳂I(yè)務(wù)PaaS無(wú)法和微軟,亞馬遜等PaaS業(yè)界巨頭競(jìng)爭(zhēng),不禁讓人唏噓。

Docker其實(shí)是容器化技術(shù)的具體技術(shù)實(shí)現(xiàn)之一,采用go語(yǔ)言開(kāi)發(fā)。很多朋友剛接觸Docker時(shí),認(rèn)為它就是一種更輕量級(jí)的虛擬機(jī),這種認(rèn)識(shí)其實(shí)是錯(cuò)誤的,Docker和虛擬機(jī)有本質(zhì)的區(qū)別。容器本質(zhì)上講就是運(yùn)行在操作系統(tǒng)上的一個(gè)進(jìn)程,只不過(guò)加入了對(duì)資源的隔離和限制。而Docker是基于容器的這個(gè)設(shè)計(jì)思想,基于Linux Container技術(shù)實(shí)現(xiàn)的核心管理引擎。

為什么資源的隔離和限制在云時(shí)代更加重要?在默認(rèn)情況下,一個(gè)操作系統(tǒng)里所有運(yùn)行的進(jìn)程共享CPU和內(nèi)存資源,如果程序設(shè)計(jì)不當(dāng),最極端的情況,某進(jìn)程出現(xiàn)死循環(huán)可能會(huì)耗盡CPU資源,或者由于內(nèi)存泄漏消耗掉大部分系統(tǒng)資源,這在企業(yè)級(jí)產(chǎn)品場(chǎng)景下是不可接受的,所以進(jìn)程的資源隔離技術(shù)是非常必要的。

我當(dāng)初剛接觸Docker時(shí),以為這是一項(xiàng)新的技術(shù)發(fā)明,后來(lái)才知道,Linux操作系統(tǒng)本身從操作系統(tǒng)層面就支持虛擬化技術(shù),叫做Linux container,也就是大家到處能看到的LXC的全稱。

LXC的三大特色:cgroup,namespace和unionFS。

cgroup:

CGroups 全稱control group,用來(lái)限定一個(gè)進(jìn)程的資源使用,由Linux 內(nèi)核支持,可以限制和隔離Linux進(jìn)程組 (process groups) 所使用的物理資源 ,比如cpu,內(nèi)存,磁盤和網(wǎng)絡(luò)IO,是Linux container技術(shù)的物理基礎(chǔ)。

namespace:

另一個(gè)維度的資源隔離技術(shù),大家可以把這個(gè)概念和我們熟悉的C++和Java里的namespace相對(duì)照。

如果CGroup設(shè)計(jì)出來(lái)的目的是為了隔離上面描述的物理資源,那么namespace則用來(lái)隔離PID(進(jìn)程ID),IPC,Network等系統(tǒng)資源。

我們現(xiàn)在可以將它們分配給特定的Namespace,每個(gè)Namespace里面的資源對(duì)其他Namespace都是透明的。

不同container內(nèi)的進(jìn)程屬于不同的Namespace,彼此透明,互不干擾。

我們用一個(gè)例子來(lái)理解namespace的必要。

假設(shè)多個(gè)用戶購(gòu)買了一臺(tái)Linux服務(wù)器的Nginx服務(wù),每個(gè)用戶在該服務(wù)器上被分配了一個(gè)Linux系統(tǒng)的賬號(hào)。我們希望每個(gè)用戶只能訪問(wèn)分配給其的文件夾,這當(dāng)然可以通過(guò)Linux文件系統(tǒng)本身的權(quán)限控制來(lái)實(shí)現(xiàn),即一個(gè)用戶只能訪問(wèn)屬于他本身的那些文件夾。

但是有些操作仍然需要系統(tǒng)級(jí)別的權(quán)限,比如root,但我們肯定不可能給每個(gè)用戶都分配root權(quán)限。因此我們就可以使用namespace技術(shù):

我們能夠?yàn)閁ID = n的用戶,虛擬化一個(gè)namespace出來(lái),在這個(gè)namespace里面,該用戶具備root權(quán)限,但是在宿主機(jī)上,該UID =n的用戶還是一個(gè)普通用戶,也感知不到自己其實(shí)不是一個(gè)真的root用戶這件事。

同樣的方式可以通過(guò)namespace虛擬化進(jìn)程樹(shù)。

在每一個(gè)namespace內(nèi)部,每一個(gè)用戶都擁有一個(gè)屬于自己的init進(jìn)程,pid = 1,對(duì)于該用戶來(lái)說(shuō),仿佛他獨(dú)占一臺(tái)物理的Linux服務(wù)器。

對(duì)于每一個(gè)命名空間,從用戶看起來(lái),應(yīng)該像一臺(tái)單獨(dú)的Linux計(jì)算機(jī)一樣,有自己的init進(jìn)程(PID為1),其他進(jìn)程的PID依次遞增,A和B空間都有PID為1的init進(jìn)程,子容器的進(jìn)程映射到父容器的進(jìn)程上,父容器可以知道每一個(gè)子容器的運(yùn)行狀態(tài),而子容器與子容器之間是隔離的。從圖中我們可以看到,進(jìn)程3在父命名空間里面PID 為3,但是在子命名空間內(nèi),他就是1.也就是說(shuō)用戶從子命名空間 A 內(nèi)看進(jìn)程3就像 init 進(jìn)程一樣,以為這個(gè)進(jìn)程是自己的初始化進(jìn)程,但是從整個(gè) host 來(lái)看,他其實(shí)只是3號(hào)進(jìn)程虛擬化出來(lái)的一個(gè)空間而已。

看下面的圖加深理解。

父容器有兩個(gè)子容器,父容器的命名空間里有兩個(gè)進(jìn)程,id分別為3和4, 映射到兩個(gè)子命名空間后,分別成為其init進(jìn)程,這樣命名空間A和B的用戶都認(rèn)為自己獨(dú)占整臺(tái)服務(wù)器。

Linux操作系統(tǒng)到目前為止支持的六種namespace:

unionFS:

顧名思義,unionFS可以把文件系統(tǒng)上多個(gè)目錄(也叫分支)內(nèi)容聯(lián)合掛載到同一個(gè)目錄下,而目錄的物理位置是分開(kāi)的。

要理解unionFS,我們首先要認(rèn)識(shí)bootfs和rootfs。

1. boot file system (bootfs):包含操作系統(tǒng)boot loader 和 kernel。用戶不會(huì)修改這個(gè)文件系統(tǒng)。

一旦啟動(dòng)完成后,整個(gè)Linux內(nèi)核加載進(jìn)內(nèi)存,之后bootfs會(huì)被卸載掉,從而釋放出內(nèi)存。

同樣內(nèi)核版本的不同的 Linux 發(fā)行版,其bootfs都是一致的。

2. root file system (rootfs):包含典型的目錄結(jié)構(gòu),包括 /dev, /proc, /bin, /etc, /lib, /usr, and /tmp

就是我下面這張圖里的這些文件夾:

等再加上要運(yùn)行用戶應(yīng)用所需要的所有配置文件,二進(jìn)制文件和庫(kù)文件。這個(gè)文件系統(tǒng)在不同的Linux 發(fā)行版中是不同的。而且用戶可以對(duì)這個(gè)文件進(jìn)行修改。

Linux 系統(tǒng)在啟動(dòng)時(shí),roofs 首先會(huì)被掛載為只讀模式,然后在啟動(dòng)完成后被修改為讀寫模式,隨后它們就可以被修改了。

不同的Linux版本,實(shí)現(xiàn)unionFS的技術(shù)可能不一樣,使用命令docker info查看,比如我的機(jī)器上實(shí)現(xiàn)技術(shù)是overlay2:

看個(gè)實(shí)際的例子。

新建兩個(gè)文件夾abap和java,在里面用touch命名分別創(chuàng)建兩個(gè)空文件:

新建一個(gè)mnt文件夾,用mount命令把a(bǔ)bap和java文件夾merge到mnt文件夾下,-t執(zhí)行文件系統(tǒng)類型為aufs:

sudo mount -t aufs -o dirs=./abap:./java none ./mnt

mount完成后,到mnt文件夾下查看,發(fā)現(xiàn)了來(lái)自abap和java文件夾里總共4個(gè)文件:

現(xiàn)在我到j(luò)ava文件夾里修改spring,比如加上一行spring is awesome, 然后到mnt文件夾下查看,發(fā)現(xiàn)mnt下面的文件內(nèi)容也自動(dòng)被更新了。

那么反過(guò)來(lái)會(huì)如何呢?比如我修改mnt文件夾下的aop文件:

而java文件夾下的原始文件沒(méi)有受到影響:

實(shí)際上這就是Docker容器鏡像分層實(shí)現(xiàn)的技術(shù)基礎(chǔ)。如果我們?yōu)g覽Docker hub,能發(fā)現(xiàn)大多數(shù)鏡像都不是從頭開(kāi)始制作,而是從一些base鏡像基礎(chǔ)上創(chuàng)建,比如debian基礎(chǔ)鏡像。

而新鏡像就是從基礎(chǔ)鏡像上一層層疊加新的邏輯構(gòu)成的。這種分層設(shè)計(jì),一個(gè)優(yōu)點(diǎn)就是資源共享。

想象這樣一個(gè)場(chǎng)景,一臺(tái)宿主機(jī)上運(yùn)行了100個(gè)基于debian base鏡像的容器,難道每個(gè)容器里都有一份重復(fù)的debian拷貝呢?這顯然不合理;借助Linux的unionFS,宿主機(jī)只需要在磁盤上保存一份base鏡像,內(nèi)存中也只需要加載一份,就能被所有基于這個(gè)鏡像的容器共享。

當(dāng)某個(gè)容器修改了基礎(chǔ)鏡像的內(nèi)容,比如 /bin文件夾下的文件,這時(shí)其他容器的/bin文件夾是否會(huì)發(fā)生變化呢?

根據(jù)容器鏡像的寫時(shí)拷貝技術(shù),某個(gè)容器對(duì)基礎(chǔ)鏡像的修改會(huì)被限制在單個(gè)容器內(nèi)。

這就是我們接下來(lái)要學(xué)習(xí)的容器 Copy-on-Write 特性。

容器鏡像由多個(gè)鏡像層組成,所有鏡像層會(huì)聯(lián)合在一起組成一個(gè)統(tǒng)一的文件系統(tǒng)。如果不同層中有一個(gè)相同路徑的文件,比如 /text,上層的 /text 會(huì)覆蓋下層的 /text,也就是說(shuō)用戶只能訪問(wèn)到上層中的文件 /text。

假設(shè)我有如下這個(gè)dockerfile:

FROM debian

RUN apt-get install emacs

RUN apt-get install apache2

CMD ["/bin/bash"]

執(zhí)行docker build .看看發(fā)生了什么。

生成的容器鏡像如下:

當(dāng)用docker run啟動(dòng)這個(gè)容器時(shí),實(shí)際上在鏡像的頂部添加了一個(gè)新的可寫層。這個(gè)可寫層也叫容器層。

容器啟動(dòng)后,其內(nèi)的應(yīng)用所有對(duì)容器的改動(dòng),文件的增刪改操作都只會(huì)發(fā)生在容器層中,對(duì)容器層下面的所有只讀鏡像層沒(méi)有影響。

要獲取更多Jerry的原創(chuàng)文章,請(qǐng)關(guān)注公眾號(hào)"汪子熙

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多