容器的三大作用

2025-06-07

容器的三大作用

我一直在观看 Brian Holt 在 Frontend Masters 上主持的容器简介(这是一个付费录制的研讨会,非常值得订阅,而且课程笔记也可以在线免费获取),并且学到了一些关于容器的知识,我觉得我应该分享一下。

容器对于多租户云环境来说有三项重要的作用:

  • 任何进程都不能访问其邻居的文件系统
  • 任何进程都不应该能够看到或控制其邻居正在运行的进程
  • 任何进程都不应该剥夺其邻居的系统资源(CPU、内存等)

如果你和我一样是前端开发者,你可能对容器优于虚拟机有一个模糊的概念,并且你可能知道无服务器函数在容器中运行。你甚至可能见过这样的图片,它展示了容器比虚拟机更轻量,因为虚拟机中内置了操作系统:

https://sites.google.com/site/mytechnicalcollection/_/rsrc/1461078190451/cloud-computing/docker/container-vs-process/docker-containers-vms.png

但你可能从未真正想过容器是如何构建的!Brian 的研讨会首先展示了如何从零开始构建一个容器,这不仅让你领略了容器的神奇之处,也清晰地解释了为什么你需要 Docker 这样的工具来帮你处理所有细节。

为什么选择容器

Brian 首先开始阐述为什么是容器- 并且隐含地 - 为什么容器是部署的未来和云的未来(对于你们中的许多人来说,它们已经存在并且很无聊,但请记住未来是不均衡的!)。

这里需要理解的主要内容是,我们需要完成下面要描述的 3 项工作,即我们(更重要的是公共云供应商)希望多个应用程序(租户)尽可能经济高效地共享同一台机器。

管理虚拟机的成本很高(无论是金钱成本还是计算速度/效率),因为每个虚拟机都在宿主机操作系统中运行一个操作系统。因此,我们希望这些应用运行在同一个操作系统中,同时又能保证安全性和资源隔离。这不仅是为了防止恶意攻击者窥探其邻居,也是为了防止其他人利用代码糟糕的无限循环来霸占或崩溃虚拟机,并破坏邻居的应用程序。

期望结果

因此我们需要以下三个属性:

  • 任何进程都不能访问其邻居的文件系统
  • 任何进程都不应该能够看到或控制其邻居正在运行的进程
  • 任何进程都不应该剥夺其邻居的系统资源(CPU、内存等)

还有很多,但我们将讨论其中最重要的三个。

任务 1:隔离文件系统

任何进程都不能访问其邻居的文件系统

https://miro.medium.com/max/4448/1*QuHou1T2IBoPgi8-dB7kBQ.png

这里的“技巧”是使用Linuxchroot命令。这是一个神奇的命令,它限制了当前正在运行的进程的根目录,因此它无法超出该目录的范围。

mkdir my-new-root
sudo chroot my-new-root pwd
# chroot: pwd: No such file or directory
Enter fullscreen mode Exit fullscreen mode

