容器技术Linux Namespaces和Cgroups

对操作系统了解多少,仅仅敲个命令吗

  1. 操作系统虚拟化(容器技术)的发展历程

1979 年,UNIX 的第 7 个版本引入了 Chroot 特性。Chroot 现在被认为是第一个操作系统虚拟化(Operating system level virtualization)技术的原型,本质是一种操作系统文件系统层的隔离技术。

2006 年,Google 发布了在 Linux 上运行的 Process Container(进程容器)技术,其目标是提供一种类似于 Virtual Mahine(计算机虚拟化技术)的、但主要针对 Process 的操作系统级别资源限制、优先级控制、资源审计能力和进程控制能力。

2007 年,Google 推动 Process Container 代码合入 Linux Kernel。同时由于 Container 这一命名在 Kernel 具有许多不同的含义,所以为了避免代码命名的混乱,就将 Process Container 更名为了 Control Groups,简称:Cgroups

2008 年,Linux 社区整合了 Chroot、Cgroups、Namespaces、SELinux、Seccomp 等多种技术并发布了 LXC(Linux Container)v0.1.0 版本。LXC 通过将 Cgroups 的资源配额管理能力和 Namespace 的资源视图隔离能力进行组合,实现了完备的轻量级操作系统虚拟化。

2013 年 3 月 15 日,在加利福尼亚州圣克拉拉召开的 Python 开发者大会上,DotCloud 的创始人兼首席执行官 Solomon Hvkes 在一场仅 5 分钟的微型演讲中,首次发布了基于 LXC 封装的 Docker Container,并于会后将其源码开源并托管到 Github。

图片

2.   容器的优势

传统模式的部署,直接将多个应用运行在物理服务器上,如果其中一个应用占用了大部分资源,可能会导致其他应用的性能下降。

虚拟化部署时代,可以在单个物理服务器的 CPU 上运行多个虚拟机(VM),每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件(包括了操作系统)。因此,可以让不同的应用在 VM 之间安全地隔离运行,更好地利用物理服务器上的资源。

容器与 VM 类似,具有自己的文件系统、CPU、内存、进程空间等,但与 VM 不同的是,容器之间共享操作系统(OS)。 所以,容器被认为是一种轻量级的操作系统层面的虚拟化技术。

相比于 VM ,轻量级的容器更适合云原生模式的实践。

 

 3.  容器的本质

容器是一种轻量级的操作系统层面的虚拟化技术。

重点是 “操作系统层面” ,即容器本质上是利用操作系统提供的功能来实现虚拟化。

容器技术的代表之作 Docker ,则是一个基于 Linux 操作系统,使用 Go 语言编写,调用了 Linux Kernel 功能的虚拟化工具。

为了更好地理解容器的本质,我们来看看容器具体使用了哪些 Linux Kernel 技术,以及在 Go 中应该如何去调用。

图片

3.1  Chroot

Chroot 是一个可供 User Process 调用的 System Call 接口,可以让一个 Process 把指定的目录作为根目录(Root Directory),随后 Process 所有的文件系统操作都只能在这个指定目录中进行。故称之为 Change Root。

chroot() 的函数原型非常简单:

  • 调用权限:Root 用户。

  • 形参列表

    • path:一个指向字符串的指针,是一个绝对路径,表示将 Process 的根目录更改为的该目录路径。

  • 函数返回

    • 成功:返回 0;

    • 失败:返回 -1。

#include <unistd.h>

int chroot(const char *path);

需要注意的是,在更改了 Process 的根目录后,Process 只能访问新的根目录以及其子目录中的文件和资源。因此,在调用 chroot() 后,应确保 Process 所需要访问的所有文件和资源都存在于新的根目录下。

chroot() 目前主要主要用于:

安全隔离场景:限制将 Process 的访问范围,以此提高系统的安全性。

调试环境场景:创建一个与主系统隔离的环境,用于调试、测试和运行 Process。

系统救援场景:在 Linux 操作系统损坏或遭受攻击时,可以使用 chroot 将 Process 切换到受损系统的根目录中,以便进行修复和救援操作。

可见,chroot() 确实在 Linux File System(文件系统)层面提供了针对 Process 的隔离性,但并不提供完全的安全隔离,无法阻止其他方式的攻击。因此,要想实现 Processes 之间的安全隔离,还需要需采取其他安全措施。

3.2  NameSpaces

Linux Namespaces(命名空间)是一种操作系统层级的资源视图隔离技术,能够将 Linux 的全局资源,划分为 Namespace 范围内可见的资源。

由于容器之间共享 OS ,对于操作系统而言,容器的实质就是进程,多个容器运行,对应操作系统也就是运行着多个进程。

当进程运行在自己单独的命名空间时,命名空间的资源隔离可以保证进程之间互不影响,大家都以为自己身处在独立的一个操作系统里。这种进程就可以称为容器。

Namespaces 具有多种类型,基本上涵盖了构成一个操作系统所需要的基本元素:

命名空间 系统调用参数 作用
Mount (mnt) CLONE_NEWNS 文件目录挂载隔离。用于隔离各个进程看到的挂载点视图
Process ID (pid) CLONE_NEWPID 进程 ID 隔离。使每个命名空间都有自己的初始化进程,PID 为 1,作为所有进程的父进程
Network (net) CLONE_NEWNET 网络隔离。使每个 net 命名空间有独立的网络设备,IP 地址,路由表,/proc/net 目录等网络资源
Interprocess Communication (ipc) CLONE_NEWIPC 进程 IPC 通信隔离。让只有相同 IPC 命名空间的进程之间才可以共享内存、信号量、消息队列通信
UTS CLONE_NEWUTS 主机名或域名隔离。使其在网络上可以被视作一个独立的节点而非主机上的一个进程
User ID (user) CLONE_NEWUSER 用户 UID 和组 GID 隔离。例如每个命名空间都可以有自己的 root 用户
Control group (cgroup) Namespace CLONE_NEWCGROUP Cgroup 信息隔离。用于隐藏进程所属的控制组的身份,使命名空间中的 cgroup 视图始终以根形式来呈现,保障安全
Time Namespace CLONE_NEWTIME 系统时间隔离。允许不同进程查看到不同的系统时间

通过 /proc/{pid}/ns 文件可以查看指定 Process 运行在哪些 Namespaces Instance 中,并且每个 Namespace Instance 都具有一个唯一的标识。

[root@192 dongguangming]#  ls -l --time-style='+' /proc/$$/ns
total 0
lrwxrwxrwx. 1 root root 0  ipc -> ipc:[4026531839]
lrwxrwxrwx. 1 root root 0  mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0  net -> net:[4026531956]
lrwxrwxrwx. 1 root root 0  pid -> pid:[4026531836]
lrwxrwxrwx. 1 root root 0  user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0  uts -> uts:[4026531838]
[root@192 dongguangming]# 

最终,用户可以通过创建多种不同类型的 Namespaces Instance 来提供的操作系统资源的隔离,再结合创建多种不同类型的 cgroups 来提供操作系统的资源配额,就构成了一个最基本的操作系统容器,即:Process Container。

UTS namespace

UTS namespace 为 Container 提供了 Hostname 和 Domain Name 的隔离。

Container 中的 Process 可以根据需要调用 sethostname 和 setdomainname 指令来进行配置,让每个 Container 都可以被视为网络中的一个独立的节点。

PID namespace

PID namespace 为 Container 提供了进程号的隔离。

每个 Containers 都拥有自己的进程环境,Container 的 init Process 都是 PID 1 号进程,它作为所有子进程的父进程。要想做到进程的隔离,首先需要创建出 PID 1 号进程,它具有以下特性:

  • 如果某个子进程脱离了父进程(父进程没有 wait 它),那么 init Process 就会负责回收资源并结束这个子进程。

  • 如果 init Process  被终止,那么 Kernel 就会调用 SIGKILL 终止此 PID namespace 中的所有进程。

IPC namespace

IPC namespace 为 Container 提供了 IPC(进程间)通信机制的隔离,包括信号量、消息队列、共享内存等机制。

每个 Containers 都拥有以下 /proc 文件接口:

  • /proc/sys/fs/mqueue:POSIX Message Queues 接口类型;

  • /proc/sys/kernel:System V IPC 接口类型;

  • /proc/sysvipc:System V IPC 接口类型。

Mount namespace

Mount namespace 为 Container 提供了 Filesystem 挂载点的隔离,继而实现了 VFS 的隔离。

每个 Containers 都拥有以下 /proc 文件接口,可以构成一个独立的 rootfs(Root 文件系统):

  • /proc/[pid]/mounts

  • /proc/[pid]/mountinfo

  • /proc/[pid]/mountstats

实际上,Mount namespace 是基于 Chroot 的不断改良而开发出来的。为 Container 创建的 rootfs 只是一个操作系统发行版所包含的文件、目录和配置,并不包括 Kernel 的文件。

Network namespace

Network namespace 为 Container 提供了网络资源的隔离,包括:

  • Network devices(网络设备)

  • IPv4 and IPv6 protocol stacks(IPv4、IPv6 的协议栈)

  • IP routing tables(IP 路由表)

  • Firewall rules(防火墙规则)

  • Sockets 套接字

  • /proc/[pid]/net

  • /sys/class/net

  • /proc/sys/net

需要注意的是,同一个 Network device 只能存在于一个 Namespace Instance 中,所以常常结合虚拟网络设备来使用。

图片

User namespace

User namespace 为 Container 提供了用户权限和安全属性相关的隔离,包括:User ID、User Group ID、Root 目录以及特殊的权限。

每个 Containers 都拥有以下 /proc 文件接口:

  • /proc/[pid]/uid_map

  • /proc/[pid]/gid_map

NameSpace 的具体描述可以查看 Linux man 手册中的 namespaces(7) - Linux manual page,手册中还描述了几个 NameSpace API ,主要是和进程相关的系统调用函数。

图片

clone()
int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...
                 /* pid_t *parent_tid, void *tls, pid_t *child_tid */ );

clone() 用于创建新进程,通过传入一个或多个系统调用参数( flags 参数)可以创建出不同类型的 NameSpace ,并且子进程也将会成为这些 NameSpace 的成员。

setns()
int setns(int fd, int nstype);

setns() 用于将进程加入到一个现有的 Namespace 中。其中 fd 为文件描述符,引用 /proc/[pid]/ns/ 目录里对应的文件,nstype 代表 NameSpace 类型。

unshare()
int unshare(int flags);

unshare() 用于将进程移出原本的 NameSpace ,并加入到新创建的 NameSpace 中。同样是通过传入一个或多个系统调用参数( flags 参数)来创建新的 NameSpace 。

ioctl()
int ioctl(int fd, unsigned long request, ...);

ioctl() 用于发现有关 NameSpace 的信息。

上面

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值