Namespace

在Linux 系统中,namespace是在内核级别以一种抽象的形式来封装系统资源的,通过将系统资 源放在不同的namespace中,来实现资源隔离的目的。设置了不同namespace的程序,就可以 享有彼此独立的一份系统资源。 Linux 中当前可用的命名空间如下:

当前系统使用到的命名空间有,cgroup ns:隔离CGroup视图。ipc ns: 隔离进程间通信资源。 mnt ns: 隔离文件系统挂载点。net ns: 隔离网络资源。pid ns: 隔离进程 ID。user ns: 隔离用户 和用户组ID。uts ns: 隔离主机名和域名。pid_for_children: 当前进程的子进程将继承的PID ns

下面通过从非管理账户user1的角度来具体理解命名空间的工作原理。

手工创建一个资源隔离的类似容器对象

(1)首先配置user1用户sudo免密,并将user1添加到docker组

配置/etc/sudoers文件

user1 ALL=(ALL) NOPASSWD:ALL

用visudo -f /etc/sudoers.d/user1

用 visudo 安全编辑器,打开 /etc/sudoers.d 目录下叫 user2 的文件,用来给 user2 用户配置 sudo 权限。

(2)运行一个conns容器

docker run = 创建并启动一个容器 --name conns = 给容器起名字:conns --rm = 容器停止后**自动删除**(干净) -i = 交互式(保持标准输入打开) -d = 后台运行(守护进程) alpine = 使用最小 Linux 镜像(只有几MB,带 rootfs) ash = 容器启动后运行的终端(轻量shell,类似bash)

(3)容器中包含一个精简完整的文件系统

(4)将conns容器的文件系统导出

(5)使用chroot命令把当前shell切换到刚创建的文件系统

sudo chroot $PWD/rootfs ash

新的文件系统好像是独立的root文件系统,但是看ip link命令显示的网络信息,但是网络信息和系统进程信息,可以发现,除了挂载点之外的网络、进程等资源在"模拟容器"中都能看到,这些资源没有隔离。

(6)回到user1,使用unshare命令隔离出一组新的命名空间的集合,unshare命令用于创建一个 新ns集合,并在其中启动一个Bash shell,实现资源隔离,这是Linux容器技术的基础之一。

词逐参数详细解释

unshare

