找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3162

积分

0

好友

408

主题
发表于 昨天 02:36 | 查看: 1| 回复: 0

1.起源与演进

Linux命名空间诞生于2000年代初,旨在满足多用户系统中日益增长的资源隔离需求。其发展历程可概括为:

  • 2002年(内核2.4.19):首个命名空间(挂载命名空间)出现,允许为每个进程创建独立的挂载点视图
  • 2008年:逐步扩展,加入PID命名空间(进程隔离)、网络命名空间和IPC命名空间
  • 2013年:Docker的兴起标志着重大转折点,它结合命名空间与cgroups,创造了轻量级、可快速部署的容器,推动了应用开发和部署方式的变革
  • 现今:命名空间已成为Kubernetes等编排技术的核心基础,支撑着生产环境中成千上万个容器的协调运行

2.核心概念与基本原理

命名空间本质上是一种作用域隔离机制——类似于C++或Python中的命名空间概念,但作用于系统资源层面。它改变了进程对特定系统资源的“视角”,使得不同命名空间内的进程看到不同的资源视图。

# 关键特性:

(1)继承性:子进程继承父进程的所有命名空间副本
(2)生命周期:当命名空间中最后一个进程终止时,内核会自动销毁该命名空间
(3)架构类型

  • 层级架构:子命名空间与父命名空间存在映射关系(如PID命名空间)
  • 非层级架构:资源完全独立,无映射关系(如UTS命名空间)

父子命名空间关系示意图

3. 八大命名空间详解

3.1 UTS命名空间(UNIX Time-sharing System Namespace)

(1)核心功能:隔离主机名和域名系统信息
(2)原理与特性
UTS命名空间允许每个容器拥有独立的主机名和域名,使得在容器内部修改这些信息不会影响宿主机或其他容器。这是最轻量级的命名空间之一,主要用于提供容器身份标识。
(3)实践示例

# 创建UTS命名空间
[root@yyzcdb81 ~]# unshare --uts /bin/bash

# 修改主机名(只影响本命名空间)
[root@yyzcdb81 ~]# hostname mysubhost

# 验证,输出为mysubhost
[root@yyzcdb81 ~]# hostname
mysubhost
[root@yyzcdb81 ~]# 

然后再打开一个新终端,查看主机名为原主机名:

[root@yyzcdb81 ~]# hostname
yyzcdb81
[root@yyzcdb81 ~]# 

也可以在上面终端中退出后查看:

[root@yyzcdb81 ~]# exit
exit
[root@yyzcdb81 ~]# hostname
yyzcdb81
[root@yyzcdb81 ~]# 

3.2 PID命名空间(Process ID Namespace)

(1)核心功能:隔离进程ID编号空间
(2)原理与特性:PID命名空间为进程提供独立的PID编号系统,不同命名空间中的进程可以有相同的PID。每个PID命名空间都有自己的PID 1进程(类似init进程),负责回收孤儿进程。
(3)实践示例

创建一个新的PID命名空间,然后查看当前进程:

[root@yyzcdb81 ~]# unshare --pid --fork --mount-proc /bin/bash
[root@yyzcdb81 ~]# 
[root@yyzcdb81 ~]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.4  0.0 116968  3344 pts/0    S    11:10   0:00 /bin/bash
root         31  0.0  0.0 155448  1852 pts/0    R+   11:10   0:00 ps aux
[root@yyzcdb81 ~]# 

新建PID命名空间中的进程列表

再从宿主机或另一个新终端查看,它显示真实的宿主PID:

[root@yyzcdb81 ~]# pstree -p | grep unshare
           |-sshd(1091)-+-sshd(75769)---bash(75772)---unshare(84850)---bash(84851)
[root@yyzcdb81 ~]# 

宿主机视角下的进程树

3.3 网络命名空间(Network Namespace)

(1)核心功能:提供完全隔离的网络栈
(2)原理与特性
网络命名空间为进程提供独立的网络环境,包括:

  • 网络接口(物理/虚拟)
  • IP地址和路由表
  • 防火墙规则(iptables/nftables)
  • 套接字列表
    (3)实践示例
