应用LXCFS来解决容器内获取CPU/内存不准的问题

图片

一  容器内获取CPU/内存不准的问题

不知道小伙伴们有没有遇到这种情况,你明明启动的是一个4核8G的容器或Pod,但是进入容器使用free或top看到的却不是4核8G。比如,云君随手使用docker run命令甩出一个只有256mb的容器,待容器启动之后发现free和top显示的都是宿主机的CPU和内存等信息:

图片

这会导致啥后果呢?默认情况下,这会让容器中的应用程序误以为自己可以使用更多的资源(宿主机资源)。

例如:go语言环境的runtime.GOMAXPROCS(runtime.NumCPU()),nodejs的Environment::GetCurrent()等,直接从容器中读取了不准确的CPU信息。又比如nginx设置的CPU亲和性绑定worker_cpu_affinity,也可能绑定了不准确的CPU……

怎么样?是不是感觉有点不爽?

二  几种解决方案

2.1  解决思路

出现上面这个问题,究其原因是容器创建的时候将宿主机上的/proc/cpuinfo、/proc/meminfo等信息自动加载进来,使得容器从中读取了宿主机的相关信息。解决方案无非是让容器读取到正确的资源信息,方案一般有以下几种:

  • 将容器的配置信息写入到容器内的一个标准文件container_info中,然后应用根据container_info中的资源信息,调整应用的配置来解决。比如修改jvm的一些参数,nginx的修改绑定的cpu编号等。

  • 在新版本的docker中,容器自己的cgroup会被挂载到容器内部,也就是说容器内部可以直接通过访问/sys/fs/cgroup中对应的文件获取容器的配置信息,就不必再用写入标准文件的方式了。

  • 使用LXCFS向容器提供正确的/proc/cpuinfo、/proc/meminfo信息。

如果你的应用愿意改造为读取 container_info或/sys/fs/cgroup信息,可以使用前两种方案。如果你的应用默认从/proc读取信息,但又难以进行改造(比如Linux自带的top和free等工具应用),可以考虑后面这种LXCFS方案。

2.2  LXCFS方案简介

图片

应用 LXCFS来提供容器中的资源可见性是业内常见的做法之一。LXCFS 是一个开源的用户态文件系统FUSE服务实现来支持LXC容器,它也可以支持Docker容器。LXCFS通过用户态文件系统,在容器中提供procfs 文件。比如,把宿主机的 /var/lib/lxcfs/proc/memoinfo 文件挂载到Docker容器的/proc/meminfo位置后。容器中进程读取相应文件内容时,LXCFS的FUSE实现会从容器对应的cgroup中读取正确的内存限制。从而使得应用获得正确的资源约束设定。

三  LXCFS的安装部署

3.1  安装FUSE及相关依赖包

云君这里有台CentOS 7测试机器,就直接使用yum install fuse fuse-lib fuse-devel命令来安装FUSE及相关依赖包了。

如果你的系统是CentOS 8的话,也可以使用dnf install fuse fuse-lib fuse-devel命令来安装;如果你的系统是SUSE Linux的话,可以使用zypper install fuse fuse-lib fuse-devel命令来安装。

3.2  编译并安装LXCFS

将LXCFS的源码拉下来,然后进行编译安装:

git clone https://github.com/lxc/lxcfs.gitcd lxcfs./bootstrap.sh./configuremakemake install

3.3  将LXCFS注册为systemd服务

在/etc/systemd/system/目录下创建一个名为lxcfs.service的文件,编写内容如下:​​​​​​​

[Unit]Description=FUSE filesystem for LXC
[Service]ExecStart=/usr/bin/lxcfs -s -o allow_other /var/lib/lxcfs/KillMode=processRestart=on-failureExecStopPost=-/usr/bin/rm -rf /var/lib/lxcfs/proc/Delegate=yes
[Install]WantedBy=multi-user.target

然后使用systemctl restart lxcfs.service命令启动LXCFS服务即可。使用systemctl status lxcfs.service命令查看服务运行状态:

图片

使用systemctl enable lxcfs.service命令设置LXCFS服务开机启动。

图片

说明:除了可以使用systemd的方式来托管LXCFS外,你还可以把LXCFS打到Docker容器镜像中,使用Kubernetes的DaemonSet形式在宿主机上启动LXCFS服务,有兴趣的小伙伴也可以试试……

四  LXCFS的挂载使用

4.1  在Docker容器中挂载LXCFS

举例,加入你需要给某个容器分配256mb内存,可以使用docker run命令来这样启动:​​​​​​​

# 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 \          cloudnativer/alpine:3.12 /bin/bash

待容器进入容器启动之后,使用free或top命令看到的容器内存就是是256mb了。

图片

4.2  在Kubernetes Pod中挂载LXCFS

上面讲了在Docker里面如何挂载LXCFS,那么如何在kubernetes Pod中使用 LXCFS 呢?创建一个名为cloudnativer-test的Deployment,具体的YAML代码如下:​​​​​​​

apiVersion: apps/v1kind: Deploymentmetadata:  name:cloudnativer-test  namespace: defaultspec:  replicas: 3  selector:    matchLabels:      app:cloudnativer-test  template:    metadata:      labels:        app:cloudnativer-test    spec:      containers:      - name:cloudnativer-test        image:cloudnativer/alpine:3.12        imagePullPolicy: IfNotPresent        resources:          requests:            cpu: 1            memory:60Mi          limits:            cpu: 1            memory:256Mi       volumeMounts:        - name:lxcfs-cpuinfo          mountPath:/proc/cpuinfo        - name:lxcfs-diskstats          mountPath:/proc/diskstats        - name:lxcfs-meminfo          mountPath:/proc/meminfo        - name:lxcfs-stat          mountPath: /proc/stat        - name:lxcfs-swaps          mountPath:/proc/swaps        - name:lxcfs-uptime          mountPath:/proc/uptime      volumes:      - name:lxcfs-cpuinfo        hostPath:          path:/var/lib/lxcfs/proc/cpuinfo      - name:lxcfs-diskstats        hostPath:          path:/var/lib/lxcfs/proc/diskstats      - name:lxcfs-meminfo        hostPath:          path:/var/lib/lxcfs/proc/meminfo      - name:lxcfs-stat        hostPath:          path:/var/lib/lxcfs/proc/stat      - name:lxcfs-swaps        hostPath:          path:/var/lib/lxcfs/proc/swaps      - name:lxcfs-uptime        hostPath:          path:/var/lib/lxcfs/proc/uptime

使用kubectl apply -f cloudnativer-test.yaml命令进行创建。

然后我们再进入pod,使用free或top命令看到的容器内存就是是256mb了。

图片

另外,Kubernetes还提供了Initializer扩展机制,你可以用于对资源创建进行拦截和注入处理,也可以借助它完成对LXCFS文件的挂载。还有使用DaemonSet形式部署LXCFS等更多的特性有待着大家去探索……

好了,今天就先介绍到这里了,我们下期再见。

参考文档:

https://github.com/lxc/lxcfs

https://cloudnativer.github.io

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值