2013年12月25日 星期三

docker 原理簡介

    Docker 官網上的簡介,寫了"Docker is an open-source project to easily create lightweight, portable, self-sufficient containers from any application."。不過 containers 是啥呢? 有點難解釋,基本上可以想像成一個 sandbox。不過 docker 還可以在上面跑完整的 linux distributions。

    先看看 Docker 怎麼實作的。他是建立在 lxc 和 aufs 的基礎上。那 lxc 是什麼呢? 官網上講"LXC is a userspace interface for the Linux kernel containment features."。官網上還有這一段話。

Features

Current LXC uses the following kernel features to contain processes:
  • Kernel namespaces (ipc, uts, mount, pid, network and user)
  • Apparmor and SELinux profiles
  • Seccomp policies
  • Chroots (using pivot_root)
  • Kernel capabilities
  • Control groups (cgroups)
    他用到 kernel 許多特性,不過和 container 有關的主要是 kernel namespace 和 control groups。不過能做到 container 主要是靠 kernel namespace。


    namespace 是什麼呢? 以 pid namespace 為例,在每個 namespace 裡,每個 pid 都是唯一的。而不同的 namespace 裡, pid 可以重複。因此在 A namespace 哩,會有一個自以為 pid = 1 的程序,在 B namespace 哩,也會有一個自以為 pid = 1 的程序。如果 A 和 B 繼承自最上層的 namespace (也就是 host 所在的 namespace,叫做 C namespace ),那麼從 C namespace 的觀點來看,前面那兩個自以為是 pid = 1 的程序,其實他的 pid 都不為 1 。這樣可以做到程序隔離的功能,也可以做到虛擬化。 lxc 用到的 namespace 就 ipc, uts, mount, pid, network and user。這篇文章有詳細說明 docker 用到的 namespace 作用。http://blog.dotcloud.com/under-the-hood-linux-kernels-on-dotcloud-part

    這樣要怎麼做到模擬作業系統呢? 一個 linux distributions 就是一個 linux kernel 加上很多其他程式。 namespace 沒辦法跑 kernel。不過那不重要,反正核心都差不多。剩下的程式,就可以把它丟進 namespace 跑,而那些程式在跑的時候,會以為整台電腦都是他的(因為被 namespace) 隔離了。所以他會建立 init(pid = 1) 程序,再做一些其他開機步驟。有 system call 就由 host 的 kernel 來處理。他活在虛擬的世界,還活得很開心。

虛線表示那兩個是同一個。箭頭表示程序間的父子關係。有箭頭的表示子程序。

                       
    如上圖所示, A namespace 的程序無法看到 root namespace 的程序。因此,我們可以在 A namespace 跑 centos 的開機程序,也可跑 ubuntu 的開機程序。在 A namespace 哩,無法察覺 root namespace 存在,他們會以為自己就是 root namespace。

    解決了程序的問題後,還有一個問題,檔案系統。基本上,用原本系統的檔案系統即可做到模擬作業系統,不過 docker 選擇使用 aufs,選用 aufs 還有個好處是可以做版本控制。

    Aufs,全名叫 advanced multi layered unification filesystem。恩,名字不太重要。基本上就分層。以下圖為例:

                                   


       上圖表示至少兩個檔案系統,你可以從 Delete file B 這個往下看,那你看到的檔案系統會是對 Base 加了C(B一加刪,最後看不到)。而從 Add file E 往下看,則看到的檔案系統是對 Base 加了 ADE 這三個檔案。每層只記錄和上一層的差異。要顯示完整的作業系統則把自己到 base 各層 union 起來。

       介紹完 lxc 和 aufs , 來看看 docker 如何整合。



    如上圖所示, docker 把客端作業系統安裝在 aufs 上,你可以 commit 你的修改,他會把你的修改當作一層新的 layer 蓋在上一層。當你要 run 客端作業系統時,他會在你要跑的 image 上面再蓋一層,叫做 container(image 是 read only)。之後 docker 會建立新的 namespace,把 namespace 的 root directory,然後執行 debian 的 init 程序(開機程序),這樣客端作業系統就成功執行了。


如果你想更了解 docker,強烈推薦閱讀  http://blog.dotcloud.com/category/under-the-hood
也可以參考我演講投影片:http://www.slideshare.net/ya790026/docker-33456641

參考資料:

4 則留言: