containerd中文翻译系列(六)内容流

内容流

containerd 的一个主要目标是创建一个可将内容用于执行容器的系统。 为了执行该流程,containerd 需要内容并对其进行管理。

本文档描述了内容如何流入 containerd、如何对其进行管理,以及在此过程中的每个阶段它存在于何处。 我们以从已知镜像 docker.io/library/red... 来探索 内容流。

内容区域

内容存在于 containerd 生命周期中的多个领域:

  • OCI 注册表,例如 hub.docker.comquay.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 中。

要创建容器,必须进行以下操作:

  1. 必须将镜像及其所有内容加载到内容存储中。这通常是通过从 OCI 注册表下载实现的,但也可以直接加载内容。
  2. 必须从图像的每一层内容创建已提交快照。
  3. 必须在映像的最后一层内容顶部创建活动快照。

现在可以创建一个容器,将其根文件系统作为活动快照。

本文其余部分将详细介绍每个区域的内容,以及它们之间的关系。

镜像格式

注册表中的镜像通常按以下格式存储。image由一个称为描述符的 JSON 文档组成。 描述符。描述符总是包含一个元素 mediaType,它告诉我们这是什么类型。它有两种选择:

  • 清单(manifest),其中列出了将镜像作为容器运行的配置文件哈希值,以及为镜像创建文件系统的二进制数据层
  • 一个索引(index),列出清单的哈希值,每个平台一个,平台是架构(如 amd64 或 arm64)和操作系统(如 linux)的组合。

索引的目的是让我们选择与目标平台相匹配的清单。

