Docker底层-User Namespace

复制代码
root@LAPTOP-LU4HDAFV:~# id
uid=0(root) gid=0(root) groups=0(root),987(docker)
root@LAPTOP-LU4HDAFV:~# echo $$
285399
root@LAPTOP-LU4HDAFV:~# cat /proc/$$/uid_map
         0          0 4294967295
root@LAPTOP-LU4HDAFV:~# 

UID/GID 详解

基本概念

  • UID (User ID):用户标识符,Linux 用数字标识用户
  • GID (Group ID):组标识符,Linux 用数字标识用户组

    ┌─────────────────────────────────────────────────────────┐
    │ Linux 用户系统结构 │
    │ │
    │ ┌──────────────────────────────────────────────────┐ │
    │ │ 用户名 (Username) │ │
    │ │ │ │
    │ │ 例如:alice, bob, root │ │
    │ │ (人类可读的名称) │ │
    │ └──────────────────────────────────────────────────┘ │
    │ │ │
    │ │ 映射关系 │
    │ ↓ │
    │ ┌──────────────────────────────────────────────────┐ │
    │ │ UID (User ID) │ │
    │ │ │ │
    │ │ 例如:1000, 1001, 0 │ │
    │ │ (系统内部使用的数字) │ │
    │ └──────────────────────────────────────────────────┘ │
    │ │ │
    │ │ 属于某个组 │
    │ ↓ │
    │ ┌──────────────────────────────────────────────────┐ │
    │ │ GID (Group ID) │ │
    │ │ │ │
    │ │ 例如:1000, 1001, 0 │ │
    │ │ (用户所属组的数字) │ │
    │ └──────────────────────────────────────────────────┘ │
    │ │
    │ 系统实际使用 UID/GID,而不是用户名! │
    └─────────────────────────────────────────────────────────┘

为什么需要 UID/GID?

  1. 性能:数字比较更快
  1. 唯一性:每个用户有唯一 UID
  1. 系统内部:内核使用数字,用户名只是映射

    ┌─────────────────────────────────────────────────────────┐
    │ 用户名 vs UID │
    │ │
    │ 人类视角: │
    │ whoami │ │ alice │ │ │ │ 系统视角: │ │ id │
    │ uid=1000(alice) gid=1000(alice) │
    │ │
    │ 内核实际使用: │
    │ UID: 1000 ← 内核只认识这个数字 │
    │ GID: 1000 ← 内核只认识这个数字 │
    │ │
    │ 用户名 "alice" 只是方便人类记忆的别名! │
    └─────────────────────────────────────────────────────────┘

User Namespace 工作原理详解

核心概念:UID/GID 映射

User Namespace 通过映射表将 Namespace 内的 UID/GID 映射到主机上的真实 UID/GID。

复制代码
┌─────────────────────────────────────────────────────────┐
│  User Namespace 的 UID/GID 映射机制                     │
│                                                          │
│  ┌──────────────────────────────────────────────────┐  │
│  │ 主机上的真实用户                                  │  │
│  │                                                  │  │
│  │  用户:alice                                     │  │
│  │  UID: 1000  (主机上的真实 UID)                  │  │
│  │  GID: 1000  (主机上的真实 GID)                  │  │
│  │                                                  │  │
│  │  执行命令:                                       │  │
│  │  unshare --user --map-root-user /bin/bash        │  │
│  │         │                                        │  │
│  │         └─────────┐                              │  │
│  └───────────────────┼──────────────────────────────┘  │
│                      │                                  │
│                      │ 创建新的 User Namespace           │
│                      ↓                                  │
│  ┌──────────────────────────────────────────────────┐  │
│  │ User Namespace 内部                               │  │
│  │                                                  │  │
│  │  ┌──────────────────────────────────────────┐   │  │
│  │  │ UID/GID 映射表                          │   │  │
│  │  │                                        │   │  │
│  │  │ Namespace UID  →  主机 UID             │   │  │
│  │  │ ──────────────    ─────────            │   │  │
│  │  │      0        →     1000               │   │  │
│  │  │      1        →     1001               │   │  │
│  │  │      2        →     1002               │   │  │
│  │  │    ...        →     ...                │   │  │
│  │  │   65534       →    106534              │   │  │
│  │  └──────────────────────────────────────────┘   │  │
│  │                                                  │  │
│  │  进程在 Namespace 内看到:                       │  │
│  │  $ id                                            │  │
│  │  uid=0(root) gid=0(root) groups=0(root)         │  │
│  │                                                  │  │
│  │  但实际上映射到主机的 UID 1000!                 │  │
│  └──────────────────────────────────────────────────┘  │
│                                                          │
│  关键:Namespace 内的 root (uid=0) 映射到主机的 UID 1000 │
└─────────────────────────────────────────────────────────┘

