前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >容器那些事儿-从graph dirver谈起

容器那些事儿-从graph dirver谈起

作者头像
zouyee
发布2022-05-25 10:09:28
5470
发布2022-05-25 10:09:28
举报
文章被收录于专栏:Kubernetes GO

时间拉回到五年前,当安装docker时,都会看到grahp driver这一目录,但在docker将libe-containerd独立,并捐献成为containerd项目后,为何不见了grahp driver?

文|Crosby

编辑|zouyee

技术深度|简单

Containerd 并没有 graph driver,但是它有snapshotter。这样处理不是为了造新轮子,而是为了填坑,毕竟当初 graph driver 的设计,一直多为诟病。先来回顾一下 graph driver 的历史。

该文目前不介绍docker、containerd的演化转变史,后续会单独出文逐一介绍。

容器文件系统类型

容器中使用两种文件系统:overlay 和 snapshotting。AUFS 和 OverlayFS 都为 overlay 文件系统,有多个目录为镜像中的每一层提供文件 diff。而 snapshot 文件系统包括 devicemapper、btrfs 和 ZFS,它们在块层级处理文件 diff。overlay 通常工作在 EXT4 和 XFS 这类文件系统上,而 snapshot 文件系统只在其格式化的卷上。

graph driver的历史

探究graph driver的历史,必然有此番定体问:什么是 graph driver?为什么有?为何叫 graph driver?

当然要回答这些问题,需要把时间线拉得更长一点,回到 Docker 0.8 所在的时间线。当时的 Docker 只支持 Ubuntu,因为它是唯一支持 AUFS 的Linux发行版,Docker 使用 overlay 文件系统来构建镜像和容器的读写层。为了让 Docker 能够支持老版本的内核,需要 Docker 除 AUFS 以为更多的文件系统。因此,对支持device mapper(LVM thinpool)成为替换 AUFS 兼容老版本的可选项。

起初,device mapper 似乎能够解决所有的问题,当然 Docker 支持所有内核运行的目标确实由 device mapper 实现了。当时社区一度想取消对 AUFS 的支持,只让容器的文件系统使用 device mapper,但在测试过POC后,发现这并不是理想的解决方案。发行版之间存在诸多问题。社区确实需要实现支持Docker兼容多架构多Linux发行版的目标,但前提是不能以牺牲现有 Ubuntu 用户运行的性能为代价。

为了让更多Linux发行版用户用上 Docker,文件系统的支持必须是可插拔的。Solomon 设计了一个新的驱动 API 以支持 Docker 中的多个文件系统。Solomon设计了 API,而 Crosby 则改造 AUFS实现,以验证API的完备性。

他们将新 API 命名为 graph driver,因为 Docker 将镜像各层的关系建模在“图”中,而文件系统主要存储镜像。

起初 graph driver 接口设计的简易且运作稳定。但是随着时间的推移,需求日益增多,graph driver API 逐步支持下述功能:

  • 构建方面的优化,例如缓存和共享层以加速构建
  • 内容可寻址性特性,以确保文件系统被安全地识别
  • 运行时从 LXC 变更为 runc

这些变更导致 graph driver API 及其底层实现与它们所支持的高级功能逐渐交织糅合到一起,从而导致了一些问题:

  • graph driver API 日渐复杂
  • 每个驱动中都有内置的代码以优化构建
  • 驱动程序与容器生命周期紧密耦合
  • 难以维护,因为 graph driver 的范围很广

没有如今这些需求,一开始是不可能预见到这些设计问题的。

破局者snapshotter

直到捐献Containerd,才有时间来厘清这些长期存在的问题,并尝试去解决其中的一部分问题,确实也是时候重新构思 graph driver 应该如何与容器协作。

API 复杂度

为了解决 graph driver 巨型API 的问题,首先需要明确 overlay 和 snapshot 文件系统理应支持的功能。正如所知道的,snapshot 不如 overlay 文件系统灵活,因为快照有严格的层级关系。因为snapshot 在块层级工作,因此需要在创建子快照前必须生成一个父快照。

尽量在 I/O 方面最不灵活的地方抽象一个接口,这是编码实现的基本路线,这也是为什么 containerd 将文件系统组件称为 snapshotter,因为是以它们为模型设计了接口。在为 snapshotter 开发了最初的 API 后,支持多种 overlay 文件系统就变得易如反掌。

可以在这看到完整的接口以及每种方法的相关信息:https://pkg.go.dev/github.com/containerd/containerd/snapshot?utm_source=godoc#Snapshotter

容器生命周期的变化

在使用graph driver时,一直是驱动为容器挂载和卸载 root文件系统。这源于 当初Docker 还在使用 LXC 时,必须在完全挂载的 rootfs 中执行容器。在切到 runc 后,这个问题也就不存在了。

我们希望所有挂载都发生在 mount 命名空间内而非宿主机上,同时我们不希望 snapshotter 挂载任何东西,这样有以下几点好处:

  • 调用者作为 builder 或执行组件,可以决定何时需要挂载 rootfs;何时执行结束,这样就可以卸载。
  • 在容器的命名空间挂载,当容器消亡时,内核将卸载该命名空间中的所有东西。这解决了一些 graph driver 遗留文件句柄的问题。

设计snapshotter API 返回一个序列化的mount调用来实现,由调用者挂载和卸载。containerd 中的执行组件 containerd-shim 挂载容器的 rootfs,并在任务执行结束后卸载。

社区维护

最后,我们希望确保 snapshotter 可被长期维护。这点通过一个简易的接口来实现,允许我们去掉大部分调用者的需求,这样 snapshotter 就可以专注于成为一个 snapshotter。

从这一点来看,snapshotter 可以视作 graph driver 的一个演变版本。这也算修复graph driver用户面临的长期未决的一部分问题。

参考文献

1.https://blog.mobyproject.org/where-are-containerds-graph-drivers-145fc9b7255

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DCOS 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • graph driver的历史
  • 破局者snapshotter
  • 容器生命周期的变化
  • 社区维护
相关产品与服务
容器镜像服务
容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档