使用 LXCFS 文件系统实现容器资源可见性
前言:
Linux 利用 Cgroup
实现了对容器资源的限制,但是当在容器内运行 top
命令时就会发现,它显示的信息是宿主机的 CPU 和 内存数据,而不是当前容器的数据。造成这个问题的原因,就是因为 /proc
文件系统并不了解 Cgroup
限制的存在。
社区中常见的做法是利用
lxcfs
文件系统来为容器提供资源可见性。
一、基本介绍
LXCFS 是一个开源的 Fuse(用户态文件系统),支持 LXC 容器,同时支持 Docker 容器。启动以后会在指定目录中维护 /proc
目录中的文件同名的文件,从而保证容器在读取数据时读取到 lxcfs
维护的 /proc
文件中的信息数据。
- LXCFS 通过用户态文件系统,在容器中提供下列
procfs
的文件。
/proc/cpuinfo
/proc/diskstats
/proc/meminfo
/proc/stat
/proc/swaps
/proc/uptime
LXCFS 的示意图如下:
- 比如,把宿主机的
/var/lib/lxcfs/proc/meminfo
文件挂载到容器的proc/meminfo
位置后; - 容器中进程读取相应文件内容时,
LXCFS
的Fuse
实现会从容器对应的Cgroup
中读取正确的内存限制。
二、LXCFS 安装与使用
1.安装 LXCFS 文件系统
[root@localhost ~]# wget http://copr-be.cloud.fedoraproject.org/results/ganto/lxc3/epel-7-x86_64/01041891-lxcfs/lxcfs-3.1.2-0.2.el7.x86_64.rpm
[root@localhost ~]# yum -y localinstall lxcfs-3.1.2-0.2.el7.x86_64.rpm
[root@localhost ~]# sed -i 's@ExecStart=.*@ExecStart=/usr/bin/lxcfs -o nonempty /var/lib/lxcfs/@g' /usr/lib/systemd/system/lxcfs.service
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl start lxcfs && systemctl enable lxcfs
如果 lxcfs
重启时出现如下报错,说明挂载的目录不是空目录,需要增加 -o nonempty
参数。
fuse: mountpoint is not empty
fuse: if you are sure this is safe, use the 'nonempty' mount option
2.基于 Docker 实现容器资源可见性
[root@localhost ~]# docker run -it -m 512Mb --cpus 2 \
-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 \
tomcat:8.5.87 /bin/bash
3.基于 Kubernetes 实现容器资源可见性
- 通过
https://github.com/denverdino/lxcfs-admission-webhook
的Admission Webhook
来给 Pod 注入LXCFS
设置。 - 需要检查 Kubernetes 的
api-versions
是否启动admissionregistration.k8s.io/v1beta1
(1.9.0+)
kubectl api-versions | grep 'admissionregistration.k8s.io/v1beta1'
1)安装 lxcfs
文件系统
[root@localhost ~]# git clone https://github.com/denverdino/lxcfs-admission-webhook.git
[root@localhost ~]# cd lxcfs-admission-webhook
[root@localhost lxcfs-admission-webhook]# sed -i '/^metadata/a\ namespace: kube-system' deployment/lxcfs-daemonset.yaml
[root@localhost lxcfs-admission-webhook]# kubectl apply -f deployment/lxcfs-daemonset.yaml
2)修改 Kube-APIServer 配置文件,开启服务插件
- 增加:
MutatingAdmissionWebhook,ValidatingAdmissionWebhook
[root@localhost ~]# vim /etc/systemd/system/kube-apiserver.service
--enable-admission-plugins=
3)重启 Kube-APIServer 服务
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl restart kube-apiserver
4)安装 lxcfs-admission-webhook
注射器服务
[root@localhost lxcfs-admission-webhook]# bash deployment/install.sh
creating certs in tmpdir /tmp/tmp.kK3cUmQvdG
Generating RSA private key, 2048 bit long modulus
............+++
...................+++
e is 65537 (0x10001)
certificatesigningrequest.certificates.k8s.io/lxcfs-admission-webhook-svc.default created
NAME AGE REQUESTOR CONDITION
lxcfs-admission-webhook-svc.default 1s admin Pending
certificatesigningrequest.certificates.k8s.io/lxcfs-admission-webhook-svc.default approved
secret/lxcfs-admission-webhook-certs created
NAME TYPE DATA AGE
lxcfs-admission-webhook-certs Opaque 2 0s
deployment.apps/lxcfs-admission-webhook-deployment created
service/lxcfs-admission-webhook-svc created
mutatingwebhookconfiguration.admissionregistration.k8s.io/mutating-lxcfs-admission-webhook-cfg created
查看
[root@localhost lxcfs-admission-webhook]# kubectl get secrets,pods,svc,mutatingwebhookconfigurations
6)验证
[root@localhost lxcfs-admission-webhook]# kubectl label namespace default lxcfs-admission-webhook=enabled
[root@localhost lxcfs-admission-webhook]# kubectl apply -f deployment/web.yaml
kubectl label namespace default lxcfs-admission-webhook=enabled
:将default
命名空间下所有的 Pod 都进行注册;- 这里我们需要注意,注册的命名空间要和
lxcfs
服务所在的命名空间区分开,否则lxcfs
被重启后会输出如下报错:
caused \\\"not a directory\\\"\"": unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type
[root@localhost lxcfs-admission-webhook]# kubectl exec -it web-7f4dfcc4f4-88rb7 -- /bin/bash
root@web-7f4dfcc4f4-88rb7:/usr/local/apache2# free -h
total used free shared buffers cached
Mem: 256M 6.2M 249M 0B 0B 300K
-/+ buffers/cache: 5.9M 250M
Swap: 0B 0B 0