【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 源码分析 的相关文章

  • 将列表拆分为多个具有固定元素数量的列表

    如何将元素列表拆分为最多包含 N 个项目的列表 例如 给定一个包含 7 个元素的列表 创建 4 个组 最后一组可能包含较少的元素 split List 1 2 3 4 5 6 seven 4 gt List List 1 2 3 4 Lis
  • 如何获取 android.widget.ImageView 的宽度和高度?

    ImageView Actual image 60px height of ImageView
  • 在列表列表中查找共同元素

    我有一个名为 wordlist 的单词列表列表 如下所示 dog cat sheep rabbit kiss time cow pig bomb cat sheep cake boy new 我想找到所有子列表中的共同元素 因此 我期望的上
  • 对自身内部列表的递归引用[重复]

    这个问题在这里已经有答案了 所以我在 python 中遇到了一些非常奇怪的东西 我尝试添加对列表本身的引用 该代码可能有助于比我能表达的更好地展示我所说的内容 我正在使用 IDLE 编辑器 交互模式 gt gt gt l 1 2 3 gt
  • 让 PHP 页面输出静态图像

    我希望 PHP 能够发送 3 张图像中的 1 张 具体取决于 GET 范围 我现在有三个独立的 PNG 图像 并且希望 PHP 脚本将这些图像嵌入其中 然后返回指定的图像 所以 我想要一个 PHP 脚本而不是 3 个图像 这可能吗 我不需要
  • 如何缩放图像的一部分并插入到 matplotlib 中的同一图中

    我想缩放数据 图像的一部分并将其绘制在同一个图中 看起来有点像这个图 是否可以在同一图中插入缩放图像的一部分 我认为可以用子图绘制另一个图形 但它绘制了两个不同的图形 我还阅读了添加补丁以插入矩形 圆形 但不确定将图像的一部分插入到图中是否
  • Go 中的 WebP 编码器/解码器

    是否有一个完整的 WebP 编码器和解码器与当前每周 或可分叉 兼容 它的速度与标准 png 相当吗 这个人在 GitHub 上有一个包 其中包含 WebP 的编码器和解码器 https github com chai2010 webp h
  • CGContextDrawImage 绘制非常模糊的大图像

    我正在尝试制作一个可以使用 CGContextDrawImage 绘制大图像 例如 2048 x 1537 图像的一部分的对象 它工作得很好 只是它非常模糊 我正在使用一个 drawingController 它覆盖了drawLayer i
  • 使应用程序背景适合不同设备的最佳方法

    因此 我希望通过一些漂亮的背景图像等来为我的应用程序增添一点趣味 但我很好奇的是如何确保不同的机器人正确渲染 我将在文本后面设置背景 并且我需要确保它们对于每个不同的屏幕尺寸和分辨率具有相同的尺寸和位置 有这方面好的教程吗 Thanks E
  • 按属性对对象列表进行排序 C#

    我有这门课 public class Leg public int Day get set public int Hour get set public int Min get set 我有一个获取腿列表的函数 称为 GetLegs Lis
  • React Native 中文本的图像识别

    这可能是一个疯狂的问题 但我已经看到应用程序完成了 是否有任何类型的 API 可用于识别图像中的文本 Chase 识别支票上的数字的方式 或者是否有一个 API 可用于搜索 比如谷歌 基于图像的信息 例如 如果我拍了一张企业徽标的照片 谷歌
  • Python 中两个列表列表的高效比较

    我是 python 的新手 只是在做项目时学习一些东西 这里我有两个列表列表 我需要比较和分离 A gt B 中找到的差异和 b gt A 中找到的差异 最好的比较方法是什么 A 1L test case 1 1L test case 2
  • 查找字典中列表的最大值

    我有一个字典 每个键后面都有一个存储的列表 看起来像这样 dict with values u New York u New York u NY datetime datetime 2014 8 13 0 0 10 u New York u
  • 使用部分函数短路列表映射

    因此 我创建了一个名为 tryMap 的函数 如下所示 tryMap with failure and success continuations let rec tryMapC R gt U list gt R gt T gt U opt
  • 为什么我的图像下方有空间? [复制]

    这个问题在这里已经有答案了 图像在下面获得了神秘的空白空间 即使padding 0 margin 0被应用 示范 http jsfiddle net cLETP 红色边框应该包围图像 但底部有空间 造成这种情况的原因是什么 如何删除该空间
  • PHP - 获取base64图像字符串解码并保存为jpg(生成空图像)

    嗨 我实际上是通过 ajax 发送一个 base64 图像字符串到一个 php 脚本 该脚本只是解码字符串并将内容保存为 jpg 文件 但结果是一张空图像 这怎么可能 PHP脚本 uploadedPhotos array photo 1 p
  • 当我使用 Image.FromFile() 时 FileNotFound

    我在这种情况下使用 Image FromFile string 方法 using System using System Collections Generic using System ComponentModel using Syste
  • 访问图像的 Windows“标签”元数据字段

    我正在尝试进行一些图像处理 所以现在我正在尝试读取图像 exif 数据 有 2 个内置函数可用于读取图像的 exif 数据 问题是我想读取图像标签 exifread and imfinfo这两个函数都不显示图像标签 Is there any
  • 在 Android 中调整可绘制对象的大小

    我正在为进度对话框设置一个可绘制对象 pbarDialog 但我的问题是我想每次调整可绘制的大小 但不知道如何调整 这是一些代码 Handler progressHandler new Handler public void handleM
  • 如何制作 Bash 脚本来查找项目中未使用的图像?

    如何制作一个 Bash shell 脚本 它可以识别所有 jpg gif 和 png 文件 然后识别文件夹中任何文本文件中哪些文件未通过 url href 或 src 链接 这就是我开始的 但我最终得到了与我想要的相反的结果 我不想知道引用

随机推荐