containerd 2.1.8 超深度分析 — Runtime + Task + Shim + ttrpc + Client SDK
源码:core/runtime/ (554行) + internal/shim/ (1566行) + cmd/containerd-shim-runc-v2/ (~8000行) + client/ (6744行) + pkg/shim/ (1566行)
一、Runtime 抽象层
1.1 PlatformRuntime 接口
type PlatformRuntime interface {
ID() string
Create(ctx context.Context, taskID string, opts CreateOpts) (Task, error)
Get(ctx context.Context, taskID string) (Task, error)
Tasks(ctx context.Context, all bool) ([]Task, error)
Delete(ctx context.Context, taskID string) (*Exit, error)
}
1.2 Task 接口
type Task interface {
ID() string
Namespace() string
PID() uint32
Start(ctx context.Context) error
Delete(ctx context.Context) (*Exit, error)
Kill(ctx context.Context, signal syscall.Signal, opts ...KillOpt) error
Wait(ctx context.Context) (*Exit, error)
Exec(ctx context.Context, id string, opts ExecOpts) (Process, error)
Pids(ctx context.Context) ([]ProcessInfo, error)
Resize(ctx context.Context, w, h uint32) error
IO() *IO
Status(ctx context.Context) (Status, error)
Checkpoint(ctx context.Context, opts ...CheckpointOpt) (Descriptor, error)
Update(ctx context.Context, opts ...UpdateTaskOpts) error
}
Task 状态
二、Shim 架构 — containerd-shim-runc-v2
2.1 为什么需要 Shim?
| 问题 |
Shim 解决方案 |
| containerd 崩溃 → 容器退出 |
Shim 独立于 containerd,containerd 重启不影响 |
| 信号转发 |
Shim 接收信号 → 转发给容器 init 进程 |
| 容器退出状态收集 |
Shim wait() 收集退出码 → 通知 containerd |
| reexec 安全 |
Shim 是独立进程,不共享文件描述符表 |
2.2 Shim v2 架构
v2 核心变化:一个 shim 进程管理多个容器(而非 v1 的一容器一 shim)。
2.3 Shim 生命周期
2.4 Shim Manager — 进程管理
type Manager struct {
runtime string
address string
containers map[string]*shim
tasks *nsmap.Namespaced[shimTask]
}
Shim 启动策略
| 策略 |
条件 |
行为 |
| 复用现有 Shim |
同 namespace + 同 runtime |
连接已有 shim socket |
| 新建 Shim |
不同 runtime 或首次 |
exec shim 二进制 |
| Sandbox Shim |
Pod 沙箱模式 |
一个 shim 管理 Pod 所有容器 |
三、ttrpc — 轻量级 RPC 协议
3.1 为什么用 ttrpc 而非 gRPC?
| 特性 |
gRPC |
ttrpc |
| 协议 |
HTTP/2 + protobuf |
自定义帧 + protobuf |
| 依赖 |
grpc-go (大量依赖) |
极小依赖 |
| Unix socket 性能 |
HTTP/2 开销大 |
帧协议高效 |
| 适用场景 |
外部客户端 |
shim 间通信 |
设计原因:shim 是短小精悍的进程,不能依赖 gRPC 的庞大运行时。
3.2 ttrpc 帧格式
+----------+--------+---------+
| Length | StreamID| Flags | Header (9 bytes)
+----------+--------+---------+
| Payload (protobuf) | Body (Length bytes)
+----------------------------+
四、Client SDK — Go 客户端
4.1 Client 结构体
type Client struct {
conn *grpc.ClientConn
defaultns string
runtime *runtimeOpts
services *serviceDescriptors
containers containersapi.ContainersClient
content types.ContentClient
diff diffapi.DiffClient
events types.EventClient
images imagesapi.ImagesClient
leases leasesapi.LeasesClient
namespaces namespacesapi.NamespacesClient
sandboxs sandboxsapi.ControllerClient
snapshots snapshotsapi.SnapshotsClient
tasks tasksapi.TasksClient
transfer transferapi.TransferClient
version versionservice.VersionClient
}
4.2 Client.New — 连接建立
func New(address string, opts ...Opt) (*Client, error) {
var copts clientOpts
for _, o := range opts {
o(&copts)
}
c := &Client{defaultns: copts.defaultns}
conn, err := grpc.NewClient(
dialer.DialAddress(address),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithContextDialer(dialer.ContextDialer),
)
c.conn = conn
c.containers = containersapi.NewContainersClient(conn)
c.content = types.NewContentClient(conn)
c.diff = diffapi.NewDiffClient(conn)
c.images = imagesapi.NewImagesClient(conn)
c.tasks = tasksapi.NewTasksClient(conn)
return c, nil
}
4.3 Container 操作
func (c *Client) NewContainer(ctx context.Context, id string, opts ...NewContainerOpts) (Container, error) {
}
type Container interface {
ID() string
Info(ctx context.Context, ...InfoOpts) (containers.Container, error)
Delete(ctx context.Context, ...DeleteOpts) error
NewTask(ctx context.Context, ioCreate cio.Creator, ...NewTaskOpts) (Task, error)
Spec(ctx context.Context) (*specs.Spec, error)
Image(ctx context.Context) (Image, error)
Labels(ctx context.Context) (map[string]string, error)
SetLabels(ctx context.Context, labels map[string]string) (map[string]string, error)
Extensions(ctx context.Context) (map[string]interface{}, error)
Update(ctx context.Context, ...UpdateContainerOpts) error
}
4.4 Task 操作
func (c *Container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...NewTaskOpts) (Task, error) {
}
type Task interface {
ID() string
PID() uint32
Start(ctx context.Context) error
Delete(ctx context.Context, ...DeleteOpts) (*ExitStatus, error)
Kill(ctx context.Context, signal syscall.Signal, ...KillOpts) error
Wait(ctx context.Context) (<-chan ExitStatus, error)
Exec(ctx context.Context, id string, opts ...ExecOpts) (Process, error)
Resize(ctx context.Context, w, h uint32) error
IO() *cio.IO
Status(ctx context.Context) (Status, error)
}
4.5 Pull 镜像
func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image, error) {
}
4.6 Client → gRPC → Plugin 调用链
五、Sandbox — Pod 级沙箱
5.1 Sandbox 接口
type Sandbox interface {
ID() string
Metadata() SandboxMetadata
Labels() map[string]string
Create(ctx context.Context, ...SandboxCreateOpt) error
Start(ctx context.Context) error
Stop(ctx context.Context) error
Wait(ctx context.Context) (<-chan ExitStatus, error)
Shutdown(ctx context.Context) error
Status(ctx context.Context) (SandboxStatus, error)
}
5.2 Sandbox Controller 接口
type Controller interface {
Create(ctx context.Context, sandboxID string, opts ...CreateOpt) (Sandbox, error)
Start(ctx context.Context, sandboxID string) (Sandbox, error)
Stop(ctx context.Context, sandboxID string) (Sandbox, error)
Wait(ctx context.Context, sandboxID string) (<-chan ExitStatus, error)
Shutdown(ctx context.Context, sandboxID string) error
}
两种 Sandbox 模式
| 模式 |
Controller |
描述 |
| PodSandbox |
podsandbox |
pause 容器作为沙箱 (CRI 兼容) |
| Custom |
第三方实现 |
自定义沙箱控制器 (例如 Firecracker) |
六、CRI Plugin — Kubernetes CRI 兼容
6.1 CRI 服务接口
type CRIService interface {
RuntimeServiceServer
ImageServiceServer
}
CRI RuntimeService 核心方法
| 方法 |
对应 containerd 操作 |
RunPodSandbox |
Sandbox.Create + Sandbox.Start |
StopPodSandbox |
Sandbox.Stop |
RemovePodSandbox |
Sandbox.Shutdown + Container.Delete |
CreateContainer |
Container.NewContainer |
StartContainer |
Task.Start |
StopContainer |
Task.Kill + Task.Wait |
RemoveContainer |
Task.Delete + Container.Delete |
ExecSync |
Task.Exec + Wait |
Exec |
Task.Exec (streaming) |
CRI ImageService 核心方法
| 方法 |
对应 containerd 操作 |
PullImage |
Transfer.Pull |
ListImages |
ImageStore.List |
ImageStatus |
ImageStore.Get |
RemoveImage |
Image.Delete |
七、Events — 异步事件总线
7.1 事件类型
| 事件 |
Topic |
触发时机 |
| ContainerCreate |
/containers/create |
容器创建 |
| ContainerUpdate |
/containers/update |
容器更新 |
| ContainerDelete |
/containers/delete |
容器删除 |
| TaskCreate |
/tasks/{id}/create |
任务创建 |
| TaskStart |
/tasks/{id}/start |
任务启动 |
| TaskExit |
/tasks/{id}/exit |
任务退出 |
| TaskDelete |
/tasks/{id}/delete |
任务删除 |
| ImageCreate |
/images/create |
镜像创建 |
| ImageUpdate |
/images/update |
镜像更新 |
| ImageDelete |
/images/delete |
镜像删除 |
| SnapshotPrepare |
/snapshots/prepare |
快照准备 |
| SnapshotCommit |
/snapshots/commit |
快照提交 |
事件发布-订阅
八、设计模式总结
| # |
模式 |
体现 |
| 1 |
Shim 隔离 |
独立进程,containerd 重启不影响 |
| 2 |
ttrpc 轻量协议 |
替代 gRPC 用于 shim 通信 |
| 3 |
多容器一 Shim |
v2 架构,减少进程数 |
| 4 |
Proxy 模式 |
Client → gRPC → Plugin → Shim |
| 5 |
Sandbox 抽象 |
Pod 级管理,支持自定义控制器 |
| 6 |
CRI 适配 |
CRI Service → containerd API 转换 |
| 7 |
事件总线 |
Publish/Subscribe 解耦 |
| 8 |
IO Creator |
cio.NewCreator/NewPipe 策略 |
| 9 |
Wait Channel |
Task.Wait → <-chan ExitStatus |
| 10 |
Namespace 隔离 |
gRPC metadata → context namespace |
所有评论(0)