Docker原理,居然這麼簡單!

原創:小姐姐味道(微信公衆號ID:xjjdog),歡迎分享,轉載請保留出處。node

不少接觸Docker的同窗,都接觸過cgroup這個名詞。它是Linux上的一項古老的技術,用來實現資源限制,好比CPU、內存等。但有不少同窗反映,這項技術有點晦澀,不太好懂。程序員

這就是本篇文章存在的目的,會讓你以最簡單直觀的方式,瞭解cgroups究竟是個什麼東西。docker

接上上篇文章:《5分鐘快速瞭解Docker的底層原理 | namespace篇》shell

cgroups,是實現docker功能的重要底層設施。如上圖,使用cgroups,可以把操做系統的各項資源變成池子,而後經過配置獲取相應的資源。bash

那它是怎麼實現的呢?微信

要注意cgroups這個名詞,它有兩個特性。首先是c,就是Control的意思,是個動詞;第二部分,就是groups,證實它是個markdown

1. 動詞的目標

control,用來限制什麼呢?除了CPU、內存,還有啥?網絡

使用mount命令,查看當前系統支持的限制目標,它有個專用的名詞,叫作子系統架構

# mount | grep cgroup
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup 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/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
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/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/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
複製代碼

不一樣的系統版本,會有一些細微的區別,大致上,子系統的分類包含下面這些:併發

  • cpu,cpuacct cpu主要限制進程的 cpu 使用率,cpuacct能夠統計 cgroups 中的進程的 cpu 使用報告
  • cpuset 能夠爲 cgroups 中的進程分配單獨的 cpu 節點或者內存節點,就像Numa作的那些事情同樣
  • blkio 能夠限制進程的塊設備 io,好比物理設備(磁盤,固態硬盤,USB 等等)
  • devices 控制進程可以訪問某些設備
  • net_cls 標記 cgroups 中進程的網絡數據包,而後可使用 tc 模塊(traffic control)對數據包進行控制
  • net_prio — 這個子系統用來設計網絡流量的優先級
  • freezer 能夠掛起或者恢復 cgroups 中的進程。
  • ns 可使不一樣 cgroups 下面的進程使用不一樣的 namespace
  • hugetlb 主要針對於HugeTLB系統進行限制,這是一個大頁文件系統。

內容不少,但咱們日常關注的大多數就是內存和CPU,這些繁雜的細節,不影響咱們理解它的設計原則。

下面就以CPU爲例,來看一會兒系統的實際表現。

2. CPU使用限制的例子

首先,咱們進入cpu子系統目錄。

cd /sys/fs/cgroup/cpu
複製代碼

而後,建立一個組名爲xjjdog的cgroups,這個名字,就叫作控制組

mkdir xjjdog
複製代碼

這時候,神奇的事情發生了。咱們使用ll命令,查看xjjdog目錄中的內容,發現系統已經爲咱們默認生成了一堆文件。

# ll xjjdog/
total 0
-rw-r--r-- 1 root root 0 Jan 28 21:09 cgroup.clone_children
--w--w--w- 1 root root 0 Jan 28 21:09 cgroup.event_control
-rw-r--r-- 1 root root 0 Jan 28 21:09 cgroup.procs
-r--r--r-- 1 root root 0 Jan 28 21:09 cpuacct.stat
-rw-r--r-- 1 root root 0 Jan 28 21:09 cpuacct.usage
-r--r--r-- 1 root root 0 Jan 28 21:09 cpuacct.usage_percpu
-rw-r--r-- 1 root root 0 Jan 28 21:09 cpu.cfs_period_us
-rw-r--r-- 1 root root 0 Jan 28 21:09 cpu.cfs_quota_us
-rw-r--r-- 1 root root 0 Jan 28 21:09 cpu.rt_period_us
-rw-r--r-- 1 root root 0 Jan 28 21:09 cpu.rt_runtime_us
-rw-r--r-- 1 root root 0 Jan 28 21:09 cpu.shares
-r--r--r-- 1 root root 0 Jan 28 21:09 cpu.stat
-rw-r--r-- 1 root root 0 Jan 28 21:09 notify_on_release
-rw-r--r-- 1 root root 0 Jan 28 21:09 tasks
複製代碼

