【Linux】资源隔离机制 — 命名空间(Namespace)详解

【Linux】资源隔离机制 — 命名空间(Namespace)详解

文章目录

一、什么是Namespace1.1 Namespace 的作用与原理1.2 命名空间的操作1.3 常见命名空间1.4 如何隔离两个容器中的进程

二、相关命令2.1 dd 命令2.2 mkfs 命令2.3 df 命令2.4 mount 命令2.5 unshare 命令

三、实际操作3.1 PID 隔离3.2 Mount 隔离

一、什么是Namespace

Namespace(命名空间) 是 Linux 内核提供的一种资源隔离机制。

它允许将系统资源分隔成多个虚拟的“空间”,每个命名空间内的进程只能访问该命名空间下的资源,而不能访问其他命名空间中的资源。

通过 namespace,不同的进程可以在同一个操作系统内共享硬件资源,但又能感知到各自独立的环境。具体来说,namespace 可以将一个或多个进程的资源隔离到同一个命名空间中,确保这些进程只能看到和操作该命名空间内的资源。

1.1 Namespace 的作用与原理

Linux namespaces 是对全局系统资源的一种封装与隔离。处于不同 namespace 的进程拥有独立的全局系统资源。修改某个 namespace 中的资源(如网络、PID、文件系统等)只会影响该命名空间中的进程,不会影响其他命名空间中的进程。

例如:

一个进程可能在一个独立的网络命名空间中运行,无法看到其他命名空间的网络接口和路由。另一个进程可能在不同的用户命名空间中运行,从而拥有不同的用户ID和权限。

1.2 命名空间的操作

Linux 提供了几个系统调用来操作命名空间,常用的 API 包括:

clone():创建新进程并指定要使用的命名空间。setns():使当前进程加入指定的命名空间。unshare():将当前进程从现有的命名空间中分离出来,并创建新的命名空间。

在使用这些 API 时,通常需要指定一些参数来选择隔离的资源类型。

例如,可以通过按位或 | 组合多个命名空间类型来同时隔离多个资源。

1.3 常见命名空间

下面是一些常见的命名空间及其对应的系统调用参数和功能:

命名空间系统调用参数被隔离的全局系统资源引入内核版本UTSCLONE_NEWUTS主机名和域名2.6.19IPCCLONE_NEWIPC信号量、消息队列和共享内存(进程间通信)2.6.19PIDCLONE_NEWPID进程编号2.6.24NetworkCLONE_NEWNET网络设备、网络栈、端口等2.6.29MountCLONE_NEWNS文件系统挂载点2.4.19UserCLONE_NEWUSER用户和用户组3.8

下面是上面的命名空间容器下的隔离效果:

UTS:每个容器可以拥有独立的主机名和域名,容器内的进程只看到自己的 hostname,互不干扰。IPC:同一个 IPC 命名空间内的进程可以相互通信,而不同的 IPC 命名空间中的进程则无法通信。PID:每个 PID 命名空间内的进程有独立的进程编号,因此每个容器可以有一个 PID 为 1 的 root 进程。Network:每个容器拥有独立的网络环境,包括网络设备、IP 地址、路由表、端口号等。容器内的网络与主机或其他容器的网络互相隔离。Mount:每个容器拥有独立的文件系统层次结构,容器内的进程只能看到自己的文件系统挂载点。User:每个容器内的进程可以拥有独立的用户和组 ID,与主机或其他容器的用户和组 ID 隔离。

1.4 如何隔离两个容器中的进程

在容器化环境中,如果我们要隔离容器 A 和容器 B 中的进程,需要从以下几个方面进行资源隔离:

PID 隔离:

容器内的进程需要拥有独立的 PID(进程编号)。通过 PID 命名空间,容器 A 和容器 B 内的进程将有独立的 PID 系统,彼此无法相互识别或干扰。 IPC 隔离:

容器 A 和容器 B 中的进程不能共享信号量、消息队列或共享内存等 IPC 资源。通过 IPC 命名空间,每个容器内的进程只能与同一容器中的进程进行通信,而无法访问其他容器的 IPC 资源。 Mount 隔离:

