栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

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

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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

1. 执行如下命令 ctr image pull

    首先分析 ctr 命令,实现在 cmd/ctr 的子命令 listCommand 实现,利用 GRPC 链接到 remote cotainerd 端请求,核心函数 img, err := c.fetch(ctx, fetchCtx, ref, 0)

1.1 fetch 函数

    Resolver.Resolve 向 docker registry 请求 mainifest 文件清单, 本文示例镜像 docker.io/library/nginx:latest, 具体实现就不详细讲解, remotes/docker/resolver.go 中 dockerResolver 结构体实现了 Resolver 接口。

func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, limit int) (images.Image, error) {
	store := c.ContentStore()
	name, desc, err := rCtx.Resolver.Resolve(ctx, ref)

   name: 为 docker.io/library/nginx:latest;

   desc 为如下内容, Digest 在 response 的 header 里返回的;

   1.2 dockerResolver 实现 Fetcher 方法

    将镜像进行分析,包括远端 registry 名称, 仓库名称, tag等, 发请求就知道 host 地址

func (r *dockerResolver) Fetcher(ctx context.Context, ref string) (remotes.Fetcher, error) {
	base, err := r.resolveDockerBase(ref)
	if err != nil {
		return nil, err
	}

	return dockerFetcher{
		dockerBase: base,
	}, nil
}

   1.3 Dispatch 核心函数

   参数 handler 切片包含多个 handler 函数, descs 镜像的文件清单, 递归把子文件清单也处理了。 接着看几个关键的 handler 函数。

func Dispatch(ctx context.Context, handler Handler, limiter *semaphore.Weighted, descs ...ocispec.Descriptor) error {
	eg, ctx2 := errgroup.WithContext(ctx)
	for _, desc := range descs {
		desc := desc

		eg.Go(func() error {
			desc := desc

			children, err := handler.Handle(ctx2, desc)

			if len(children) > 0 {
				return Dispatch(ctx2, handler, limiter, children...)
			}

			return nil
		})
	}

	return eg.Wait()
}
		handlers := append(rCtx.BaseHandlers,
			remotes.FetchHandler(store, fetcher),
			convertibleHandler,
			childrenHandler,
			appendDistSrcLabelHandler,
		)

2. remotes FetchHandler 

   这里 ingester 是 store 接口, 实现的是 proxyContentStore 结构体, 路径为 content/proxy/content_store.go 文件, 其向 containerd 守护进程发起 GRPC 请求。 接着看 fetch 函数实现。

// FetchHandler returns a handler that will fetch all content into the ingester
// discovered in a call to Dispatch. Use with ChildrenHandler to do a full
// recursive fetch.
func FetchHandler(ingester content.Ingester, fetcher Fetcher) images.HandlerFunc {
	return func(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error) {
		switch desc.MediaType {
		default:
			err := fetch(ctx, ingester, fetcher, desc)
			return nil, err
		}
	}
}
   2.1 fetch 函数

    content.OpenWriter 向 containerd 发送 GRPC WriteContentRequest 请求, 包括 ref, total, digest。在看 containerd 处理 WriteContentRequest 请求。 containerd 先写入到 io.containerd.content.v1.content/ingest 下, 最后 commit GRPC WriteContentRequest 请求成功时在移入到 io.containerd.content.v1.content/blobs/sha256 目录下。

    fetcher.Fetch 实现在 remotes/docker/fetcher.go

func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc ocispec.Descriptor) error {
	cw, err := content.OpenWriter(ctx, ingester, content.WithRef(MakeRefKey(ctx, desc)), content.WithDescriptor(desc))

	ws, err := cw.Status()

	rc, err := fetcher.Fetch(ctx, desc)

	return content.Copy(ctx, cw, rc, desc.Size, desc.Digest)
}

总结:

    拉取镜像, 首先获取到 mainifest 文件清单, 在递归将子层下载到 content中, 最后将每一层解压到 snapshotter 下。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/904363.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号