# 创建新的网络命名空间
ip netns add netns1

# 进入网络命名空间
ip netns exec netns1 bash

# 查看网络接口
ip link show
# 仅显示lo(环回接口)

# 启用环回接口
ip link set lo up

# 创建veth对连接命名空间
ip link add veth0 type veth peer name veth1
ip link set veth1 netns netns1

3.4 挂载命名空间(Mount Namespace)

(1)核心功能:隔离文件系统挂载点视图
(2)原理与特性
挂载命名空间允许每个容器拥有独立的文件系统视图,包括:

  • 挂载点列表
  • 文件系统类型
  • 挂载选项
  • 传播类型(shared, private, slave, unbindable)
    (3)实践示例
# 创建新的挂载命名空间
unshare --mount /bin/bash

# 创建私有挂载点
mkdir /mnt/private
mount --bind /home/user/data /mnt/private

# 查看当前挂载点
findmnt -o TARGET,PROPAGATION
# 容器内可见新挂载点,宿主机不可见

# 设置挂载传播类型
mount --make-private /mnt/private   # 私有挂载
mount --make-shared /mnt/shared     # 共享挂载
mount --make-slave /mnt/slave       # 从属挂载

# 补充:传播类型对比

类型 描述 容器应用场景
private 挂载事件不传播 默认的容器挂载
shared 挂载事件双向传播 共享存储卷
slave 只接收不发送事件 从主机挂载到容器
unbindable 不可绑定挂载 临时文件系统

3.5 用户命名空间(User Namespace)

(1)核心功能:隔离用户和组ID映射
(2)原理与特性
用户命名空间允许在容器内部以root身份运行进程,而在宿主机上以普通用户身份运行。这是容器安全的基础,实现了权限提升的虚拟化。
(3)实践示例

# 无特权创建用户命名空间
unshare -r /bin/bash  # -r 表示映射当前用户为命名空间内的root

# 验证用户身份
id
# 容器内: uid=0(root) gid=0(root)
# 宿主机: uid=1000(user) gid=1000(user)

# 查看映射关系
cat /proc/self/uid_map
# 输出: 0 1000 1  (容器内0映射到宿主机1000)

# 创建嵌套映射
echo “0 1000 1000” > /proc/self/uid_map
echo “0 1000 1000” > /proc/self/gid_map

3.6 Cgroup命名空间(Cgroup Namespace)

(1)核心功能:隔离控制组视图
(2)原理与特性
Cgroup命名空间隐藏宿主机cgroup层次结构,为容器提供简化的cgroup视图。这使容器认为自己是资源管理的根,增强了资源隔离的透明性。
(3)实践示例

查看宿主机cgroup视图:

[root@yyzcdb81 ~]# cat /proc/self/cgroup
11:blkio:/
10:hugetlb:/
9:perf_event:/
8:devices:/user.slice
7:memory:/
6:net_prio,net_cls:/
5:pids:/user.slice
4:cpuacct,cpu:/
3:cpuset:/
2:freezer:/
1:name=systemd:/user.slice/user-0.slice/session-7424.scope
[root@yyzcdb81 ~]# 

宿主机cgroup文件内容

3.7 IPC命名空间(IPC Namespace)

(1)核心功能:隔离进程间通信资源
(2)原理与特性
IPC命名空间隔离System V IPC对象和POSIX消息队列,包括:

  • 共享内存段(shared memory)
  • 信号量数组(semaphores)
  • 消息队列(message queues)
    (3)实践示例

在宿主机内查看共享内存段:

[root@yyzcdb81 ~]# ipcs -m

------------ 共享内存段 --------------
键        shmid      拥有者  权限     字节     nattch     状态      
0x00000000 12         oracle     600        8900608    114                     
0x00000000 13         oracle     600        2449473536 57                      
0x00000000 14         oracle     600        7876608    57                      
0xf11181d8 15         oracle     600        16384      57                      

[root@yyzcdb81 ~]# 

ipcs命令查看共享内存段

3.8 时间命名空间(Time Namespace)