容器内的文件系统应该是独立的,这样容器 A 的进程不能访问容器 B 的文件系统。通过 Mount 命名空间,每个容器的文件系统挂载点是独立的,不同容器之间的文件系统层次结构互不干扰。 网络隔离:

容器 A 和容器 B 的网络应该是独立的,容器 A 无法访问容器 B 的网络接口、端口或网络资源。通过 Network 命名空间,每个容器可以拥有独立的网络设备、IP 地址、路由表等资源。 主机名隔离:

每个容器应该有自己的主机名和域名,这样容器 A 内的进程无法读取容器 B 的主机名。通过 UTS 命名空间,每个容器可以有独立的主机名和域名。

二、相关命令

2.1 dd 命令

Linux 下 dd 命令用于读取、转换并输出数据。

dd 可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准输出;

语法

dd OPTION

参数 / 选项:

参数说明if=文件名输入文件名,默认为标准输入(指定源文件)。of=文件名输出文件名,默认为标准输出(指定目标文件)。ibs=bytes一次读取 bytes 个字节,即指定输入块的大小。obs=bytes一次输出 bytes 个字节,即指定输出块的大小。bs=bytes同时设置读取和输出的块大小为 bytes 个字节。cbs=bytes一次转换 bytes 个字节,即指定转换缓冲区的大小。skip=blocks从输入文件开头跳过 blocks 个块后再开始复制。seek=blocks从输出文件开头跳过 blocks 个块后再开始复制。count=blocks仅复制 blocks 个块,块大小由 ibs 指定。conv=<关键字>文件转换方式,支持以下关键字:ascii:将 EBCDIC 转换为 ASCIIebcdic:将 ASCII 转换为 EBCDICibm:将 ASCII 转换为 IBM 格式的 EBCDICblock:将每行转换为长度为 cbs 的块,短于 cbs 的部分用空格填充unblock:使每行的长度为 cbs,短于 cbs 的部分用空格填充lcase:将大写字符转换为小写字符ucase:将小写字符转换为大写字符swap:交换输入中的每对字节noerror:出错时不停止继续执行notrunc:不截断输出文件sync:将每个输入块填充到 ibs 字节,不足部分用 NUL 字符补齐--help显示帮助信息--version显示版本信息

案例

# 生成一个大小为 80MB 的空白镜像文件 image.img,内容是 0 字节。

dd if=/dev/zero of=image.img bs=8k count=10240

# 将 testfile 文件中的所有英文字母转换为大写,然后转成为 testfile_1 文件

dd if=testfile_2 of=testfile_1 conv=ucase

2.2 mkfs 命令

mkfs 命令 用于 在设备上创建 Linux 文件系统,即格式化,比如我们使用 U 盘的时候可以格式化。

语法

mkfs [-V] [-t fstype] [fs-options] filesys [blocks]

参数解释

-t fstype:指定要建立何种文件系统;如 ext3, ext4filesys :指定要创建的文件系统对应的设备文件名;

blocks:指定文件系统的磁盘块数。

-V : 详细显示模式

fs-options:传递给具体的文件系统的参数

案例

# 将 sda6 分区格式化为 ext4 格式

mkfs -t ext4 /dev/sda6

# 格式化镜像文件为 ext4

mkfs -t ext4 ./image.img

2.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:显示文件系统的形式

案例

# 查看磁盘使用情况

df -h

# 查看磁盘的系统类型

df -Th

2.4 mount 命令

mount 命令用于加载文件系统到指定的加载点。也常用于挂载光盘,使我们可以访问光盘中的数据,因为将光盘插入光驱中后,Linux 并不会自动挂载,必须使用 mount 命令来手动完成挂载。

Linux 系统下不同目录可以挂载不同分区和磁盘设备,它的目录和磁盘分区是分离的,可以自由组合(通过挂载)不同的目录数据可以跨越不同的磁盘分区或者不同的磁盘设备。

挂载的实质是为磁盘添加入口(挂载点)。

语法

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: 挂载点的目录 案例

# 将 /dev/hda1 挂在 /mnt 之下。

mount /dev/hda1 /mnt

# 将镜像挂载到/mnt/testext4 下面,需要确保挂载点(目录)存在

mkdir -p /mnt/testext4

