docker 網絡之host模式底層實現

衆所周知,docker有4種網絡模式:橋接、host、容器、none,默認使用橋接。今天主要介紹一下host模式。

host模式,本質是容器與物理主機在網絡空間是同一個namesapce。docker在創建容器後會在默認路徑/var/run/docker/netns/ 生成一個文件,創建一個容器並且指定網絡是爲--net=host,具體如下可知:

我們通過上圖可知,藍色中實際爲文件inode id,三者是完全相同的。其中進程1的net namespace代表就是物理主機net namespace,由此可知容器和物理主機是處在相同net namespace中

我們都知道,在linux下面創建一個文件,都會對應一個inode節點,每個文件對應的inode都是不一樣的,那麼docker是通過什麼技術實現的呢是不同文件映射到同一個inode上呢?這裏先公佈答案:通過系統調用函數mount,具體流程圖:

  

具體代碼:docker/libnetwork/osl/namespace_linux.go

func reexecCreateNamespace() {
	if len(os.Args) < 2 {
		logrus.Fatal("no namespace path provided")
	}
	if err := mountNetworkNamespace("/proc/self/ns/net", os.Args[1]); err != nil {
		logrus.Fatal(err)
	}
}

func mountNetworkNamespace(basePath string, lnPath string) error {
	return syscall.Mount(basePath, lnPath, "bind", syscall.MS_BIND, "")
}

其中basePath爲當前進程下面ns/net,lnPath爲/var/run/docker/ns/default(這個default文件要先創建出來),然後在執行系統調用mount,進行bind操作。通過上面一系列操作可知,最終是通過mount操作,將default文件mount到ns/net所指向的inode節點,也就是說將容器net namespace指向物理主機net namespace(即在相同namespace)。

總結:從這部分邏輯可知,我們最後還是調用系統調用,那麼我們是不是也可以通過C語言方式實現這個功能呢?答案是肯定。

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