containerd 插件体系完全指南:从代理插件到内置插件

发布时间:2026/9/13 13:32:40

containerd 插件体系完全指南:从代理插件到内置插件 containerd 插件体系完全指南从代理插件到内置插件【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerd本篇技术指南以 containerd 官方文档 docs/PLUGINS.md 为核心骨架系统讲解 containerd 的可扩展插件架构包括智能客户端设计理念、通过二进制与 gRPC 代理两种方式扩展外部插件、V2 运行时shim的接入机制以及内置插件的管理与配置。读完本文你将掌握如何在无需重新编译守护进程的前提下为 containerd 接入自定义快照器snapshotter、内容存储content store与差异应用器diff applier并能够正确使用ctr plugins ls与containerd config排查插件加载问题。插件化设计的总体思路containerd 通过其定义的大部分接口来支持功能扩展包括自定义运行时runtime、快照器snapshotter、内容存储content store甚至可以新增 gRPC 接口。这意味着生态中的第三方实现如各类远程快照器、专用内容校验服务都能以标准方式接入而不必修改 containerd 主程序。智能客户端模型containerd 采用智能客户端Smart Client架构凡是守护进程不强制需要的功能都交由客户端完成。这包括大多数高层交互例如创建容器的 specOCI 运行时规范与镜像仓库registry交互从 tar 归档加载镜像。containerd 的 Go 客户端见 client/client.go为用户提供了大量的扩展点从创建容器时的自定义 option到镜像仓库名称解析都可以在客户端侧注入自定义逻辑。这一设计让守护进程保持精简与稳定把灵活性下放到客户端生态中。外部插件无需重新编译的两种扩展方式外部插件允许使用官方发布版本的 containerd 即可扩展功能无需重新编译守护进程。containerd 通过两种方法支持扩展通过 containerd PATH 中的可执行文件典型代表是 V2 运行时 shim通过配置 containerd 代理到另一个 gRPC 服务即代理插件。V2 运行时以二进制方式扩展containerd 支持多种容器运行时每个容器都可以使用不同的运行时启动。运行时名称既可以是 URI 风格的字符串如io.containerd.runc.v2也可以是可执行文件的真实路径。当使用 CRI 插件时可以在 containerd 配置文件中定义命名运行时named runtimes创建容器时未指定运行时时使用配置的默认运行时也可以显式指定某个命名运行时通过 CRI gRPC 的runtime_handler字段选择要使用的运行时处理器。当ctr或nerdctl这类客户端创建容器时可以可选地指定运行时及其选项若未指定containerd 使用默认运行时。containerd 将 V2 运行时作为系统上的二进制来调用用它们启动 containerd 的 shim 进程。这允许 containerd 使用运行时 shim 二进制返回的 runtime shim API 来启动和管理容器。关于运行时与 shim 的完整说明包括如何调用与配置参见 core/runtime/v2/README.md。从源码结构看URI 风格的运行时名称会被转换为二进制名将.替换为-取最后两个组件并加上containerd-shim前缀。例如io.containerd.runc.v2对应containerd-shim-runc-v2二进制它位于 containerd 的 PATH 中本仓库即提供了该 shim 的实现入口 cmd/containerd-shim-runc-v2/main.go。代理插件Proxy Plugins以 gRPC 服务方式扩展代理插件通过 containerd 的配置文件进行配置会在 containerd 启动时与内置插件一同加载。这些插件通过一个本地 socket与 containerd 相连socket 上提供 containerd 的某个 gRPC API 服务。每个插件与内置插件一样都配有type和name。从实现侧看cmd/containerd/server/server.go 的LoadPlugins函数遍历配置中的代理插件根据type建立对应的 gRPC 客户端并包装成 containerd 内部接口。当前支持的代理插件类型在源码中明确可查type取值对应接口源码依据snapshot快照器接口snapshots.Snapshottercore/snapshots/snapshotter.gocontent内容存储接口core/content/content.godiff差异应用接口core/diff/diff.gosandbox沙箱控制器接口core/sandbox/controller.go此外cmd/containerd/server/config/config.go 中的ProxyPlugin结构体还支持platform、exports、capabilities等可选字段分别用于声明插件运行的平台、导出元数据与能力集合。代理插件配置示例配置文件默认位于/etc/containerd/config.toml。添加[proxy_plugins]段落并为具体插件添加[proxy_plugins.name]子段落。address必须指向 containerd 进程有权限访问的本地 socket 文件version 2 [proxy_plugins] [proxy_plugins.customsnapshot] type snapshot address /var/run/mysnapshotter.sock实现一个代理插件实现代理插件本质上就是为对应服务实现 gRPC API。在 Go 中相关服务接口位于仓库的 api/services 目录下例如内容存储服务api/services/content/v1ContentServer接口快照服务api/services/snapshots/v1SnapshotsServer接口差异服务api/services/diff/v1DiffServer接口。下面的示例创建了一个快照插件二进制它可以与任何满足snapshots.Snapshotter接口的实现配合使用源码示例见 contrib/snapshotservice/service.go 的FromSnapshotter转换函数package main import ( fmt net os google.golang.org/grpc snapshotsapi github.com/containerd/containerd/api/services/snapshots/v1 github.com/containerd/containerd/v2/contrib/snapshotservice github.com/containerd/containerd/v2/plugins/snapshots/native ) func main() { // 提供一个 unix 地址用于监听这就是 proxy_plugin 配置中的 address // root 目录用于存放快照 if len(os.Args) 3 { fmt.Printf(invalid args: usage: %s unix addr root\n, os.Args[0]) os.Exit(1) } // 创建 gRPC 服务器 rpc : grpc.NewServer() // 配置你的自定义快照器本示例使用内置的 native 快照器和一个根目录。 // 相比内置快照器自定义快照器往往能提供更有价值的特性。 sn, err : native.NewSnapshotter(os.Args[2]) if err ! nil { fmt.Printf(error: %v\n, err) os.Exit(1) } // 将快照器转换为 gRPC 服务 service : snapshotservice.FromSnapshotter(sn) // 向 gRPC 服务器注册服务 snapshotsapi.RegisterSnapshotsServer(rpc, service) // 监听并提供服务 l, err : net.Listen(unix, os.Args[1]) if err ! nil { fmt.Printf(error: %v\n, err) os.Exit(1) } if err : rpc.Serve(l); err ! nil { fmt.Printf(error: %v\n, err) os.Exit(1) } }将上述代码与前面的配置配合使用可以这样运行一个快照插件# 在一个终端中启动插件 $ go run ./main.go /var/run/mysnapshotter.sock /tmp/snapshots # 在另一个终端中使用 ctr $ CONTAINERD_SNAPSHOTTERcustomsnapshot ctr images pull docker.io/library/alpine:latest $ tree -L 3 /tmp/snapshots /tmp/snapshots |-- metadata.db -- snapshots -- 1 |-- bin |-- dev |-- etc |-- home |-- lib |-- media |-- mnt |-- proc |-- root |-- run |-- sbin |-- srv |-- sys |-- tmp |-- usr -- var 18 directories, 1 file可以看到CONTAINERD_SNAPSHOTTERcustomsnapshot环境变量让ctr选择名为customsnapshot的代理快照器拉取镜像后/tmp/snapshots下生成了metadata.db元数据文件与按快照层snapshots/1组织的完整 rootfs 目录树。内置插件内部实现与外部插件平权containerd 在内部也大量使用插件机制目的是确保内部实现解耦、稳定并且与外部插件平权对待。查看 containerd 全部插件使用$ ctr plugins ls TYPE ID PLATFORMS STATUS io.containerd.content.v1 content - ok io.containerd.snapshotter.v1 btrfs linux/amd64 ok io.containerd.snapshotter.v1 aufs linux/amd64 error io.containerd.snapshotter.v1 native linux/amd64 ok io.containerd.snapshotter.v1 overlayfs linux/amd64 ok io.containerd.snapshotter.v1 zfs linux/amd64 error io.containerd.metadata.v1 bolt - ok io.containerd.differ.v1 walking linux/amd64 ok io.containerd.gc.v1 scheduler - ok io.containerd.service.v1 containers-service - ok io.containerd.service.v1 content-service - ok io.containerd.service.v1 diff-service - ok io.containerd.service.v1 images-service - ok io.containerd.service.v1 leases-service - ok io.containerd.service.v1 namespaces-service - ok io.containerd.service.v1 snapshots-service - ok io.containerd.runtime.v1 linux linux/amd64 ok io.containerd.runtime.v2 task linux/amd64 ok io.containerd.monitor.v1 cgroups linux/amd64 ok io.containerd.service.v1 tasks-service - ok io.containerd.internal.v1 restart - ok io.containerd.grpc.v1 containers - ok io.containerd.grpc.v1 content - ok io.containerd.grpc.v1 diff - ok io.containerd.grpc.v1 events - ok io.containerd.grpc.v1 healthcheck - ok io.containerd.grpc.v1 images - ok io.containerd.grpc.v1 leases - ok io.containerd.grpc.v1 namespaces - ok io.containerd.grpc.v1 snapshots - ok io.containerd.grpc.v1 tasks - ok io.containerd.grpc.v1 version - ok io.containerd.grpc.v1 cri linux/amd64 ok输出中可以看到全部插件以及未成功加载的插件。在上面的例子中aufs和zfs未能加载是预期行为——当前机器不支持它们。日志会说明失败原因你也可以用-d选项获取更详细的信息$ ctr plugins ls -d idaufs idzfs Type: io.containerd.snapshotter.v1 ID: aufs Platforms: linux/amd64 Exports: root /var/lib/containerd/io.containerd.snapshotter.v1.aufs Error: Code: Unknown Message: modprobe aufs failed: modprobe: FATAL: Module aufs not found in directory /lib/modules/4.17.2-1-ARCH\n: exit status 1 Type: io.containerd.snapshotter.v1 ID: zfs Platforms: linux/amd64 Exports: root /var/lib/containerd/io.containerd.snapshotter.v1.zfs Error: Code: Unknown Message: path /var/lib/containerd/io.containerd.snapshotter.v1.zfs must be a zfs filesystem to be used with the zfs snapshotter-d输出中的Exports展示了插件导出的元数据例如快照器根目录Error段则给出了插件返回的具体错误信息说明插件无法加载的原因——本例中aufs是因为内核模块缺失zfs是因为目标路径不是 zfs 文件系统。内置插件的配置插件通过配置文件的[plugins]段落配置。每个插件都可以使用[plugins.plugin type.plugin id]模式拥有自己的配置段落version 2 [plugins] [plugins.io.containerd.monitor.v1.cgroups] no_prometheus false查看完整配置示例可运行containerd config default若想获得默认配置与你的配置合并后的结果运行containerd config dump。插件的类型常量如io.containerd.snapshotter.v1、io.containerd.differ.v1、io.containerd.content.v1、io.containerd.sandbox.controller.v1集中定义在 plugins/types.go这也是ctr plugins ls输出中 TYPE 列的直接来源。配置版本Version headercontainerd 有多个配置版本Version 3containerd 2.x 推荐在 containerd 2.0 引入此版本中部分插件 ID 发生了变化例如 cgroups monitor 插件从io.containerd.monitor.v1.cgroups变为io.containerd.monitor.task.v1.cgroupsVersion 2containerd 1.x 推荐在 containerd 1.3 引入containerd v2.x 仍支持。插件 ID 改为带io.containerd.前缀的完整限定形式Version 1在 containerd 1.0 引入containerd 2.0 中已移除。Version 2 或 3的配置必须在头部指定version 2或version 3并且[plugins]段落必须使用完整限定的插件 IDversion 3 [plugins] [plugins.io.containerd.monitor.task.v1.cgroups] no_prometheus falseversion 2 [plugins] [plugins.io.containerd.monitor.v1.cgroups] no_prometheus falseVersion 1的配置不得有version头也不需要完整限定插件 ID[plugins] [plugins.cgroups] no_prometheus false从 cmd/containerd/server/config/config.go 的结构定义看ProxyPlugins与[plugins]在配置结构中并列存在前者管理外部 gRPC 代理插件后者承载所有内置插件的参数。Decode方法同文件 config.go负责按插件 ID 解码对应配置并对未知 TOML 键给出告警而非直接报错这保证了配置的向前兼容性。小结containerd 的插件体系遵循一切皆插件、内外平等的原则智能客户端把高层逻辑放到客户端侧守护进程保持精简V2 运行时通过 PATH 中的二进制shim扩展容器执行能力代理插件通过本地 socket 上的 gRPC 服务扩展快照、内容、差异乃至沙箱能力全程无需重新编译守护进程内置插件与外部插件采用同一套注册、加载与配置机制ctr plugins ls -d是排查插件加载失败的第一手工具。动手实践时可从containerd config default生成完整配置骨架再按本文的代理插件示例接入自己的快照器实现并结合ctr plugins ls验证加载状态。【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/13 13:27:40

单片机复位电路四大方案:从RC到监控型复位全解析

1. 复位键失灵不是玄学,是电路设计在“说谎” 你手里的开发板按了复位键,LED没灭、串口没停、程序还在跑——这绝不是单片机成精了,而是复位信号根本没送到CPU的RST引脚上。我干嵌入式硬件十年,修过上千块板子,90%的“…

2026/9/13 14:12:42

无人机集群协同攻击仿真系统的Matlab实现与优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 14:12:42

Linux设备驱动开发实战:从字符设备到设备树与I2C

Linux设备驱动开发:从字符设备框架到设备树与I2C,一位嵌入式老兵的实战笔记先说说为什么想写这篇东西。前阵子帮一个转行的朋友梳理驱动开发的学习路线,发现网上的资料要么太散,要么直接扔给你一堆源码注释,看完还是一…

2026/9/13 14:12:42

Windows下用WSL2跑vLLM:从零部署Qwen3-8B-FP8

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 14:12:42

ECS自建MySQL迁移到RDS MySQL实战:成本、流程与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 14:07:42

Taro开发微信小程序全流程技术解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/13 11:18:28

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码