容器 = 命名空间 + Cgroups + 文件系统
容器技术的本质是通过 命名空间(Namespaces)、控制组(Cgroups) 和 文件系统(Filesystem) 三大核心机制,实现进程的 资源隔离、资源限制 和 环境封装。以下是三者协同工作的详细说明:
一、命名空间(Namespaces)—— 资源隔离
1. 作用
命名空间是 Linux 内核提供的资源隔离机制,为容器提供独立的系统视图,确保容器内的进程无法感知或影响其他容器及宿主机资源。
2. 关键命名空间
- PID 命名空间:隔离进程 ID,容器内进程的 PID 独立于宿主机。
- Mount 命名空间:隔离文件系统挂载点,容器拥有独立的根目录和挂载树。
- Network 命名空间:隔离网络设备、IP 地址、端口和路由表,容器拥有独立网络栈。
- UTS 命名空间:隔离主机名和域名,容器可自定义
hostname
。 - IPC 命名空间:隔离进程间通信(消息队列、信号量等)。
- User 命名空间:隔离用户和用户组 ID,允许容器内以 root 运行而宿主机非特权。
3. 示例
当运行一个 Docker 容器时,Docker 引擎会为容器创建所有上述命名空间:
# 查看容器的命名空间
docker inspect <容器ID> | grep -i pid
# 输出示例: "Pid": 1234
ls -l /proc/1234/ns # 显示容器进程的命名空间信息
二、控制组(Cgroups)—— 资源限制
1. 作用
Cgroups 是 Linux 内核功能,用于限制、统计和隔离进程组的资源使用(如 CPU、内存、磁盘 I/O、网络带宽等),防止容器耗尽宿主机资源。
2. 核心子系统
- cpu:限制 CPU 使用时间(如
cpu.shares
设置权重)。 - memory:限制内存使用(如
memory.limit_in_bytes
设置上限)。 - blkio:限制块设备 I/O(如磁盘读写速率)。
- devices:控制设备访问权限。
- net_cls:标记网络数据包,配合流量控制工具(如 tc)限制网络带宽。
3. 示例
Docker 容器启动时,自动创建 Cgroup 规则:
# 运行一个限制内存为 512MB 的容器
docker run -it --memory=512m ubuntu /bin/bash
# 查看容器的 Cgroup 配置
cat /sys/fs/cgroup/memory/docker/<容器ID>/memory.limit_in_bytes
# 输出:536870912(即 512MB)
三、文件系统(Filesystem)—— 环境封装
1. 作用
容器需要独立的文件系统环境,包括应用程序、依赖库和配置文件。通过 联合文件系统(UnionFS) 实现镜像的 分层存储 和 写时复制(Copy-on-Write),优化存储效率和启动速度。
2. 常用文件系统
- OverlayFS:现代容器默认使用,支持多只读层和一个可写层。
- AUFS:早期 Docker 使用的联合文件系统。
- devicemapper:基于块设备的存储驱动(适用于 CentOS/RHEL)。
- Btrfs/ZFS:支持高级功能的文件系统(快照、压缩等)。
3. 分层结构
- 镜像层(只读):基础镜像(如
ubuntu:22.04
)和应用依赖层。 - 容器层(可写):容器运行时新增的文件和修改。
- 示例:
# 查看 Docker 镜像的分层结构 docker history ubuntu:22.04
4. 示例
启动容器时,Docker 挂载 OverlayFS:
# 查看容器的挂载信息
docker inspect <容器ID> | grep MergedDir
# 输出示例: "MergedDir": "/var/lib/docker/overlay2/.../merged"
# 进入容器文件系统
ls /var/lib/docker/overlay2/<层ID>/merged
四、三者协同工作原理
1. 容器启动流程
- 创建命名空间:为容器分配独立的 PID、Mount、Network 等命名空间。
- 挂载文件系统:基于镜像层和可写层构建容器的根文件系统(如 OverlayFS)。
- 设置 Cgroups:为容器进程分配资源限制(CPU、内存等)。
- 启动进程:在隔离环境中运行应用程序(如
/bin/bash
)。
2. 运行时交互
- 隔离性:命名空间确保容器进程、网络、文件系统等资源独立。
- 资源控制:Cgroups 动态监控和限制容器的资源使用。
- 环境一致性:联合文件系统保证容器内依赖和配置与镜像一致。
3. 示例:Docker 容器的生命周期
# 1. 拉取镜像(文件系统层下载)
docker pull nginx:alpine
# 2. 启动容器(创建命名空间 + Cgroups)
docker run -d --name my-nginx --memory=1g nginx:alpine
# 3. 进入容器(隔离的进程、网络、文件系统)
docker exec -it my-nginx /bin/sh
# 4. 停止容器(释放资源)
docker stop my-nginx
五、总结
组件 | 核心功能 | 类比 |
---|---|---|
命名空间 | 资源隔离(进程、网络、文件系统等) | 公寓的独立房间 |
Cgroups | 资源限制(CPU、内存、I/O 等) | 房间的水电配额 |
文件系统 | 环境封装(镜像分层、写时复制) | 房间的家具和装修(标准化+个性化) |
通过三者的结合,容器实现了:
- 轻量级:共享宿主机内核,无需虚拟化硬件。
- 一致性:镜像保证环境一致,解决“开发-生产环境差异”。
- 安全性:隔离性 + 资源限制,避免单个容器影响整体系统。
理解这一底层机制,有助于优化容器性能、排查故障及设计自定义容器运行时(如基于 runc
实现)。