經過控制這些文件裏面的數值,就能夠對資源進行限制。好比cpu.cfs_quota_us文件,若是咱們往裏寫入100000(十萬),那麼就證實使用了xjjdog的cgroup,最多可以使用1核的CPU。寫入20000,證實最多使用使用1/5核的CPU。

這是由於,cpu.cfs_period_us這個配置文件,默認把1核cpu分紅了10萬份。

那咱們就寫入20000試一下。

sudo echo 20000 > xjjdog/cpu.cfs_quota_us
複製代碼

咱們把當前shell的pid,加入被受控進程列表。

echo $$ > xjjdog/tasks
複製代碼

執行完畢以後,再啓動一個死循環。

while true;do ;done;
複製代碼

從新打開一個shell,使用top觀察CPU的使用率。能夠發現,咱們的死循環,最多隻使用了20%的CPU。us保持在20%如下,且不間斷的在各個cpu之間切換。

依次試驗如下的命令,能夠發現CPU的使用,會逐步增長,大致上和咱們的限額是相等的。

sudo echo 40000 > xjjdog/cpu.cfs_quota_us
sudo echo 60000 > xjjdog/cpu.cfs_quota_us
sudo echo 100000 > xjjdog/cpu.cfs_quota_us
複製代碼

其餘的資源限制,都是相似的思路。那麼最重要的工做,就是須要知道cpu.cfs_quota_us這樣的字眼,表明的是什麼意思,這些對着手冊來看是很容易掌握的。好比quota是配額的意思,很明顯就是限制資源的使用。

如上圖,子系統能夠控制多個tasks,把它歸入到控制組以內。咱們上篇文章講到,能夠將bash進程,做爲docker系統的1號進程,那麼一樣的,這個1號進程的子進程,都會共享一樣的限額配置。

3. group的意思

淺顯的來說,group就是指的對各類資源進行分組。不一樣名字的資源,有不一樣的隔離配置。但它有更多的特性。

比較重要的,是它的層級關係(hierarchy)。這個也比較好理解,它主要是爲了簡化配置而存在的。

好比我上面的xjjdog目錄,對cpu的限制限制在0.5核。這時候,我想要有另一個應用,對cpu的使用限制在0.5核,同時限制內存1gb,那麼就能夠直接在xjjdog目錄下建立xjjdog0目錄,在xjjdog0目錄下只配置內存方面的就能夠了。

另外,若是你在外層的cpu限額限制了2core,而後在繼承的目錄裏限制了1/5核,那它就只能使用操做系統的2/5核。這也是繼承的一個特性。

End

cgroups是2006年誕生的,發起人是Google 的工程師( Rohit SethPaul Menage )。在 2008 年成功合入 Linux 2.6.24 版本中,能夠說這項技術是很古老的。cgroups目前已經成爲 systemd、Docker、Linux Containers(LXC) 等技術的基礎。

像Windows平臺的WSL,是沒有cgroups功能的,使用mount命令能夠驗證,這證實了它是不能把docker跑起來的,由於缺少基礎。不過,WSL2已經能夠了。

有些同窗對docker目前的發展示狀有些擔憂,但當你熟悉了這幾個常見的底層原理,讀完容器的標準以後,就會發現,上層的實現不管是換成docker也好,換成containerd也罷,都同樣!

做者簡介:小姐姐味道 (xjjdog),一個不容許程序員走彎路的公衆號。聚焦基礎架構和Linux。十年架構,日百億流量,與你探討高併發世界,給你不同的味道。個人我的微信xjjdog0,歡迎添加好友,​進一步交流。​

相關文章
相關標籤/搜索