13

Containerd 中的 Snapshot 到底是个什么鬼?

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzU1MzY4NzQ1OA%3D%3D&%3Bmid=2247490352&%3Bidx=1&%3Bsn=0a1387ea80c99fd5ae839e55129e5979
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

mqaiuuZ.gif!mobile

更多奇技淫巧欢迎订阅博客:https://fuckcloudnative.io

先问大家问题,containerd 的 snapshot 是什么鬼?难道是给容器做快照的吗?

7JVvAje.png!mobile

答案是:是也不是

为什么说是呢?它的确可以实现部分快照的功能,但他和常规意义的虚拟机快照又不是一回事。

我们先看一下 containerd 是干嘛的?譬如我们拉镜像

zyAvE3v.png!mobile

可以看到 snapshot 的服务作用是准备 rootfs 的,就是通过 mount 各个层,提供容器的 rootfs。所有。content 只是保存 tar 和 mainfest 和 config 文件的,是 OCI 那套东西,我们需要将他们逐一解压、mount 后提供给容器。

所以 push 操作就和 snapshot 没有毛关系了。如下所示:

z2mMVz.png!mobile

当我们理解 snapshot 是干嘛的以后,可以通过源码看一下 containerd 目前的 snapshot 有哪些实现:

EzM7FbA.png!mobile

那么大家可能又有疑惑了,为啥他们可以加入 snapshot,因为这些文件系统都有一个共同的特性就是:支持快照。这就是这个模块的名称叫做 snapshot 了。每个文件系统的接入就需要实现下面的接口。

type Snapshotter interface {
// Stat returns the info for an active or committed snapshot by name or
// key.
//
// Should be used for parent resolution, existence checks and to discern
// the kind of snapshot.
Stat(ctx context.Context, key string) (Info, error)

// Update updates the info for a snapshot.
//
// Only mutable properties of a snapshot may be updated.
Update(ctx context.Context, info Info, fieldpaths ...string) (Info, error)

// Usage returns the resource usage of an active or committed snapshot
// excluding the usage of parent snapshots.
//
// The running time of this call for active snapshots is dependent on
// implementation, but may be proportional to the size of the resource.
// Callers should take this into consideration. Implementations should
// attempt to honer context cancellation and avoid taking locks when making
// the calculation.
Usage(ctx context.Context, key string) (Usage, error)

// Mounts returns the mounts for the active snapshot transaction identified
// by key. Can be called on an read-write or readonly transaction. This is
// available only for active snapshots.
//
// This can be used to recover mounts after calling View or Prepare.
Mounts(ctx context.Context, key string) ([]mount.Mount, error)

// Prepare creates an active snapshot identified by key descending from the
// provided parent. The returned mounts can be used to mount the snapshot
// to capture changes.
//
// If a parent is provided, after performing the mounts, the destination
// will start with the content of the parent. The parent must be a
// committed snapshot. Changes to the mounted destination will be captured
// in relation to the parent. The default parent, "", is an empty
// directory.
//
// The changes may be saved to a committed snapshot by calling Commit. When
// one is done with the transaction, Remove should be called on the key.
//
// Multiple calls to Prepare or View with the same key should fail.
Prepare(ctx context.Context, key, parent string, opts ...Opt) ([]mount.Mount, error)

// View behaves identically to Prepare except the result may not be
// committed back to the snapshot snapshotter. View returns a readonly view on
// the parent, with the active snapshot being tracked by the given key.
//
// This method operates identically to Prepare, except that Mounts returned
// may have the readonly flag set. Any modifications to the underlying
// filesystem will be ignored. Implementations may perform this in a more
// efficient manner that differs from what would be attempted with
// `Prepare`.
//
// Commit may not be called on the provided key and will return an error.
// To collect the resources associated with key, Remove must be called with
// key as the argument.
View(ctx context.Context, key, parent string, opts ...Opt) ([]mount.Mount, error)

// Commit captures the changes between key and its parent into a snapshot
// identified by name. The name can then be used with the snapshotter's other
// methods to create subsequent snapshots.
//
// A committed snapshot will be created under name with the parent of the
// active snapshot.
//
// After commit, the snapshot identified by key is removed.
Commit(ctx context.Context, name, key string, opts ...Opt) error

// Remove the committed or active snapshot by the provided key.
//
// All resources associated with the key will be removed.
//
// If the snapshot is a parent of another snapshot, its children must be
// removed before proceeding.
Remove(ctx context.Context, key string) error

// Walk will call the provided function for each snapshot in the
// snapshotter which match the provided filters. If no filters are
// given all items will be walked.
// Filters:
// name
// parent
// kind (active,view,committed)
// labels.(label)
Walk(ctx context.Context, fn WalkFunc, filters ...string) error

// Close releases the internal resources.
//
// Close is expected to be called on the end of the lifecycle of the snapshotter,
// but not mandatory.
//
// Close returns nil when it is already closed.
Close() error
}

当我们通过 pull 下载镜像的时候就会 apply 每一层:

func applyLayers(ctx context.Context, layers []Layer, chain []digest.Digest, sn snapshots.Snapshotter, a diff.Applier, opts []snapshots.Opt, applyOpts []diff.ApplyOpt) error {

mounts, err = sn.Prepare(ctx, key, parent.String(), opts...)

diff, err = a.Apply(ctx, layer.Blob, mounts, applyOpts...)


if err = sn.Commit(ctx, chainID.String(), key, opts...); err != nil {
err = errors.Wrapf(err, "failed to commit snapshot %s", key)
return err
}

return nil
}

通过 prepare --> apply --> commit 三步完成 layer 的构建。其中 prepare 只返回了具体 mount 列表,并不做具体的 mount 擦着,具体实现在 apply 这个方法:

func apply(ctx context.Context, mounts []mount.Mount, r io.Reader) error {
return mount.WithTempMount(ctx, mounts, func(root string) error {
_, err := archive.Apply(ctx, root, r)
return err
})
}

其中 archive.Apply 就是解压 tar 包写层的”archive/tar.go“

func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
. . .

总结一下,snapshot 目的是为了给容器的提供 rootfs,通过实现 snapshot 的接口,就可以接入不同的具有快照功能的文件系统。

原文链接: https://blog.csdn.net/u010278923/article/details/111721116

jEJraeF.png!mobile

你可能还喜欢

点击下方图片即可阅读

JVBrMr.jpg!mobile

WireGuard 真的很香吗?香个屁!

vam2EvY.gif!mobile

云原生是一种信仰 

eQF3Ebj.png!mobile

码关注公众号

后台回复◉k8s◉获取史上最方便快捷的 Kubernetes 高可用部署工具,只需一条命令,连 ssh 都不需要!

JV73iue.gif!mobile

jeeyYzV.gif!mobile

点击  "阅读原文"  获取 更好的阅读体验!

:heart: 给个 「在看」 ,是对我最大的支持:heart:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK