Overview
图一:Overview
Containerd 一个容器运行时,管理容器完整的生命进程,包括拉取,构建,运行等,containerd 是为了嵌入到其他项目中运行的,所以提供的接口并不像 docker 一样简单,docekr 其实是基于 containerd 的,所以很多地方都推荐使用 containerd,因为 docker 只是 containerd 的封装。
Client
图二:Client
这里的 Client 是指的 SDK 中的 Client,containerd 还提供了 crd 作为命令行工具,containerd 对外暴露基本都是通过 GRPC 实现的。
Server
HandleSignals
图三:handleSignals
对于 Server 的推出,启动了一个 Goroutine,接受 os.Signal, 并且通过一个 chan 进行 Server 的延迟初始化,
Plugin
containerd 通过 Plugin 的形式可以很轻松的添加新的功能,其中它最为重要的功能 CRI,就是通过插件去支持的。Plugin 生成的结果可能是一个个的 Service,通过将这些 Service 注册到 Server 上(像 grpc 一样),containerd 就可以添加新的功能。
图三:Plugin
在程序启动时,会通过初始化的形式将进行注册,Containerd 通过将生成好的 Plugin 都添加到 InitContext 中,保证再 Init 过程中,可以使用其他的 Plugin 作为依赖,这就要求了调用 Init 的顺序必须是满足以来关系的,containerd 通过再 LoadPlugin 的最后,调用 Graph 将 register 中的插件顺序化,保证了这一点。
通过导入包,将 Service 注册,其中包含 initFn
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
ID: "images",
Requires: []plugin.Type{
plugin.ServicePlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
plugins, err := ic.GetByType(plugin.ServicePlugin) // 通过 Context 获取已经生成好的 plugin
if err != nil {
return nil, err
}
p, ok := plugins[services.ImagesService]
if !ok {
return nil, errors.New("images service not found")
}
i, err := p.Instance()
if err != nil {
return nil, err
}
return &service{local: i.(imagesapi.ImagesClient)}, nil
},
})
}