1. 程式人生 > 實用技巧 >lxcfs 是什麼? 怎樣通過 lxcfs 在容器內顯示容器的 CPU、記憶體狀態

lxcfs 是什麼? 怎樣通過 lxcfs 在容器內顯示容器的 CPU、記憶體狀態

說明

容器中的top/free/df等命令,展示的狀態資訊是從/proc目錄中的相關檔案裡讀取出來的:

/proc/cpuinfo
/proc/diskstats
/proc/meminfo
/proc/stat
/proc/swaps
/proc/uptime

LXCFS,FUSE filesystem for LXC是一個常駐服務,它啟動以後會在指定目錄中自行維護與上面列出的/proc目錄中的檔案同名的檔案,容器從lxcfs維護的/proc檔案中讀取資料時,得到的是容器的狀態資料,而不是整個宿主機的狀態。

安裝

yum安裝

wget https://copr-be.cloud.fedoraproject.org/results/ganto/lxd/epel-7-x86_64/00486278-lxcfs/lxcfs-2.0.5-3.el7.centos.x86_64.rpm
yum install lxcfs
-2.0.5-3.el7.centos.x86_64.rpm

編譯安裝

也可以自己編譯,需要提前安裝fuse-devel:

yum install -y fuse-devel

下載程式碼編譯,bootstrap.sh執行結束後,會在生成configure等檔案,編譯安裝方法在INSTALL檔案中:

git clone https://github.com/lxc/lxcfs.git
cd lxcfs
git checkout lxcfs-3.0.3

./bootstrap.sh
./configure --prefix=/
make
make install

如果要除錯,可以設定為DEBUG模式:

CFLAGS="-O0 -DDEBUG"  ./configure --prefix=/data/lxcfs/lxcfs_install/

可以用下面的方法啟動:

/etc/init.d/lxcfs start

但是/etc/init.d/lxcfs這個啟動指令碼比較古老,在CentOS7上執行可能會遇到下面的問題:

/etc/init.d/lxcfs: line 20: /lib/lsb/init-functions: No such file or directory
/etc/init.d/lxcfs: line 29: init_is_upstart: command not found

與其修改這個啟動指令碼,不足自己寫一個systemd檔案,lxcfs命令用法很簡單,只有三個引數:

$ lxcfs -h
Usage:

lxcfs [-f|-d] [-p pidfile] mountpoint
  -f running foreground by default; -d enable debug output
  Default pidfile is /run/lxcfs.pid
lxcfs -h

lxcfs.service可以簡單寫成這樣:

cat > /usr/lib/systemd/system/lxcfs.service <<EOF
[Unit]
Description=lxcfs

[Service]
ExecStart=/usr/bin/lxcfs -f /var/lib/lxcfs
Restart=on-failure
#ExecReload=/bin/kill -s SIGHUP $MAINPID

[Install]
WantedBy=multi-user.target
EOF

啟動:

systemctl daemon-reload
systemctl start lxcfs

使用

用前面的systemctl命令啟動,或者在宿主機上直接執行lxcfs:

lxcfs /var/lib/lxcfs 

檢視容器記憶體狀態

啟動一個容器,用lxcfs維護的/proc檔案替換容器中的/proc檔案,容器記憶體設定為256M:

docker run -it -m 256m \
      -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \
      -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \
      -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \
      -v /var/lib/lxcfs/proc/stat:/proc/stat:rw \
      -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \
      -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \
      ubuntu:latest /bin/bash

在容器內看到記憶體大小是256M:

# free -h
              total        used        free      shared  buff/cache   available
Mem:           256M        1.2M        254M        6.1M        312K        254M
Swap:          256M          0B        256M

注意:如果是alpine映象看到還是宿主機上的記憶體狀態,alpine中的free命令,似乎是通過其它渠道獲得記憶體狀態的。

檢視容器CPU狀態

容器的CPU設定有兩種方式,一個是--cpus 2,限定容器最多隻能使用兩個邏輯CPU,另一個是--cpuset-cpus "0,1",限定容器 可以使用的宿主機CPU。

top命令顯示的是容器可以使用的宿主機cpu,如果使用--cpus 2,看到的cpu個數是宿主機上的cpu個數。使用--cpuset-cpus "0,1"的時候,在容器看到cpu個數是--cpuset指定的cpu的個數。

訂正:這個問題已經解決,見Lxcfs根據cpu-share、cpu-quota等cgroup資訊生成容器內的/proc檔案(下)

docker run -it --rm -m 256m  --cpus 2 --cpuset-cpus "0,1" \
      -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \
      -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \
      -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \
      -v /var/lib/lxcfs/proc/stat:/proc/stat:rw \
      -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \
      -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \
      ubuntu:latest /bin/sh

這時候在容器內看到的CPU個數是2個:

top - 07:30:32 up 0 min,  0 users,  load average: 0.03, 0.09, 0.13
Tasks:   2 total,   1 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu0  :  0.6 us,  0.6 sy,  0.0 ni, 98.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  :  0.6 us,  0.0 sy,  0.0 ni, 99.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

指定容器只能在指定的CPU上執行應當是利大於弊,就是在建立容器的時候需要額外做點工作,合理分配cpuset。

根據cpu-share和cpu-quota顯示cpu資訊的問題在Does lxcfs have plans to support cpu-shares and cpu-quota?中有討論。aither64修改lxcfs的實現,實現了按照cpu的配額計算應該展現的cpu的數量:

Yes, I have itimplemented, but I haven’t gotten around to cleaning it up and making a PR yet. It works with CPU quotas set e.g. usinglxc.cgroup.cpu.cfs_{quota,period}_us, CPU shares didn’t make sense to me.

lxc/lxcfs的master分支已經合入了aither64的修改,stable-3.0和stable-2.0分支沒有合入:Merge pull request #260 from aither64/cpu-views。lxcfs的實現分析見:修改lxcfs,根據cpu-share和cpu-quota生成容器的cpu狀態檔案(一):lxcfs的實現學習(原始碼分析)

注意:在容器中用uptime看到的系統執行時間是容器的執行時間,但是後面的load還是宿主機的load。

注意:在容器內看到的CPU的使用率依然是宿主機上的CPU的使用率! 這個功能似乎有點雞肋。

在kubernetes中使用lxcfs

在kubernetes中使用lxcfs需要解決兩個問題:

第一個問題是每個node上都要啟動lxcfs,這個簡單,部署一個daemonset就可以了。

第二個問題是將lxcfs維護的/proc檔案掛載到每個容器中,阿里雲用Initializers實現的做法,值得借鑑:Kubernetes之路 2 - 利用LXCFS提升容器資源可見性

開啟initializers功能

initializers的工作過程見Kubernetes initializer功能的使用方法:在Pod落地前修改Pod

在Kubernetes 1.13中initializers還是一個alpha特性,需要在Kube-apiserver中新增引數開啟。

這裡使用的是kubernetes 1.12,設定方法是一樣的:

--enable-admission-plugins="Initializers,NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"
--runtime-config=admissionregistration.k8s.io/v1alpha1

--enable-admission-plugins--admission-control互斥,如果同時設定,kube-apiserver啟動報錯:

error: [admission-control and enable-admission-plugins/disable-admission-plugins flags are mutually exclusive, 
enable-admission-plugins plugin "--runtime-config=admissionregistration.k8s.io/v1alpha1" is unknown]

initializer controller的實現

github有一個例子:lxcfs-initializer

延伸內容

修改lxcfs,支援根據cpu-share和cpu-quota顯示容器的cpu狀態

參考

  1. Kubernetes之路 2 - 利用LXCFS提升容器資源可見性
  2. FUSE filesystem for LXC
  3. Kubernetes Initializers
  4. Kubernetes initializer功能的使用方法:在Pod落地前修改Pod
  5. lxcfs-initializer
  6. 修改lxcfs,根據cpu-share和cpu-quota生成容器的cpu狀態檔案(一):lxcfs的實現學習(原始碼分析)

轉載:https://www.lijiaocn.com/%E6%8A%80%E5%B7%A7/2019/01/09/kubernetes-lxcfs-docker-container.html