写点什么

《containerd 系列》作为资深 CRUD Boy,你知道 containerd 是如何保存容器元数据的吗?

  • 2024-04-26
    浙江
  • 本文字数:3761 字

    阅读完需:约 12 分钟

本文内容节选自 《containerd 原理剖析与实战》,本书正参加限时优惠内购,点击阅读原文,限时 69.9 元购买

containerd 的整体架构

containerd 为典型的 C/S 架构,其中我们提到的 containerd 主要为 Server 端实现,架构图如下:



<p align=center>containerd API、Service、 MetaData 架构</p>


如图所示, containerd GRPC API、Service、 MetaData 为典型的 API 层、逻辑层、数据层架构。GRPC API 层为暴露服务的接口层,Service 层为具体的逻辑处理层,Metadata 为数据层,Service、 MetaData 两层为 Core 层。

MetaData

containerd 中的各个微服务插件的元数据都保存在 metadata 中,存储采用了 boltdb 开源数据库。


boltdb 是基于 Golang 实现的 KV 数据库。boltdb 提供最基本的存储功能,并不支持网络连接,不支持复杂的 SQL 查询。单个数据库数据存储在单个文件里,通过 API 的方式对数据文件读写,达到数据持久化的效果。bolt 通过嵌入在程序中进行使用,我们熟知的 ETCD 就是基于 boltdb 实现的。


containerd 通过 boltdb 对相关对象的的元数据进行存储,如 snapshots、image、container 等,同时 containerd 对 metadata 中的数据还会定期执行垃圾收集,用于自动清理过期不使用的资源。


containerd 中的对象在 boltdb 中保存格式如下。


<version>/<namespace>/<object>/<key> -> <field>
复制代码


其中:


  • <version> : containerd 的版本,当前为 v1

  • <namespace>: 对象所对应的 namespace

  • <object>: 要保存在 boltdb 中的对象类型

  • <key>: 用于指定特定对象的唯一值   containerd 中的 boltdb schema 数据结构可以参考 github.com/containerd/containerd/metadata/buckets.go 文件中的定义,如下。


 └──v1                                        - Schema version bucket    ├──version : <varint>                     - Latest version, see migrations    ╘══*namespace*   ├──labels   │  ╘══*key* : <string>                 - Label value   ├──image   │  ╘══*image name*   │     ├──createdat : <binary time>     - Created at   │     ├──updatedat : <binary time>     - Updated at   │     ├──target   │     │  ├──digest : <digest>          - Descriptor digest   │     │  ├──mediatype : <string>       - Descriptor media type   │     │  └──size : <varint>            - Descriptor size   │     └──labels   │        ╘══*key* : <string>           - Label value   ├──containers   │  ╘══*container id*   │     ├──createdat : <binary time>     - Created at   │     ├──updatedat : <binary time>     - Updated at   │     ├──spec : <binary>               - Proto marshaled spec   │     ├──image : <string>              - Image name   │     ├──snapshotter : <string>        - Snapshotter name   │     ├──snapshotKey : <string>        - Snapshot key   │     ├──runtime   │     │  ├──name : <string>            - Runtime name   │     │  └──options : <binary>         - Proto marshaled options   │     ├──extensions   │     │     ╘══*name* : <binary>       - Proto marshaled extension   │     └──labels   │        ╘══*key* : <string>           - Label value   ├──snapshots   │  ╘══*snapshotter*   │     ╘══*snapshot key*   │        ├──name : <string>            - Snapshot name in backend   │        ├──createdat : <binary time>  - Created at   │        ├──updatedat : <binary time>  - Updated at   │        ├──parent : <string>          - Parent snapshot name   │        ├──children   │        │  ╘══*snapshot key* : <nil>  - Child snapshot reference   │        └──labels   │           ╘══*key* : <string>        - Label value   ├──content   │  ├──blob   │  │  ╘══*blob digest*   │  │     ├──createdat : <binary time>  - Created at   │  │     ├──updatedat : <binary time>  - Updated at   │  │     ├──size : <varint>            - Blob size   │  │     └──labels   │  │        ╘══*key* : <string>        - Label value   │  └──ingests   │     ╘══*ingest reference*   │        ├──ref : <string>             - Ingest reference in backend   │        ├──expireat : <binary time>   - Time to expire ingest   │        └──expected : <digest>        - Expected commit digest   ├──sandboxes   │  ╘══*sandbox id*   │     ├──createdat : <binary time>     - Created at   │     ├──updatedat : <binary time>     - Updated at   │     ├──spec : <binary>               - Proto marshaled spec   │     ├──runtime   │     │  ├──name : <string>            - Runtime name   │     │  └──options : <binary>         - Proto marshaled options   │     ├──extensions   │     │  ╘══*name* : <binary>       - Proto marshaled extension   │     └──labels   │        ╘══*key* : <string>           - Label value   └──leases      ╘══*lease id*          ├──createdat : <binary time>     - Created at          ├──labels          │  ╘══*key* : <string>           - Label value          ├──snapshots          │  ╘══*snapshotter*          │     ╘══*snapshot key* : <nil>  - Snapshot reference          ├──content          │  ╘══*blob digest* : <nil>      - Content blob reference          └─────ingests               ╘══*ingest reference* : <nil> - Content ingest reference