正如您所见,它并不像运行命令那么简单 - 您还必须复制通常位于根路径上的所有标准库,ls否则bash您将无法使用它们!(请参阅注释以了解如何操作

要安装这些库,您可以使用debootstrap,这是一个将 Debian 基础系统安装到另一个已安装系统的子目录中的工具:

apt-get update -y
apt-get install debootstrap -y
debootstrap --variant=minbase bionic my-new-root


mkdir my-new-root
sudo chroot my-new-root pwd 
/           # now pwd works!
Enter fullscreen mode Exit fullscreen mode

任务 2:隔离正在运行的进程

任何进程都不应该能够看到或控制其邻居正在运行的进程

进程对其他不相关的进程拥有惊人的控制权。您可以ps查看系统上运行的其他进程,并任意地控制kill它们:

$ ps

  PID TTY           TIME CMD
16448 ttys000    0:02.56 zsh -l
57031 ttys000    0:00.19 MY_SUPER_SECRET_RUNTIME
47986 ttys003    1:38.59 /bin/zsh --login

$ kill 57031

# MY_SUPER_SECRET_RUNTIME killed
Enter fullscreen mode Exit fullscreen mode

我们显然不能这样做。为了解决这个问题,我们引入了 2002 年引入的命名空间。您可以使用 创建一个命名空间,并为其指定标志来控制每个ed 环境unshare可以锁定的内容:chroot

unshare --mount --uts --ipc --net --pid --fork --user --map-root-user chroot /better-root bash # this also chroot's for us
Enter fullscreen mode Exit fullscreen mode

7 种命名空间

  • 挂载点(--mount)
  • 进程 ID(--pid)
  • 网络(--net):每个命名空间都有一组私有的 IP 地址、自己的路由表、套接字列表、连接跟踪表、防火墙和其他网络相关资源。
  • 进程间通信(--ipc):这可以防止不同 IPC 命名空间中的进程使用例如 SHM 系列函数在两个进程之间建立一系列共享内存。
  • UTS(--uts):UTS 命名空间允许单个系统对不同的进程显示不同的主机名和域名。
  • 用户 ID(--user):构建一个看似具有管理权限的容器,但实际上并不赋予用户进程提升的权限
  • 对照组:这个似乎比较新。

这既是为了防御攻击者,也是为了保护我们自己。

工作 3:隔离系统资源

任何进程都不应该剥夺其邻居的系统资源(CPU、内存等)

每个隔离环境都可以访问服务器的所有物理资源——主要是 CPU 和内存,但也包括存储和网络访问等其他资源。Google 工程师于 2006 年提出了控制组 (cgroups),将资源隔离到各自的进程。

https://leezhenghui.github.io/assets/materials/build-scalable-system/architecture-nomad-isolation-java-driver-tech.png

# outside of unshare'd environment get the tools we'll need here
apt-get install -y cgroup-tools htop

# create new cgroups
cgcreate -g cpu,memory,blkio,devices,freezer:/sandbox

# add our unshare'd env to our cgroup
ps aux # grab the bash PID that's right after the unshare one
cgclassify -g cpu,memory,blkio,devices,freezer:sandbox <PID>

# Limit usage at 5% for a multi core system
cgset -r cpu.cfs_period_us=100000 -r cpu.cfs_quota_us=$[ 5000 * $(getconf _NPROCESSORS_ONLN) ] sandbox

# Set a limit of 80M
cgset -r memory.limit_in_bytes=80M sandbox
Enter fullscreen mode Exit fullscreen mode

再次,您可以在cgroups 的注释中阅读更多内容。

结论

这些可能不是容器的唯一作用,它们只是 Brian 强调的 3 个作用,我认为值得分享。

我本来想尝试绘制一些这样的系统,但认为我不会做得很好,所以这里有一些我发现现在有意义的图表:

https://www.insecure.ws/_images/ns3.png

https://duffy.fedorapeople.org/blog/designs/cgroups/diagram2.png

当然,如果你想了解更多类似的内容,请查看Brian Holt 在 Frontend Masters 上撰写的《容器简介》

一旦您从第一原则的角度来理解技术,您就会学到可以在其他场景中重新应用的持久知识,并获得批判性地分析技术权衡的能力,而不是只从表面上看待别人的想法。

附录:Firecracker 和 microVM

最近的进展模糊了虚拟机和容器之间的界限。AWS的 Firecracker 被视为一种微虚拟机解决方案:

到目前为止,您需要在启动速度快、密度高的容器和基于硬件虚拟化的强大安全性和工作负载隔离功能的虚拟机之间做出选择。有了 Firecracker,您无需再做出选择。Firecracker 支持您将工作负载部署在轻量级虚拟机(称为 microVM)中,与传统虚拟机相比,microVM 可提供增强的安全性和工作负载隔离,同时还能实现容器的速度和资源效率。

Firecracker 附带一份纸质报告,以下是更易于理解的细分

因此,Firecracker 的核心是一个新的 VMM,它使用 Linux 内核的 KVM 基础架构来提供支持现代 Linux 主机以及 Linux 和 OSv 客户机的最小虚拟机 (MicroVM)。它大约有 50kloc 的 Rust 代码量,即显著减小的代码占用空间,并且使用安全的语言编写。Firecracker 尽可能利用 Linux 中内置的组件(例如,用于块 IO、进程调度和内存管理以及 TUN/TAP 虚拟网络接口)。通过瞄准容器和无服务器工作负载,Firecracker 仅需要支持有限数量的模拟设备,比 QEMU 少很多(例如,不支持 USB、视频和音频设备)。virtio 用于网络和块设备。Firecracker 设备提供内置的速率限制器,足以满足 AWS 的需求,尽管灵活性仍然远不如 Linux cgroups。

进一步阅读

文章来源:https://dev.to/swyx/ Three-jobs-of-containers-436p
PREV
30 个 React 示例项目供您学习(开源,初级至高级)
NEXT
回顾《50 课学会 TypeScript》