docker系列1—docker隔離和限制技術
- 本篇文章主要回答了以下幾個問題
- Docker和行程的關系是什么
- Docker如何在各容器共享內核的情況下,擁有他自己的PID空間以及如何實作資源隔離
docker 與行程
- docker使用起來給人的感覺是像虛擬機,但是docker和虛擬機是有本質的區別的
- 虛擬機在運行一個虛擬機作業系統的時候,宿主機作業系統之上,在一個分配好的完整磁盤空間,安裝、運行作業系統,(作業系統是一個軟體,這相當于又運行了一個作業系統軟體),這顯然是隔離的
- 而docker在啟動一個容器之后,那個容器(效果和虛擬機里面的一個系統相似)是作為一個作業系統的一個行程在宿主機中存在的,作為一個行程存在,也就意味著多個容器之間或者說,容器和其他行程之間都共享者作業系統的內核,換而言之,在docker啟動容器的代價是啟動行程的代價,對比虛擬機啟動一個虛擬機內的系統就要運行一套新的系統內核來說,開銷大幅度降低,當然,作為一個取代虛擬機的產品,虛擬機的資源隔離,比如檔案隔離,行程ID隔離,用戶名隔離這些東西要在容器作為一個行程運行的基礎上完成,本文將在之后分析實作資源隔離的兩個技術Namespace和Cgroups技術
- docker雖然消耗小,但是也有他的局限性,如下
- 既然是作為一個行程存在,那么也就意味著容器中的系統必須在和他相同內核或者兼容的內核的宿主機上運行,像Windows上的docker運行linux或者linux上的docker 運行windows都是不行的,那低內核版本的linux想要運行高內核版本的linux,也是不行的
NameServer
-
這個是Linux系統的技術,可以實作對各種資源的隔離,如PID Namespace,Mount Namespace(只讓被隔離的行程看到當前Namespace里的掛載點資訊),Network(只讓被隔離行程看到當前Namespace里的網路設備和配置)和User這種資源,這些NameServer,Linux系統通過提供了系統呼叫api來讓別人呼叫,docker是通過呼叫這些系統呼叫來實作各種資源的隔離的
-
下面拿PID Namespace來舉例子
-
容器作為一個行程存在,和宿主機的其他行程處于一個平等競爭的關系,所以他也有一個宿主機分配的PID,比如是1005,
-
docker run -it busybox /bin/sh,比如這一條命令,把容器運行起來之后,你進去容器查看行程的情況,你會發現有一個PID為1的行程和ps行程(ps -ef里的那個ps),而在宿主機里看,PID為1005,可以發現這個docker容器實作了和宿主機行程隔離開來的一個效果,這種效果是通過在被隔離應用的行程空間做了改動,讓這些行程只能看到被修改過之后的行程編號
-
int pid = clone(main_function, stack_size, SIGCHLD, NULL); -
上面的代碼塊是一個系統呼叫,呼叫后,系統會幫我們創建一個新的行程,并且回傳這個行程的PID
-
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL); -
多了那個CLONE_NEWPID,那這個行程由于是系統管的,那個行程能看到的東西也是系統管的,在這個行程里面運行的時候通過系統呼叫獲得的PID那就是修改后的,其他的Namespace也類似,通過這個例子我想說明的是,這些Namespace是通過Linux的機制去實作的,
-
CGroup
-
在默認的情況下,是不對行程進行資源限制的,行程所利用的計算資源會不斷的變化,那為了限制好計算資源,來達到類似虛擬機那樣的計算資源隔離的效果,CGroup被docker用于實作這個目標
-
首先,CGroup是一個系統呼叫,先來看看他的用法,他是通過Linux中的某個目錄里面檔案的變動去呼叫這個功能的
-
$ mount -t cgroup # 用于顯示各種資源,表示了對不同硬體資源的操控呼叫的目錄所在處 cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd) cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct) cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio) cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb) cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset) cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory) cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer) cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio) cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids) cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event) cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices) -
上面的代碼塊中,/sys/fs/cgroup/cpu,像這個就是呼叫cpu資源的入口,對于不同行程的CPU限制的呼叫,我們可以在這個目錄下創建一個子目錄,對應一個執行緒,如下
cd /sys/fs/cgroup/cpu mkdir test # 創建了檔案夾之后馬上進去看 cd test ll test drwxr-xr-x 2 root root 0 Sep 12 22:20 ./ dr-xr-xr-x 7 root root 0 Sep 12 22:20 ../ -rw-r--r-- 1 root root 0 Sep 12 22:20 cgroup.clone_children -rw-r--r-- 1 root root 0 Sep 12 22:20 cgroup.procs -r--r--r-- 1 root root 0 Sep 12 22:20 cpuacct.stat -rw-r--r-- 1 root root 0 Sep 12 22:20 cpuacct.usage -r--r--r-- 1 root root 0 Sep 12 22:20 cpuacct.usage_percpu -rw-r--r-- 1 root root 0 Sep 12 22:20 cpu.cfs_period_us -rw-r--r-- 1 root root 0 Sep 12 22:20 cpu.cfs_quota_us -rw-r--r-- 1 root root 0 Sep 12 22:20 cpu.shares -r--r--r-- 1 root root 0 Sep 12 22:20 cpu.stat -rw-r--r-- 1 root root 0 Sep 12 22:20 notify_on_release -rw-r--r-- 1 root root 0 Sep 12 22:20 tasks #可以發現系統自動幫我們創建好了這些東西,那么我們應該如何去使用呢對于cpu來說,有兩個比較關鍵的檔案,一個是cpu.cfs_quota_us,另外一個是cpu.cfs_period_us,這兩個一般搭配起來使用,表示的是每cpu.cfs_period_us的時間里,cpu只能占用cpu.cfs_quota_us的時間,讓這些配置生效還需要在tasks里面指定被限制的執行緒的PID,在這個cpu里面的子檔案夾或者遞回的子檔案夾只要創建了了一個檔案夾,這些檔案都是會在每一個檔案夾出現的,但是沒有在tasks里面指定任務的id的話就不會生效,那么大概可以猜想,docker生成一個容器,獲得他的pid之后,通過操作這些目錄,就可以輕松達到限制資源的目的
-
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/45832.html
標籤:其他