复制代码


可以看到 metadata 中保存了诸如 imagescontainerssnapshotscontentleases 等对象的基本信息。metadata 在宿主机上保存的路径为 /var/lib/containerd/io.containerd.metadata.v1.bolt/meta.db  可以通过 boltbrowser 查看 boltdb 中的内容,操作如下。

1. 首先停止 containerd

通过 systemctl 来停止 containerd,命令如下。


systemctl stop containerd

2. 安装 boltbrowser

通过下面的命令下载并安装 boltbrowser,boltbrowser 是一款开源的 boltdb 数据库浏览器。


git clone https://github.com/br0xen/boltbrowser.gitcd boltbrowsergo build
复制代码

3. 查看对应的 blotdb

通过 boltbrowser 指令查看 boltdb 数据库。


boltbrowser /var/lib/containerd/io.containerd.metadata.v1.bolt/meta.db
复制代码


boltbrowser 是可视化的界面,可以通过上线移动光标选中对象,按 enter 进入查看或者关闭查看。下面的输出是光标指在 "containers" 时的界面:


         boltbrowser: /var/lib/containerd/io.containerd.metadata.v1.bolt/meta.db========================================|=================================  - v1                                          | Path: v1 → default → containers    + buildkit                                   | Buckets: 23    - default                                    | Pairs: 0      - containers                               |        + 14f6ea28faa77d4db41088e1a7f1f4cc2a   |        + 272587a117b8d2f1cb87489a78325c3fd4  |        + 534ccbb979222b85190c1c5e6108e71ee7 |        + 57510ed4290ca701447ea6686339909d23 |        + 5a4cedbad48ce3028ae14424c70b5a0d3b |        + ...   省略部分容器 ...        + busybox1                             |        + nginx_1                               |        + zjz                                   |      + content                                 |      + images                                 |      + leases                                  |      + snapshots                               |    + docker                                    |    + k8s.io                                     |    + moby                                     |    version: 06                                  |
复制代码


上述介绍了 containerd 是如何利用 bbolt 保存 metadata 的,作为 典型的 C/S 架构,containerd 还有 API 层、Core 层、Backend 层,详细的解读可以参考 《containerd 原理剖析与实战》这本书。



containerd 系列文章参考


【史上最全】带你全方位了解containerd 的几种插件扩展模式


了解 containerd 中的 snapshotter,先从 native 开始


一文了解 containerd 中的 snapshot


一文读懂 containerd 中的 NRI 机制


一文了解 containerd 中的镜像加解密


本文使用 文章同步助手 同步

发布于: 刚刚阅读数: 4
用户头像

just do it 2018-09-25 加入

赵吉壮,《containerd 原理剖析与实战》作者,曾就职于华为 Cloud BU,字节跳动 Data 团队,专注于 k8s, Serverless, Go 云原生

评论

发布
暂无评论
《containerd 系列》作为资深 CRUD Boy,你知道 containerd 是如何保存容器元数据的吗?_Docker_公众号:云原生Serverless_InfoQ写作社区