内容流
containerd 的一个主要目标是创建一个可将内容用于执行容器的系统。
为了执行该流程,containerd 需要内容并对其进行管理。
本文档描述了内容如何流入 containerd、如何对其进行管理,以及在此过程中的每个阶段它存在于何处。
我们以从已知镜像
docker.io/library/red…
来探索 内容流。
内容区域
内容存在于 containerd 生命周期中的多个领域:
- OCI 注册表,例如 hub.docker.com 或 quay.io
- containerd 内容存储,在containerd 的本地存储空间下,例如,在标准 Linux 安装上,位于
/var/lib/containerd/io.containerd.content.v1.content
下 - 快照,位于containerd的本地存储空间下,例如,在标准 Linux 安装中位于
/var/lib/containerd/io.containerd.snapshotter.v1.<type>
。对于 overlayfs snapshotter 而言,它位于/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs
中。
要创建容器,必须进行以下操作:
现在可以创建一个容器,将其根文件系统作为活动快照。
本文其余部分将详细介绍每个区域的内容,以及它们之间的关系。
镜像格式
注册表中的镜像通常按以下格式存储。image
由一个称为描述符的 JSON 文档组成。
描述符。描述符总是包含一个元素 mediaType
,它告诉我们这是什么类型。它有两种选择:
清单
(manifest),其中列出了将镜像作为容器运行的配置文件哈希值,以及为镜像创建文件系统的二进制数据层- 一个
索引
(index),列出清单的哈希值,每个平台一个,平台是架构(如 amd64 或 arm64)和操作系统(如 linux)的组合。
索引的目的是让我们选择与目标平台相匹配的清单。
要将镜像参考(如 redis:5.0.9
)从注册表转换为实际的磁盘存储,我们需要:
mediaType
中确定描述符是清单还是索引:
- 如果描述符是索引,则在其中找到代表我们要在其上运行容器的平台(架构+操作系统)的哈希值,然后使用该哈希值检索清单
- 如果描述符已经是清单,则继续
我们使用示例镜像 redis:5.0.9
来说明这一过程。
当我们首次解析 redis:5.0.9
时,会得到以下 JSON 文档:
{
"manifests": [
{
"digest": "sha256:9bb13890319dc01e5f8a4d3d0c4c72685654d682d568350fd38a02b1d70aee6b",
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"platform": {
"architecture": "amd64",
"os": "linux"
},
"size": 1572
},
{
"digest": "sha256:aeb53f8db8c94d2cd63ca860d635af4307967aa11a2fdead98ae0ab3a329f470",
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"platform": {
"architecture": "arm",
"os": "linux",
"variant": "v5"
},
"size": 1573
},
{
"digest": "sha256:17dc42e40d4af0a9e84c738313109f3a95e598081beef6c18a05abb57337aa5d",
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"platform": {
"architecture": "arm",
"os": "linux",
"variant": "v7"
},
"size": 1573
},
{
"digest": "sha256:613f4797d2b6653634291a990f3e32378c7cfe3cdd439567b26ca340b8946013",
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"platform": {
"architecture": "arm64",
"os": "linux",
"variant": "v8"
},
"size": 1573
},
{
"digest": "sha256:ee0e1f8d8d338c9506b0e487ce6c2c41f931d1e130acd60dc7794c3a246eb59e",
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"platform": {
"architecture": "386",
"os": "linux"
},
"size": 1572
},
{
"digest": "sha256:1072145f8eea186dcedb6b377b9969d121a00e65ae6c20e9cd631483178ea7ed",
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"platform": {
"architecture": "mips64le",
"os": "linux"
},
"size": 1572
},
{
"digest": "sha256:4b7860fcaea5b9bbd6249c10a3dc02a5b9fb339e8aef17a542d6126a6af84d96",
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"platform": {
"architecture": "ppc64le",
"os": "linux"
},
"size": 1573
},
{
"digest": "sha256:d66dfc869b619cd6da5b5ae9d7b1cbab44c134b31d458de07f7d580a84b63f69",
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"platform": {
"architecture": "s390x",
"os": "linux"
},
"size": 1573
}
],
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"schemaVersion": 2
}
上面描述符的末尾显示,mediaType
是一个 manifest.list
,用 OCI 术语来说,就是一个索引。
它有一个名为 manifests
的数组字段,每个元素都列出了一个平台和该平台的清单哈希值。
platform
是 architecture
和 os
的组合。由于我们将运行在常见的
linux on amd64,因此我们要在 manifests
中查找包含 platform
条目的条目,如下所示:
"platform": {
"architecture": "amd64",
"os": "linux"
}
这是列表中的第一个,它的哈希值为 sha256:9bb13890319dc01e5f8a4d3d0c4c72685654d682d568350fd38a02b1d70aee6b
。
然后,我们检索具有该散列值的项目,特别是 docker.io/library/redis@sha256:9bb13890319dc01e5f8a4d3d0c4c72685654d682d568350fd38a02b1d70aee6b
。
这样我们就得到了 linux/amd64 上镜像的清单:
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 7648,
"digest": "sha256:987b553c835f01f46eb1859bc32f564119d5833801a27b25a0ca5c6b8b6e111a"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 27092228,
"digest": "sha256:bb79b6b2107fea8e8a47133a660b78e3a546998fcf0427be39ac9a0af4a97e90"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 1732,
"digest": "sha256:1ed3521a5dcbd05214eb7f35b952ecf018d5a6610c32ba4e315028c556f45e94"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 1417672,
"digest": "sha256:5999b99cee8f2875d391d64df20b6296b63f23951a7d41749f028375e887cd05"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 7348264,
"digest": "sha256:bfee6cb5fdad6b60ec46297f44542ee9d8ac8f01c072313a51cd7822df3b576f"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 98,
"digest": "sha256:fd36a1ebc6728807cbb1aa7ef24a1861343c6dc174657721c496613c7b53bd07"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 409,
"digest": "sha256:97481c7992ebf6f22636f87e4d7b79e962f928cdbe6f2337670fa6c9a9636f04"
}
]
}
mediaType
告诉我们这是一份 清单(manifest)
,它符合正确的格式:
- 一个
config
,其哈希值为sha256:987b553c835f01f46eb1859bc32f564119d5833801a27b25a0ca5c6b8b6e111a
- 一个或多个
layer
;本例中有 6 层
这些元素(索引、清单、配置文件和每个层)都单独存储在注册表中,并可以独立下载。
当内容加载到 containerd 的内容存储中时,它的存储方式与注册表非常相似。
每个组件都存储在一个文件中,文件名就是组件的哈希值。
继续以 redis 为例,如果我们执行 client.Pull()
或 ctr pull
操作,我们的
内容存储中:
sha256:2a9865e55c37293b71df051922022898d8e4ec0f579c9b53a0caee1b170bc81c
- 索引sha256:9bb13890319dc01e5f8a4d3d0c4c72685654d682d568350fd38a02b1d70aee6b
-linux/amd64
的清单sha256:987b553c835f01f46eb1859bc32f564119d5833801a27b25a0ca5c6b8b6e111a
- 配置sha256:97481c7992ebf6f22636f87e4d7b79e962f928cdbe6f2337670fa6c9a9636f04
- 0层sha256:5999b99cee8f2875d391d64df20b6296b63f23951a7d41749f028375e887cd05
- 层 1sha256:bfee6cb5fdad6b60ec46297f44542ee9d8ac8f01c072313a51cd7822df3b576f
- 第 2 层sha256:fd36a1ebc6728807cbb1aa7ef24a1861343c6dc174657721c496613c7b53bd07
- 第 3 层sha256:bb79b6b2107fea8e8a47133a660b78e3a546998fcf0427be39ac9a0af4a97e90
- 第 4 层sha256:1ed3521a5dcbd05214eb7f35b952ecf018d5a6610c32ba4e315028c556f45e94
- 第 5 层
如果我们查看内容存储,就会看到这些内容(为了便于阅读,我进行了过滤和排序):
$ tree /var/lib/containerd/io.containerd.content.v1.content/blobs
/var/lib/containerd/io.containerd.content.v1.content/blobs
└── sha256
├── 2a9865e55c37293b71df051922022898d8e4ec0f579c9b53a0caee1b170bc81c
├── 9bb13890319dc01e5f8a4d3d0c4c72685654d682d568350fd38a02b1d70aee6b
├── 987b553c835f01f46eb1859bc32f564119d5833801a27b25a0ca5c6b8b6e111a
├── 97481c7992ebf6f22636f87e4d7b79e962f928cdbe6f2337670fa6c9a9636f04
├── 5999b99cee8f2875d391d64df20b6296b63f23951a7d41749f028375e887cd05
├── bfee6cb5fdad6b60ec46297f44542ee9d8ac8f01c072313a51cd7822df3b576f
├── fd36a1ebc6728807cbb1aa7ef24a1861343c6dc174657721c496613c7b53bd07
├── bb79b6b2107fea8e8a47133a660b78e3a546998fcf0427be39ac9a0af4a97e90
└── 1ed3521a5dcbd05214eb7f35b952ecf018d5a6610c32ba4e315028c556f45e94
如果使用 containerd 接口,我们可以看到同样的内容。同样,我们对其进行了排序,以方便查看。
$ ctr content ls
DIGEST SIZE AGE LABELS
sha256:2a9865e55c37293b71df051922022898d8e4ec0f579c9b53a0caee1b170bc81c 1.862kB 20 minutes containerd.io/distribution.source.docker.io=library/redis,containerd.io/gc.ref.content.m.0=sha256:9bb13890319dc01e5f8a4d3d0c4c72685654d682d568350fd38a02b1d70aee6b,containerd.io/gc.ref.content.m.1=sha256:aeb53f8db8c94d2cd63ca860d635af4307967aa11a2fdead98ae0ab3a329f470,containerd.io/gc.ref.content.m.2=sha256:17dc42e40d4af0a9e84c738313109f3a95e598081beef6c18a05abb57337aa5d,containerd.io/gc.ref.content.m.3=sha256:613f4797d2b6653634291a990f3e32378c7cfe3cdd439567b26ca340b8946013,containerd.io/gc.ref.content.m.4=sha256:ee0e1f8d8d338c9506b0e487ce6c2c41f931d1e130acd60dc7794c3a246eb59e,containerd.io/gc.ref.content.m.5=sha256:1072145f8eea186dcedb6b377b9969d121a00e65ae6c20e9cd631483178ea7ed,containerd.io/gc.ref.content.m.6=sha256:4b7860fcaea5b9bbd6249c10a3dc02a5b9fb339e8aef17a542d6126a6af84d96,containerd.io/gc.ref.content.m.7=sha256:d66dfc869b619cd6da5b5ae9d7b1cbab44c134b31d458de07f7d580a84b63f69
sha256:9bb13890319dc01e5f8a4d3d0c4c72685654d682d568350fd38a02b1d70aee6b 1.572kB 20 minutes containerd.io/distribution.source.docker.io=library/redis,containerd.io/gc.ref.content.config=sha256:987b553c835f01f46eb1859bc32f564119d5833801a27b25a0ca5c6b8b6e111a,containerd.io/gc.ref.content.l.0=sha256:bb79b6b2107fea8e8a47133a660b78e3a546998fcf0427be39ac9a0af4a97e90,containerd.io/gc.ref.content.l.1=sha256:1ed3521a5dcbd05214eb7f35b952ecf018d5a6610c32ba4e315028c556f45e94,containerd.io/gc.ref.content.l.2=sha256:5999b99cee8f2875d391d64df20b6296b63f23951a7d41749f028375e887cd05,containerd.io/gc.ref.content.l.3=sha256:bfee6cb5fdad6b60ec46297f44542ee9d8ac8f01c072313a51cd7822df3b576f,containerd.io/gc.ref.content.l.4=sha256:fd36a1ebc6728807cbb1aa7ef24a1861343c6dc174657721c496613c7b53bd07,containerd.io/gc.ref.content.l.5=sha256:97481c7992ebf6f22636f87e4d7b79e962f928cdbe6f2337670fa6c9a9636f04
sha256:987b553c835f01f46eb1859bc32f564119d5833801a27b25a0ca5c6b8b6e111a 7.648kB 20 minutes containerd.io/distribution.source.docker.io=library/redis,containerd.io/gc.ref.snapshot.overlayfs=sha256:33bd296ab7f37bdacff0cb4a5eb671bcb3a141887553ec4157b1e64d6641c1cd
sha256:97481c7992ebf6f22636f87e4d7b79e962f928cdbe6f2337670fa6c9a9636f04 409B 20 minutes containerd.io/distribution.source.docker.io=library/redis,containerd.io/uncompressed=sha256:d442ae63d423b4b1922875c14c3fa4e801c66c689b69bfd853758fde996feffb
sha256:5999b99cee8f2875d391d64df20b6296b63f23951a7d41749f028375e887cd05 1.418MB 20 minutes containerd.io/distribution.source.docker.io=library/redis,containerd.io/uncompressed=sha256:223b15010c47044b6bab9611c7a322e8da7660a8268949e18edde9c6e3ea3700
sha256:bfee6cb5fdad6b60ec46297f44542ee9d8ac8f01c072313a51cd7822df3b576f 7.348MB 20 minutes containerd.io/distribution.source.docker.io=library/redis,containerd.io/uncompressed=sha256:b96fedf8ee00e59bf69cf5bc8ed19e92e66ee8cf83f0174e33127402b650331d
sha256:fd36a1ebc6728807cbb1aa7ef24a1861343c6dc174657721c496613c7b53bd07 98B 20 minutes containerd.io/distribution.source.docker.io=library/redis,containerd.io/uncompressed=sha256:aff00695be0cebb8a114f8c5187fd6dd3d806273004797a00ad934ec9cd98212
sha256:bb79b6b2107fea8e8a47133a660b78e3a546998fcf0427be39ac9a0af4a97e90 27.09MB 19 minutes containerd.io/distribution.source.docker.io=library/redis,containerd.io/uncompressed=sha256:d0fe97fa8b8cefdffcef1d62b65aba51a6c87b6679628a2b50fc6a7a579f764c
sha256:1ed3521a5dcbd05214eb7f35b952ecf018d5a6610c32ba4e315028c556f45e94 1.732kB 20 minutes containerd.io/distribution.source.docker.io=library/redis,containerd.io/uncompressed=sha256:832f21763c8e6b070314e619ebb9ba62f815580da6d0eaec8a1b080bd01575f7
标签
请注意,每个 Blob 内容上都有多个标签。本小节将介绍这些标签。
这并不是对标签的全面概述。
常用标签
对于从远程提取的镜像,"containerd.io.distribution.source.=[<repo/1>,<repo/2>]"标签
会被添加到镜像的每个 blob 中,以指示其来源。
containerd.io/distribution.source.docker.io=library/redis
如果 blob 被同一注册表中的不同 repo 共享,则会添加 repo 名称:
containerd.io/distribution.source.docker.io=library/redis,myrepo/redis
层标签
我们从层本身开始。它们只有一个标签:containerd.io/uncompressed
。这些文件是
标签的值给出了它们解压缩后的哈希值。您可以通过以下方式获取:
$ cat <file> | gunzip - | sha256sum -
比如:
$ cat /var/lib/containerd/io.containerd.content.v1.content/blobs/sha256/1ed3521a5dcbd05214eb7f35b952ecf018d5a6610c32ba4e315028c556f45e94 | gunzip - | sha256sum -
832f21763c8e6b070314e619ebb9ba62f815580da6d0eaec8a1b080bd01575f7
这与最后一层正好吻合:
sha256:1ed3521a5dcbd05214eb7f35b952ecf018d5a6610c32ba4e315028c556f45e94 1.732kB 20 minutes containerd.io/distribution.source.docker.io=library/redis,containerd.io/uncompressed=sha256:832f21763c8e6b070314e619ebb9ba62f815580da6d0eaec8a1b080bd01575f7
配置标签
我们只有一个配置层,即 sha256:987b553c835f01f46eb1859bc32f564119d5833801a27b25a0ca5c6b8b6e111a
。它的标签前缀为containerd.io/gc.ref.
,表明标签会影响垃圾回收。
在本例中,标签为 containerd.io/gc.ref.snapshot.overlayfs
,值为 sha256:33bd296ab7f37bdacff0cb4a5eb671bcb3a141887553ec4157b1e64d6641c1cd
。
它用于将此配置连接到快照。我们将在讨论快照时对此进行说明。
清单标签
清单上的标签也以 containerd.io/gc.ref
开头,表明它们用于控制
垃圾回收。清单有几个 "子节点"。它们通常是配置和层。我们希望
确保只要镜像(即清单)还在,子代就不会被垃圾回收。
因此,我们使用标签来引用每个子代:
containerd.io/gc.ref.content.config
引用配置containerd.io/gc.ref.content.l.<index>
引用层
在我们的示例中,清单是 sha256:9bb13890319dc01e5f8a4d3d0c4c72685654d682d568350fd38a02b1d70aee6b
,标签如下。
containerd.io/gc.ref.content.config=sha256:df57482065789980ee9445b1dd79ab1b7b3d1dc26b6867d94470af969a64c8e6
containerd.io/gc.ref.content.l.0=sha256:97481c7992ebf6f22636f87e4d7b79e962f928cdbe6f2337670fa6c9a9636f04
containerd.io/gc.ref.content.l.1=sha256:5999b99cee8f2875d391d64df20b6296b63f23951a7d41749f028375e887cd05
containerd.io/gc.ref.content.l.2=sha256:bfee6cb5fdad6b60ec46297f44542ee9d8ac8f01c072313a51cd7822df3b576f
containerd.io/gc.ref.content.l.3=sha256:fd36a1ebc6728807cbb1aa7ef24a1861343c6dc174657721c496613c7b53bd07
containerd.io/gc.ref.content.l.4=sha256:bb79b6b2107fea8e8a47133a660b78e3a546998fcf0427be39ac9a0af4a97e90
containerd.io/gc.ref.content.l.5=sha256:1ed3521a5dcbd05214eb7f35b952ecf018d5a6610c32ba4e315028c556f45e94
这些正是清单的子清单--配置和层--存储在我们的内容存储中。
索引标签
索引上的标签也以 containerd.io/gc.ref
开头,表明它们用于控制
垃圾收集。如上所述,一个索引有几个 子索引
,即清单,每个平台一个。
我们要确保只要索引还在,子索引就不会被垃圾回收。
因此,我们为每个子代设置了 containerd.io/gc.ref.content.m.<index>
标签。
在我们的示例中,索引是 sha256:2a9865e55c37293b71df051922022898d8e4ec0f579c9b53a0caee1b170bc81c
,标签如下:
containerd.io/gc.ref.content.m.0=sha256:9bb13890319dc01e5f8a4d3d0c4c72685654d682d568350fd38a02b1d70aee6b
containerd.io/gc.ref.content.m.1=sha256:aeb53f8db8c94d2cd63ca860d635af4307967aa11a2fdead98ae0ab3a329f470
containerd.io/gc.ref.content.m.2=sha256:17dc42e40d4af0a9e84c738313109f3a95e598081beef6c18a05abb57337aa5d
containerd.io/gc.ref.content.m.3=sha256:613f4797d2b6653634291a990f3e32378c7cfe3cdd439567b26ca340b8946013
containerd.io/gc.ref.content.m.4=sha256:ee0e1f8d8d338c9506b0e487ce6c2c41f931d1e130acd60dc7794c3a246eb59e
containerd.io/gc.ref.content.m.5=sha256:1072145f8eea186dcedb6b377b9969d121a00e65ae6c20e9cd631483178ea7ed
containerd.io/gc.ref.content.m.6=sha256:4b7860fcaea5b9bbd6249c10a3dc02a5b9fb339e8aef17a542d6126a6af84d96
containerd.io/gc.ref.content.m.7=sha256:d66dfc869b619cd6da5b5ae9d7b1cbab44c134b31d458de07f7d580a84b63f69
请注意,该索引有 8 个子索引,但所有子索引的平台除了 linux/amd64
其它都不是我们的平台,
因此只有其中一个,即 sha256:9bb13890319dc01e5f8a4d3d0c4c72685654d682d568350fd38a02b1d70aee6b
在我们的内容存储中。
这并无大碍,只是意味着其他内容也不会被垃圾回收。因为它们不存在,所以它们也就不会被删除。
快照
内容存储中的内容是不可变的,但其格式往往也是不可用的。例如
大多数容器层都是 tar-gzip 格式。我们不能简单地挂载 tar-gzip 文件。即使可以
我们希望我们的不可变内容不仅是没有被改变过,而是不可改变,哪怕是意外,即不可变的?(*这句没有看懂原文是这样:
we want to leave our immutable content not only unchanged, but unchangeable, even by accident, i.e. immutable. 。
为了使用它,我们要创建内容快照。
具体过程如下
回到我们的示例,每一层都有一个对应的不可变快照层。回顾一下
我们的示例有 6 层,因此我们预计会看到 6 个已提交的快照。输出已排序,以便于查看
它与内容存储和清单本身的层相匹配。
$ ctr snapshot ls
KEY PARENT KIND
sha256:d0fe97fa8b8cefdffcef1d62b65aba51a6c87b6679628a2b50fc6a7a579f764c Committed
sha256:2ae5fa95c0fce5ef33fbb87a7e2f49f2a56064566a37a83b97d3f668c10b43d6 sha256:d0fe97fa8b8cefdffcef1d62b65aba51a6c87b6679628a2b50fc6a7a579f764c Committed
sha256:a8f09c4919857128b1466cc26381de0f9d39a94171534f63859a662d50c396ca sha256:2ae5fa95c0fce5ef33fbb87a7e2f49f2a56064566a37a83b97d3f668c10b43d6 Committed
sha256:aa4b58e6ece416031ce00869c5bf4b11da800a397e250de47ae398aea2782294 sha256:a8f09c4919857128b1466cc26381de0f9d39a94171534f63859a662d50c396ca Committed
sha256:bc8b010e53c5f20023bd549d082c74ef8bfc237dc9bbccea2e0552e52bc5fcb1 sha256:aa4b58e6ece416031ce00869c5bf4b11da800a397e250de47ae398aea2782294 Committed
sha256:33bd296ab7f37bdacff0cb4a5eb671bcb3a141887553ec4157b1e64d6641c1cd sha256:bc8b010e53c5f20023bd549d082c74ef8bfc237dc9bbccea2e0552e52bc5fcb1 Committed
父级
除根节点外,每个快照都有一个父级。它是一棵树,或者说是一个堆叠的蛋糕,从第一层开始。
这与层的构建方式一致。
名称
快照的key或名称与内容存储的哈希值不匹配。这是因为
内容存储中的哈希值是_原始_内容的哈希值,在本例中是压缩后的 tar-gzipped。快照会将其扩展到
文件系统,使其发挥作用。它也与未压缩的内容不匹配,即没有经过 gzip 压缩的 tar 文件。
containerd.io/uncompressed "标签上的内容。
相反,该名称是将层应用到前一层并散列的结果。按照这种逻辑,树的根
的哈希值和名称应该与第一层 blob 的未压缩值相同。
的确如此。根层是 sha256:bb79b6b2107fea8e8a47133a660b78e3a546998fcf0427be39ac9a0af4a97e90
。
解压缩后,其值为 sha256:d0fe97fa8b8cefdffcef1d62b65aba51a6c87b6679628a2b50fc6a7a579f764c
、
是快照中的第一个图层,也是内容存储中该图层的标签:
sha256:bb79b6b2107fea8e8a47133a660b78e3a546998fcf0427be39ac9a0af4a97e90 27.09MB 19 minutes containerd.io/distribution.source.docker.io=library/redis,containerd.io/uncompressed=sha256:d0fe97fa8b8cefdffcef1d62b65aba51a6c87b6679628a2b50fc6a7a579f764c
最终层
最终层或顶层是您希望创建活动快照以启动容器的位置。
因此,我们需要对其进行跟踪。这正是放置在配置上的标签。在我们的示例中
配置位于 sha256:987b553c835f01f46eb1859bc32f564119d5833801a27b25a0ca5c6b8b6e111a
处,标签为
containerd.io/gc.ref.snapshot.overlayfs=sha256:33bd296ab7f37bdacff0cb4a5eb671bcb3a141887553ec4157b1e64d6641c1cd
.
查看我们的快照,堆栈最后一层的值确实是这样:
sha256:33bd296ab7f37bdacff0cb4a5eb671bcb3a141887553ec4157b1e64d6641c1cd sha256:bc8b010e53c5f20023bd549d082c74ef8bfc237dc9bbccea2e0552e52bc5fcb1 Committed
还请注意,内容存储中配置的标签以 containerd.io/gc.ref
开头。这是一个
垃圾回收标签。正是这个标签阻止了垃圾回收器删除快照。
因为配置有一个引用,所以顶层受到了垃圾回收的 保护
。这一层
反过来又依赖于下一层,因此下一层也受到保护,不会被收集,依此类推,直到根层或基础层。
容器
有了上述内容,我们就知道如何创建对容器有用的活动快照了。我们只需
需要 Prepare()活动快照、
传给它一个 ID 和父节点,在本例中就是已提交快照的顶层。
因此,步骤如下