因?yàn)檎腥瞬豁樌脑?,開始在公司內(nèi)做容器及K8S開發(fā)的系統(tǒng)性培訓(xùn),從容器基礎(chǔ)開始也是對自己知識結(jié)構(gòu)的總結(jié),有興趣加入我們的小伙伴,請私信或留言,坐標(biāo)重慶。
鏡像部分
概念
- bootfs
- rootfs
- layer
- union file system
bootfs(boot file system)
主要包含bootloader和kernel, bootloader主要是引導(dǎo)加載kernel, Linux剛啟動時會加載bootfs文件系統(tǒng),在Docker鏡像的最底層是bootfs。這一層與我們典型的Linux/Unix系統(tǒng)是一樣的,包含boot加載器和內(nèi)核。當(dāng)boot加載完成之后整個內(nèi)核就都在內(nèi)存中了,此時內(nèi)存的使用權(quán)已由bootfs轉(zhuǎn)交給內(nèi)核,此時系統(tǒng)也會卸載bootfs。
rootfs
rootfs 是掛載在容器根目錄上、用來為容器進(jìn)程提供隔離后執(zhí)行環(huán)境的文件系統(tǒng),這個文件系統(tǒng)是一個操作系統(tǒng)的完整文件系統(tǒng)。需要明確的是,rootfs 只是一個操作系統(tǒng)所包含的文件、配置和目錄,并不包括操作系統(tǒng)內(nèi)核。在 Linux 操作系統(tǒng)中,這兩部分是分開存放的,操作系統(tǒng)只有在開機(jī)啟動時才會加載指定版本的內(nèi)核鏡像。
長這樣。
$ ls /
bin dev etc home lib lib64 mnt opt proc root run sbin sys tmp usr var
容器的本質(zhì)
- 啟用 Linux Namespace 配置;
- 設(shè)置指定的 Cgroups 參數(shù);
- 切換進(jìn)程的根目錄(優(yōu)先使用 pivot_root 系統(tǒng)調(diào)用, 如果系統(tǒng)不支持,使用Change Root)。
思考?:rootfs 可以看做一個最基礎(chǔ)的操作系統(tǒng)。此時如果要運(yùn)行java程序,就需要在這個基礎(chǔ)的操作系統(tǒng)里安裝jre。rootfs 就被污染了,成為了jre 特定的基礎(chǔ)操作系統(tǒng),如果另一個人需要運(yùn)行python 程序怎么辦?重新制作rootfs?
Layer
如果修改都基于一個基礎(chǔ)的 rootfs,而將變更做成增量,所有人都只需要維護(hù)相對于 base rootfs 修改的增量內(nèi)容,而不是每次修改都制造一個“fork”。
docker 的創(chuàng)新在于用戶制作鏡像的每一步操作,都會生成一個層,也就是一個增量。

我們可以通過 docker image inspect 來查看鏡像的層
root@ubuntudev ~# docker image inspect golang:1.16
...
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:688e187d6c79c46e8261890f0010fd5d178b8faa178959b0b46b2635aa1eeff3",
"sha256:00bcea93703b384ab61d2344d6e721c75b0e47198b7912136a86759d8d885711",
"sha256:ccb9b68523fdb47816f2a15d7590d06ff3d897dfdb3e0733e9c06a2bb79ebfc7",
"sha256:685934357c8993799eda4a6d71c2bb2d2c54b1138d6e037f675eeeeffc719f2d",
"sha256:9d52e952d0a781ee401640f2a7a9155f313c927ba5b3880959e055619a3391a9",
"sha256:762eb5b089c5c496c946d1ffb5d8088a4b3b4648635fd46e8e4c82ee36c33687",
"sha256:c92e53084342a99bee2b3d5a410f5f6d4df192eff4a8381c5c558cb0f150646d"
]
},
...
每一層的變更,都存放在/var/lib/docker/overlay2/<sha256>
層的可讀寫性

容器(container)的定義和鏡像(image)幾乎一模一樣,也是一堆層的統(tǒng)一視角,唯一區(qū)別在于容器的最上面那一層是可讀可寫的。
思考:bin etc 這些操作系統(tǒng)目錄被拉平到根目錄下,如何還能正常工作?
Union File System
就是用來解決這樣一個問題。
UnionFS (聯(lián)合文件系統(tǒng)) 是一種分層、輕量級并且高性能的文件系統(tǒng),它支持對文件系統(tǒng)的修改作為一’ 次提交來一層層的疊加,同時可以將不同月錄掛載到同一個虛擬文件系統(tǒng)下(unite several directories into a single virtual filesystem)。Union 文件系統(tǒng)是Docker鏡像的基礎(chǔ)。鏡像可以通過分層來進(jìn)行繼承,基于基礎(chǔ)鏡像(沒有父鏡像),可以制作各種具體的應(yīng)用鏡像。
特性:一次同時加載多個文件系統(tǒng),但從外面看起來,只能看到一個文件系統(tǒng),聯(lián)合加載會把各層文件系統(tǒng)疊加起來,這樣最終的文件系統(tǒng)會包含所有底層的文件和目錄
感受一下
cd /tmp
mkdir a b c
echo "aaa" > a/a.txt
echo "bbb" > b/b.txt
mount -v -t aufs -o br=/tmp/a:/tmp/b none /tmp/c
ls /tmp/c
解釋下mount命令各參數(shù)含義:
- -t aufs 指定文件系統(tǒng)類型為aufs
- -o 后面是掛載選項,指定我們要掛載哪些目錄
- none 說明我們掛載的不是設(shè)備文件,因?yàn)檫@里我們是直接掛載目錄的
AUFS的檢測級別可以通過udba指定
udba有三種級別:none、reval、inotify,對性能的影響依次增加,當(dāng)然安全性也有所增強(qiáng)。
None: 這種檢測是最快的,但可能導(dǎo)致錯誤的數(shù)據(jù),例如在原始目錄修改文件,在aufs中讀取,不完全保證正確
reval:aufs會訪問重新原始目錄,如果文件有更新,在會反映在aufs中
Notify: 會在所有原始目錄中的所有目錄上注冊notify事件,這會嚴(yán)重的影響性能,不建議使用。
mount -v -t aufs -o br=/tmp/a:/tmp/b -o udba=none none /tmp/c
設(shè)置讀寫
mount -v -t aufs -o br=/tmp/a=rw:/tmp/b=ro -o udba=none none /tmp/c