英文意思:不共享 作用:创建一个 "独立隔离空间" (Linux 叫 Namespace 命名空间

你可以把它理解成:

我要开一个独立房间,不和外面共享任何东西!


每个开关到底做什么?(超级关键)

--mount

创建独立挂载空间

  • 你在里面挂载 overlay、分区、目录

  • 外面完全看不见、不受影响

  • 这就是你之前 overlay 挂载失败的原因!必须开这个才能挂载!


--pid

创建独立进程空间

  • 里面 ps 只能看到自己的进程

  • 看不到宿主机进程

  • 容器 PID 从 1 开始


--net

创建独立网络空间

  • 里面有独立的网卡、IP

  • 默认只有 lo 本地回环

  • 和外面网络完全隔离


--uts

独立主机名、域名

  • 你可以随便改 hostname

  • 外面不受影响


--ipc

独立进程通信

  • 隔离信号量、共享内存

  • 防止容器间互相干扰


--user

独立用户空间

  • 里面的 UID、GID 独立

  • 可以映射成 root,更安全


--map-root-user

最神奇的参数!

  • 在隔离环境里,你是 root

  • 在宿主机上,你只是普通用户

  • 权限安全隔离,不会搞坏系统


--fork

  • 新建一个子进程来运行隔离环境

  • 保证 PID 命名空间正常工作


最后 /bin/bash

进入这个隔离环境后,运行 bash 终端


执行这条命令后,你得到了什么?

你得到了一个:

✅ 独立 root 权限(安全映射)✅ 独立进程✅ 独立网络✅ 独立挂载✅ 独立主机名✅ 独立 IPC✅ 完全隔离、不会影响宿主机

(7)echo $$

输出当前 shell 进程的 PID(进程 ID)

  • echo:在标准输出上打印其参数。

  • $$:是一个特殊的 shell 变量,它扩展为当前 shell 的进程 ID(PID)。

(8)

(9)如果此时我们在其他终端上检查主机中的进程时,会看到,即使上面的用户root, 在进程之外,也是在普通用户user1的凭据下执行的

这就是PID命名空间的神奇之处,它使得一个进程具有不同的PID号,例如K8s pod场景

PID 命名空间的 "魔术"

当你加上 --pid 参数后:

  • unshare 会创建一个独立的 PID 命名空间

  • fork() 出来的新 bash 进程,在宿主机上的 PID 是 3859

  • 但在这个新的 PID 命名空间里,它看到的自己的 PID 是 1(容器里的 PID 1)

也就是说:

  • 宿主机视角:进程 PID = 3859

  • 容器视角:同一个进程,PID = 1

这就是 PID 命名空间的隔离效果。

(10)回到"模拟容器"环境,如果想要显示当前正在运行的进程,结果先显示的是主机中的所有进程

挂载 /proc 是 PID 命名空间隔离的 "最后一步":只有让容器里的 /proc 指向自己的进程列表,ps 这类工具才能真正 "看到隔离后的世界"。

挂载 /proc 前:

  • 此时 ps 读取的是宿主机全局的 /proc,所以能看到所有进程
  • 你的 PID 命名空间虽然已经创建,但 ps 工具不知道要读 "自己的 /proc

挂载 /proc 后:mount -t proc proc /proc

  • 此时 ps 读取的是新 PID 命名空间对应的 /proc
  • 只能看到自己命名空间里的进程
  • 你的 bash 进程,在这个命名空间里的 PID 变成了 1(容器里的 "init 进程")

(11)我们在容器外部创建一个网络设备并将其放入命名空间:

回到"模拟容器"环境,会看到有一个新的网络设备出现了

核心目标

你这段操作,就是给 unshare 创建的 "模拟容器",配置一个独立的虚拟网卡,让它和宿主机可以通信。

这也是 Docker/K8s 容器网络的底层原型!


二、命令拆解(从宿主机操作)

  1. 创建一对虚拟网卡(veth pair)

bash

运行

复制代码
sudo ip link add vethLocal type veth peer name vethContainer
  • 这会创建一对 "网线两端" 的虚拟网卡:

    • vethLocal:留在宿主机这边

    • vethContainer:准备放到容器里

  • 它们天生是连通的,宿主机和容器可以通过这对网卡互相通信

  1. 把网卡都 up 起来

bash

运行

复制代码
sudo ip link set vethLocal up
sudo ip link set vethContainer up
  • 让这对虚拟网卡从 DOWN 变成 UP 状态,准备好工作
  1. 找到容器进程的 PID

bash

运行

复制代码
ps -ef | grep '/bin/bash'
# 得到容器内 bash 进程的 PID:3591
  • 这个 3591 就是你 unshare 启动的隔离环境里的 bash 进程 PID

  • 它同时也属于新创建的网络命名空间

  1. 把容器端的网卡,移动到容器的网络命名空间里

bash

运行

复制代码
sudo ip link set vethContainer netns 3591
  • 关键操作:把 vethContainer 这一端,"塞" 进 PID 3591 进程所属的网络命名空间里

  • 宿主机这边就看不到 vethContainer 了,只有容器里能看到它

问题1:/proc # 挂载点:把它挂到系统的 /proc 目录上 挂载到了系统的/proc为什么 ps -ef 不是系统的进程

unshare 开了独立命名空间,从宿主机全局 /proc 里,隔离拆分出专属这个容器自己的 /proc

  1. 先分清两个关键

  2. 你开了:unshare --mount👉 拥有独立挂载命名空间 👉 你里面的所有 mount只在你这个隔离环境生效,不影响外面宿主机

  3. mount -t proc proc /proc

    • 语法里最后 /proc:是当前隔离环境内 的根下 /proc

    • 不是直接改写宿主机真实全局 /proc

  4. 为什么挂载同名目录,进程不一样

  • 没挂载前:你环境里的 /proc 继承自宿主机,里面是全系统所有进程ps 能看到宿主机所有进程

  • 执行挂载后:在你自己独立挂载视图 里,把当前目录下的 /proc,重新挂载了一份绑定当前 PID 命名空间procfs这份新proc只显示本 PID 命名空间内的进程,和宿主机进程列表切割开

  1. 最通俗比喻

整台电脑 = 一栋大楼

  • 宿主机 /proc = 大楼总监控室,看所有人

  • unshare进去 = 单独一间独立房间

  • 房间里也有一个牌子叫 /proc你在房间里重新装了只看本房间人员的小监控 虽然门牌都叫 /proc,但数据源完全不一样

  1. 一句话直击本质

路径名都是/proc,但挂载来源 + 绑定的命名空间不同

  • 旧挂载:关联全局 PID 空间 → 看全系统进程

  • 新挂载:关联新建独立 PID 空间 → 只看容器内进程

相关推荐
用户296208001304 小时前
RocketMQ Broker 0 处理延迟 32 秒排障实录:从现象到根因到修复
运维
nan madol4 小时前
openEuler部署 Kubernetes v1.35.5 集群
云原生·容器·kubernetes
木雷坞5 小时前
K8s containerd 镜像源配置:用 1ms-helper 处理 ImagePullBackOff
云原生·容器·kubernetes
散着步的码农5 小时前
frp配置内网穿透傻瓜式教程
运维
Bert.Cai5 小时前
Linux printf命令详解
linux·运维·服务器
闫记康5 小时前
Linux学习day4
linux·运维·学习
xG8XPvV5d5 小时前
GitHub Actions自动化部署全攻略
运维·自动化·github
申耀的科技观察5 小时前
【观察】戴尔科技:以“解耦化+自动化”重塑私有云,定义“云智能”进化新范式
运维·科技·自动化
pigs20185 小时前
Docker容器中Kingbase数据库授权到期更换解决方案
数据库·docker·容器