【containerd 源码分析】containerd image list 源码分析

2023-05-16

    本文分析 containerd 列出所有镜像的分析过程,包括 ctr image 命令行以及 containerd daemon 执行 过程,也包含镜像 metadata,content 等内容。

1. 执行如下命令 ctr images list

    首先分析 ctr 命令,实现在 cmd/ctr 的子命令 listCommand 实现,利用 GRPC 链接到 remote cotainerd 端请求,使用了如下两个服务,其中 imageStore 实现了文件 image/images.go 的 Store 接口,cs 实现了 content/content.go Store 接口,如下 1.1 1.2 所示:

imageStore = client.ImageService()
cs         = client.ContentStore()

   1.1 文件 image/image.go 接口 Store

    Store 接口很好理解,增删改查的操作。

// Store and interact with images
type Store interface {
	Get(ctx context.Context, name string) (Image, error)
	List(ctx context.Context, filters ...string) ([]Image, error)
	Create(ctx context.Context, image Image) (Image, error)

	// Update will replace the data in the store with the provided image. If
	// one or more fieldpaths are provided, only those fields will be updated.
	Update(ctx context.Context, image Image, fieldpaths ...string) (Image, error)

	Delete(ctx context.Context, name string, opts ...DeleteOpt) error
}

   1.2 文件 content/content.go 接口 Store

    Store 接口🈶包含四个匿名接口, Manager 提供了 content 接口, Provider 提供了指定内容的读接口, IngestManager 提供了管理 ingest 的方法, Ingester 提供了写 content 的方法。

// Store combines the methods of content-oriented interfaces into a set that
// are commonly provided by complete implementations.
type Store interface {
	Manager
	Provider
	IngestManager
	Ingester
}

2. 向 containerd 发起 list 请求 

imageList, err := imageStore.List(ctx, filters...)

   2.1 containerd 处理 GRPC ListImagesRequest 请求

    其核心处理函数在 containerd/services.images/service.go 文件中 List 方法。

