菜鸟笔记
提升您的技术认知

容器技术的基石:namespace和cgroups

文章目录

  • Namespace
  • Cgroups

Namespace

虚拟技术基本要求就是资源隔离,简单的说就是我独占当前所有的资源。比如我在 8080 端口起 web 服务器,不用担心其他进程端口占用。Linux 自带 namespace 就能达到这个目的。Linux现有的namespace有六种:

Docker通过clone()在创建新进程的同时创建namespace。

int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg);

介绍其中三种:

  • UTS namespace
    UTS(UNIX Time-sharing System)namespace提供了主机名与域名的隔离,这样每个docker容器就可以拥有独立的主机名和域名了,在网络上可以被视为一个独立的节点,而非宿主机上的一个进程。
  • IPC namespace
    进程间通信(Inter-Process Communication,IPC)涉及的IPC资源包括常见的信号量、消息队列和共享内存。在同一个IPC namespace下的进程彼此可见,不同IPC namespace下的进程则互相不可见。
  • PID namespace
    PID namespace隔离非常实用,它对进程PID重新标号,即两个不同namespace下的进程可以有相同的PID。每个PID namespace都有自己的计数程序。内核为所有的PID namespace维护了一个树状结构,最顶层的是系统初始时创建的,被称为root namespace,它创建的心PID namespace被称为child namespace(树的子节点)。
    通过这种方式,不同的PID namespace会形成一个层级体系。所属的父节点可以看到子节点中的进程,并可以通过信号等方式对子节点中的进程产生影响。反过来,子节点却不能看到父节点PID namespace中的任何内容。

可以通过三个系统调用的方式

  • clone,创建新的进程和新的namespace,新创建的进程 attach 到新创建的 namespace
  • unshare,不创建新的进程,创建新的 namespace 并把当前进程 attach 上
  • setns, attach 进程到已有的 namespace 上

shell 也提供了一个和系统调用同名的 unshare 命令可以非常简单的创建 namespace。

sudo unshare --fork --pid --mount-proc bash

这样创建了一个新的 PID namespace 并在里面运行了 bash。我们看看当前 namespace 的进程

在这个 namespace 里,就只有两个进程了。

Cgroups

Docker 使用CGroups实现资源的配额管理。Docker中的 CPU,内存,网络的限制均通过 cgroups 实现。

  • 2007年由谷歌工程师研发
  • 2008年并入 Linux Kernel 2.6.24
  • C语言实现

cgroups 是 control groups 控制组的意思, 可以通过文件系统来访问这些信息。一般cgroups 挂载在 /sys/fs/cgroup


内核会读取这些信息来调度资源分配给每个进程。