容器隔离技术揭秘
Docker容器并非虚拟机,而是Linux内核特性的巧妙运用.本文深入解析Namespace和Cgroups原理.
Namespace:资源隔离
Namespace让进程拥有独立的系统资源视图,就像拥有独立的操作系统.
6种Namespace类型
| Namespace | 隔离资源 | 用途 |
|---|---|---|
| PID | 进程ID | 容器内PID从1开始 |
| NET | 网络设备,端口 | 容器拥有独立IP |
| MNT | 文件系统挂载点 | 容器有自己的根目录 |
| UTS | 主机名/域名 | 容器可设独立hostname |
| IPC | 进程间通信 | 隔离共享内存,信号量 |
| USER | 用户/组ID | 容器内root映射到宿主机普通用户 |
动手实验:创建隔离的Shell
# 使用unshare命令创建新的Namespace
# -u: UTS namespace (hostname)
# -i: IPC namespace
# -n: NET namespace
# -p: PID namespace
# -m: MNT namespace
# --fork: 创建新的进程
# --mount-proc: 挂载新的proc文件系统
$ sudo unshare --uts --ipc --net --pid --fork --mount-proc /bin/bash
# 在新Namespace中
[root@new-namespace]# hostname container1
[root@new-namespace]# hostname
container1
# 查看进程,只能看到自己Namespace的进程
[root@new-namespace]# ps aux
PID USER COMMAND
1 root /bin/bash
15 root ps aux
# 退出后回到宿主机,hostname不变
[root@new-namespace]# exit
$ hostname
original-hostname
Cgroups:资源限制
Cgroups(Control Groups)限制进程能使用的资源量.
Cgroups子系统
# 查看Cgroups挂载点 $ mount | grep cgroup tmpfs on /sys/fs/cgroup type tmpfs... cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup... cgroup on /sys/fs/cgroup/memory type cgroup... cgroup on /sys/fs/cgroup/blkio type cgroup... # 主要子系统: # cpu - CPU时间分配 # memory - 内存限制 # blkio - 块设备IO限制 # pids - 进程数量限制
动手实验:限制进程CPU
# 创建cgroup并设置CPU限制 cd /sys/fs/cgroup/cpu # 创建新的cgroup sudo mkdir mygroup cd mygroup # 设置CPU使用限制(相对权重) echo 512 | sudo tee cpu.shares # 默认1024,512表示最多使用50% CPU # 设置CPU使用率硬限制(cfs_quota) echo 100000 | sudo tee cpu.cfs_quota_us # 100ms echo 100000 | sudo tee cpu.cfs_period_us # 每100ms周期 echo 50000 | sudo tee cpu.cfs_quota_us # 限制为50% # 将进程加入cgroup echo $$ | sudo tee cgroup.procs # 现在当前shell及其子进程都被限制了CPU
动手实验:限制内存
# 创建内存cgroup cd /sys/fs/cgroup/memory sudo mkdir memlimit cd memlimit # 设置内存限制为100MB echo 104857600 | sudo tee memory.limit_in_bytes # 设置swap限制(防止用swap绕过限制) echo 104857600 | sudo tee memory.memsw.limit_in_bytes # 测试:运行一个吃内存的程序 echo $$ | sudo tee cgroup.procs python3 -c "a = 'x' * 200 * 1024 * 1024" # 申请200MB # 结果:进程被OOM Killer杀死
Docker如何使用这些技术
# 查看容器的Namespace $ docker inspect nginx | grep -A20 Namespace # 查看容器在宿主机上的进程 $ docker top nginx PID USER COMMAND 12345 root nginx: master process # 查看该进程的Namespace $ ls -la /proc/12345/ns/ lrwxrwxrwx 1 root root 0 Jan 1 00:00 ipc -> ipc:[4026532278] lrwxrwxrwx 1 root root 0 Jan 1 00:00 mnt -> mnt:[4026532276] lrwxrwxrwx 1 root root 0 Jan 1 00:00 net -> net:[4026532281] lrwxrwxrwx 1 root root 0 Jan 1 00:00 pid -> pid:[4026532279] lrwxrwxrwx 1 root root 0 Jan 1 00:00 user -> user:[4026531837] lrwxrwxrwx 1 root root 0 Jan 1 00:00 uts -> uts:[4026532277] # 查看容器的Cgroups限制 $ cat /proc/12345/cgroup 12:memory:/docker/nginx-container-id 11:cpu,cpuacct:/docker/nginx-container-id ...
容器 vs 虚拟机架构对比
[虚拟机] [容器]
┌─────────────┐ ┌─────────────┐
│ App │ │ App │
├─────────────┤ ├─────────────┤
│ Libs │ │ Libs │
├─────────────┤ ├─────────────┤
│ Guest OS │ │ Namespace │
│ (完整内核) │ │ (隔离视图) │
├─────────────┤ ├─────────────┤
│ Hypervisor │ │ Cgroups │
├─────────────┤ │ (资源限制) │
│ Host OS │ ├─────────────┤
├─────────────┤ │ Host OS │
│ Hardware │ │ (共享内核) │
└─────────────┘ ├─────────────┤
│ Hardware │
└─────────────┘
总结
容器技术本质是Namespace提供隔离视图,Cgroups提供资源限制.理解这些原理,能帮助你更好地排查容器问题和优化资源使用.
