高品质的音视频能力是怎样的? | Qcon 全球软件开发大会·上海站邀请函 了解详情
写点什么

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

  • 2020-02-26
  • 本文字数:2827 字

    阅读完需:约 9 分钟

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

通常有一些业务已经习惯了在传统的物理机/虚拟机上使用 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 的内容如下:


[Unit]Description=FUSE filesystem for LXCConditionVirtualization=!containerBefore=lxc.serviceDocumentation=man:lxcfs(1)
[Service]ExecStart=/usr/bin/lxcfs -l /var/lib/lxc/lxcfs/KillMode=processRestart= alwaysDelegate=yesExecStopPost=-/bin/fusermount -u /var/lib/lxc/lxcfsExecReload=/bin/kill -USR1 $MAINPID
# add remount scriptExecStartPost=/usr/local/bin/container_remount_lxcfs.sh
[Install]WantedBy=multi-user.targetlxcfs重启成功之后,执行的重新挂载脚本内容如下:#! /bin/bash
PATH=$PATH:/binLXCFS="/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 文件系统的挂载操作。


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


本文转载自 360 云计算公众号。


原文链接:https://mp.weixin.qq.com/s/SCxD4OiDYsmoIyN5XMk4YA


2020-02-26 23:45682

评论

发布
暂无评论
发现更多内容

快手能做好ToB吗?

ToB行业头条

tob 快手

如何为开源项目撰写 RFC

Databend

大数据 开源 #开源 databend

设计模式的艺术 第五章工厂方法设计模式练习(设计一个程序来读取各种不同类型的图片格式,针对每种格式都设计一个图片读取器)

代廉洁

设计模式的艺术

中大型现代服务行业的ERP,Telework现代服务中台

sofiya

MobTech短信验证 Android端快速集成

MobTech袤博科技

android android-studio 短信验证

【微信小程序开发】自定义tabBar案例(定制消息99+小红心)

计算机魔术师

8月月更

设计模式的艺术 第十六章责任链设计模式练习(提供一个假条审批模块:如果员工请假天数小于3天,主任审批该请假条;如果天数大于或等于3天,小于10天,经理审批;如果天数大于或等于10天,小于30天,总经理审批;如果超过30天,总经理不能审批,提示相应拒绝信息)

代廉洁

设计模式的艺术

华为云发布《云原生2.0架构白皮书》,GaussDB技术再升级

sofiya

defi质押挖矿dapp系统开发智能合约部署详解

开发微hkkf5566

基于KubeEdge的边缘节点分组管理设计与实现

华为云开发者联盟

云计算 云原生 后端

【Django | 开发】 (国际化项目&支持多语言)

计算机魔术师

8月月更

Python如何用类和对象来编程?

和牛

Python 8月月更

教育部“产学合作协同育人”项目华为云GaussDB项目入选名单公布

sofiya

数字藏品系统开发:NFT系统开发

开源直播系统源码

数字藏品 数字藏品软件开发 数字藏品源码出售 数字藏品开发

【小程序项目开发-- 京东商城】uni-app之商品列表页面 (下)

计算机魔术师

8月月更

技术分享 | 常见接口协议解析

测吧(北京)科技有限公司

TCP/IP

容器资源可视化隔离的实现方法_容器_王希刚_InfoQ精选文章