容器目錄掛載原理

前言

就我目前的對容器的瞭解, 使用namespace技術實現隔離, 使用cgroups技術實現資源限制. 但是具體是如何實現卻從未深究過.

閒來無事, 挑其中的Mount Namespace來康康, 容器是如何實現目錄隔離的.

目錄隔離

耗子叔的這篇文章中對此技術進行了介紹.

c函數庫中, 可通過如下方式實現目錄的隔離:

int container_main(void* arg)
{
 // 調用 mount 方法, 觸發目錄隔離機制. 將根目錄替換爲 /root/tmp
 mount("/root/tmp", "/", "tmpfs", 0, "");
 // dosomething
 return 1;
}

void main(){
  // 調用 clone 創建子進程
	// 傳遞 CLONE_NEWNS 標識, 標明需要創建目錄隔離
  clone(container_function, stack, CLONE_NEWNS | SIGCHLD , NULL)
}

如果想在命令行中測試目錄隔離, 也可以如此操作:


# 創建用於掛載的臨時目錄
mkdir -p mount/bin
mkdir -p mount/lib64
mkdir -p mount/lib
# 將執行文件放進去
cp /bin/ls  mount/bin
# 將依賴的鏈接庫放入 (依賴庫可通過命令 ldd /bin/ls 查看)
cp /lib/x86_64-linux-gnu/libselinux.so.1 mount/lib
cp /lib/x86_64-linux-gnu/libc.so.6 mount/lib/
cp /lib/x86_64-linux-gnu/libpcre.so.3 mount/lib/
cp /lib/x86_64-linux-gnu/libdl.so.2 mount/lib/
cp /lib64/ld-linux-x86-64.so.2 mount/lib64/
cp /lib/x86_64-linux-gnu/libpthread.so.0 mount/lib/
# 替換運行進程的根目錄
# 執行此命令時, chroot 命令會將 ls 命令的運行根目錄替換爲 ./mount 目錄
# 可以嘗試着執行 /bin/ls 命令查看
chroot ./mount /bin/ls

至此, 雖然舉的例子很簡單, 但依然足夠我們理解目錄隔離了. 容器啓動後, 會將整個進程的根目錄換掉, 甚至直接掛載整個操作系統的ISO. 這也就解釋了爲什麼容器只是一個運行在宿主機上的進程, 卻可以表現爲不同的操作系統.

docker中, 容器和鏡像的文件系統目錄, 保存在宿主機的/var/lib/docker/overlay2.

你可以通過命令docker inspect <container_id>來查看容器的層級關係.

至於docker是如何將鏡像的多層進行聚合, 最終展現給容器的, 簡單說是通過UnionFS 技術, 將多個目錄掛載到同一個目錄下, 且可以設置優先級. 因爲使用了union mount技術, 因此在overlay2中是看不到容器的完整文件系統的. 它實際上並沒有在磁盤上創建一個包含所有層文件的單一目錄。相反,當你查看容器的文件系統時,Docker 和 Linux 內核會動態地將所有層組合在一起,使它們看起來像一個單一的文件系統。因此,即使你可以在 /var/lib/docker/overlay2 下找到每個層的文件,你也不能直接在這裏找到一個包含容器完整文件系統的單一目錄.

雖然在overlay2目錄下沒有容器的完整文件系統, 但其實在宿主機的/proc/<pid>/root目錄中可以看到, 不過前面也說了, 完整的文件系統是動態組合的, 因此/proc/<pid>/root目錄也只是一個軟連接. 至於容器的pid, 可以通過命令docker inspect --format '{{ .State.Pid }}' <container_id>獲取.

exec

目錄隔離使得容器啓動後文件系統自成一派. 那麼執行exec命令進入容器時, 又是如何做到的呢?

那必然是系統已經支持的啦. 在/proc/<pid>/ns目錄下, 記錄了命令空間隔離的數據.

image-20230520175409411

其中的mnt記錄的就是目錄隔離. 可以使用命令行nsenter -t <pid> -m來進入到特定進程的目錄命名空間. (-m 表示要進入 mount namespace). 命令執行後, 再執行ls命令, 就會發現已經進入到容器的文件系統中了.

c的函數庫中, 則使用setns函數來實現此功能. 函數具體使用不做贅述.


至此, 容器是如何做到目錄隔離的, 有了一個大致模糊的印象. 收工.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章