作者:烧鸡太子爷
来源:恒生LIGHT云社区
背景
最近在给组内新人讲解一些docker容器化,大家都能够理解,docker容器实际上就是运行的一个进程,只不过由于docker帮助我们包装了这个进程,给这个进程加以一个可运行的微linux环境而已,让我们感觉看起来"像"虚拟机而已。那么他是如何做到资源控制的呢,大家也都知道是用了namespace、cgroup。个人也比较好奇,所以也花了一点时间去学习了一下,也做一些笔记,可以和大家一起学习一下
Linux namespace
Linux namespace 是一种内核级别的资源隔离机制,用来让运行在同一个操作系统上的进程互相不会干扰。
namespace 目的就是隔离,要做到的效果是:如果某个 namespace 中有进程在里面运行,它们只能看到该 namespace 的信息,无法看到 namespace 以外的东西。
我们来想一下:一个进程在运行的时候,它会知道哪些信息?
- 看到系统的 hostname
- 可用的网络资源(bridge、interface、网络端口的时候情况……)
- 进程的关系(有哪些进程,进程之间的父子关系等)、
- 系统的用户信息(有哪些用户、组,它们的权限是怎么样的)
- 文件系统(有哪些可用的文件系统,使用情况)
- IPC(怎么实现进程间通信)
- …… 也就是说,如果要实现隔离,必须保证不同 namespace 中进程看到的上面这些东西是不同的。
如果让我来做,首先的想法是每个 namespace 都实现一整套上述资源的隔离,但是实际上 linux 的实现中,上述的所有资源都是可以多带带隔离的。
目前 linux 内核主要实现了一下几种不同的资源 namespace,官网有如下介绍:
名称 | 宏定义 | 宏定义 |
---|---|---|
IPC | CLONE_NEWIPC | System V IPC, POSIX message queues (since Linux 2.6.19) |
Network | CLONE_NEWNET | network device interfaces, IPv4 and IPv6 protocol stacks, IP routing tables, firewall rules, the /proc/net and /sys/class/net directory trees, sockets, etc (since Linux 2.6.24) |
Mount | CLONE_NEWNS | Mount points (since Linux 2.4.19) |
PID | CLONE_NEWPID | Process IDs (since Linux 2.6.24) |
User | CLONE_NEWUSER | User and group IDs (started in Linux 2.6.23 and completed in Linux 3.8) |
UTS | CLONE_NEWUSER | Hostname and NIS domain name (since Linux 2.6.19) |
Cgroup | CLONE_NEWCGROUP | Cgroup root directory (since Linux 4.6) |
这些 namespace 基本上覆盖了一个程序运行所需的环境,保证运行在的隔离的 namespace 中的,会让程序不会受到其他收到 namespace 程序的干扰。但不是所有的系统资源都能隔离,时间就是个例外,没有对应的 namespace,因此同一台 Linux 启动的容器时间都是相同的。
但是Namespace解决的问题主要是环境隔离的问题,这只是虚拟化中最最基础的一步,我们还需要解决对计算机资源使用上的隔离。也就是说,虽然你通过Namespace把我加到一个特定的环境中去了,但是我在其中的进程使用用CPU、内存、磁盘等这些计算资源其实还是可以随心所欲的。所以,我们希望对进程进行资源利用上的限制或控制。这就是Linux CGroup出来了的原因。
Linux cgroup
Linux CGroup全称Linux Control Group, 是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如CPU、内存、磁盘输入输出等)。
Linux CGroupCgroup 可让您为系统中所运行任务(进程)的用户定义组群分配资源 — 比如 CPU 时间、系统内存、网络带宽或者这些资源的组合。您可以监控您配置的 cgroup,拒绝 cgroup 访问某些资源,甚至在运行的系统中动态配置您的 cgroup。
它主要提供了如下功能:
- Resource limitation: 限制资源使用,比如内存使用上限以及文件系统的缓存限制。
- Prioritization: 优先级控制,比如:CPU利用和磁盘IO吞吐。
- Accounting: 一些审计或一些统计,主要目的是为了计费。
- Control: 挂起进程,恢复执行进程。 使用 cgroup,系统管理员可更具体地控制对系统资源的分配、优先顺序、拒绝、管理和监控。可更好地根据任务和用户分配硬件资源,提高总体效率。
cgroups 的作用:
- 资源限制
cgroups可以对任务使用的资源(内存,CPU,磁盘等资源)总额进行限制。 如 设定应用运行时使用的内存上限,一旦超过配额就发出OOM提示 - 优先级分配
通过分配的CPU时间片数量以及磁盘IO带宽大小,实际上就相当于控制了任务运行的优先级 - 资源统计
cgroups可以统计系统的资源使用量 如CPU使用时长,内存用量等,这个功能非常适用于计费 - 任务控制
cgroups 可以对任务进行挂起、恢复等操作
总结
Docker容器的本质是宿主机上的一个进程。Docker通过namespace实现了资源隔离,通过cgroups实现了资源限制。 namespace技术实际上修改了应用进程看待整个计算机“视图”,即它的“视线”被操作系统做了限制,只能“看到”默写指定的内容,而这个进程能够使用的资源量,则受cgroup配置的限制,但对于宿主机来说,这些被隔离和限制了的进程和其他进程并没有太大的区别。
另外,namespace和cgroup虽然已经做的很好了,但是他们还是有很多不完善的地方,比如做不到时间的隔离,比如/proc文件系统的问题,这些后面有时间也可以和大家一起讨论一下,本章不做具体的介绍了。