通常有一些业务已经习惯了在传统的物理机/虚拟机上使用 top,free 等命令来查看系统的资源使用情况,而在容器中使用这些命令看到的仍然是物理机/虚拟机上的数据。本文针对该问题,介绍了使用 Lxcfs 和 kubernetes Admission Webhook 来实现对容器的资源可视化隔离。
PS:丰富的一线技术、多元化的表现形式,尽在“360 云计算”,点关注哦!
1.为什么对容器的资源进行可视化隔离?
容器技术提供了不同于传统虚拟机技术的环境隔离方式。通常的 Linux 容器对容器打包和启动进行了加速,但也降低了容器的隔离强度。其中 Linux 容器最为知名的问题就是资源视图隔离问题。
容器可以通过 cgroup 的方式对资源的使用情况进行限制,包括: 内存,CPU 等。但是需要注意的是,如果容器内的一个进程使用一些常用的监控命令,如: free, top 等命令其实看到还是物理机的数据,而非容器的数据。这是由于容器并没有做到对/proc,/sys 等文件系统的隔离。
2.容器资源视图隔离有哪些应用场景?
1)在容器生产环境,通常有一些业务已经习惯了在传统的物理机,虚拟机上使用 top,free 等命令来查看系统的资源使用情况,但是容器没有做到资源视图隔离,那么在容器里面看到的数据还是物理机的数据。
2)在应用程序的视角来看,在容器里面运行进程和在物理机虚拟机上运行进程的运行环境是不同的。并且有些应用在容器里面运行进程会存在一些安全隐患:
对于很多基于 JVM 的 java 程序,应用启动时会根据系统的资源上限来分配 JVM 的堆和栈的大小。而在容器里面运行运行 JAVA 应用由于 JVM 获取的内存数据还是物理机的数据,而容器分配的资源配额又小于 JVM 启动时需要的资源大小,就会导致程序启动不成功。并且在 java 应用里,一些 java 库也会根据资源视图分配堆和栈的大小,这同样会存在安全隐患。
在 CPU 上也会存在问题,大多数的应用程序,比如 nginx 或者一些其它的中间件服务会根据其视图的 cpuinfo 文件信息设定默认的启动线程数。但是在容器内的进程总会从/proc/cpuinfo 中获取到 CPU 的核数,而容器里面的/proc 文件系统还是物理机的,从而会影响到运行在容器里面服务的性能。
3.容器资源视图没有完全解决的问题,如何做?
使用 lxcfs 和 kubernetes admission webhook 机制来实现容器资源视图隔离的效果。
1)lxcfs 官方介绍
LXCFS is a small FUSE filesystem written with the intention of making Linux containers feel more like a virtual machine. It started as a side-project of LXC but is useable by any runtime.
关于 lxcfs 的详细内容,请戳:https://github.com/lxc/lxcfs.
在应用 Lxcfs 在线上环境需要注意以下几点:
当前(lxcfs release 3.1.2)版本只对 procfs 文件系统进行了虚拟化,并没有对/sys/devices/system/cpu/online 文件进行虚拟化,但是对/sys/devices/system/cpu/online 的虚拟化工作已经被合并到 master 分支了,如果想要对其进行隔离操作的话,请单独对 lxcfs 进行编译再使用。
为什么需要对/sys/devices/system/cpu/online 文件进行视图虚拟化?主要问题是由于一些语言在启动 runtime 时,会从该文件获取 cpu 的数量,来启动默认的线程数,比如: Java JVM 或者 Nginx。如果在容器里面获取的还是物理机的数据,会影响到应用程序的性能。
lxcfs 需要部署在 k8s 集群的各个 Node 节点上,当 lxcfs 服务重启或者 crash 时,之前已经挂载在容器/proc 的挂载点会失效,导致在容器中执行 free,top 命令会失效。为了解决这个问题,现在的做法是使用 systemd 的方式在各个节点启动 lxcfs 服务,当 lxcfs 服务 crash 之后重启成功之后,会通过 ExecStartPost 的方式执行/usr/local/bin/container_remount_lxcfs.sh 脚本来对之前已经挂载过的容器进行重新挂载操作。
lxcfs.service 的内容如下:
2)基于 kuernetes 可扩展的 admission webhook 机制对发送创建 POD 的请求数据进行拦截,并对其请求的 Body 进行修改之后(在 lxcfs 中主要是对 pod 进行 procfs 文件系统的挂载操作),再放行到具体的 handler 中并持久化数据到 etcd。
再配一张图更能体现 adminssion webhook 在请求中的哪个位置进行工作。
作者基于开源的 lxcfs-admission-webhook 进行了修改,增加对/sys/devices/system/cpu/online 文件的虚拟化。详细的代码请戳: https://github.com/xigang/lxcfs-admission-webhook/tree/dev.
在使用 lxcfs-admission-webhook 服务时,需要注意的几点如下:
kubernetes 的版本需要大于等于 1.9。
配置 kube-apiserver 配置文件,对–admission-control 增加 MutatingAdmissionWebhook,ValidatingAdmissionWebhook 参数,使 kubernetes 开启 admissionregistration.k8s.io/v1beta1 API。
如果 kubernetes master 节点没有部署 kube-proxy, 需要为 kube-apiserver 增加–enable-aggregator-routing=true 的参数。
如果使用的 runc 版本比较低,需要升级各个 Node 节点的 runc,以允许容器对 procfs 文件系统的挂载操作。
最终体现容器资源可视化隔离的效果如下所示:
本文转载自 360 云计算公众号。
原文链接:https://mp.weixin.qq.com/s/SCxD4OiDYsmoIyN5XMk4YA
评论