(1)核心功能
时间命名空间的主要功能是隔离系统时钟视图,为每个命名空间提供独立的时钟偏移量,从而实现系统时间层面的虚拟化与隔离。
(2)原理与特性
该命名空间基于 Linux 5.6+ 内核实现,允许在命名空间级别对两类系统时钟进行偏移设置:

  • 调整单调时钟(CLOCK_MONOTONIC):影响系统启动后的时间流逝感知
  • 调整启动时间(CLOCK_BOOTTIME):改变系统运行时间统计的起点
    其主要应用场景包括容器/虚拟机实时迁移、时间敏感型任务调试,以及为进程组设置独立时间环境而不影响主机系统。该机制虽日常使用尚未普及,但标志着系统资源隔离体系的进一步完善。

4.实战:使用 Linux 命名空间从零构建容器

下面在不使用任何容器运行时的情况下创建一个最小化的容器,目标是手动组装命名空间,并在一个类似容器的隔离环境中运行简单进程。这有助于更深入地理解容器引擎在其友好用户界面之下的工作原理。

4.1 创建根文件系统

容器需要自己的文件系统,在本演示中,我们将使用 BusyBox 作为最小的根文件系统。

user@host: ROOTFS=“$HOME/rootfs”
user@host: mkdir -p “$ROOTFS”/{bin,proc,sys,dev}
user@host: cp /usr/bin/busybox “$ROOTFS/bin/”
user@host: for cmd in sh mount umount ls mkdir ps ping hostname; do
    ln -sf busybox “$ROOTFS/bin/$cmd”
done

这样就建立了一个包含基础二进制文件的最小文件系统。实际上,也可以使用 Debian、Ubuntu 或 Alpine 的根文件系统。核心思路是创建一个包含 /bin/proc/sys/dev 以及可选 /etc 的目录结构。

4.2 启动一组新的命名空间

下面将组合Mount、PID、UTS、IPC、网络和用户命名空间,这会创建一个类似容器的环境:

user@host: sudo unshare --mount --pid --uts --ipc --net --fork /bin/bash 

在这个新 shell 中,我们将在全新的命名空间中操作,在此用户命名空间内拥有 root 权限,拥有独立的 PID 树,且挂载操作不会影响主机。

4.3 准备挂载命名空间

首先,在根文件系统中挂载一个新的 proc 实例:

root@host: mount --bind “$ROOTFS/dev” “$ROOTFS/dev”
root@host: mount -t proc proc “$ROOTFS/proc”
root@host: mount -t sysfs sys “$ROOTFS/sys”

为 UTS 命名空间设置主机名:

root@host: hostname isolated-box

启动环回网络(即使在最小化演示中,可用的环回接口也很重要):

ip link set lo up

这为命名空间提供了基础网络功能。外部网络则需要虚拟以太网对或 macvlan 接口,这些通常由容器运行时自动配置。

使用 chroot 切换到新的根文件系统:

root@host: chroot “$ROOTFS” /bin/sh 

这样,现在已拥有一个隔离的文件系统环境,其中 /proc/sys/dev 均已正确挂载,在此环境中的所有挂载更改都不会影响主机。

4.4 在命名空间内启动 PID 1 进程

创建一个充当 PID 1 的新 shell:

exec /bin/bash

现在运行:

ps aux

将只看到一个非常小的进程树,这正是真实容器 PID 命名空间的样子:

手动构建容器中的进程列表

至此,我们已经构建了一个最小化的容器,它拥有自己的根文件系统、独立的网络命名空间、环回接口和主机名。这正是容器引擎所创建的环境,但它们自动化了挂载传播、网络配置、UID 映射、镜像分层、cgroup 资源限制和生命周期管理等功能。

理解这些底层机制,能帮助我们在使用 Docker 或 Kubernetes 时更清晰地洞察容器内部的运作方式,也是深入操作系统内核和虚拟化技术的重要基础。如果你在探索这些底层技术时希望找到一个可以交流讨论的平台,不妨看看云栈社区,那里聚集了不少对底层技术充满热情的开发者。




上一篇:市值归一化订单流因子:提升信噪比与知情交易识别
下一篇:2026年自考避雷指南:盘点5类需谨慎报考的高难度专业
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-6 06:10 , Processed in 0.283265 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表