公司动态
揭开Docker底层面纱-Namespace隔离与cgroups控制
揭开 Docker 底层面纱Namespace 隔离与 cgroups 控制 目录一、核心认知隔离与控制是内核能力二、空间隔离实战Namespace1. 基础命令2. 实战一PID 隔离3. 实战二Mount 隔离三、资源控制实战cgroups1. 基础工具2. cgroups 信息查看3. 实战一内存控制4. 实战二CPU 控制四、LXC 容器实战1. LXC 常用命令2. 安装 LXC3. LXC 容器操作实战一、核心认知隔离与控制是内核能力在动手之前先明确一个核心认知隔离能力并非 Docker 提供而是操作系统内核提供的基本能力。Namespace 负责空间隔离cgroups 负责资源控制LXC 是早期把这些能力封装起来的工具而 Docker 是 LXC 的增强版——它的价值在于易用性和镜像设计而非底层隔离/控制技术本身。本篇通过三个实战用最原始的内核命令亲手验证这些能力实战使用的内核能力验证目标空间隔离Namespaceunshare 命令PID 隔离、Mount 隔离资源控制cgroups/sys/fs/cgroup内存限制、CPU 限制LXC 容器Namespace cgroupslxc-* 命令容器的另一种实现二、空间隔离实战Namespace1. 基础命令空间隔离实战需要掌握几个 Linux 基础命令命令功能关键参数dd读取/转换/输出数据if输入文件、of输出文件、bs块大小、count块数mkfs在设备上创建文件系统格式化-t指定文件系统类型如 ext4df显示磁盘使用情况-h人可读、-T显示文件系统类型mount加载文件系统到挂载点-t类型、-o选项如 loop/ro/rwunshare使用与父程序不共享的命名空间运行程序-iIPC、-mMount、-nNet、-pPID、-uUTS、-Uuser、--fork、--mount-proc2. 实战一PID 隔离目标通过unshare创建一个新的 PID Namespace观察进程隔离效果。# 1. 主机执行 ps -efPID 1 为 init 进程ps-ef# 2. 创建新 PID Namespaceunshare--fork--pid--mount-proc /bin/bash关键知识点--fork新建 bash 进程。如果不加会报Cannot allocate memory。--mount-proc挂载 /proc使 top/ps 在新 namespace 中正常工作。# 3. 在新 namespace 中执行 ps -efps-ef# 此时进程空间已隔离bash 成为启动进程PID 1看不到主机其他进程# 4. 退出exit3. 实战二Mount 隔离目标通过unshare创建 Mount Namespace在隔离环境中创建并挂载磁盘镜像验证主机看不到隔离环境的挂载。窗口 A主机# 查看主机默认磁盘挂载df-h窗口 B隔离环境# 1. 创建 Mount Namespaceunshare--mount--fork/bin/bash# 2. 创建挂载目录mkdir-p/data/tmpmount# 3. 创建磁盘镜像文件80MBddif/dev/zerooffdimage.imgbs8kcount10240# 4. 格式化为 ext4mkfs-text4 ./fdimage.img# 5. 挂载mount./fdimage.img /data/tmpmount# 6. 写入文件echoHello world!/data/tmpmount/hello.txtcat/data/tmpmount/hello.txt# 能读取# 7. 查看挂载df-h# 窗口 B 有 /dev/loop0 挂载对比验证# 窗口 A主机执行 df -h没有 /dev/loop0 挂载# 窗口 A 执行 cat /data/tmpmount/hello.txt报 No such file or directory# 窗口 B 能读取窗口 A 不能 → Mount 隔离验证成功# 退出隔离环境exit三、资源控制实战cgroups1. 基础工具资源控制实战需要两个监控和压力测试工具工具功能关键参数安装pidstat监控进程的 CPU/内存/线程/IO 占用-uCPU、-r内存、-dIO、-p指定PID、-C按进程名apt install sysstat -y或yum install sysstat -ystress压力测试工具CPU/Memory/IO/磁盘-cCPU、-m内存、--vm-bytes内存大小、--vm-keep、-t超时apt install stress -y或yum install stress -y2. cgroups 信息查看# 1. 查看版本cgroup2 表示支持 v2cat/proc/filesystems|grepcgroup# v2 判断方法stat-fc%T /sys/fs/cgroup/# 输出 cgroup2fs 表示 v2tmpfs 表示 v1# 2. 查看子系统# v1cat/proc/cgroups# 输出cpuset cpu cpuacct blkio memory devices freezer 等# v2cat/sys/fs/cgroup/cgroup.controllers# 输出cpuset cpu io memory 等# 3. 查看挂载信息mount|grepcgroup# 默认存储在 /sys/fs/cgroup# 4. 查看进程的 cgroup 限制cat/proc/$$/cgroup3. 实战一内存控制cgroup v1 操作# 1. 进入 memory 子系统目录创建 test_memory自动生成配置文件cd/sys/fs/cgroup/memorymkdirtest_memory# 2. 配置策略最大 20Mexpr20\*1024\*1024# 计算得 20971520echo20971520test_memory/memory.limit_in_bytes# 3. 窗口 B启动消耗 50M 内存的进程stress-m1--vm-bytes 50M# 4. 窗口 B用 pidstat 查看pidstat-r-Cstress-pALL110000# 5. 窗口 C将进程 PID 移入 cgroupechoPIDtest_memory/tasks# 6. 结果进程因无法申请足够内存而退出cgroup v2 操作# 1. 确认 memory 支持cat/sys/fs/cgroup/cgroup.controllers# 2. 创建子 cgroupmkdir/sys/fs/cgroup/test_memory# 3. 配置 20Mecho20M/sys/fs/cgroup/test_memory/memory.max# 4. 启动 stress 并查看stress-m1--vm-bytes 50M pidstat-r-Cstress-pALL110000# 5. 移入 cgroupechoPID/sys/fs/cgroup/test_memory/cgroup.procs# 6. 结果进程消失退出4. 实战二CPU 控制cgroup v1 操作# 1. 进入 cpu 子系统目录创建 test_cpucd/sys/fs/cgroup/cpumkdirtest_cpu# 2. 窗口 B模拟 CPU 100% 任务stress-c1# 3. 查看 CPU 使用率看到 100%pidstat-u-Cstress-pALL110000# 4. 窗口 C设置 30%# CPU 使用率 cfs_quota_us / cfs_period_us# cfs_period_us 默认 100000cfs_quota_us 设 30000 即 30%echo30000test_cpu/cpu.cfs_quota_us# 5. 移入进程echoPIDtest_cpu/tasks# 6. 结果CPU 使用率由 100% 降为 30%cgroup v2 操作# 1. 创建子 cgroupmkdir/sys/fs/cgroup/test_cpu# 2. 启动 stress 并查看100%stress-c1pidstat-u-Cstress-pALL110000# 3. 设 30%格式quota periodecho30000 100000/sys/fs/cgroup/test_cpu/cpu.max# 4. 移入 cgroupechoPID/sys/fs/cgroup/test_cpu/cgroup.procs# 5. 结果CPU 降为 30%总结Docker 本质也是调用 cgroups API 完成资源管理Docker 的易用性和镜像设计更人性化。以上操作揭示了 Docker-m、--cpus等参数的底层原理。四、LXC 容器实战 Docker 自 0.9 版本起引入 libcontainer 替代 LXC。LXC 这项技术随系统升级几乎无人维护这里只是用来理解docker 并非容器的唯一实现。1. LXC 常用命令命令功能lxc-checkconfig检查系统环境是否满足容器要求lxc-create -n NAME -t TEMPLATE_NAME创建容器lxc-start -n NAME -d启动容器lxc-ls -f列出所有容器-f 打印常用信息lxc-info -n NAME查看容器信息lxc-attach --nameNAME [-- COMMAND]进入容器执行命令lxc-stop -n NAME停止容器lxc-destroy -n NAME删除停机状态的容器2. 安装 LXCUbuntu 安装# 卸载旧版systemctl status lxc# 如有容器先清理lxc-stop / lxc-destroyapt-getpurge --auto-remove lxc lxc-templates# 安装aptinstalllxc lxc-templates bridge-utils-y# 检查systemctl status lxcCentOS 安装# 卸载旧版yum remove lxc lxc-templates lxc-libs lxc-extra libvirtdebootstrap# 配置 EPEL 源yum-yinstallepel-release# 安装yum-yinstalllxc lxc-templates bridge-utils lxc-libs libcgroup libvirt lxc-extradebootstrap# 启动systemctl start lxc systemctl start libvirtd3. LXC 容器操作实战# 1. 检查 lxc 是否运行systemctl status lxc# 2. 检查 lxc 功能支持查看 Namespaces/Cgroups/Misc 等内核特性是否 enabledlxc-checkconfig# 3. 查看容器模板ls/usr/share/lxc/templates/# 输出lxc-alpine lxc-centos lxc-debian lxc-ubuntu lxc-download 等# 4. 创建容器Ubuntu 上建 ubuntu 容器lxc-create-tubuntu-nlxchost1 ---rxenial-aamd64# CentOS 上建 centos 容器lxc-create -t centos -n lxchost1# Ubuntu 上建 centos 容器lxc-create -t download -n lxchost1 -- --distcentos --release7 --archamd64# 5. 容器目录说明# 容器放在 /var/lib/lxc/容器名/根文件系统在 rootfs/# 下载缓存在 /var/cache/lxc# 6. 查看容器lxc-ls-f# 7. 启动容器lxc-start-nlxchost1-d# 看到 IP 如 10.0.3.248# 8. 查看详情lxc-info-nlxchost1# 输出 State/PID/IP/CPU/Memory/网络统计# 9. ssh 进入容器sshubuntu10.0.3.248# 验证隔离性ip addr、uname、ll /、df -h、ps -ef 与宿主机不同# 10. 容器外执行命令lxc-attach-nlxchost1 --clear-env --echoHello bit# 11. 停止容器lxc-stop-nlxchost1# 12. 删除容器lxc-destroy-nlxchost1