Z.S.K.'s Records

Kubernetes学习(使用lxcfs实现容器资源隔离)

Linuxs利用Cgroup实现了对容器的资源限制,但在容器内部依然缺省挂载了宿主机上的procfs(内存文件系统)的/proc目录,其包含如:meminfo, cpuinfo,stat, uptime等资源信息。一些监控工具如free/top或遗留应用还依赖上述文件内容获取资源配置和使用情况。当它们在容器中运行时,就会把宿主机的资源状态读取出来,引起错误和不便。

背景

最近就出现过类似的问题:

在kubernetes集群中部署了一个nginx用作ingress-nginx,出现一个很奇怪的现象是,隔一段时音就会有些连接被自动断开,排查后发现问题原因在于:

默认情况下,nginx会根据cpu的数量来启动worker的个数, 由于nginx容器所有的节点配置非常高,cpu为256, 导致nginx中启动了256个worker, 因为集群中有很多ing对象,ingress-nginx-controller会高频率地更新配置,每次的变更都需要同步到所有worker进行加载

因此这种情况下,要么手工显示地指定worker的数量,当然更好的办法是让nginx能够正确地识别容器中cpu的个数
是否可行呢?

lxcfs

当然是可以的,lxcfs作为一种CNCF推荐的方式,用于实现容器中的资源隔离, 主要有以下几种:

1
2
3
4
5
6
7
8
/proc/cpuinfo
/proc/diskstats
/proc/meminfo
/proc/stat
/proc/swaps
/proc/uptime
/proc/slabinfo
/sys/devices/system/cpu/online

流程

总体说起来很简单,当容器启动时,/proc/xxx会被挂载成host上lxcfs的目录。当请求读取/proc/meminfo的信息时,请求就会被导向lxcfs,而lxcfs就会通过cgroup的信息来返回正确的值给容器内的请求方

流程图

具体实现

LXCFS是基于FUSE(filesystems in user space)实现而成的一套用户态文件系统,和其他文件系统最本质的区别在于,文件系统通过用户态程序和内核FUSE模块交互完成。Linux内核从2.6.14版本开始通过FUSE模块支持在用户空间实现文件系统。通过LXCFS的源码可以看到,LXCFS主要通过调用底层fuse的lib库libfuse和内核模块fuse交互实现成一个用户态的文件系统。此外,LXCFS涉及到对cgroup文件系统的管理则是通过cgmanager用户态程序实现
FUSE的实现,感兴趣的可以看看5分钟搞懂用户空间文件系统FUSE工作原理

lxcfs on kubernetes

在kubernetes中,已经有相应的解决方案lxcfs-on-kubernetes
P.S. 推荐一个fork版本,去除了对cert-manager的依赖,作者亲测有效, 项目地址AEGQ lxcfs-on-kubernetes,
lxcfs-on-kubernetes安装方式也非常简单,helm几乎不需要改动即可发布,分为manager跟agent两个程序
manager就是一个webhook, 当有请求到达时,为相应的容器挂载lxcfs目录
agent就是一个lxcfs二进制程序, 做为daemonset运行在宿主机上

需要通过给namespace打label来开启自动挂载的功能

1
kubectl label namespace default mount-lxcfs=enabled

重要的是, 如果pod中没有指定limit,则看到的还是node上所有的资源,因此,必须指定limit,才能获取到正确的cgroup

这样,发布到default里的pod都将得到正确的资源值

集群安全无小事,不放过每处细节

参考文章:

转载请注明原作者: 周淑科(https://izsk.me)

 wechat
Scan Me To Read on Phone
I know you won't do this,but what if you did?