Categories
程式開發

《你好架構師之 壓榨硬件價值的利器容器(Docker)》


無論你選擇吃下紅藥丸還是藍藥丸,世界總是強者恆強。如騰訊、阿里這樣的互聯網帝國,總是生長在過剩的硬件資源之上。為了能夠將這些在如雙十一之外的日子裡閒置的資源加以利用,勤儉持家的工程師們提議將它們打包成產品銷售給大眾。那麼應該如何將硬件資源量化從而產生出最終售賣的產品呢。此刻應想起我們滴第一條架構廢物理論:

任何混亂複雜的架構,都可以通過增加中間層來簡化

而這個硬件與操作系統之間的層就是”虛擬化”。其技術特點就是通過增加虛擬化層,為運行在其上的操作系統,模擬出一整套完整的硬件體驗,而運行在虛擬環境中的應用程序對硬件資源的調度,都通過這個中間層傳導,並最終實現硬件資源的調度。

當然你也聽出了問題所在,這一過程是需要消耗額外的性能的。更直觀的感受是,通常所見的虛擬化環境的操作系統,如vmware的虛擬系統文件足有2~4G之巨。

《你好架構師之 壓榨硬件價值的利器容器(Docker)》 1

有浪費就有勤儉的手段,為了省去虛擬程序在應用程序與硬件資源之間的中間商賺差價,也為了更加有效的利用硬件資源的能力,就有瞭如今常見的“容器”技術。它也被稱之為“輕量級虛擬化技術”。

請記住: 一個個“輕量”虛擬化技術的產物:容器實例。在系統層面依然是一個的進程。這是容器與虛擬化的技術最大的區別。

換言之,容器技術其實就是對進程級別進行的資​​源限制、系統文件(視圖限制,如PID、掛載目錄…)限制這類技術的總稱。僅此而已。

如何驗證?

容器內,認為自己是1號進程

《你好架構師之 壓榨硬件價值的利器容器(Docker)》 2

而真實情況他的PID:8662進程,

《你好架構師之 壓榨硬件價值的利器容器(Docker)》 3

以上現像也就證實了容器不過是操作系統中的一個簡單進程。

如何實現對容器進程的視圖限制呢?

這種屏蔽真實進程號的技術,就是Linux的Namespace機制。該機制其實是Linux創建新進程時的一個可選參數。在Linux系統中創建線程的系統調用時clone()

int pid = clone(main_function, stack_size, SIGCHLD,NULL);

該函數在系統調用後將會為我們創建一個新的進程,並且返回它的進程號pid。調用時指定CLONE_NEWPID參數,新創建的這個進程就會看到一個全新的進程空間,它的PID是1。

int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);

而除了這裡的PID Namespace,Linux系統還提供了Mount、UTS、IPC、Network、User這些Namespace,用來對各種不同的進程上下文進行“障眼法”操作。

Mount Namespace,用於讓被隔離進程只看到當前Namespace裡的掛載點信息;Network Namespace,用於讓被隔離進程看到當前Namespace裡網絡設備和配置;

我以為我就是根目錄

《你好架構師之 壓榨硬件價值的利器容器(Docker)》 4

我以為我用是eth0

《你好架構師之 壓榨硬件價值的利器容器(Docker)》 5

以上的“障眼法”只能影響到應用進程如何看待整個計算機的“視圖”,但資源依然共享著整個計算機的資源。

那麼對進程的資源限制是如何實現的呢?

它就是Linux Control Group。它的主要作用,就是限制一個進程組能夠使用的資源上限,包括CPU、內存、磁盤、網絡帶寬等等。

此外Cgroups還能對進程進行優先級設置、審計,以及將進程掛起和恢復等操作。

mount -t cgroupmount -t cgroup 可以用於查詢系統中已經mount 的cgroup的文件系統,這裡的t表示type

《你好架構師之 壓榨硬件價值的利器容器(Docker)》 6

ls -l /sys/fs/cgroup

《你好架構師之 壓榨硬件價值的利器容器(Docker)》 7

我們來嘗試控製鏡像的資源吧?

1. 創建contianer目錄,自動添加一下內容

[email protected]:/sys/fs/cgroup/cpu$ mkdir [email protected]:/sys/fs/cgroup/cpu$ ls container/

輸出:cgroup.clone_children cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_releasecgroup.procs cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks

2.其中cpu.cfs_quota_us和cpu.cfs_period_us,表示container控制組裡的CPU quota沒有任何限制(即:-1),CPU period則是默認100ms(100000us)

–cpu-period(週期),–cpu-quota(配額)

例如: –cpu-period=1000000 –cpu-quota=500000 1秒週期內能使用0.5秒(50%的CPU使用權)

《你好架構師之 壓榨硬件價值的利器容器(Docker)》 8

建立測試腳本: 假設腳本PID為226

while : ; do : ; done &[1] 226

將cfs_quota修改為20ms(20000us):在每100ms時間裡,該控制組限制的進程只能使用20ms的CPU時間,也就是這個進程只能使用到20%的CPU帶寬

echo 20000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us

將task文件內容修改為腳本的PID: 之前修改的設置會對寫入task進程生效

echo 226 > /sys/fs/cgroup/cpu/container/tasks

可以查看到的現象: CPU的使用率立刻降到了20%

除了CPU子系統外,Cgroups的每一項子系統都擁有獨有的資源限制能力,例如:

blkio,為塊設備設定I/O限制,一般用於磁盤設備;cpuset,為進程分配單獨的CPU核和對應的內存節點;memory,為進程設定內存使用的限制;

好了到此先打住。

填充的架構板塊:

《你好架構師之 壓榨硬件價值的利器容器(Docker)》 9

架構黑話之一:任何混亂複雜的架構,都可以通過增加中間層來簡化