容器资源可视化隔离的实现方法

栏目: IT技术 · 发布时间: 4年前

内容简介:容器技术提供了不同于传统虚拟机技术的环境隔离方式。通常的Linux容器对容器打包和启动进行了加速,但也降低了容器的隔离强度。其中Linux容器最为知名的问题就是资源视图隔离问题。容器可以通过cgroup的方式对资源的使用情况进行限制,包括: 内存,CPU等。但是需要注意的是,如果容器内的一个进程使用一些常用的监控命令,如: free, top等命令其实看到还是物理机的数据,而非容器的数据。这是由于容器并没有做到对/proc,/sys等文件系统的隔离。使用 lxcfs 和 kubernetes admissi

奇技指南

通常有一些业务已经习惯了在传统的物理机/虚拟机上使用top,free等命令来查看系统的资源使用情况,而在容器中使用这些命令看到的仍然是物理机/虚拟机上的数据。本文针对该问题,介绍了使用Lxcfs和kubernetes Admission Webhook来实现对容器的资源可视化隔离。

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在线上环境需要注意以下几点:

  1. 当前(lxcfs release 3.1.2)版本只对procfs文件系统进行了虚拟化,并没有对/sys/devices/system/cpu/online文件进行虚拟化,但是对/sys/devices/system/cpu/online的虚拟化工作已经被合并到master分支了,如果想要对其进行隔离操作的话,请单独对lxcfs进行编译再使用。

  2. 为什么需要对/sys/devices/system/cpu/online文件进行视图虚拟化?主要问题是由于一些语言在启动runtime时,会从该文件获取cpu的数量,来启动默认的线程数,比如: Java JVM或者Nginx。如果在容器里面获取的还是物理机的数据,会影响到应用程序的性能。

  3. lxcfs需要部署在k8s集群的各个Node节点上,当lxcfs服务重启或者crash时,之前已经挂载在容器/proc的挂载点会失效,导致在容器中执行free,top命令会失效。为了解决这个问题,现在的做法是使用systemd的方式在各个节点启动lxcfs服务,当lxcfs服务crash之后重启成功之后,会通过ExecStartPost的方式执行 /usr/local/bin/container_remount_lxcfs.sh脚本来对之前已经挂载过的容器进行重新挂载操作。

lxcfs.service的内容如下:

[Unit]

Description=FUSE filesystem for LXC

ConditionVirtualization=!container

Before=lxc.service

Documentation=man:lxcfs(1)


[Service]

ExecStart=/usr/bin/lxcfs -l /var/lib/lxc/lxcfs/

KillMode=process

Restart= always

Delegate=yes

ExecStopPost=-/bin/fusermount -u /var/lib/lxc/lxcfs

ExecReload=/bin/kill -USR1 $MAINPID


# add remount script

ExecStartPost=/usr/local/bin/container_remount_lxcfs.sh


[Install]

WantedBy=multi-user.target

lxcfs重启成功之后,执行的重新挂载脚本内容如下:

#! /bin/bash


PATH=$PATH:/bin

LXCFS="/var/lib/lxc/lxcfs"

LXCFS_ROOT_PATH="/var/lib/lxc"


containers=$(docker ps | grep -v pause | grep -v calico | awk '{print $1}' | grep -v CONTAINE)


for container in $containers;do

mountpoint=$(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination "/var/lib/lxc" }}{{ .Source }}{{ end }}{{ end }}' $container)

if [ "$mountpoint" = "$LXCFS_ROOT_PATH" ];then

echo "remount $container"

PID=$(docker inspect --format '{{.State.Pid}}' $container)

# mount /proc

for file in meminfo cpuinfo loadavg stat diskstats swaps uptime;do

echo nsenter --target $PID --mount -- mount -B "$LXCFS/proc/$file" "/proc/$file"

nsenter --target $PID --mount -- mount -B "$LXCFS/proc/$file" "/proc/$file"

done

# mount /sys

for file in online;do

echo nsenter --target $PID --mount -- mount -B "$LXCFS/sys/devices/system/cpu/$file" "/sys/devices/system/cpu/$file"

nsenter --target $PID --mount -- mount -B "$LXCFS/sys/devices/system/cpu/$file" "/sys/devices/system/cpu/$file"

done

fi

done

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服务时,需要注意的几点如下:

1. kubernetes的版本需要大于等于1.9。

2. 配置kube-apiserver配置文件,对–admission-control增加MutatingAdmissionWebhook,ValidatingAdmissionWebhook参数,使kubernetes开启admissionregistration.k8s.io/v1beta1 API。

3. 如果kubernetes master节点没有部署kube-proxy, 需要为kube-apiserver增加--enable-aggregator-routing=true的参数。

4. 如果使用的runc版本比较低,需要升级各个Node节点的runc,以允许容器对procfs文件系统的挂载操作。

最终体现容器资源可视化隔离的效果如下所示:

容器资源可视化隔离的实现方法

容器资源可视化隔离的实现方法

相关文章

  • https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/

  • https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/

  • https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/

容器资源可视化隔离的实现方法

向所有一线抗疫勇士致敬!

360技术公众号

技术干货|一手资讯|精彩活动


以上所述就是小编给大家介绍的《容器资源可视化隔离的实现方法》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C++数据结构与程序设计

C++数据结构与程序设计

克鲁斯 / 钱丽萍 / 清华大学出版社 / 2004-1 / 59.00元

《C++数据结构与程序设计》这本精心制作的课本结合面向对象程序设计和C++强有力的特性,构建数据结构的基本思想,设计了程序和有趣的应用。在此过程中,《C++数据结构与程序设计》探讨了作为软件设计基本工具的问题求解和设计原理、数据抽象、递归和算法的比较分析。《C++数据结构与程序设计》使用真实的案例研究、可重用的软件开发和程序设计项目来增强理解。一起来看看 《C++数据结构与程序设计》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试