PouchContainer 是 Alibaba 開源的一款容器運行時產品,當前最新版本是 0.3.0,代碼地址位於:github.com/alibaba/pou…。PouchContainer 從設計之初即支持 LXCFS,實現高可靠容器隔離。Linux 使用 cgroup 技術實現資源隔離,然而容器內仍然掛載宿主機的 /proc 文件系統,用戶在容器內讀取 /proc/meminfo 等文件時,獲取的是宿主機的信息。容器內缺乏的 /proc 視圖隔離
會帶來一系列的問題,進而拖慢或阻礙企業業務容器化。LXCFS (github.com/lxc/lxcfs) 是開源 FUSE 文件系統,用以解決 /proc 視圖隔離
問題,使容器在表現層上更像傳統的虛擬機。本文首先介紹 LXCFS 適用業務場景,而後剖析 LXCFS 的原理,最後簡要介紹 LXCFS 在 PouchContainer 內部集成的工做。git
在物理機和虛擬機時代,公司內部逐漸造成了本身的一套工具鏈,諸如編譯打包、應用部署、統一監控等,這些工具已經爲部署在物理機和虛擬機中的應用提供了穩定的服務。接下來將從監控、運維工具、應用部署等方面詳細闡述 LXCFS 在上述業務容器化過程當中發揮的做用。github
大部分的監控工具,依賴 /proc 文件系統獲取系統信息。以阿里巴巴爲例,阿里巴巴的部分基礎監控工具是經過 tsar(github.com/alibaba/tsa…) 收集信息。而 tsar 對內存、CPU 信息的收集,依賴 /proc 文件系統。咱們能夠下載 tsar 的源碼,查看 tsar 對 /proc 目錄下一些文件的使用:docker
$ git remote -v
origin https://github.com/alibaba/tsar.git (fetch)
origin https://github.com/alibaba/tsar.git (push)
$ grep -r cpuinfo .
./modules/mod_cpu.c: if ((ncpufp = fopen("/proc/cpuinfo", "r")) == NULL) {
:tsar letty$ grep -r meminfo .
./include/define.h:#define MEMINFO "/proc/meminfo"
./include/public.h:#define MEMINFO "/proc/meminfo"
./info.md:內存的計數器在/proc/meminfo,裏面有一些關鍵項
./modules/mod_proc.c: /* read total mem from /proc/meminfo */
./modules/mod_proc.c: fp = fopen("/proc/meminfo", "r");
./modules/mod_swap.c: * Read swapping statistics from /proc/vmstat & /proc/meminfo.
./modules/mod_swap.c: /* read /proc/meminfo */
$ grep -r diskstats .
./include/public.h:#define DISKSTATS "/proc/diskstats"
./info.md:IO的計數器文件是:/proc/diskstats,好比:
./modules/mod_io.c:#define IO_FILE "/proc/diskstats"
./modules/mod_io.c:FILE *iofp; /* /proc/diskstats*/
./modules/mod_io.c: handle_error("Can't open /proc/diskstats", !iofp);
複製代碼
能夠看到,tsar 對進程、IO、CPU 的監控都依賴 /proc 文件系統。bash
當容器內 /proc 文件系統提供的是宿主機資源信息時,這類監控不能監控容器內信息。爲了知足業務需求,須要適配容器監控,甚至須要單獨爲容器內監控開發另外一套監控工具。這種改變勢必會拖慢甚至阻礙企業現存業務容器化的步伐,容器技術要儘量兼容公司原有的工具鏈,兼顧工程師的使用習慣。app
PouchContainer 支持 LXCFS 能夠解決上述問題,依賴 /proc 文件系統的監控、運維工具,部署在容器內或宿主機上對工具是透明的,現存監控、運維工具無需適配或從新開發,便可平滑遷移到容器內,實現容器內的監控和運維。運維
接下來讓咱們從實例中直觀感覺一下,在一臺 Ubuntu 虛擬機中安裝 PouchContainer 0.3.0 :工具
# uname -a
Linux p4 4.13.0-36-generic #40~16.04.1-Ubuntu SMP Fri Feb 16 23:25:58 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
複製代碼
systemd 拉起 pouchd ,默認不開啓 LXCFS,此時建立的容器沒法使用 LXCFS 的功能,咱們看一下容器內相關 /proc 文件的內容:測試
# systemctl start pouch
# head -n 5 /proc/meminfo
MemTotal: 2039520 kB
MemFree: 203028 kB
MemAvailable: 777268 kB
Buffers: 239960 kB
Cached: 430972 kB
root@p4:~# cat /proc/uptime
2594341.81 2208722.33
# pouch run -m 50m -it registry.hub.docker.com/library/busybox:1.28
/ # head -n 5 /proc/meminfo
MemTotal: 2039520 kB
MemFree: 189096 kB
MemAvailable: 764116 kB
Buffers: 240240 kB
Cached: 433928 kB
/ # cat /proc/uptime
2594376.56 2208749.32
複製代碼
能夠看到,在容器內看到的 /proc/meminfo、uptime 文件的輸出與宿主機一致,雖然啓動容器的時候指定了內存爲 50M,/proc/meminfo 文件並未體現出容器內的內存限制。fetch
在宿主機內啓動 LXCFS 服務,手動拉起 pouchd 進程,並指定相應的 LXCFS 相關參數:ui
# systemctl start lxcfs
# pouchd -D --enable-lxcfs --lxcfs /usr/bin/lxcfs >/tmp/1 2>&1 &
[1] 32707
# ps -ef |grep lxcfs
root 698 1 0 11:08 ? 00:00:00 /usr/bin/lxcfs /var/lib/lxcfs/
root 724 32144 0 11:08 pts/22 00:00:00 grep --color=auto lxcfs
root 32707 32144 0 11:05 pts/22 00:00:00 pouchd -D --enable-lxcfs --lxcfs /usr/bin/lxcfs
複製代碼
啓動容器,獲取相應的文件內容:
# pouch run --enableLxcfs -it -m 50m registry.hub.docker.com/library/busybox:1.28
/ # head -n 5 /proc/meminfo
MemTotal: 51200 kB
MemFree: 50804 kB
MemAvailable: 50804 kB
Buffers: 0 kB
Cached: 4 kB
/ # cat /proc/uptime
10.00 10.00
複製代碼
使用 LXCFS 啓動的容器,讀取容器內 /proc 文件,能夠獲得容器內的相關信息。
對於大部分對系統依賴較強的應用,應用的啓動程序須要獲取系統的內存、CPU 等相關信息,從而進行相應的配置。當容器內的 /proc 文件沒法準確反映容器內資源的狀況,會對上述應用形成不可忽視的影響。
例如對於一些 Java 應用,也存在啓動腳本中查看 /proc/meminfo 動態分配運行程序的堆棧大小,當容器內存限制小於宿主機內存時,會發生分配內存失敗引發的程序啓動失敗。對於 DPDK 相關應用,應用工具須要根據 /proc/cpuinfo 獲取 CPU 信息,獲得應用初始化 EAL 層所使用的 CPU 邏輯核。若是容器內沒法準確獲取上述信息,對於 DPDK 應用而言,則須要修改相應的工具。
PouchContainer 從 0.1.0 版開始即支持 LXCFS,具體實現能夠參見: github.com/alibaba/pou… .
簡而言之,容器啓動時,經過-v 將宿主機上 LXCFS 的掛載點 /var/lib/lxc/lxcfs/proc/ 掛載到容器內部的虛擬 /proc 文件系統目錄下。此時在容器內部 /proc 目錄下能夠看到,一些列proc文件,包括 meminfo, uptime, swaps, stat, diskstats, cpuinfo 等。具體使用參數以下:
-v /var/lib/lxc/:/var/lib/lxc/:shared
-v /var/lib/lxc/lxcfs/proc/uptime:/proc/uptime
-v /var/lib/lxc/lxcfs/proc/swaps:/proc/swaps
-v /var/lib/lxc/lxcfs/proc/stat:/proc/stat
-v /var/lib/lxc/lxcfs/proc/diskstats:/proc/diskstats
-v /var/lib/lxc/lxcfs/proc/meminfo:/proc/meminfo
-v /var/lib/lxc/lxcfs/proc/cpuinfo:/proc/cpuinfo
複製代碼
爲了簡化使用,pouch create 和 run 命令行提供參數 --enableLxcfs
, 建立容器時指定上述參數,便可省略複雜的 -v
參數。
通過一段時間的使用和測試,咱們發現因爲lxcfs重啓以後,會重建proc和cgroup,致使在容器裏訪問 /proc 出現 connect failed
錯誤。爲了加強 LXCFS 穩定性,在 PR:github.com/alibaba/pou… 中,refine LXCFS 的管理方式,改由 systemd 保障,具體實現方式爲在 lxcfs.service 加上 ExecStartPost 作 remount 操做,而且遍歷使用了 LXCFS 的容器,在容器內從新 mount。
PouchContainer 支持 LXCFS 實現容器內 /proc 文件系統的視圖隔離,將大大減小企業存量應用容器化的過程當中原有工具鏈和運維習慣的改變,加快容器化進度。有力支撐企業從傳統虛擬化到容器虛擬化的平穩轉型。