containerd 2017-03-17 开发报告解读:首个端到端镜像拉取与容器 Prometheus 指标的诞生
发布时间:2026/9/13 16:23:01 锦皓数字建站

containerd 2017-03-17 开发报告解读首个端到端镜像拉取与容器 Prometheus 指标的诞生【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerd这篇技术文章基于 containerd 历史开发报告 docs/historical/reports/2017-03-17.md完整梳理 containerd 2017 年 3 月 17 日周报中记录的四项里程碑多平台测试计划、Windows 运行时移植启动、基于 Prometheus 的容器级指标导出以及首个端到端镜像拉取概念验证dist pull/dist images/ctr run。文章同时对照当前仓库中的源码如 core/metrics/cgroups/cgroups.go、cmd/ctr/commands/images/pull.go、client/pull.go说明 2017 年埋下的这些能力如何在今天的 containerd 中落地演化帮助读者理解 containerd 从理论架构走向可运行系统的关键转折点。一、背景containerd 周报体系与这份报告的地位containerd 在 2017 年上半年以双周开发报告Development Report的形式记录进展完整系列保存在 docs/historical/reports/ 目录下从 2017-01-13 到 2017-06-23 共 14 份。2017-03-17 这一期之所以关键是因为它标志着 containerd 从各子系统分别开发进入了子系统端到端串联阶段——报告原文明确指出Up to this point, the relationship between subsystems has been somewhat theoretical.此前各子系统之间的关系还多少停留在理论层面。而这份报告中的 Image Pull 章节第一次让 fetching内容拉取、snapshot drivers快照驱动、rootfs service根文件系统服务、image metadata镜像元数据与 execution service执行服务五个部分在一条真实命令链中被同时调用验证了 containerd 提出的整体模型。二、Testing Plan面向 ARM、Windows、Linux、Power 的 CI 战略报告开头讨论的是测试计划Testing Plan。作者感谢 gianarb 发起了 containerd 测试与 CI 计划的讨论核心动机是让用户能够安心地依赖 containerdfeel secure depending on containerd。报告点出了 containerd 测试的特殊困难它需要覆盖的系统平台非常多当时已列出的支持平台包括ARM、Windows、Linux、Power以及更多变体。这与 containerd 作为底层容器运行时的定位一致——它不像应用框架可以选择性地支持操作系统而是必须跟随 OCI 生态覆盖几乎所有主流架构。报告中提到的测试计划讨论在 containerd 社区的 issue #634 中进行原文以外链给出此处不复述社区贡献者可围绕 CI 平台矩阵持续补充。从当前仓库结构看多平台支持至今仍是主线构建系统按平台拆分为 Makefile.linux、Makefile.darwin、Makefile.freebsd、Makefile.windows默认路径逻辑也按平台拆分在 defaults/defaults_linux.go、defaults/defaults_darwin.go、defaults/defaults_windows.go 等文件中印证了 2017 年平台矩阵这一测试难题的长期性。三、Windows Runtime执行代码移植启动报告确认 Windows 运行时的执行代码移植porting over the Windows execution code已经启动移植完成后还有大量测试要做PR 即将提交。这一条对应的是 containerd 早期先 Linux 后 Windows的演进路线。从源码结构看当前仓库中 Windows 相关能力已相当完整执行层有 pkg/cio/io_windows.goWindows 控制台/管道 IO 处理、pkg/os/ 下的 Windows 实现、挂载层有 core/mount/mount_windows.go、core/diff/stream_windows.go集成测试目录中也存在 integration/client/client_windows_test.go、integration/sandbox_clean_remove_windows_test.go 等 Windows 专项用例。可以说2017-03 这次移植启动的 PR 正是后来这些 Windows 实现的起点。四、Metrics容器级指标首次通过 Prometheus 导出这是本报告信息量最大的部分。2017 年 3 月团队启动了将容器级指标通过 Prometheus 导出的工作报告贴出了当时的完整初始输出以idtest的容器为例containerd_container_blkio_io_service_bytes_recursive_bytes{idtest,major8,minor0,opAsync} 958464 containerd_container_blkio_io_service_bytes_recursive_bytes{idtest,major8,minor0,opRead} 958464 containerd_container_blkio_io_service_bytes_recursive_bytes{idtest,major8,minor0,opSync} 0 containerd_container_blkio_io_service_bytes_recursive_bytes{idtest,major8,minor0,opTotal} 958464 containerd_container_blkio_io_service_bytes_recursive_bytes{idtest,major8,minor0,opWrite} 0 containerd_container_blkio_io_serviced_recursive_total{idtest,major8,minor0,opAsync} 17 containerd_container_blkio_io_serviced_recursive_total{idtest,major8,minor0,opRead} 17 containerd_container_blkio_io_serviced_recursive_total{idtest,major8,minor0,opSync} 0 containerd_container_blkio_io_serviced_recursive_total{idtest,major8,minor0,opTotal} 17 containerd_container_blkio_io_serviced_recursive_total{idtest,major8,minor0,opWrite} 0 containerd_container_cpu_kernel_nanoseconds{idtest} 1e07 containerd_container_cpu_throttle_periods_total{idtest} 0 containerd_container_cpu_throttled_periods_total{idtest} 0 containerd_container_cpu_throttled_time_nanoseconds{idtest} 0 containerd_container_cpu_total_nanoseconds{idtest} 2.1428791e07 containerd_container_cpu_user_nanoseconds{idtest} 0 containerd_container_hugetlb_failcnt_total{idtest,page1GB} 0 containerd_container_hugetlb_failcnt_total{idtest,page2MB} 0 containerd_container_hugetlb_max_bytes{idtest,page1GB} 0 containerd_container_hugetlb_max_bytes{idtest,page2MB} 0 containerd_container_hugetlb_usage_bytes{idtest,page1GB} 0 containerd_container_hugetlb_usage_bytes{idtest,page2MB} 0 containerd_container_memory_active_anon_bytes{idtest} 0 containerd_container_memory_active_file_bytes{idtest} 659456 containerd_container_memory_cache_bytes{idtest} 925696 containerd_container_memory_dirty_bytes{idtest} 0 containerd_container_memory_hierarchical_memory_limit_bytes{idtest} 9.223372036854772e18 containerd_container_memory_hierarchical_memsw_limit_bytes{idtest} 9.223372036854772e18 containerd_container_memory_inactive_anon_bytes{idtest} 73728 containerd_container_memory_inactive_file_bytes{idtest} 266240 containerd_container_memory_kernel_failcnt_total{idtest} 0 containerd_container_memory_kernel_limit_bytes{idtest} 9.223372036854772e18 containerd_container_memory_kernel_max_bytes{idtest} 0 containerd_container_memory_kernel_usage_bytes{idtest} 0 containerd_container_memory_kerneltcp_failcnt_total{idtest} 0 containerd_container_memory_kerneltcp_limit_bytes{idtest} 9.223372036854772e18 containerd_container_memory_kerneltcp_max_bytes{idtest} 0 containerd_container_memory_kerneltcp_usage_bytes{idtest} 0 containerd_container_memory_mapped_file_bytes{idtest} 577536 containerd_container_memory_oom_total{idtest} 0 containerd_container_memory_pgfault_bytes{idtest} 770 containerd_container_memory_pgmajfault_bytes{idtest} 6 containerd_container_memory_pgpgin_bytes{idtest} 651 containerd_container_memory_pgpgout_bytes{idtest} 407 containerd_container_memory_rss_bytes{idtest} 73728 containerd_container_memory_rss_huge_bytes{idtest} 0 containerd_container_memory_swap_failcnt_total{idtest} 0 containerd_container_memory_swap_limit_bytes{idtest} 9.223372036854772e18 containerd_container_memory_swap_max_bytes{idtest} 1.527808e06 containerd_container_memory_swap_usage_bytes{idtest} 999424 containerd_container_memory_total_active_anon_bytes{idtest} 0 containerd_container_memory_total_active_file_bytes{idtest} 659456 containerd_container_memory_total_cache_bytes{idtest} 925696 containerd_container_memory_total_dirty_bytes{idtest} 0 containerd_container_memory_total_inactive_anon_bytes{idtest} 73728 containerd_container_memory_total_inactive_file_bytes{idtest} 266240 containerd_container_memory_total_mapped_file_bytes{idtest} 577536 containerd_container_memory_total_pgfault_bytes{idtest} 770 containerd_container_memory_total_pgmajfault_bytes{idtest} 6 containerd_container_memory_total_pgpgin_bytes{idtest} 651 containerd_container_memory_total_pgpgout_bytes{idtest} 407 containerd_container_memory_total_rss_bytes{idtest} 73728 containerd_container_memory_total_rss_huge_bytes{idtest} 0 containerd_container_memory_total_unevictable_bytes{idtest} 0 containerd_container_memory_total_writeback_bytes{idtest} 0 containerd_container_memory_unevictable_bytes{idtest} 0 containerd_container_memory_usage_failcnt_total{idtest} 0 containerd_container_memory_usage_limit_bytes{idtest} 9.223372036854772e18 containerd_container_memory_usage_max_bytes{idtest} 1.527808e06 containerd_container_memory_usage_usage_bytes{idtest} 999424 containerd_container_memory_writeback_bytes{idtest} 0 containerd_container_per_cpu_nanoseconds{cpu0,idtest} 7.530139e06 containerd_container_per_cpu_nanoseconds{cpu1,idtest} 4.586408e06 containerd_container_per_cpu_nanoseconds{cpu2,idtest} 5.076059e06 containerd_container_per_cpu_nanoseconds{cpu3,idtest} 4.236185e06 containerd_container_pids_current{idtest} 1 containerd_container_pids_limit{idtest} 0这些指标覆盖了四个 cgroup 资源域blkio块设备 IO 的服务字节数与请求次数按 major/minor 设备和 opAsync/Read/Sync/Total/Write维度打标cpu内核态/用户态/总 CPU 时间纳秒、CFS 配额限流计数throttle_periods、throttled_time、按核的 per_cpu_nanosecondsmemory匿名页/文件页的 active/inactive 状态、cache、dirty、mapped_file、page fault/PGIN/PGOUT、RSS、swap 用量与限额、hugetlb2MB/1GB 大页用量、OOM 计数等pids当前进程数与进程数上限。报告给出了两条关键设计决策id标签即容器 ID用户可据此过滤只关心的容器采集频率完全由 Prometheus 抓取周期决定。每次/metricsAPI 被命中时才采集容器指标containerd 内部没有定时器——If you never ask for metrics the collection never happens从不请求就从不采集。这是一种典型的按需付费pay only when you ask设计避免了常驻采集线程的固定开销。报告同时预告了 PR 即将提交以便社区讨论指标与标签命名。在今天的源码中TaskMonitor 插件与no_prometheus开关2017 年这次初始输出对应的设计如今已沉淀为正式的 cgroups 监控插件。在 core/metrics/cgroups/cgroups.go 中可以看到插件以TaskMonitorPlugin类型、IDcgroups注册并依赖EventPlugin通过容器 create/delete 事件决定监控的 cgroup 生命周期配置只有一个开关NoPrometheusTOML 键no_prometheus为 false 时创建metrics.NewNamespace(container, ...)并注册到全局指标表为 true 时仅采集不上报——这正是对按需付费理念的配置化体现实现按 cgroup 版本分流cgroups.Mode() cgroups.Unified时选择 core/metrics/cgroups/v2 的NewTaskMonitor否则使用 v1 版本分别读取 cgroup v1/v2 的 cgroupfs 统计文件。另一个细节是命名空间core/metrics/metrics.go 的init()中注册了containerd命名空间并暴露build_info计数器含 version、revision 两个 label同时定义了ShimStatsRequestTimeoutio.containerd.timeout.metrics.shimstats默认 2 秒这个超时键——从源码结构看这意味着当前的指标体系除了 cgroup 统计还包含向 shim 发起 Stats RPC 的路径这是 2017 年直接读 cgroupfs阶段之后的自然扩展。需要注意一个演进差异2017 年报告中的指标名以containerd_container_开头如containerd_container_cpu_total_nanoseconds而当前插件创建的命名空间前缀是container即container_cpu_*这类名字从源码结构看这反映了多年间指标命名规范的调整直接引用旧文档指标名的既有监控规则需要重新核对。五、Image Pull首个端到端拉取的概念验证报告后半部分是 PR #640 带来的成果containerd 首次实现了端到端拉取的 proof of concept。它串联了 fetching、snapshot 驱动、rootfs 服务、镜像元数据与执行服务验证了 containerd 的子系统模型报告也坦承存在若干待办例如需要将部分访问逻辑移入 gRPC service。5.1dist pull完整拉取并展开根文件系统dist pull是当时docker pull/git pull的对应物对一个镜像执行完整的资源拉取并把根文件系统展开进 snapshot 驱动。报告给出的原始输出$ sudo ./bin/dist pull docker.io/library/redis:latest docker.io/library/redis:latest: resolved || manifest-sha256:4c8fb09e8d634ab823b1c125e64f0e1ceaf216025aa38283ea1b42997f1e8059: done || layer-sha256:3b281f2bcae3b25c701d53a219924fffe79bdb74385340b73a539ed4020999c4: done || config-sha256:e4a35914679d05d25e2fccfd310fde1aa59ffbbf1b0b9d36f7b03db5ca0311b0: done || layer-sha256:4b7726832aec75f0a742266c7190c4d2217492722dfd603406208eaa902648d8: done || layer-sha256:338a7133395941c85087522582af182d2f6477dbf54ba769cb24ec4fd91d728f: done || layer-sha256:83f12ff60ff1132d1e59845e26c41968406b4176c1a85a50506c954696b21570: done || layer-sha256:693502eb7dfbc6b94964ae66ebc72d3e32facd981c72995b09794f1e87bac184: done || layer-sha256:622732cddc347afc9360b4b04b46c6f758191a1dc73d007f95548658847ee67e: done || layer-sha256:19a7e34366a6f558336c364693df538c38307484b729a36fede76432789f084f: done || elapsed: 1.6 s total: 0.0 B (0.0 B/s) INFO[0001] unpacking rootfs输出中每行对应一个 OCI 内容对象先resolved镜像引用再依次完成 manifest、config blob 与 6 个 layer 的下载最后一行unpacking rootfs表明根文件系统正在展开到快照驱动——报告指出当时展开进度尚未并入状态输出但整体已经差不多就是今天 docker 的样子。5.2dist images镜像元数据视图拉取完成后用dist images查看结果$ sudo ./bin/dist images REF TYPE DIGEST SIZE docker.io/library/redis:latest application/vnd.docker.distribution.manifest.v2json sha256:4c8fb09e8d634ab823b1c125e64f0e1ceaf216025aa38283ea1b42997f1e8059 1.8 kB表格四列分别是引用名REF、镜像清单类型TYPE、摘要DIGEST与大小SIZE。报告特别说明此时 SIZE 显示的是 manifest 的大小而非整个镜像的大小后续可按需补充同时预告了命名模型的几个待完善点——例如希望同时按 hash 限定名和 tag 版本索引同一个镜像这些工作将在元数据存储metadata store开发中推进。5.3ctr run第一次真正跑起 redis拉下来的镜像名可直接用于运行容器$ sudo ./bin/ctr run --id foo docker.io/library/redis:latest /usr/local/bin/redis-server 1:C 17 Mar 17:20:25.316 # Warning: no config file specified, using the default config. In order to specify a config file use /usr/local/bin/redis-server /path/to/redis.conf 1:M 17 Mar 17:20:25.317 * Increased maximum number of open files to 10032 (it was originally set to 1024). ... Redis 3.2.8 (00000000/0) 64 bit ... 1:M 17 Mar 17:20:25.326 * The server is now ready to accept connections on port 6379中间的 ASCII 艺术 banner 已省略完整输出见原文 docs/historical/reports/2017-03-17.md。报告对此的定性是So, now we are running redis!——一个真实的 redis 3.2.8 进程以 PID 1 的身份在容器里监听 6379 端口。同时报告诚实地指出了 PoC 的局限必须在ctr run参数里显式写出容器命令因为当时还没有从镜像 configconfig.cmd读取命令并转换为 OCI runtime config 的逻辑报告判断基础已经打好补上这个功能应该很直接。5.4 对照当前代码ctr image pull的三步语义没有变今天对应dist pull的是ctr image pull其命令定义在 cmd/ctr/commands/images/pull.go。命令描述中明确的三步流程——1. Fetch all resources into containerd. 2. Prepare the snapshot filesystem with the pulled resources. 3. Register metadata for the image.——与 2017 年报告对dist pull的描述拉取全部资源 展开 rootfs 到 snapshot 驱动 记录镜像元数据一脉相承。从源码看当前实现比 2017 年的 PoC 更完整的地方包括拉取路径可选默认走 server 端的 transfer serviceclient.Transfer--local则退回客户端本地拉取content.Fetch两条路径分别对应 client/pull.go 中Client.Pull与 transfer 服务的协作平台选择支持--platform、--all-platforms与--skip-metadata解决 2017 年报告里命名与索引模型待完善的遗留问题——现在可以按平台精确拉取内容与元数据下载控制--max-concurrent-downloads通过 client/pull.go 中的transfer.WithMaxConcurrentDownloads作用于 resolver提供并发限制进度输出ProgressHandlercmd/ctr/commands/images/pull.go按父子节点构建进度树并调用DisplayHierarchy渲染层级化进度条——这正是 2017 年那种逐项 done 进度条输出形态的现代化版本展开参数--sync-fs透传给diff.WithSyncFs在 unpack 时同步文件系统--print-chainid则打印快照链 chain ID 用于校验。而 2017 年 PoC 的已知局限不读镜像 config、部分能力未进 gRPC service在今天的仓库中都已兑现ctr run相关能力由 client/task.go 与 client/container.go 承担镜像与内容的访问全部通过 gRPC serviceapi/services/ 下定义暴露给远端客户端。六、小结一份周报如何映射出 containerd 的演进主线2017-03-17 这份开发报告的四个章节恰好对应 containerd 的四条长期主线且在当前仓库中都能找到延续2017-03-17 报告条目当年状态当前仓库中的延续Testing Plan多平台 CI讨论启动按平台拆分的 Makefile 与集成测试Makefile.linux、integration/client/Windows Runtime移植启动pkg/cio/io_windows.go、core/mount/mount_windows.go 等完整 Windows 实现Prometheus 容器指标初始输出 按需采集core/metrics/cgroups/cgroups.go TaskMonitor 插件cgroup v1/v2、no_prometheus开关、core/metrics/metrics.go端到端 Image Pull PoCdist pull/dist images/ctr run跑通 rediscmd/ctr/commands/images/pull.go 的三步 pull 语义、client/pull.go 的 transfer 化实现阅读这份历史报告的最大价值在于它展示了 containerd 早期先验证模型、再逐步产品化的工程节奏——2017 年 3 月用一条dist pullctr run命令链证明架构可行随后几年再把指标、Windows、元数据、gRPC 化这些报告中的待办逐项兑现为今天 core/ 与 client/ 下的正式模块。【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。