containerd中文翻译系列(七)远程快照器

远程快照器

Containerd 允许快照器重复使用其管理的某处已有的快照。

远程快照器(Remote Snapshotter)是一种快照器,它可以利用这一功能,重用存储在远程共享位置的快照。 这些远程共享的快照称为_远程快照_。 远程快照器允许 containerd 准备这些远程快照,而无需从注册表中提取层,从而有望缩短镜像提取所需的时间。

远程快照器实现之一是 Stargz Snapshotter。 它能让 containerd 利用远程快照器功能和 google/crfs 的 stargz 镜像,从符合标准的注册表中轻松提取镜像。

containerd 客户端 API

containerd 客户端的 PullAPI(带有解压缩模式)允许底层快照器在获取内容之前查询远程快照。 远程快照器需要以与普通快照器相同的方式插入containerd。

go 复制代码
import (
	containerd "github.com/containerd/containerd/v2/client"
)

image, err := client.Pull(ctx, ref,
	containerd.WithPullUnpack,
	containerd.WithPullSnapshotter("my-remote-snapshotter"),
)

传递快照器特定信息

某些远程快照程序需要通过 Pull API 获取快照程序的特定信息。 这些信息将以各种方式使用,包括从远程存储中搜索快照内容。 其中一个需要快照器特定信息的快照器示例是 stargz snapshotter。 它需要镜像引用名称和层摘要等信息,以便从注册表中搜索层内容。

快照器通过以 containerd.io/snapshot/ 为前缀的用户定义标签接收信息。 containerd 客户端支持两种将这些标签传递给底层快照器的方式。

使用快照器的 WithLabels 选项

用户定义的标签可以通过 snapshotter 选项 WithLabels 传递给底层快照器。 每次 containerd 客户端查询远程快照时,都会向下传递指定的标签。 如果无论快照如何,这些标签的值都是静态确定的,那么这个选项就非常有用。 这些用户定义的标签必须以 containerd.io/snapshot/ 为前缀。

go 复制代码
import (
	containerd "github.com/containerd/containerd/v2/client"
	"github.com/containerd/containerd/v2/core/snapshots"
)

image, err := client.Pull(ctx, ref,
	containerd.WithPullUnpack,
	containerd.WithPullSnapshotter(
		"my-remote-snapshotter",
		snapshots.WithLabels(map[string]string{
			"containerd.io/snapshot/reference": ref,
		}),
	),
)

使用 containerd 客户端的 WithImageHandlerWrapper 选项

用户定义的标签也可以使用镜像处理器包装器传递。 当标签根据快照的不同而变化时,这个选项非常有用。

每次 containerd 客户端查询远程快照时,它都会向底层快照器传递附加到目标层描述符(指为准备该快照而提取和解压缩的层描述符)的 "注释"。 这些注释作为用户定义的标签传递给快照器。 注释的值可以在处理程序包装器中动态添加和修改。 请注意,注释的前缀必须是 containerd.io/snapshot/github.com/containerd/containerd/v2/pkg/snapshotters是 CRI 软件包、nerdctl 和 moby 使用的处理程序实现。

go 复制代码
import (
	containerd "github.com/containerd/containerd/v2/client"
	"github.com/containerd/containerd/v2/pkg/snapshotters"
)

if _, err := client.Pull(ctx, ref,
	containerd.WithPullUnpack,
	containerd.WithPullSnapshotter("my-remote-snapshotter"),
	containerd.WithImageHandlerWrapper(snapshotters.AppendInfoHandlerWrapper(ref)),
)

用于查询远程快照的快照器 API

containerd 客户端使用快照器 API 向底层远程快照器查询远程快照。 本节从高层次概述了如何使用快照器 API 来实现远程快照功能,并用一些伪代码描述了 containerd 客户端中实现的简化逻辑。 更多详情,请参阅实现这一逻辑的 unpacker.go

在镜像拉取过程中,containerd 客户端会调用带有标签 containerd.io/snapshot.refPrepare API。 这是一个 containerd 定义的标签,其中包含 ChainID,目标是客户端正在尝试准备的已提交快照。 目前,用户定义的标签(前缀为 containerd.io/snapshot/)也将被合并到标签选项中。

go 复制代码
// 获取附加到目标定位层的注释,该注释将包含
// 用户传递的快照器特定信息。
labels := snapshots.FilterInheritedLabels(desc.Annotations)
if labels == nil {
	labels = make(map[string]string)
}

// 指定目标提交快照的 ChainID。
labels["containerd.io/snapshot.ref"] = chainID

// 合并用户指定的快照器选项,这些选项将包含
// 用户传递的快照器特定信息。
opts := append(rCtx.SnapshotterOpts, snapshots.WithLabels(labels))

// 使用目标标识符和快照器特定信息调用 `Prepare` API信息。
mounts, err = sn.Prepare(ctx, key, parent.String(), opts...)

如果该快照器是一个远程快照器,那么提交的快照就有希望存在,例如存在于共享的远程存储中。 远程快照器必须定义并执行有关是否使用现有快照的策略。 当远程快照器允许用户使用该快照时,它必须返回 ErrAlreadyExists

如果containerd 客户端通过 Prepare 得到 ErrAlreadyExists,它就会通过调用带有 ChainID 的 Stat 来确保已提交快照的存在。 如果该快照可用,容器客户机就会跳过准备和提交该快照所需的提取和解压缩层。

go 复制代码
mounts, err = sn.Prepare(ctx, key, parent.String(), opts...)
if err != nil {
	if errdefs.IsAlreadyExists(err) {
		//确保层存在
		if _, err := sn.Stat(ctx, chainID); err != nil {
			//处理错误
		} else {
			// 发现带有 ChainID 的快照将跳过提取/解包
			continue
		}
	} else {
		return err
	}
}
相关推荐
东风微鸣7 小时前
TTRSS 迁移实战
docker·云原生·kubernetes·可观察性
Smile_Gently8 小时前
Docker
云原生·eureka
Diligent_lvan9 小时前
聊聊istio服务网格
云原生·istio
企鹅侠客10 小时前
kube-proxy怎么修改ipvs规则?
云原生·kubernetes·kubelet
仇辉攻防10 小时前
【云安全】云原生- K8S 污点横移
web安全·网络安全·云原生·容器·kubernetes·k8s·安全威胁分析
ITPUB-微风15 小时前
云原生监控体系建设:Kubernetes架构下的全面监控策略
云原生·架构·kubernetes
ITPUB-微风18 小时前
网易严选DevOps实践:从传统到云原生的演进
运维·云原生·devops
桂月二二18 小时前
基于eBPF的全栈可观测性系统:重新定义云原生环境诊断范式
云原生
ITPUB-微风19 小时前
云原生数据抽象与弹性加速:Fluid开源系统的技术解析
云原生·开源
爬山算法19 小时前
Zookeeper(58)如何在Zookeeper中实现分布式锁?
分布式·zookeeper·云原生