一、实战目的
了解隔离能力并不是 Docker 提供的,而是操作系统内核提供基本能力。
二、基础知识
1、dd 命令详解
Linux dd 命令用于读取、转换并输出数据。
dd 可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准输出。
语法:
dd OPTION
参数:
- if=文件名:输入文件名,默认为标准输入,即指定源文件。
- of=文件名:输出文件名,默认为标准输出,即指定目的文件。
- ibs=bytes:一次读入 bytes 个字节,即指定一个块大小为 bytes 个字节。
- obs=bytes:一次输出 bytes 个字节,即指定一个块大小为 bytes 个字节。
- bs=bytes:同时设置读入 / 输出的块大小为 bytes 个字节。
- cbs=bytes:一次转换 bytes 个字节,即指定转换缓冲区大小。
- skip=blocks:从输入文件开头跳过 blocks 个块后再开始复制。
- seek=blocks:从输出文件开头跳过 blocks 个块后再开始复制。
- count=blocks:仅拷贝 blocks 个块,块大小等于 ibs 指定的字节数。
- conv=<关键字>,关键字可以有以下 12 种:
- conversion:用指定的参数转换文件。
- ascii:转换 ebcdic 为 ascii。
- ebcdic:转换 ascii 为 ebcdic。
- ibm:转换 ascii 为 alternate ebcdic。
- block:把每一行转换为长度为 cbs,不足部分用空格填充。
- unblock:使每一行的长度都为 cbs,不足部分用空格填充。
- lcase:把大写字符转换为小写字符。
- ucase:把小写字符转换为大写字符。
- swap:交换输入的每对字节。
- noerror:出错时不停止。
- notrunc:不截短输出文件。
- sync:将每个输入块填充到 ibs 个字节,不足部分用空(NUL)字符补齐。
- --help:显示帮助信息
- --version:显示版本信息
生成 test.img 和 test2.img 两个镜像文件:
将 in.txt 文件中的所有英文字母转换为大写,然后转成为 out.txt 文件:
2、mkfs 命令详解
用于在设备上创建 Linux 文件系统,俗称格式化。比如我们使用 U 盘的时候可以进行格式化。
语法:
mkfs [-V] [-t fstype] [fs-options] filesys [blocks]
参数:
- -t fstype:指定要建立何种文件系统,如 ext3,ext4。
- filesys:指定要创建的文件系统对应的设备文件名。
- blocks:指定文件系统的磁盘块数。
- -V:详细显示模式。
- fs-options:传递给具体的文件系统的参数。
将 test.img 分区格式化为 ext4 格式:
3、df 命令详解
Linux df(disk free) 命令用于显示目前在 Linux 系统上的文件系统磁盘使用情况统计。
语法:
df [OPTION]... [FILE]...
常见参数:
- -a,--all:包含所有的具有 0 Blocks 的文件系统。
- -h,--human-readable:使用人类可读的格式(预设值是不加这个选项的...)。
- -H,--si:很像 -h,但是用 1000 为单位而不是用 1024。
- -t,--type=TYPE:限制列出文件系统的 TYPE。
- -T,--print-type:显示文件系统的形式。
查看磁盘使用情况:
查看磁盘的系统类型:
4、mount 命令详解
mount 命令用于加载文件系统到指定的加载点。此命令的也常用于挂载光盘,使我们可以访问光盘中的数据,因为你将光盘插入光驱中,Linux 并不会自动挂载,必须使用 Linux mount 命令来手动完成挂载。
Linux 系统下不同目录可以挂载不同分区和磁盘设备,它的目录和磁盘分区是分离的,可以自由组合(通过挂载)。
不同的目录数据可以跨越不同的磁盘分区或者不同的磁盘设备。
挂载的实质是为磁盘添加入口(挂载点)。
mount 常见用法:
mount [-l]mount [-t vfstype] [-o options] device dir
常见参数:
- -l:显示已加载的文件系统列表。
- -t:加载文件系统类型支持常见系统类型的 ext3、ext4、iso9660、tmpfs、xfs 等,大部分情况可以不指定,mount 可以自己识别。
- -o options 主要用来描述设备或档案的挂接方式。
- loop:用来把一个文件当成硬盘分区挂接上系统。
- ro:采用只读方式挂接设备。
- rw:采用读写方式挂接设备。
- device:要挂接(mount)的设备。
- dir:挂载点的目录。
将 /test.img 挂在 ~/testmymount 之下:
5、unshare 命令详解
unshare 主要能力是使用与父程序不共享的名称空间运行程序。
语法:
unshare [options] program [arguments]
常用参数:
退出子进程,回到宿主机的命名空间:
三、实战操作一(PID 隔离)
1、在主机上执行 ps -ef,可以看到进程列表如下,其中启动进程 PID 1 为 init 进程
父进程是外层的 share,用 -p 指定了隔离之后,内部启动的 bash 的看不见外部的 pid 信息,因为 pid 已经发生了隔离,所以 /bin/bash 启动时没有父进程就发生了报错。
所以,需要用 --fork 来创建一个全新的进程:
用 ps -ef 来观察启动的新进程和宿主机上的进程是否一致:
2、打开另外一个 shell ,执行下面命令创建一个 bash 进程,并且新建一个 PID Namespace
--fork 新建了一个 bash 进程,是因为如果不建新进程,新的 namespace 会用 unshare 的 PID 作为新的空间的父进程,而这个 unshare 进程并不在新的 namespace 中,所以会报个错 Cannot allocate memory。
--pid 表示我们的进程隔离的是 pid,而其他命名空间没有隔离。
mount-proc 是因为 Linux 下的每个进程都有一个对应的 /proc/PID 目录,该目录包含了大量的有关当前进程的信息。 对一个 PID namespace 而言,/proc 目录只包含当前 namespace 和它所有子孙后代 namespace 里的进程的信息。创建一个新的 PID namespace 后,如果想让子进程中的 top、ps 等依赖 /proc 文件系统的命令工作,还需要挂载 /proc 文件系统。而文件系统隔离是 mount namespace 管理的,所以 linux 特意提供了一个选项--mount-proc 来解决这个问题。如果不带这个,那么看到的进程还是系统的进程信息。
3、执行 ps -ef 查看进程信息
可以看到此时进程空间内的内容已经变了,而且启动进程也变成了我们的 bash 进程。说明我们已经看不到主机上的进程空间了,我们的进程空间发生了隔离。
4、执行 exit 退出进程
四、实战操作二(Mount 隔离)
1、打开第一个 shell 窗口 A,执行命令:df -h,查看主机默认命名空间的磁盘挂载情况
2、打开一个新的 shell 窗口 B,执行 Mount 隔离命令
- --mount 表示要隔离 Mount 命名空间
- --fork 表示新建进程
3、在窗口 B 中添加新的磁盘挂载
4、在窗口 B 挂载的磁盘中添加文件
5、查看窗口 B 中的磁盘挂载信息
6、查看窗口 A 中的文件信息,可以看到窗口 B 中新建的文件和磁盘挂载在主机的窗口中并没有,说明我们实现了文件系统隔离。
data2mount 已经发生了 mount 隔离: