containerd 2017-03-24 开发报告精读:容器级 Metrics、镜像分发与快照驱动三大里程碑
containerd 2017-03-24 开发报告精读容器级 Metrics、镜像分发与快照驱动三大里程碑【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerdcontainerd 的docs/historical/reports/目录保留了项目早期面向社区同步的开发报告2017-03-24.md 是其中一份关键文档。本报告记录了 containerd 在 2017 年 3 月下旬的三个技术突破首个容器级 Prometheus 指标、镜像拉取到运行的端到端能力以及 overlay/btrfs 快照驱动的共享元数据存储层。结合当前仓库的源码可以清晰地看到这三条线索各自如何演进为今日 containerd 的标配能力。报告背景为什么开发报告值得精读2017 年 3 月是 containerd 从 CRI 运行时底座向“完整容器运行时”演进的关键节点。报告开篇提到一个里程碑已经完成——端到端 pull and run 的概念验证PoC即从 registry 拉取镜像并成功运行容器。此后一周的工作重心是把这套代码放到正确的位置并找出实现缺口。报告将进展划分为三大板块容器级指标Container Level Metrics、分发Distribution又细分为 Image to OCI Spec、Image handlers、镜像列表展示三项、快照驱动改进Snapshot driver improvements。下文逐一展开并把每一项映射到当前仓库中的真实实现。容器级 Metrics从第一版指标到 Prometheus 插件体系报告第一部分记录了 containerd 合入首个容器级指标的实现使其 Prometheus 输出中首次包含“所有运行在 containerd 上的容器”的完整指标。报告同时坦承指标名称与结构仍需评审尚未达到“可以长期承诺支持”的稳定性——这一点对理解 containerd 指标演进的保守风格很有价值先有数据通路再冻结指标契约。从当前仓库的源码结构看这一思路延续至今core/metrics/metrics.go 中通过go-metrics注册了containerd命名空间并在启动时上报build_info计数器携带version与revision两个标签同时定义了ShimStatsRequestTimeout默认 2 秒这一超时键——这正是当年“容器级指标需要跨进程向 shim 采集”这一通路的遗留配置项说明容器级指标的采集链路daemon → shim → cgroup 统计从那时起就已定型。指标输出侧plugins/server/grpc/metrics.go 注册了grpc-prometheus指标插件其配置结构体中提供GRPCHistogram bool对应 TOML 键grpc_histogram默认false。开启后会附加WithServerHandlingTimeHistogram()用直方图度量每个 RPC 的处理时延。也就是说当年“指标名称与结构需要评审”的遗留问题最终演化为一个可按需开启的、结构化的插件化指标框架而非硬编码的指标列表。容器资源统计的落地实现在 core/metrics/cgroups/ 目录下按 cgroup v1/v2 与平台分别实现供运行时读取容器的 CPU、内存等统计数据。对今天的读者这份报告的价值在于解释了 containerd 指标体系的两层结构gRPC 服务级指标由 Metrics 插件提供与容器级运行时指标由 shim 上报 cgroups 统计提供后者正是 2017 年 3 月这次合入的直接产物。Distribution从 PoC 到可操作的 pull run报告第二部分的主线是把“端到端拉取并运行”这一 PoC 代码重构到正确位置并补齐实现缺口。它包含三个子项其中第一项是实操性最强的。从镜像配置生成 OCI SpecImage to OCI Spec报告记录已合入支持“把从 registry 拉取的镜像 config 生成一份基于镜像属性的 OCI spec”的能力集成在ctr命令中。其意义在于你可以直接从 registry 拉取镜像并按镜像构建时的配置运行它而不需要手动编写 bundle。报告也明确指出当时实现“非常简单”并计划把 Docker 的默认 spec 与生成代码移植成一个可被 containerd 客户端轻松消费的包。报告中给出的验证方式历史命令形态$ sudo dist pull docker.io/library/redis:alpine $ sudo ctr run --id redis -t docker.io/library/redis:alpine其中dist是当时分发子命令的临时命名后并入ctr。在当前仓库中这条链路已经固化为标准的ctr images pull与ctr run命令实现分别位于 cmd/ctr/commands/images/pull.go 与 cmd/ctr/commands/run/run.go而报告中预告的“spec 生成代码移植成独立包”对应现在仓库中的 pkg/oci/ 包——它负责按镜像 config 生成与修饰 OCI 运行时 spec被 CRIinternal/cri/与 client 库共同消费。这一“从命令行试验场到可复用包”的演进路径正是当年报告中预告的方向。镜像处理器接口化Image handlers报告记录了把fetch命令重构为更通用的“镜像处理器接口”的工作。动机是前瞻性的为了同时支持完整的 OCI 镜像规范和 Docker 分发规范需要移除一切带“观点”opinionated的代码让分发逻辑尽可能通用、高效。在当前仓库中可以看到该接口的直接后裔core/images/handlers.go 定义了按媒体类型分发的处理器集合core/images/mediatypes.go 集中管理各规范OCI、Docker manifest/config 等的媒体类型常量core/remotes/ 则实现了 registry 拉取的 resolver 与 handlers 组合含 core/remotes/docker/ 的 Docker Hub 特化实现。“去掉 opinionated 代码、以 handler 接口解耦规范差异”这一 2017 年确立的架构决策至今仍是 containerd 分发子系统的骨架。镜像列表输出完整镜像大小报告展示了dist images命令当时新增的 SIZE 列输出样例$ dist images REF TYPE DIGEST SIZE docker.io/library/redis:latest application/vnd.docker.distribution.manifest.v2json sha256:1b358a2b0dc2629af3ed75737e2f07e5b3408eabf76a8fa99606ec0c276a93f8 71.0 MiB值得注意的是该输出同时暴露了三个字段语义REF镜像引用、TYPEmanifest 的媒体类型样例中为 Docker manifest v2、DIGEST内容寻址摘要、SIZE人类可读的总大小如71.0 MiB。这一输出形态在今天的ctr images ls中保持不变实现见 cmd/ctr/commands/images/images.go。它体现的内容寻址设计以 digest 而非 tag 作为身份也是 containerd content store 的核心原则。快照驱动改进共享的元数据存储层报告第三部分记录了overlay与btrfs两个快照驱动实现的完成以及一个影响更深远的设计决策两者共享同一套元数据存储实现。报告的原话是这个新的元数据存储包“不仅让快照驱动更容易编写也让我们可以集中精力把现有驱动做得更健壮、更稳定”。在当前仓库中这个“元数据存储包”依然以当时的形态存在即 core/snapshots/storage/metastore.go。它的包注释非常值得细读Package storage provides a metadata storage implementation for snapshot drivers. Drive implementations are responsible for starting and managing transactions using the defined context creator. This storage package uses BoltDB for storing metadata.关键设计点可以从源码中逐条确认BoltDB 承载元数据MetaStore内部持有*bolt.DBmetastore.go 第 69-75 行的结构定义只存储快照的“名称、状态与父子关系”name, state and parentage而不暴露裸事务句柄。强一致性与事务模型NewMetaStore的注释说明该实现“强一致”所有元数据变更都在事务中完成防止进程崩溃导致元数据不一致配套的Transactor接口要求写事务必须显式Commit非写事务与中止的写事务必须Rollback。可选而非强制注释明确指出“使用 MetaStore 不是实现快照驱动的必要条件”——驱动实现可以选择自己管理持久化。这种“提供工具但不绑架接口”的风格与 Distribution 部分“去掉 opinionated 代码”的思路一脉相承。快照父子链的表示Snapshot结构体中的ParentIDs有序记录 committed 快照链注释规定顺序“从最高层基础到最低层基础”应用时从最后一个索引向第一个索引进行——这套数据模型至今仍被 overlay 等驱动复用。基于该存储层仓库中 plugins/snapshots/overlay/ 与 plugins/snapshots/btrfs/ 等驱动各自只关注文件系统层面的 prepare/commit/Remove 语义元数据一致性则统一交由 BoltDB 事务保证。报告所说的“让驱动更 resilient 和 stable”的长期目标具体落点就是这个共享存储包及其事务约束。小结一份开发报告留下的三条主线2017-03-24.md 篇幅不长但它记录的三个决策点几乎都成了 containerd 当前架构的承重墙容器级指标的先行合入——确立了“daemon shim cgroups”的指标采集通路今天由 core/metrics/ 与 gRPC 侧的 Prometheus 插件plugins/server/grpc/metrics.go延续分发逻辑的去中心化重构——fetch命令退化为通用的 image handlers 接口演化为 core/images/handlers.go 与 core/remotes/ 的组合式实现快照元数据共享层——BoltDB 支撑的 core/snapshots/storage/ 包使 overlay、btrfs 等驱动plugins/snapshots/得以把精力集中在文件系统语义而非持久化复杂度上。对想理解 containerd 架构演进的读者这类开发报告比正式文档更能呈现“决策当时为什么这么定”而当前仓库的对应源码则是验证这些决策是否兑现的最直接证据。【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考