容器底层-Cgroups 的使用

Linux Cgroups(Linux Control Group)是 Linux 内核中用来为进程设置资源限制的一个功能。它最主要的做用就是限制一个进程组可以使用的资源上限,包括 CPU、内存、磁盘、网络带宽等。此外,Cgroups 还可以对进程进行优先级设置、审计,以及将进程挂起和恢复等操做。web

那么为何除了 Namespace 以外还须要 Cgroups 呢?由于虽然容器里的 1 号进程只能看到容器里的状况,可是在宿主机上,它做为 100 号进程(好比宿主机上它的 PID 是 100)与其余全部进程之间依然是平等的竞争关系。也就是说,虽然 100 号进程表面上被隔离了起来,可是它可以使用的资源(好比 CPU、内存)是所有的,它可能把全部资源耗光。那么这样显然不是一个容器应该表现出来的合理行为。docker

在 Linux 中,Cgroups 给用户暴露出来的操做接口是文件系统,即操做接口是以文件和目录的方式组织在操做系统的 /sys/fs/cgroup 路径下。咱们能够经过 mount 命令来查看一下,能够发现输出结果是一系列文件系统目录。安全

咱们查看 /sys/fs/cgroup 的时候还能够看到一系列子目录,这些子目录又被称为子系统。这些都是我这台机器上当前能够被 Cgroups 进行限制的资源种类。好比:微信

  • cpu 只要限制 CPU 的使用时间
  • cpuset 为进程分配单独的 CPU 核和对应的内存节点
  • memory 为进程设定内存使用的限制
  • blkio 块设备设定 IO 限制,通常用于磁盘等设备

而在子目录下面能够看到该子系统对应的资源能够被限制的方法,好比对于 CPU 子系统来讲,咱们能够看到以下几个配置文件。网络

其中 cpu.cfs_period_us 和 cpu.cfs_quota_us 这两个文件组合使用能够限制进程在长度为 cfs_period 的一段时间内,只能被分配到总量为 cfs_quota 的 CPU 时间。app

Cgoups 配置示例

下面基于 Cgroups 提供的操做接口进行配置,咱们先在相应的子系统中再建立一个目录,好比 container ,这个目录就被称为“控制组”。当将这个目录建立好了以后,你会发现这个目录已经生成了该子系统对应的资源限制文件。编辑器

接下去,咱们经过修改 container 中的文件内容来设置限制。好比向 container 中的 cpu.cfs_quota_us 中写入 20 ms,也就是 20000,就表示每 cpu_period_us (100ms)被控制组限制的进程只能使用 20ms 的 CPU 时间。微服务

接下去咱们把要限制的进程 PID 写入 container 目录中的 tasks 文件中,那么该设置对要限制的进程就有效了。性能

Docker 实现

对于 Docker 等 Linux 容器项目来讲,它们只须要在每一个子系统下面,为每一个容器建立一个控制组(也就是建立一个新目录),而后在启动容器进程以后,把这个进程的 PID 写入到这个控制组的 tasks 文件中便可。而控制组中的资源限制要填上什么值,就要看用户执行 docker run 时指定的参数内容。在 Docker 主机中,每一个子系统下面都有 docker 控制组。学习

下面咱们来演示 docker 进行设置的效果,就会在 CPU 子系统的 docker 控制组中进行相关的设置。

docker run -it --rm --cpu-period=100000 --cpu-quota=20000 -d alpine sleep 500s

以下所示,docker 还会在 docker 控制组建立一个新的目录,在这个目录中对资源进行设置,从而达到限制资源使用的效果。

总结

跟 Namespace 状况相似,Cgoups 对资源的限制能力也有不少不完善的地方,其中被说起最多的是 /proc 文件系统的问题。/proc 目录存储着当前内核运行状态的一系列特殊文件,用户能够经过访问这些文件,查看系统以及当前正在运行的进程的信息,好比 CPU 使用状况、内存占用率等,这些文件也是 top 指令查看系统信息的主要数据来源。

可是,若是你在容器里执行 top 指令,就会发现,它显示的信息竟然仍是宿主机的 CPU 和内存数据。这是由于  /proc 文件系统并不知道用户经过 Cgroups 给这个容器作了什么样的资源限制,因此它返回的仍是整个宿主机的。那么这个问题会致使,容器内的应用程序读取到的 CPU 核数、可用内存等信息仍是宿主机的,而不是作了限制以后的。这就是容器相比较于虚拟机另外一个不尽如人意的地方。

固然,为了解决上面的那个问题。直观的作法就是容器不挂载宿主机的该目录就能够了,那么实际上能够经过 lxcfs 来实现隔离,lxcfs 在宿主机上维护进程组的信息,而后容器启动的时候将 lxcfs 维护的进程组信息所在的目录挂载到容器的 /proc 目录,当容器中获取 /proc 信息时,实际上获取宿主机上对该容器的进程组信息。

20201008理解:/proc 存的是当前宿主机内核运行状态的状况,好比 CPU 使用状况、内存占用率等。容器在它看来其实就是一个作了限制的进程而已,它作计算仍是针对整个内核的状况。可是,容器内的实际使用状况应该是根据容器中的相关限制来得出的,好比已经对容器作了 CPU 使用的限制,那么 top 命令获得的应该是在这个限制下,容器内进程的实际使用状况。



后台回复“加群”,带你进入高手如云交流群


推荐阅读:

10大高性能开发利器

安全容器gVisor详解

TCP协议灵魂 12 问,总会用获得

QUIC也不是万能的

超详干货!Linux环境变量配置全攻略

为何要选择智能网卡?

60,000毫秒内对Linux进行性能诊断

为何Linux须要Swapping

Linux系统经常使用命令速查手册

一文读懂容器网络发展

一文搞懂CDN加速原理

8 个问题完全搞透 DNS 协议

三张图完全搞懂iptables和netfilter

故障排查:K8s中Pod没法正常解析域名

网络排错大讲解~

OVS 和 OVS-DPDK 对比

微软出品的最新K8S学习指南3.0下载



喜欢,就给我一个“在看”



10T 技术资源大放送!包括但不限于:云计算、虚拟化、微服务、大数据、网络、Linux、Docker、Kubernetes、Python、Go、C/C++、Shell、PPT 等。在公众号内回复「1024,便可免费获取!!

本文分享自微信公众号 - Linux云计算网络(cloud_dev)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索