我以为我懂容器了。直到我试着构建一个。 笔记

我以为我懂容器了。直到我试着构建一个。

作者尽管通过了 Docker 认证考试,却意识到实际的容器知识与理论理解存在差异。最初尝试使用 unshare 命令时,发现对 PID 命名空间存在误解,必须使用 --fork 标志才能在新的命名空间中正确建立 PID 1。随后,在命名空间内重新挂载 /proc 文件系统至关重要,这使得 ps 等工具能够准确反映隔离后的进程层级。UTS 命名空间的演示展示了主机名如何实现隔离,并通过清晰的对照与处理场景验证了这一概念。旅程继续推进至 pivot_root,作者旨在让进程拥有独立的文件系统。初期遇到的障碍是一个动态链接的 BusyBox 可执行文件失败,因为其所需的解释器在新根文件系统中不可用。解决方案是在文件系统切换期间使用静态链接的 BusyBox 作为桥梁,并解决 Bash 的哈希缓存记住旧命令路径的问题。针对 Mac 上 virtiofs 与符号链接执行相关的特定问题,通过将根文件系统移至原生容器路径得以解决。pivot_root 操作本身需要特定的设置:新根必须是一个挂载点,而旧根需在正式切换前单独准备。成功在新组装的文件系统中执行命令,例如显示 Alpine Linux 的 /etc/os-release,带来了切实的成就感。最后,探索 cgroups 作为文件系统 API 展示了资源限制功能,揭示了在 cgroup v2 中启用控制器时“无内部进程”的规则。通过仔细迁移进程,然后在父 cgroup 上启用控制器,作者成功为子 cgroup 设置了内存和 PID 限制。强制执行这些限制,特别是通过 dmesg 观察到内存不足(OOM)杀进程事件,进一步巩固了对 cgroups 的理解——它们并非抽象配置,而是与内核文件系统的直接交互。这种动手实践消除了对 Kubernetes Pod 的神秘感,揭示其本质是这些基础 Linux 原语(命名空间、文件系统隔离和 cgroups)的有组织实现。因此,容器化工具如 Docker、containerd 和 Kubernetes 从品牌产品转变为这些核心脚本的结构化编排。