func (c *imagesClient) List(ctx context.Context, in *ListImagesRequest, opts ...grpc.CallOption) (*ListImagesResponse, error) {
	out := new(ListImagesResponse)
	err := c.cc.Invoke(ctx, "/containerd.services.images.v1.Images/List", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

    2.2 service List 方法

    看出最终调用的是 local.List 方法, 那主要分析到 local 实现也在相同目录 containerd/services.images 中。

func (s *service) List(ctx context.Context, req *imagesapi.ListImagesRequest) (*imagesapi.ListImagesResponse, error) {
	return s.local.List(ctx, req)
}

   2.3 结构体 local

   其中又包含三个接口, store gcScheduler Publisher, local 实现了 ImagesClient 的接口

type local struct {
	store     images.Store
	gc        gcScheduler
	publisher events.Publisher
}

var _ imagesapi.ImagesClient = &local{}

   2.4 初始化 init 注册插件 io.containerd.service.v1

    io.containerd.service.v1 需要插件 io.containerd.metadata.v1 和 io.containerd.gc.v1, 可以看出来 store 接口是插件 io.containerd.metadata.v1 实现的。 在看看 metadata 初始化插件

func init() {
	plugin.Register(&plugin.Registration{
		Type: plugin.ServicePlugin,
		ID:   services.ImagesService,
		Requires: []plugin.Type{
			plugin.MetadataPlugin,
			plugin.GCPlugin,
		},
		InitFn: func(ic *plugin.InitContext) (interface{}, error) {
			m, err := ic.Get(plugin.MetadataPlugin)
			if err != nil {
				return nil, err
			}
			g, err := ic.Get(plugin.GCPlugin)
			if err != nil {
				return nil, err
			}

			return &local{
				store:     metadata.NewImageStore(m.(*metadata.DB)),
				publisher: ic.Events,
				gc:        g.(gcScheduler),
			}, nil
		},
	})
}

   2.5 插件 metadata 初始化

    可以看出来使用的 db 为 bolt, 在 io.containerd.metadata.v1.bolt 目录创建了数据库文件 meta.db。

	plugin.Register(&plugin.Registration{
		Type: plugin.MetadataPlugin,
		ID:   "bolt",
		Requires: []plugin.Type{
			plugin.ContentPlugin,
			plugin.SnapshotPlugin,
		},
		Config: &srvconfig.BoltConfig{
			ContentSharingPolicy: srvconfig.SharingPolicyShared,
		},
		InitFn: func(ic *plugin.InitContext) (interface{}, error) {
            .........................
			db, err := bolt.Open(path, 0644, &options)
			close(doneCh)
			if err != nil {
				return nil, err
			}

			var dbopts []metadata.DBOpt
			if !shared {
				dbopts = append(dbopts, metadata.WithPolicyIsolated)
			}
			mdb := metadata.NewDB(db, cs.(content.Store), snapshotters, dbopts...)

    回到正题, 还是继续看 List 流程, 可以看到调用了 store.List 方法, 实现为 boltdb 数据库。

func (l *local) List(ctx context.Context, req *imagesapi.ListImagesRequest, _ ...grpc.CallOption) (*imagesapi.ListImagesResponse, error) {
	images, err := l.store.List(ctx, req.Filters...)
	if err != nil {
		return nil, errdefs.ToGRPC(err)
	}

	return &imagesapi.ListImagesResponse{
		Images: imagesToProto(images),
	}, nil
}

    这里以 namespace 作为 bucket, 剩下的就从 boltdb 读取, key value 读取完成,  具体内容在后续 pull 镜像讲解。

func (s *imageStore) List(ctx context.Context, fs ...string) ([]images.Image, error) {
	namespace, err := namespaces.NamespaceRequired(ctx)
	if err != nil {
		return nil, err
	}

总结:

   list image 依赖 metadata 数据库 boltdb 读取 key,value

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【containerd 源码分析】containerd image list 源码分析 的相关文章

  • 正在使用 PIL 保存损坏的图像

    我遇到一个问题 操作图像像素导致保存损坏的图像 因此 我使用 PIL 打开图像 然后将其转换为 NumPy 数组 image Image open myimage png np image np asarray image 然后 我转置图像
  • 将签名位图转换为签名字符串(很奇怪的一个)

    基本上我需要将位图图像转换为字符串 但这不是常见的 困境在于该字符串由两部分组成 1 积分 2 线路 我需要将图像转换为由 分隔的两个部分 我得到的一个例子是 221A 221A270A270A25032503200720071716171
  • Python:如何在不先创建整个列表的情况下计算列表的总和?

    通常我们必须 1 声明一个列表 2 使用以下方法计算该列表的总和sum 但现在我希望指定一个以 1 开头 间隔为 4 100 个元素的列表 如下所示 1 5 9 13 17 21 25 29 33 37 我不想涉及数学公式 所以 1 如何在
  • 使用 jQuery 清除 IMG

    我正在尝试从 a 中删除加载的图像 img 元素 但清除或删除 src 不会执行此操作 该怎么办 HTML img src https www google com images srpr logo3w png JQUERY img att
  • 图像梯度角计算

    我实际上是按照论文的说明进行操作的 输入应该是二进制 边缘 图像 输出应该是一个新图像 并根据论文中的说明进行了修改 我对指令的理解是 获取边缘图像的梯度图像并对其进行修改 并使用修改后的梯度创建一个新图像 因此 在 MATLAB Open
  • 在Python中按属性获取对象列表中的索引

    我有具有属性 id 的对象列表 我想找到具有特定 id 的对象的索引 我写了这样的东西 index 1 for i in range len my list if my list i id specific id index i break
  • 如何以编程方式将多个 JPEG 合并为无损 wav 中的更大 JPEG (.net)

    我有几张 JPEG 图像 我想将它们组合成一张大 JPEG 图像 我可以通过创建一个来做到这一点Bitmap然后将它们组合在一起 但这样如果我再次将其保存为 JPEG 图像将会恶化 那么 有没有什么方法可以在解码 编码时在不损失质量的情况下
  • 正确的标头 php mysql blob 显示图像

    我正在尝试在我的 PHP 页面中显示来自 mysql blob 的图像 我知道这不是最佳实践 然后我会将其引入我的 iOS 应用程序中 我在设置页面标题时遇到问题 我认为需要将其设置为图像 所以 这显示了图像 但我不相信页眉是正确的 hea
  • 对 numpy 数组中存在的元组中的列进行切片

    我已将一个文本文件导入到 numpy 数组中 如下所示 data np genfromtxt f dtype None delimiter names None 其中 f 包含我的 csv 文件的路径 现在数据包含以下内容 array 53
  • 如何从链表中删除节点?

    将整数添加到列表中工作正常 但删除和打印时出现问题 我对调试器还不友好 但我发现节点指针 first 有错误 它的值为 17891602 我不知道发生了什么事 include
  • 我可以在没有 http 处理程序的情况下隐藏 ASP.NET 页面上的图像路径吗?

    我的网站结构中的目录下有许多静态图像 并且我不关心图像的热链接或复制保护 由于多种原因 我需要做的不是在网站上显示图像路径 或显示假路径 有什么方法可以在不求助于 http 处理程序或辅助 asp net 页面的情况下执行此操作吗 你可以使
  • 返回列表的前 n 个

    如何返回第一个n列表的元素 这是我所拥有的 define returns lambda list n cond null list 0 n n 1 car list cons car list returns cdr list n else
  • Python 的高效图像缩略图控制?

    Python GUI 应用程序显示大量缩略图的最佳选择是什么 例如10000 或更多 出于性能原因 此类缩略图控件必须支持虚拟项目 即仅请求应用程序当前对用户可见的那些缩略图 In wxPython http wxpython org 您可
  • 添加到列表时有没有办法避免循环?

    我想知道这样的代码 List
  • 如何使用foldr为列表创建显示实例?

    我想为我的数据类型 我的列表 编写自己的显示实例 到目前为止 我的方法是有效的 但我总是在末尾有一个逗号 我已经尝试用最后一个元素启动折叠并将其从列表中删除 但它很麻烦而且不起作用 有没有更简单的方法来获得正确的解决方案 实际 1 2 3
  • 考虑到我的图像链接存储在MySQL数据库中,如何通过php显示存储在文件夹中的图像

    作为良好的做法 我只将图像链接存储在数据库中 问题是 我应该如何存储图像的链接 假设它在 c 上 c image jpg 我应该使用哪段 PHP 代码来显示该图像 我只显示路径 我该怎么做才能显示图像 我可以用这个吗 query SELEC
  • 如何通过 md5 比较图像?

    该方法是否比较图像的像素值 我猜它不会起作用 因为它们的尺寸彼此不同 但如果它们相同但格式不同怎么办 例如 我截图并保存为 jpg另一个并保存为 gif MD5哈希是实际的二进制数据 因此不同的格式将具有完全不同的二进制数据 因此 要使 M
  • 无法使用 SLComposeViewController 将图像发布到 Facebook?

    我想将图像发布到 Facebook 和 Twitter 我对 twitter 很满意 但对使用 SLComposeViewController 类的 facebook 不太满意 无需添加图像 我就可以将文本和网址发布到 Facebook 中
  • 哪个更快:清除集合或实例化新集合

    我的代码中有一些通用列表 其中有数十或数百个元素 有时我需要用其他对象重新填充此列表 所以问题是 调用什么会更快Clear 方法或创建一个new List
  • R 中的整数或双精度列表

    我有一个大约 1000 个整数的列表 我需要能够进行一些数学计算 但它们被困在列表或字符形式中 我怎样才能切换它们以便它们可用 样本数据 gt y 1 1 7 3 1 6 7 1 7 6 5 3 1 3 3 0 6 2 4 9 19 1 9

随机推荐