也許你會好奇,我們不是已經通過 linux namespace 給容器建立了乙個容器了嗎,為什麼還需要對容器做限制呢?
因為在 linux 程序中,容器程序並不是物理隔離的,在執行時是和宿主機上的其他程序共享同乙個 cpu 和記憶體,如果不加以限制,必定會造成資源競爭。
在容器中,第 1 號程序在「障眼法」的干擾下只能看到容器裡的情況,但是宿主機上,它作為第 100 號程序與其他所有程序之間依然是平等的競爭關係。這就意味著,雖然第 100 號程序表面上被隔離了起來,但是它所能夠使用到的資源(比如 cpu、記憶體),卻是可以隨時被宿主機上的其他程序(或者其他容器)占用的。當然,這個 100 號程序自己也可能把所有資源吃光。這些情況,顯然都不是乙個「沙盒」應該表現出來的合理行為。
而linux cgroups 就是 linux 核心中用來為程序設定資源限制的乙個重要功能。
linux cgroups 的全稱是 linux control group。它最主要的作用,就是限制乙個程序組能夠使用的資源上限,包括 cpu、記憶體、磁碟、網路頻寬等等。
在 linux 中,cgroups 給使用者暴露出來的操作介面是檔案系統,即它以檔案和目錄的方式組織在作業系統的 /sys/fs/cgroup 路徑下。在 centos 機器裡,我可以用 mount 指令把它們展示出來,這條命令是:
$ mount -t cgroupcgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_prio,net_cls)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
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)
如果沒有掛載則直接使用 yum install libcgroup 安裝 cgroups 模組
可以看到,在 /sys/fs/cgroup 下面有很多諸如 cpuset、cpu、 memory 這樣的子目錄,也叫子系統。這些都是我這台機器當前可以被 cgroups 進行限制的資源種類。而在子系統對應的資源種類下,你就可以看到該類資源具體可以被限制的方法。比如,對 cpu 子系統來說,我們就可以看到如下幾個配置檔案,這個指令是:
$ ls /sys/fs/cgroup/cpuaegis cgroup.clone_children cgroup.procs cpuacct.stat cpuacct.usage_percpu cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat notify_on_release system.slice user.slice
assist cgroup.event_control cgroup.sane_beh**ior cpuacct.usage cpu.cfs_period_us cpu.rt_period_us cpu.shares docker release_agent tasks
root@centos:/sys/fs/cgroup/cpu$ mkdir containerroot@centos/sys/fs/cgroup/cpu$ ls container/cgroup.clone_children cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release
cgroup.procs cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks
這個目錄就稱為乙個「控制組」。你會發現,作業系統會在你新建立的 container 目錄下,自動生成該子系統對應的資源限制檔案。現在,我們在後台執行這樣一條指令碼:
$ while : ; do : ; done &[1] 226
這樣,我們可以用 top 指令來確認一下 cpu 有沒有被打滿:
$ top%cpu0 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
在輸出裡可以看到,cpu 的使用率已經 100% 了(%cpu0 :100.0 us)。而此時,我們可以通過檢視 container 目錄下的檔案,看到 container 控制組裡的 cpu quota 還沒有任何限制(即:-1),cpu period 則是預設的 100 ms(100000 us):
$ cat /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us-1$ cat /sys/fs/cgroup/cpu/container/cpu.cfs_period_us
100000
接下來,我們可以通過修改這些檔案的內容來設定限制。比如,向 container 組裡的 cfs_quota 檔案寫入 20 ms(20000 us):
$ echo 20000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us
結合前面的介紹,你應該能明白這個操作的含義,它意味著在每 100 ms 的時間裡,被該控制組限制的程序只能使用 20 ms 的 cpu 時間,也就是說這個程序只能使用到 20% 的 cpu 頻寬。接下來,我們把被限制的程序的 pid 寫入 container 組裡的 tasks 檔案,上面的設定就會對該程序生效了:
$ echo 226 > /sys/fs/cgroup/cpu/container/tasks
我們可以用 top 指令檢視一下:
$ top%cpu0 : 20.3 us, 0.0 sy, 0.0 ni, 79.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
可以看到,計算機的 cpu 使用率立刻降到了 20%(%cpu0 : 20.3 us)。
除 cpu 子系統外,cgroups 的每乙個子系統都有其獨有的資源限制能力,比如:
linux cgroups 的設計還是比較易用的,簡單粗暴地理解呢,它就是乙個子系統目錄加上一組資源限制檔案的組合。而對於 docker 等 linux 容器專案來說,它們只需要在每個子系統下面,為每個容器建立乙個控制組(即建立乙個新目錄),然後在啟動容器程序之後,把這個程序的 pid 填寫到對應控制組的 tasks 檔案中就可以了。
而至於在這些控制組下面的資源檔案裡填上什麼值,就靠使用者執行 docker run 時的引數指定了,比如這樣一條命令:
$ docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash
在啟動這個容器後,我們可以通過檢視 cgroups 檔案系統下,cpu 子系統中,「docker」這個控制組裡的資源限制檔案的內容來確認:
$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_period_us100000
$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_quota_us
20000
所以你看,docker 容器時候的技術其實並沒有什麼特別大的創新,只是統一了linux相關功能,整合起來,形成容器技術。
docker容器入門
docker是乙個開源的應用容器引擎,可以將你的可執行檔案 配置檔案及一切其他你需要的檔案一併打包到這個容器中,並發布和應用到任意平台,其他使用者可以直接使。執行中的這個映象稱為容器,容器啟動是非常快速的。docker映象 images 軟體打包好的映象 放在docker倉庫中,可以理解為一堆靜態的...
Docker容器入門
docker 是乙個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到乙個可移植的容器中,然後發布到任何流行的 linux 機器上,也可以實現虛擬化。容器是完全使用沙箱機制,相互之間不會有任何介面。安裝好後開啟docker的設定 設定docker類似與中國映象的位址 大概這樣應該就完成了do...
Docker 入門之docker容器建立
使用docker容器的大多數人都是因為想要隔離不同執行環境的差異,使得自己的應用能更好的移植和部署。那麼我們來看看掌握docker需要掌握哪些方面。1,搭建docker環境 2,編譯映象並將其執行成容器 3,將自己的應用壓縮在多個容器中 4,在乙個集群上部署自己的應用 5,通過增加後台資料庫來儲存服...