Table of Contents generated with DocToc
资源隔离是虚拟化的前提,为vm,容器(进程)提供了环境上的隔离
如何实现进程、文件、网络等资源的隔离
- chroot的主要作用:改变执行的根目录
- cgroup 的主要作用:管理资源的分配、限制;
- namespace 的主要作用:封装抽象,限制,隔离,使命名空间内的进程看起来拥有他们自己的全局资源;
把根目录换成指定的目的目录,在 linux 系统中,系统默认的目录结构都是以 /
,即是以根 (root) 开始的。而在使用 chroot 之后,系统的目录结构将以指定的位置作为 /
位置。。
其作用如下:
- 增加系统的安全性,限制了用户的权力
- 与原系统隔离的系统目录结构,方便用户的开发
- 容灾
# 将target作为根目录(运行其中的/bin/sh):
chroot target /bin/sh
namespace 是 Linux 内核用来隔离内核资源的方式。 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前 namespace 里的进程,对其他 namespace 中的进程没有影响。
名称 | 宏定义 | 隔离资源 | 内核版本 |
---|---|---|---|
mnt | CLONE_NEWNS | Mount point | 2.4.19 |
ipc | CLONE_NEWIPC | System V IPC, POSIX message queue | 2.6.19 |
net | CLONE_NEWNET | network device interface, IPv4 and IPv6 protocol stack, IP routing table, firewall rule, the /proc/net and /sys/class/net directory tree, socket, etc | 2.6.24 |
pid | CLONE_NEWPID | Process ID | 2.6.24 |
user | CLONE_NEWUSER | User and group ID | 3.8 |
UTS | CLONE_NEWUTS | Hostname and NIS domain name | 2.6.19 |
cgroup | CLONE_NEWCGROUP | Control group root directory | 4.6 |
这些namespace基本上覆盖了一个程序运行所需的环境,包括主机名、用户权限、文件系统、网络、进程号、进程间通信。
namespace相关的系统调用主要有三个:clone
、setns
、unshare
- clone:创建新进程并设置它的namespace
- setns:让进程加入已经存在的namespace
- unshare:让进程脱离到新的namespace
主要作用是限制、记录和隔离进程组(process groups)使用的物理资源(cpu、memory、IO 等)。
cgroups子系统 主要有下
- cpu 子系统,主要限制进程的 cpu 使用率。
- cpuacct 子系统,可以统计 cgroups 中的进程的 cpu 使用报告。
- cpuset 子系统,可以为 cgroups 中的进程分配单独的 cpu 节点或者内存节点。
- memory 子系统,可以限制进程的 memory 使用量。
- blkio 子系统,可以限制进程的块设备 io。
- devices 子系统,可以控制进程能够访问某些设备。
- net_cls 子系统,可以标记 cgroups 中进程的网络数据包,然后可以使用 tc 模块(traffic control)对数据包进行控制。
- freezer 子系统,可以挂起或者恢复 cgroups 中的进程。
- ns 子系统,可以使不同 cgroups 下面的进程使用不同的 namespace。
cgroups 层级结构(Hierarchy)
VFS
VFS 是一个内核抽象层,能够隐藏具体文件系统的实现细节,从而给用户态进程提供一套统一的 API 接口。VFS 使用了一种通用文件系统的设计,具体的文件系统只要实现了 VFS 的设计接口,就能够注册到 VFS 中,从而使内核可以读写这种文件系统。 这很像面向对象设计中的抽象类与子类之间的关系,抽象类负责对外接口的设计,子类负责具体的实现。其实,VFS本身就是用 c 语言实现的一套面向对象的接口。
VFS 通用文件模型中包含以下四种元数据结构:
- 超级块对象(superblock object),用于存放已经注册的文件系统的信息。比如ext2,ext3等这些基础的磁盘文件系统,还有用于读写socket的socket文件系统,以及当前的用于读写cgroups配置信息的 cgroups 文件系统等。
- 索引节点对象(inode object),用于存放具体文件的信息。对于一般的磁盘文件系统而言,inode 节点中一般会存放文件在硬盘中的存储块等信息;对于socket文件系统,inode会存放socket的相关属性,而对于cgroups这样的特殊文件系统,inode会存放与 cgroup 节点相关的属性信息。这里面比较重要的一个部分是一个叫做 inode_operations 的结构体,这个结构体定义了在具体文件系统中创建文件,删除文件等的具体实现。
- 文件对象(file object),一个文件对象表示进程内打开的一个文件,文件对象是存放在进程的文件描述符表里面的。同样这个文件中比较重要的部分是一个叫 file_operations 的结构体,这个结构体描述了具体的文件系统的读写实现。当进程在某一个文件描述符上调用读写操作时,实际调用的是 file_operations 中定义的方法。 对于普通的磁盘文件系统,file_operations 中定义的就是普通的块设备读写操作;对于socket文件系统,file_operations 中定义的就是 socket 对应的 send/recv 等操作;而对于cgroups这样的特殊文件系统,file_operations 中定义的就是操作 cgroup 结构体等具体的实现。
- 目录项对象(dentry object),在每个文件系统中,内核在查找某一个路径中的文件时,会为内核路径上的每一个分量都生成一个目录项对象,通过目录项对象能够找到对应的 inode 对象,目录项对象一般会被缓存,从而提高内核查找速度。
Docker 就使用了 cgroups 提供的资源限制能力来完成cpu,内存等部分的资源控制。
k8s的Request和Limit,使用通过使用cgroup给用户提供的一个可以指定容器使用资源限制的一个入口。