「containers are only isolated groups of processes running on a single host, which fulfill a set of “common” features」
- 只能 single host?
- 跨 OS
- 跨處理器架構?
historical beginning
chroot:改變 process 的 root directory。
- 1979 釋出 UNIX Version 7 首次出現 chroot。
- 現今 Linux 系統呼叫 chroot()。
- 1991 亦稱為「jail」,因為用作 honeypot 來觀察駭客。
- 2000 早期才有「microservices」應用。
- 準備新的根目錄檔案架構 (複製執行檔、函式庫、設定檔等),然後 chroot。
- 只是改變 root path,仍然可以跳出。
- 現在 container runtimes 不再用 chroot,而改用 pivot_root(),好處是會把 old mounts 放到另外的目錄,後續可以卸載,讓檔案系統完全看不到而。
- 有用的適當根檔案系統 (rootfs) 包含所有執行檔、函式庫、和需要的檔案架構。peeling it from an already existing Open Container Initiative (OCI) container 可透過 skopeo and umoci 輕易達成,但還是可以看到其它 process,網路也不是獨立的。
Linux Namespaces
- 2002 Linux 2.4.19 開始出現的功能,wrap certain global system resources in an abstraction layer. 讓 namespace 內的 process 只看到自己那部份資源。
- 2013 Linux 3.8 出現 user namespace 才有完整支援 container,有幾個 distinct namespaces 實作:mnt、pid、net、ipc、uts、user、和 cgroup。
- 2016 九月提議 2 個額外 namespaces:time 和 syslog。(2019 三月尚未實作完成)
- Linux namespace API 包含 3 個主要系統呼叫:
- clone():子 process 繼承部份 execution context,如 memory space、file descriptors, 和 signal handlers。可 pass different namespace flags 給 clone() 建立 new namespaces。
- unshare():讓 process to disassociate parts of the execution context。
- setns():reassociates the calling thread with the provided namespace file descriptor. 結合現存的 namespace.
- /proc/$PID/ns 提供額外 namespace 資訊,可用來 a handle for performing operations (like setns(2)) to the referenced namespace. 讓 us for example to track in which namespaces certain processes reside. One handy tool related to namespaces within this package is lsns. It lists useful information about all currently accessible namespaces or about a single given one.
mnt:不共享掛載的檔案系統
uts (UNIX Time-sharing System):不共享 domainname 和 hostname
ipc:隔離 IPC 資源,也就是 System V IPC objects 和 POSIX message queues。
pid (Process ID):讓 process 在 host 有 PID 外,在 namespace 下有另一組 PID,且可以 nested。在 namespace 內,第 1 個 process 的 PID 是 1,和一般 init process 相同特殊對待,所有 namespace 內 processe 都 re-parented 於 namespace 的 PID 1,結束 PID 1 也結束 namespace 內所有 processe。
net (Network) namespace 用來 virtualize the network stack,每個 network namespace contains its own resource properties within /proc/net. 一開始,一個 network namespace 只有 loopback 界面。每個網路界面只會在一個 namespace 出現,可以移到不同 namespace。每個 namespace 有自己的 IP 位址、routing table、socket listing、connection tracking table、firewall、和其它網路相關資源。刪除 network namespace 會刪除 virtual 界面,physical 界面會回到原本的 network namespace。
user (User ID):讓 process 在 namespace 內有另一套 user ID 和 group ID。unprivileged user ID 的 process 在 namespace 內可以是 privileged。
cgroup (Control Group) 支援 resource limiting, prioritization, accounting and controlling。
Composing Namespaces
Demo Application
2008 發明 cgroup,出現 Linux Containers (LXC) 計畫結合 cgroup 和 namespace 提供執行應用程式的獨立環境。同時,2007 Google 開始稱為 Let Me Contain That For You (LMCTFY) 的 containerization project, 設法提供一個穩定 API 驅動的設定方式,不用了解 cgroup 和內部細節。2013 Docker 基於 LXC,包裝 container 成為 image 而可以在機器間轉移,首先讓 container 成為標準軟體單元。之後一起發展 libcontainer,採用 Go 原生方式 spawn and manage containers。2015,計畫類似 Kubernetes 到 v1.0,成立 CNCF 推行 container,成立 Open Container Initiative (OCI) 致力於建立 container 格式的標準 -- OCI Runtime Specification。libcontainer 捐給 OCI,也誕生 runc 工具直接和 libcontainer 互動、解釋 OCI Runtime Specification 並執行。runc 用在許多 container ecosystem,如 containerd (used by Docker), CRI-O and podman。也有其它計畫採用 OCI Runtime Specification,如 Kata Containers 可以建立和執行包含輕量虛擬機器的 secure containers,用硬體 virtualization 技術作為第二層 defense 提供更強大的 workload 隔離。
參考
- https://medium.com/@saschagrunert/demystifying-containers-part-i-kernel-space-2c53d6979504 或 https://github.com/saschagrunert/demystifying-containers