mount ./fdimage.img /mnt/testext4

2.5 unshare 命令

unshare 命令用于启动一个新的进程并与当前进程分离不同的命名空间。

语法

unshare [options] program [arguments]

参数

参数含义-i, --ipc不共享 IPC 空间-m, --mount不共享 Mount 空间-n, --net不共享 Net 空间-p, --pid不共享 PID 空间-u, --uts不共享 UTS 空间-U, --user不共享用户-V, --version查看版本信息--fork执行 unshare 的进程 fork 一个新的子进程,在子进程里执行传入的参数--mount-proc执行子进程前,将 proc 文件系统优先挂载过去

案例

# 启动一个完全隔离的进程,既有独立的网络、进程 ID 和挂载空间

unshare --net --pid --mount /bin/bash

三、实际操作

3.1 PID 隔离

首先在主机 shell 上执行 ps -ef 命令,可以查看进程列表,启动进程PID 为1的是init进程;

我们另开一个shell,新建一个PID的Namespace,执行下面的命令,进行进程隔离:

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

--fork:新建了一个 bash 进程,如果不创建新进程,新的命名空间会将 unshare 的 PID 作为新的空间的父进程。但这个 unshare 进程并不在新的命名空间中,就会报错:Cannot allocate memory。

--pid:表示进程通过 PID 隔离,而其他命名空间并没有隔离。

--mount-proc:在 Linux 下,每个进程都有一个对应的 /proc/PID 目录,该目录包含了大量有关当前进程的信息。对于一个 PID 命名空间而言,/proc 目录只包含当前命名空间及其所有子命名空间中的进程信息。

创建一个新的 PID 命名空间后,如果想让子进程中的 top、ps 等依赖 /proc 文件系统的命令正常工作,需要挂载 /proc 文件系统。文件系统隔离是由 mount 命名空间管理的,因此 Linux 提供了 --mount-proc 选项来解决该问题。如果不带这个选项,我们仍然会看到宿主机的进程信息,而不是当前命名空间中的进程信息。

执行 ps -ef 查看进程信息,可以观察到进程空间内的内容已经更改,启动进程变成了bash进程

执行exit命令退出命名空间exit

3.2 Mount 隔离

打开第一个 shell 窗口 A,执行命令, df -h ,查看主机默认命名空间的磁盘挂载情况

打开新的 shell 窗口 B,执行 Mount 隔离命令:

unshare --mount --fork /bin/bash

mkdir -p /data/tmpmount

在窗口B 上 添加磁盘挂载:

dd if=/dev/zero of=image.img bs=8k count=10240

mkfs -t ext4 ./image.img

mount ./image.img /data/tmpmount

在窗口B挂载的磁盘 添加文件:

echo "Hello world!" > /data/tmpmount/hello.txt

使用 df -h 命令查看窗口 B 中的磁盘挂载信息:

分别查看磁盘A、B的文件信息:

磁盘A:

磁盘B:

再次查看窗口A的磁盘挂在信息,输出结果与第一次一致,根据磁盘挂载信息与文件信息,可以看出磁盘B中的文件在磁盘A中不存在,即成功实现了文件隔离。

窗口B通过 exit 命令进行退出

exit

关于文件的生命周期:

如果窗口B在新的命名空间中创建了文件,它们的生命周期将由该命名空间控制。当执行 exit 命令时,窗口B的 Bash 进程退出并终止,新的命名空间也会被销毁。新命名空间中的所有挂载和文件都会被销毁,因为命名空间的生命周期与执行该命令的进程相关。当进程退出时,整个命名空间也会被清理,从而删除其中的所有文件。

相关推荐

魔兽要塞船坞怎么开启
365bet平台规则

魔兽要塞船坞怎么开启

📅 07-31 👁️ 1475
德国对南斯拉夫:世界杯历史上的经典对决回顾
365bet滚球网站

德国对南斯拉夫:世界杯历史上的经典对决回顾

📅 07-12 👁️ 9047
张韶涵被曝买太平洋小岛!价格近亿还配别墅?国内国外皆有房产
解决iPhone App Store下载APP失败的方法
365APP

解决iPhone App Store下载APP失败的方法

📅 10-03 👁️ 8138