Linux利用CGroup实现了对容器资源的限制,但是在容器内部还是默认挂载宿主机 /proc 目录下的资源信息文件,如:meminfo,cpuinfo,stat,uptiem等。当进入Containers执行free,df,top等命令的时候,这时候默认读取的是 /proc 目录内的资源信息文件内容,而这些资源信息文件使用的是宿主机的,所以我们看到的是宿主机的使用信息。


LXCFS简介

LXCFS是一个开源的FUSE(用户态文件系统),用来支持LXC容器,也支持Docker容器,社区中常用此工具来实现容器中的资源可见性。

LXCFS原理

以内存资源为列:通过将宿主机的 /var/lib/lxcfs/meminfo 文件挂载到容器内的/proc/meminfo,然后LXCFS会从容器的CGroup中读取正确的内存限制,然后应用到 /var/lib/lxcfs/meminfo ,这时候容器内部从而就得到了正确的内存信息。

说明:/var/lib/lxcfs/meminfo 是服务启动的时候默认指定的目录


具体使用方法

安装LXCFS

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

启动LXCFS

systemctl start lxcfs
systemctl enable lxcfs

启动一个容器测试

docker run -it -m 256m --cpuset-cpus "0,1,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 \
      ubuntu:16.04 /bin/bash

说明:-m 选项用来限制内存,--cpuset-cpus 选项用来限制使用使用CPU的核数,并指定 0,1,2,三核。

查看内存

root@32f05068ffa3:/# free -m
              total        used        free      shared  buff/cache   available
Mem:            256           6         249          23           0         249
Swap:           256           0         256

查看CPUs,实际宿主机为8核

root@32f05068ffa3:/# top
top - 09:52:34 up 0 min,  0 users,  load average: 0.21, 0.70, 0.86
Tasks:   2 total,   1 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu0  :  1.7 us,  0.7 sy,  0.0 ni, 97.3 id,  0.0 wa,  0.0 hi,  0.3 si,  0.0 st
%Cpu1  :  0.7 us,  0.7 sy,  0.0 ni, 98.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu2  :  3.7 us,  0.7 sy,  0.0 ni, 95.6 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   262144 total,   255112 free,     7032 used,        0 buff/cache
KiB Swap:   262144 total,   262144 free,        0 used.   255112 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                      
    1 root      20   0   18224   1976   1508 S   0.0  0.8   0:00.04 bash                                                                         
   13 root      20   0   36648   1704   1252 R   0.0  0.7   0:00.00 top


基于Kubernetes实战

克隆LXCFS基于Kubernetes项目到本地

git clone https://github.com/denverdino/lxcfs-initializer


部署LXCFS到每个节点

在些命令的前面需要每个节点先安装LXCFS,不需要启动

kubectl apply -f lxcfs-initializer/lxcfs-daemonset.yaml


开启Kubernetes对Initializer扩展机制的支持,如果使用的是阿里云Kubernetes默认已支持

查看是否支持

kubectl api-versions | grep admission.*v1alpha1

在启动kube-apiserver的时候增加下面两个参数,让其支持,如果是kubeadm部署,修改 /etc/kubernetes/manifests/kube-apiserver.yaml 此文件应用即可

--enable-admission-plugins=NodeRestriction,Initializers
--runtime-config=admissionregistration.k8s.io/v1alpha1=true

备注:在apply的时候有可能会会报“connection refused”,这时候kubectl无法与kube-apiserver通讯,只需要手动 telnet 下对应的 IP:PORT 即可。只是在本人自己环境出现这样的情况,各位视情况而定,执行成功后再次查看是否支持


部署Initializer扩展机制,用于自动的完成对LXCFS文件的自动挂载

kubectl apply -f lxcfs-initializer/lxcfs-initializer.yaml


确保所有程序已运行

$ kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
lxcfs-2ppnp                          1/1     Running   4          3m7s
lxcfs-bm4t6                          1/1     Running   4          3m7s
lxcfs-initializer-769d7fb857-bhgbv   1/1     Running   0          11s
lxcfs-pmmj8                          1/1     Running   0          3m7s


测试,通过添加 initializer.kubernetes.io/lxcfs: true 就会自动的挂载相对应的文件

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    "initializer.kubernetes.io/lxcfs": "true"
  name: web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: centos
          imagePullPolicy: Always
          command: 
          - "/bin/bash"
          - "-c"
          - "while true;do echo `date` && sleep 3;done"
          resources:
            requests:
              memory: "512Mi"
            limits:
              memory: "1024Mi"

验证

$ kubectl exec -ti web-65dd5b55f-6ngp8 -- free -m
              total        used        free      shared  buff/cache   available
Mem:           1024           0        1022          17           0        1022


参考资料

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

https://yq.aliyun.com/articles/566208/