要将镜像参考(如 redis:5.0.9)从注册表转换为实际的磁盘存储,我们需要:

  1. 读取镜像的描述符(JSON 文档
  2. mediaType 中确定描述符是清单还是索引:
    • 如果描述符是索引,则在其中找到代表我们要在其上运行容器的平台(架构+操作系统)的哈希值,然后使用该哈希值检索清单
    • 如果描述符已经是清单,则继续
  3. 对于清单中的每个元素--配置和一个或多个层--使用列出的哈希值来检索组件并保存它们

我们使用示例镜像 redis:5.0.9 来说明这一过程。

当我们首次解析 redis:5.0.9 时,会得到以下 JSON 文档:

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的数组字段,每个元素都列出了一个平台和该平台的清单哈希值。 platformarchitectureos的组合。由于我们将运行在常见的 linux on amd64,因此我们要在 manifests 中查找包含 platform 条目的条目,如下所示:

json 复制代码
"platform": {
  "architecture": "amd64",
  "os": "linux"
}

这是列表中的第一个,它的哈希值为 sha256:9bb13890319dc01e5f8a4d3d0c4c72685654d682d568350fd38a02b1d70aee6b

然后,我们检索具有该散列值的项目,特别是 docker.io/library/redis@sha256:9bb13890319dc01e5f8a4d3d0c4c72685654d682d568350fd38a02b1d70aee6b 。 这样我们就得到了 linux/amd64 上镜像的清单:

json 复制代码
{
    "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 - 层 1
  • sha256:bfee6cb5fdad6b60ec46297f44542ee9d8ac8f01c072313a51cd7822df3b576f - 第 2 层
  • sha256:fd36a1ebc6728807cbb1aa7ef24a1861343c6dc174657721c496613c7b53bd07 - 第 3 层
  • sha256:bb79b6b2107fea8e8a47133a660b78e3a546998fcf0427be39ac9a0af4a97e90 - 第 4 层
  • sha256:1ed3521a5dcbd05214eb7f35b952ecf018d5a6610c32ba4e315028c556f45e94 - 第 5 层

如果我们查看内容存储,就会看到这些内容(为了便于阅读,我进行了过滤和排序):

console 复制代码
$ 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 接口,我们可以看到同样的内容。同样,我们对其进行了排序,以方便查看。

console 复制代码
$ 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 中,以指示其来源。

bash 复制代码
containerd.io/distribution.source.docker.io=library/redis

如果 blob 被同一注册表中的不同 repo 共享,则会添加 repo 名称:

bash 复制代码
containerd.io/distribution.source.docker.io=library/redis,myrepo/redis
层标签

我们从层本身开始。它们只有一个标签:containerd.io/uncompressed。这些文件是 标签的值给出了它们解压缩后的哈希值。您可以通过以下方式获取:

console 复制代码
$ cat <file> | gunzip - | sha256sum -

比如:

console 复制代码
$ cat /var/lib/containerd/io.containerd.content.v1.content/blobs/sha256/1ed3521a5dcbd05214eb7f35b952ecf018d5a6610c32ba4e315028c556f45e94 | gunzip - | sha256sum -
832f21763c8e6b070314e619ebb9ba62f815580da6d0eaec8a1b080bd01575f7

这与最后一层正好吻合:

bash 复制代码
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,标签如下。

ini 复制代码
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,标签如下:

ini 复制代码
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. 。

为了使用它,我们要创建内容快照。

具体过程如下

  1. 快照器从父对象创建快照。在第一层的情况下,父快照是空白的。这就是现在的 "活动 "快照了。
  2. 差异应用程序了解层 Blob 的内部格式,它将层 Blob 应用到活动快照中。
  3. 应用差异后,快照处理程序提交快照。这就是现在的 "已提交 "快照。
  4. 已提交的快照将用作下一层的父快照。

回到我们的示例,每一层都有一个对应的不可变快照层。回顾一下 我们的示例有 6 层,因此我们预计会看到 6 个已提交的快照。输出已排序,以便于查看 它与内容存储和清单本身的层相匹配。

console 复制代码
$ 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、 是快照中的第一个图层,也是内容存储中该图层的标签:

bash 复制代码
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.

查看我们的快照,堆栈最后一层的值确实是这样:

makefile 复制代码
sha256:33bd296ab7f37bdacff0cb4a5eb671bcb3a141887553ec4157b1e64d6641c1cd sha256:bc8b010e53c5f20023bd549d082c74ef8bfc237dc9bbccea2e0552e52bc5fcb1 Committed

还请注意,内容存储中配置的标签以 containerd.io/gc.ref 开头。这是一个 垃圾回收标签。正是这个标签阻止了垃圾回收器删除快照。 因为配置有一个引用,所以顶层受到了垃圾回收的 保护。这一层 反过来又依赖于下一层,因此下一层也受到保护,不会被收集,依此类推,直到根层或基础层。

容器

有了上述内容,我们就知道如何创建对容器有用的活动快照了。我们只需 需要 Prepare()活动快照、 传给它一个 ID 和父节点,在本例中就是已提交快照的顶层。

因此,步骤如下

  1. 通过 Pull() 或通过 content.Store API 将内容加载到内容存储中。
  2. 使用 image.Unpack() 解压缩图像,为每一层创建已提交的快照。或者,如果您使用 Pull(),您也可以使用 WithPullUnpack() 向它传递一个选项,让它在提取时解包。
  3. 使用 Prepare() 创建活动快照。如果计划创建容器,可以跳过这一步,因为可以将其作为下一步的一个选项。
  4. 使用 NewContainer() 创建容器,可选择使用 WithNewSnapshot() 告诉它创建快照。
相关推荐
tangdou36909865510 小时前
1分钟搞懂K8S中的NodeSelector
云原生·容器·kubernetes
Lansonli11 小时前
云原生(四十一) | 阿里云ECS服务器介绍
服务器·阿里云·云原生
Dylanioucn12 小时前
【分布式微服务云原生】掌握分布式缓存:Redis与Memcached的深入解析与实战指南
分布式·缓存·云原生
later_rql13 小时前
k8s-集群部署1
云原生·容器·kubernetes
大G哥18 小时前
记一次K8S 环境应用nginx stable-alpine 解析内部域名失败排查思路
运维·nginx·云原生·容器·kubernetes
feng_xiaoshi18 小时前
【云原生】云原生架构的反模式
云原生·架构
程序那点事儿20 小时前
k8s 之动态创建pv失败(踩坑)
云原生·容器·kubernetes
叶北辰CHINA21 小时前
nginx反向代理,负载均衡,HTTP配置简述(说人话)
linux·运维·nginx·http·云原生·https·负载均衡
Lansonli1 天前
云原生(四十八) | Nginx软件安装部署
nginx·云原生·ecs服务器
唐大爹1 天前
项目实战:k8s部署考试系统
云原生·容器·kubernetes