为什么不需要 root 权限?

Linux 内核允许普通用户创建 User Namespace(自 Linux 3.8 起),原因:

  1. 安全性:Namespace 内的 root 权限被限制在 Namespace 内
  1. 隔离性:无法影响主机上的其他进程
  1. 映射机制:通过 UID/GID 映射表控制权限

    ┌─────────────────────────────────────────────────────────┐
    │ 权限检查流程 │
    │ │
    │ 进程在 User Namespace 内执行操作: │
    │ │
    │ 1. 访问 Namespace 内的文件 │
    │ ↓ │
    │ 检查:Namespace 内的 UID (0) │
    │ ✓ 允许(在 Namespace 内是 root) │
    │ │
    │ 2. 访问主机上的文件 │
    │ ↓ │
    │ 检查:映射后的主机 UID (1000) │
    │ ✗ 拒绝(主机上不是 root) │
    │ │
    │ 3. 影响主机上的其他进程 │
    │ ↓ │
    │ 检查:映射后的主机 UID (1000) │
    │ ✗ 拒绝(主机上不是 root) │
    │ │
    │ 结论:Namespace 内的 root 权限被限制在 Namespace 内! │
    └─────────────────────────────────────────────────────────┘

    ┌─────────────────────────────────────────────────────────┐
    │ 1. 普通用户执行命令 │
    │ │
    │ unshare --user --map-root-user /bin/bash │ │ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ 2. 内核创建新的 User Namespace │ │ │ │ │ │ │ │ • 分配新的 Namespace ID │ │ │ │ • 创建新的进程(bash) │ │ │ │ • 设置初始 UID/GID 映射 │ │ │ └──────────────────────────────────────────────────┘ │ │ │ │ │ ↓ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ 3. --map-root-user 自动设置映射表 │ │ │ │ │ │ │ │ /proc/self/uid_map: │ │ │ │ 0 <当前用户UID> 1 │ │ │ │ │ │ │ │ /proc/self/gid_map: │ │ │ │ 0 <当前用户GID> 1 │ │ │ └──────────────────────────────────────────────────┘ │ │ │ │ │ ↓ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ 4. 进程在 Namespace 内运行 │ │ │ │ │ │ │ │ id │ │
    │ │ uid=0(root) gid=0(root) │ │
    │ │ │ │
    │ │ 但实际权限检查时: │ │
    │ │ • Namespace 内操作 → 使用 UID 0 │ │
    │ │ • 主机操作 → 使用映射后的 UID 1000 │ │
    │ └──────────────────────────────────────────────────┘ │
    │ │ │
    │ ↓ │
    │ ┌──────────────────────────────────────────────────┐ │
    │ │ 5. 权限检查机制 │ │
    │ │ │ │
    │ │ 访问 Namespace 内资源: │ │
    │ │ ✓ 使用 Namespace UID (0) → 有 root 权限 │ │
    │ │ │ │
    │ │ 访问主机资源: │ │
    │ │ ✗ 使用主机 UID (1000) → 只有普通用户权限 │ │
    │ └──────────────────────────────────────────────────┘ │
    └─────────────────────────────────────────────────────────┘

相关推荐
mennekes10 分钟前
临时用电线路标识:插头颜色、钟面标识配套规范
运维·网络·科技·安全·制造
程序猿老A2 小时前
轻量云服务器总是卡,内存占比高?
运维·服务器
一只鹿鹿鹿3 小时前
智算算力、AI-芯片与产品解析(PPT文件)
大数据·运维·网络·人工智能·物联网·1024程序员节
Kobebryant-Manba4 小时前
C/S和B/S结构
运维·服务器
是枚小菜鸡儿吖5 小时前
Home Assistant跨品牌智能家居教程:Docker部署、米家接入、vivo桥接与远程访问
docker·容器·智能家居
AI_Lab015 小时前
宝塔用了两年,有没有必要换成轻量方案?
linux·运维·服务器
众壹新能源科技5 小时前
逆变器直流开关柜温度监测与预防:红外巡检发现3个120度热点
运维·人工智能·自动化
by209995 小时前
Linux GDB 调试与 CGDB 使用
linux·运维·服务器·经验分享
小Ti客栈5 小时前
Netty 零拷贝原理与实战
运维·服务器·网络
ai_coder_ai6 小时前
AIOps 智能运维架构设计及其应用
运维