Overview

containerd-overview.png
图一:Overview

Containerd 一个容器运行时,管理容器完整的生命进程,包括拉取,构建,运行等,containerd 是为了嵌入到其他项目中运行的,所以提供的接口并不像 docker 一样简单,docekr 其实是基于 containerd 的,所以很多地方都推荐使用 containerd,因为 docker 只是 containerd 的封装。

Client

containerd-client.png
图二:Client
这里的 Client 是指的 SDK 中的 Client,containerd 还提供了 crd 作为命令行工具,containerd 对外暴露基本都是通过 GRPC 实现的。

Server

HandleSignals

containerd-handleSignal.png
图三:handleSignals
对于 Server 的推出,启动了一个 Goroutine,接受 os.Signal, 并且通过一个 chan 进行 Server 的延迟初始化,

Plugin

containerd 通过 Plugin 的形式可以很轻松的添加新的功能,其中它最为重要的功能 CRI,就是通过插件去支持的。Plugin 生成的结果可能是一个个的 Service,通过将这些 Service 注册到 Server 上(像 grpc 一样),containerd 就可以添加新的功能。

containerd-plugin.png
图三:Plugin

在程序启动时,会通过初始化的形式将进行注册,Containerd 通过将生成好的 Plugin 都添加到 InitContext 中,保证再 Init 过程中,可以使用其他的 Plugin 作为依赖,这就要求了调用 Init 的顺序必须是满足以来关系的,containerd 通过再 LoadPlugin 的最后,调用 Graph 将 register 中的插件顺序化,保证了这一点。

通过导入包,将 Service 注册,其中包含 initFn

  1. func init() {
  2. plugin.Register(&plugin.Registration{
  3. Type: plugin.GRPCPlugin,
  4. ID: "images",
  5. Requires: []plugin.Type{
  6. plugin.ServicePlugin,
  7. },
  8. InitFn: func(ic *plugin.InitContext) (interface{}, error) {
  9. plugins, err := ic.GetByType(plugin.ServicePlugin) // 通过 Context 获取已经生成好的 plugin
  10. if err != nil {
  11. return nil, err
  12. }
  13. p, ok := plugins[services.ImagesService]
  14. if !ok {
  15. return nil, errors.New("images service not found")
  16. }
  17. i, err := p.Instance()
  18. if err != nil {
  19. return nil, err
  20. }
  21. return &service{local: i.(imagesapi.ImagesClient)}, nil
  22. },
  23. })
  24. }