文|唐斌

字节跳动根底架构研发工程师

Nydus 与 Nydus snapshotter 社区贡献者,专注存储,云原生技能。

本文 6964 字 阅览15 分钟


1 Nydus

1.1 存在的问题

关于容器镜像运用者

问题一: 发动容器慢:容器发动慢的状况遍及发生在当用户发动一个很大的容器镜像时,因为在容器预备阶段需求三步(以 overlayfs 为例):

下载镜像;

解压镜像;

运用 overlayfs 将容器可写层和镜像中的只读层聚合起来供给容器运转环境。

其间,下载镜像阶段需求下载整个镜像文件,不能完结文件数据按需加载。再加上下载镜像自身受限于网络带宽,当容器镜像到达 GB 级别时,下载时刻会较长,破坏了容器本来优秀的用户体验。

问题二: 较高的本地存储成本:不同镜像之间能够同享的最小单位是镜像中的层,缺点之一是重复数据的处理功率较低。

原因如下:

首要,层内部存在重复的数据;

其次,层与层之间或许存在很多重复的数据,即便有细小的不同,也会被作为不同的层;

再次,依据 OCI imagespec 对删去文件和 hardlink 的设计,镜像内部现已被上层删去的文件或许依然存在于基层,并包含在镜像中。

关于镜像供给者

这里的供给者首要指容器服务的镜像中心。

问题一: 巨大的存储资源糟蹋。

存在很多相似镜像,形成这种状况有两个原因:

  • 首要,上面说到的层的缺点,导致在容器镜像中心存在许多相似镜像;

  • 其次,OCI image 运用了 tar+gzip 格局来表明镜像中的层,而 tar 格局并不区别 tar archive entries ordering,这带来一个问题,假如用户在不同机器上 build 同一个镜像,终究或许会因为运用了不同的文件体系而得到不同的镜像,用户上传之后,镜像中心中会存在若干不同镜像的本质内容是完全相同的状况。

– 镜像去重功率低

尽管镜像中心有废物收回机制来完结去重功用,但其依然以层为单位,所以只能在有完全相同 hash value 的层之间去重。

问题二: 云原生软件供应链带来的新需求。

跟着时刻推移,和软件供应链一同发展的还有对软件供应链环节的多样性攻击手段。安全防护是软件供应链中十分重要的组成,不但表现在对软件自身的安全增强,也表现在对供应链的安全增强。因为运用运转环境被前置到了容器镜像中,所以对容器镜像的安全,包括对镜像的缝隙扫描和签名成为了容器服务供给者的必要才能。

OCI 镜像规范的缺点

首要的缺点有两点:

– tar 格局规范

  • tar 格局并不区别 tar archive entries ordering,这带来一个问题,即假如用户在不同机器上 ;build 同一个镜像,终究或许会因为运用了不同的文件体系而得到不同的镜像,比如在文件体系 A 上的 order 是 foo 在 bar 之前进入 tar,在文件体系 B 上的 order 是 bar 在 foo 之前进入tar ,那么这两个镜像是不同的;

  • 当 tar 被 gzip 压缩过之后不支撑 seek ,导致运转之前有必要先下载并解压 targz 的 image layers,而不能完结文件数据按需加载。

– 以层为镜像的根本单位

  • 内容冗余:不同层之间相同信息在传输和存储时都是冗余内容,在不读取内容的时分无法判断到这些冗余的存在;

  • 无法并行:每一层是一个整体,对同一个层既无法并行传输,也不能并行提取;

  • 无法进行小块数据的校验,只要完好的层下载完结之后,才干对整个层的数据做完好性校验;

  • 其他一些问题:比如,跨层数据删去难以完美处理。

1.2 Nydus 根底

在容器的出产实践中,偏小的容器镜像能够很快布置发动。当运用的镜像到达 GB 级以上的时分,在节点上下载镜像通常会消耗很多的时刻。Dragonfly 经过引进 P2P 网络有效地提升了容器镜像大规模分发的功率。然而,用户有必要等候镜像数据完好下载到本地,然后才干创立自己的容器。

Nydus 是在最新的 OCI Image-Spec 根底之上设计的容器镜像加快服务,从头设计了镜像格局和底层文件体系,然后加快容器发动速度,进步大规模集群中的容器发动成功率。Nydus 由阿里云和蚂蚁集团的工程师合作开发,并大规模布置在内部的 出产环境中。

Nydus 优化了现有的 OCI 镜像规范格局,并以此设计了一个用户态的文件体系。经过这些优化,Nydus 能够供给这些特性:

  • 容器镜像按需下载,用户不再需求下载完好镜像就能发动容器

  • 块级别的镜像数据去重,最大极限为用户节省存储资源

  • 镜像只要终究可用的数据,不需求保存和下载过期数据

  • 端到端的数据一致性校验,为用户供给更好的数据保护

  • 兼容 OCI 分发规范和 artifacts 规范,开箱即可用

支撑不同的镜像存储后端,镜像数据不只能够存放在镜像库房,还能够放到 NAS 或者相似 S3 的方针存储上

  • 与 Dragonfly 的良好集成

1.3 Nydus 架构

Nydus | 容器镜像基础

Nydus 的架构首要包含两部分内容:

– 新的镜像格局(Rafs)

Nydus | 容器镜像基础

– 担任解析容器镜像的 FUSE 用户态文件体系进程

Nydus 兼容多种文件体系,能够解析 FUSE 和 virtiofs 协议来支撑传统的 runc 容器、 Kata容器。关于存储后端,支撑运用容器库房( Registery )、OSS 方针存储 、NAS、Dragonfly 的超级节点和 Peer 节点作为 Nydus 的镜像数据存储后端。此外,为了加快发动速度,Nydus 还能够装备一个本地缓存,避免每次发动容器时都从远端数据源拉取数据。

1.4 Nydus 特性

容器发动速度变快

用户布置了 Nydus 镜像服务后,因为运用了按需加载镜像数据的特性,容器的发动时刻显着缩短。在官网的测验数据中,Nydus 能够把常见镜像的发动时刻,从数分钟缩短到数秒钟。理论上来说,容器镜像越大,Nydus 表现出来的效果越显着。

Nydus | 容器镜像基础

供给运转时数据一致校验

在传统的镜像中,镜像数据会先被解压到本地文件体系,再由容器运用去拜访运用。解压前,镜像数据是完好校验的。但是解压之后,镜像数据不再能够被校验。这带来的一个问题便是,假如解压后的镜像数据被无意或者歹意地修改, 用户是无法感知的。而 Nydus 镜像不会被解压到本地,一起能够对每一次数据拜访进行校验,假如数据被篡改,则能够从远端数据源从头拉取。

Nydus | 容器镜像基础

从图中能够看出,对容器镜像数据进行运转时一致性校验是经过对每个数据块核算 SHA 256 完结的,这得益于 Nydus 选用分块的方式办理镜像数据。假如在镜像文件十分大的时分,对整个镜像文件核算哈希值十分不现实。

1.5 Nydus 镜像格局:RAFS

RAFS 是对 EROFS 文件体系的增强,拓展在云原生场景下的才能,使其习惯容器镜像存储场景。RAFS v6 是内核态的容器镜像格局,除了将镜像格局下沉到内核态,还在镜像格局进步行了一系列优化,例如块对齐、愈加精简的元数据等。

RAFS v6 镜像格局

Nydus | 容器镜像基础

1.6 Nydus -snapshotter

Nydus snapshotter 是 containerd 的一个外部插件,使得 containerd 能够运用 Nydus 镜像加快服务。在 containerd 中, snapshot 的作业是给容器供给 rootfs,Nydus snapshotter 完结了 containerd 的 snapshot 的接口,使得 containerd 能够经过 Nydus 预备 rootfs 以发动容器。因为 nydus-snapshotter 完结了按需加载的特性,在 containerd 发动容器时,只需求依据容器镜像的元数据信息预备 rootfs ,部分目录对应的数据并未存储在本地,当在容器中拜访到(本地拜访未射中)这部分数据时,经过 Nydusd 从镜像 registry 拉取对应数据内容。

Nydus | 容器镜像基础

02 FUSE

用户态文件体系( filesystem in userspace, 简称 FUSE )使得用户无需修改内核代码就能创立自定义的文件体系。FUSRE 催生了著名的 fuse-overlayfs,其在 rootless 容器化中扮演重要的人物。

用户态文件体系并不完全在用户态完结,由两部分组成:内核模块和用户态进程。

  • 内核模块:文件体系数据流程的功用完结,担任截获文件拜访恳求和回来用户态进程处理恳求的成果

  • 用户态进程:担任处理详细的数据恳求,对应处理函数由内核模块触发

FUSE 的作业流程如下图:

Nydus | 容器镜像基础

其间,fuse_user 是运转在用户态的文件体系进程,该程序会在发动时注册完结的数据恳求处理接口,如 ls 、cd 、mkdir 等,一起,程序在某个途径挂载 fuse 文件体系 /tmp/fuse_fs ,当对 /tmp/fuse_fs 履行相关操作时:

  • 恳求会经过 VFS(虚拟文件体系) 到达 fuse 的内核模块

  • 内核模块依据恳求类型,调用用户态进程注册的函数

  • 当程序完结对恳求的处理后,将成果经过 VFS 回来给体系调用

03 Containerd

Containerd 最开端是 Docker Engine 中的一部分,后来,containerd 被分离出来作为独立的开源项目,方针是供给更敞开、安稳的容器运转根底设施。分离出来的 containerd 将具有更多的功用,包括整个容器运转时办理的一切需求。

Containerd 是一个行业规范的容器运转时,着重简单性、健壮性和可移植性,能够作为看护进程运转在体系中。

Containerd 的功用首要包括以下内容:

  • 办理容器的生命周期(从创立容器到毁掉容器)

  • 拉取/推送容器镜像

  • 存储办理(办理镜像及容器数据的存储)

  • 调用 runc 运转容器(与 runc 等容器运转时交互)

  • 办理容器网络接口及网络

Containerd 选用 C/S 架构,服务端经过 unix domain socket 暴露低层 gRPC 接口,客户端经过这些 gRPC 接口办理节点上的容器,containerd 担任办理容器的镜像、生命周期、网络和存储,实践运转容器是由容器运转时(runc 是其间一种)完结。

Nydus | 容器镜像基础

Containerd 将体系划分红不同的组件,每个组件由一个或多个模块协作完结(Core 部分),不同模块都以插件的方式集成到 containerd 中,插件之间相互依赖。

Nydus | 容器镜像基础

Containerd 的组件能够分红三类:Storage、Metadata 和 Runtimes,snapshot 归于 Storage 组件中的一个插件,用来办理容器镜像的文件体系快照,镜像中的每一层都会被解压成文件体系快照。在运用 Nydus 的 containerd 环境中,Nydus-snapshotter 担任完结这部分作业。

04 Erofs + fsache

Erofs over fscache 根本概念

Erofs over fscache 是 Linux 内核原生的镜像按需加载特性,于 5.19 版别合入 Linux 内核主线。

已有的用户态计划会涉及频繁的内核态/用户态上下文切换,以及内核态/用户态之间的内存复制,然后形成性能瓶颈。这一问题在容器镜像现已悉数下载到本地的时分特别杰出,容器运转进程中涉及的文件拜访,都会陷出到用户态的服务进程。

事实上咱们能够将按需加载的

(1)缓存办理和

(2)缓存未射中的时分经过各种途径 (例如网络) 获取数据,这两个操作解耦开。缓存办理能够下沉到内核态履行,这样当镜像在本地 ready 的时分,就能够避免内核态/用户态上下文的切换。而这也正是 erofs over fscache 技能的价值所在。

fscache/cachefiles (以下统称 fscache ) 是 Linux 体系中相对老练的文件缓存计划,广泛运用于网络文件体系,erofs over fscache 技能使得 fsache 能够支撑 erofs 的按需加载特性。

容器在拜访容器镜像的时分,fscache 会检查当时恳求的数据是否现已缓存,假如缓存射中 ( cache hit ),那么直接从缓存文件读取数据。这一进程全程处于内核态之中,并不会陷出到用户态。

Nydus | 容器镜像基础

缓存未射中 ( cache miss )时 需求告诉用户态的 Nydusd 进程以处理这一拜访恳求,此刻容器进程会堕入睡觉等候状况;Nydusd 经过网络从远端获取数据,经过 fscache 将这些数据写入对应的缓存文件,之后告诉之前堕入睡觉等候状况的进程该恳求现已处理完结;之后容器进程即可从缓存文件读取到数据。

Erofs over fscache 优势

– 异步预取

容器创立之后,当容器进程没有触发按需加载 (cache miss) 的时分,用户态的 Nydusd 就能够开端从网络下载数据并写入缓存文件,之后当容器拜访的文件方位恰好处于预取范围内的时分,就会触发 cache hit 直接从缓存文件读取数据,而不会再陷出到用户态。用户态计划则无法完结该优化。

Nydus | 容器镜像基础

– 网络 IO 优化

当触发按需加载 (cache miss) 时,Nydusd 能够一次性从网络下载比当时实践恳求的数据量更多的数据,并将下载的数据写入缓存文件。例如容器拜访 4K 数据触发的 cache miss,而 Nydusd 实践一次性下载 1MB 数据,以减小单位文件大小的网络传输延时。之后容器拜访接下来的这 1MB 数据的时分,就不用再陷出到用户态

用户态计划则无法完结该优化,因为即便触发 cache miss 的时分,用户态的服务进程相同完结了该优化,下一次容器拜访坐落读扩大范围内的文件数据的时分,相同会陷出到用户态。

Nydus | 容器镜像基础

– 更佳的性能表现

当镜像数据现已悉数下载到本地的时分 (即不考虑按需加载的影响), erofs over fscache 的性能表现明显优于用户态计划,一起与原生文件体系的性能相近,然后完结与原生容器镜像计划 (未完结按需加载) 相近的性能表现。

05 环境装置

nerdctl 装置

# git clone https://github.com/rootless-containers/rootlesskit.git
# cd rootlesskit
# make && sudo make install
wget https://github.com/containerd/nerdctl/releases/download/v0.22.2/nerdctl-full-0.22.2-linux-amd64.tar.gz
sudo tar -zxvf nerdctl-full-0.22.2-linux-amd64.tar.gz -C /usr/local
sudo systemctl enable --now containerd
sudo systemctl enable --now buildkit
# sudo apt-get install uidmap -y
# containerd-rootless-setuptool.sh install
sudo nerdctl version    # 需求运用sudo,否则会提示装置 rootless

Nydus | 容器镜像基础

Nydus 装置

装首要的3个东西(也能够直接下载一切东西的二进制文件,编译装置时默许没有没有 Nydusify ):

nydusify将 OCI 格局的容器镜像转化为 Nydus 格局( RAFS )容器镜像的东西。

nydus-image将解压后的容器镜像转化为 Nydus 格局镜像的东西。

nydusd解析 Nydus 格局镜像并供给 FUSE 挂载点以供容器拜访的看护程序。nydusd也能够用作 virtiofs 后端,使得 Guest 能够拜访 Host 的文件。

git clone https://github.com/dragonflyoss/image-service.git
cd image-service
make && make install
# 默许没有装置 nydusify
wget https://github.com/dragonflyoss/image-service/releases/download/v2.1.0-rc.1/nydus-static-v2.1.0-rc.1-linux-amd64.tgz
mkdir nydus-static
tar -zxvf nydus-static-v2.1.0-rc.1-linux-amd64.tgz -C nydus-static
sudo cp nydus-static/nydusify /usr/local/bin
sudo cp nydus-static/nydus-overlayfs /usr/local/bin
nydus-image --version
nydusify --version
nydusd --version

装置 Nydus-snapshotter

git clone github.com/containerd/nydus-snapshotter.git
cd nydus-snapshotter
make && make install
sudo systemctl enable nydus-snapshotter
sudo systemctl start nydus-snapshotter
systemctl status nydus-snapshotter

Nydus | 容器镜像基础

Nydus-snapshotter 以 service 的方式运转 /usr/local/bin/containerd-nydus-grpc 可履行文件,装备信息坐落 /etc/nydus/config.json 文件。

默许 address 方位:

/run/containerd-nydus/containerd-nydus-grpc.sock

默许作业目录:

/var/lib/containerd-nydus-grpc

默许缓存目录:

/var/lib/containerd-nydus-grpc/cache

布置本地镜像库房(测验用)

# sudo docker run -d -p 5000:5000 \
# --restart=always \
# --name registry \
# -v /var/lib/registry:/var/lib/registry \
# -d registry
sudo docker run -d --name=registry --restart=always -p 5000:5000 registry
sudo docker logs registry -f

将 OCI 格局的镜像转化为 RAFS 格局镜像

sudo nydusify convert \
  --nydus-image $(which nydus-image) \
  --source ubuntu:16.04 \
  --target localhost:5000/ubuntu:16.04-nydus

Nydusify 根本指令:

Nydus | 容器镜像基础

转化后的镜像层文件坐落当时目录下的 tmp 文件夹:

sudo tree tmp -L 4

Nydus | 容器镜像基础

将 OCI 规范的镜像格局转化为 Nydus 运用的 RAFS 镜像格局后,能够运用 Nydusd 解析并供给 fuse 挂载点供容器运用。编写装备文件 registry.json,使得 Nydus 运用 容器镜像 registry (现已搭建本地容器镜像 register 用于测验)作为存储后端。

{
  "device": {
    "backend": {
      "type": "registry",
      "config": {
        "scheme": "http",
        "host": "localhost:5000",
        "repo": "ubuntu"
      }
    },
    "digest_validate": false
  },
  "mode": "direct"
}

挂载 RAFS 镜像 为 fuse 挂载点,–bootstrap 参数传递坐落 tmp/bootstraps 下的文件途径:

sudo nydusd \
  --config ./registry.json \
  --mountpoint /mnt \
  --bootstrap ./tmp/bootstraps/4-sha256:fb15d46c38dcd1ea0b1990006c3366ecd10c79d374f341687eb2cb23a2c8672e \
  --log-level info

查看挂载状况:

Nydus | 容器镜像基础

输出日志信息:

Nydus | 容器镜像基础

除了运用 Nydusify 直接将 OCI 规范格局镜像转化为 Nydus 格局镜像,Nydus-image 东西也支撑直接对现已解压的 OCI 容器镜像文件层转化为 Nydus 格局镜像。

(1)获取 OCI 镜像元数据信息:

docker pull ubuntu:16.04
sudo docker inspect -f "{{json .GraphDriver }}" ubuntu:16.04  | jq .

Docker 运用 overlay2 存储驱动,经过所需的 lowerdir 、upperdir 、merged 和 workdir 结构自动创立 overlay 挂载点。

Nydus | 容器镜像基础

关于 Nydus 来说,目录树(通常是一个镜像层)由两部分组成:

  • bootstrap:存储目录的文件体系元数据信息

  • blob:存储目录中的一切文件数据

(2)建立生成 Nydus 镜像的目录:

mkdir -p nydus-image/{blobs,layer1,layer2,layer3,layer4}

(3)转化最底层的镜像层:

sudo nydus-image create \
  --bootstrap ./nydus-image/layer1/bootstrap \
  --blob-dir ./nydus-image/blobs \
  --compressor none /var/lib/docker/overlay2/78f2b3506072c95ca3929a0a797c1819e8966b8bbf5ce8427b671296ca1ad35a/diff
tree -L 2 ./nydus-image

Nydus | 容器镜像基础

(4)转化第 2 底层镜像层,–parent-bootstrap 指父层,即刚才转化好的镜像层:

sudo nydus-image create \
  --parent-bootstrap ./nydus-image/layer1/bootstrap \
  --bootstrap ./nydus-image/layer2/bootstrap \
  --blob-dir ./nydus-image/blobs \
  --compressor none /var/lib/docker/overlay2/373ea430abb0edd549583f949ec8259806d9eb7d0a0416ec1494d2fc7efeeedc/diff

Nydus | 容器镜像基础

(5)转化第 3 层和第 4 层,每次都需求指定 –parent-bootstrap 为上一次生成的镜像层:

sudo nydus-image create \
  --parent-bootstrap ./nydus-image/layer2/bootstrap \
  --bootstrap ./nydus-image/layer3/bootstrap \
  --blob-dir ./nydus-image/blobs \
  --compressor none /var/lib/docker/overlay2/05424b8c067c59368c11ad5674d68d95365e87487bdf10e3d9842b1016583369/diff
sudo nydus-image create \
  --parent-bootstrap ./nydus-image/layer3/bootstrap \
  --bootstrap ./nydus-image/layer4/bootstrap \
  --blob-dir ./nydus-image/blobs \
  --compressor none /var/lib/docker/overlay2/942c712e7276be5bde4fb7b30f72583c4a9cf0b2aaa14215cd690daf893a630e/diff

将 Nydus 镜像挂载到目录:

sudo nydusd \
  --config  ./localfs.json \
  --mountpoint /mnt \
  --bootstrap ./nydus-image/layer4/bootstrap \
  --log-level info

其间, localfs.json 文件的内容为:

{
  "device": {
    "backend": {
      "type": "localfs",
      "config": {
        "dir": "/<YOUR-WORK-PATH>/nydus-image/blobs"
      }
    }
  },
  "mode": "direct"
}

Dir 为生成的 Nydus 镜像文件中 blobs 目录的绝对途径。

06 经过 Nydus+snapshotter 发动容器

添加装备文件

Nydus 供给了 containerd 长途快照办理东西 containerd-nydus-grpc 用于预备 Nydus 镜像格局的容器 rootfs ,首要将 Nydusd 装备保存到 /etc/nydus/config.json 文件。

sudo tee /etc/nydus/config.json > /dev/null << EOF
{
  "device": {
    "backend": {
      "type": "registry",
      "config": {
        "scheme": "http",
        "skip_verify": false,
        "timeout": 5,
        "connect_timeout": 5,
        "retry_limit": 2,
        "auth": ""
      }
    },
    "cache": {
      "type": "blobcache",
      "config": {
        "work_dir": "cache"
      }
    }
  },
  "mode": "direct",
  "digest_validate": false,
  "iostats_files": false,
  "enable_xattr": true,
  "fs_prefetch": {
    "enable": true,
    "threads_count": 4
  }
}
EOF

containerd-nydus-grpc 会自动从 $HOME/.docker/config.json 中读取 docker login auth ,假如不想运用这个值,需求直接替换装备文件中的内容。

直接从终端发动 containerd-nydus-grpc,假如现现已过 containerd-nydus-grpc service 发动,则能够跳过此过程:

sudo /usr/local/bin/containerd-nydus-grpc \
    --config-path /etc/nydus/config.json \
    --shared-daemon \
    --log-level info \
    --root /var/lib/containerd/io.containerd.snapshotter.v1.nydus \
    --cache-dir /var/lib/nydus/cache \
    --address /run/containerd-nydus/containerd-nydus-grpc.sock \
    --nydusd-path /usr/local/bin/nydusd \
    --nydusimg-path /usr/local/bin/nydus-image \
    --log-to-stdout

修改 containerd 装备文件

proxy_plugins.nydus 的 address 和 containerd-nydus-grpc 的对应。

sudo tee -a /etc/containerd/config.toml << EOF
[proxy_plugins]
  [proxy_plugins.nydus]
    type = "snapshot"
    address = "/run/containerd-nydus/containerd-nydus-grpc.sock"
[plugins.cri]
  [plugins.cri.containerd]
    snapshotter = "nydus"
    disable_snapshot_annotations = false
EOF
sudo systemctl restart containerd
sudo ctr -a /run/containerd/containerd.sock plugin ls | grep nydus

经过 Nydus 发动容器

# 转化镜像并上传到本地 registry
sudo nydusify convert --nydus-image /usr/local/bin/nydus-image --source ubuntu --target localhost:5000/ubuntu-nydus
sudo nerdctl --snapshotter nydus pull localhost:5000/ubuntu-nydus:latest
sudo nerdctl --snapshotter nydus run --rm -it localhost:5000/ubuntu-nydus:latest bash

Nydus | 容器镜像基础

重启主机之后发动环境

sudo systemctl restart nydus-snapshotter
sudo systemctl restart containerd
sudo docker rm -f registry
sudo docker run -d --name=registry --restart=always -p 5000:5000 registry && sudo docker logs registry -f

07参考资料

[1]OCI 镜像规范格局: github.com/opencontain…

[2]自校验的哈希树: en.wikipedia.org/wiki/Merkle…

[3]FUSE: www.kernel.org/doc/html/la…

[4]virtiofs: virtio-fs.gitlab.io/

[5]runc 容器: github.com/opencontain…

[6]Kata容器: katacontainers.io/

[7]OSS 方针存储: www.alibabacloud.com/product/oss

[8]Nydus-snapshotter: github.com/containerd/…

[9]fuse-overlayfs: github.com/containers/…

[10]5.19 版别: git.kernel.org/pub/scm/lin…

[11]关于容器镜像运用者: mp.weixin.qq.com/s/yC-UmMSDj…

本周推荐阅览

Nydus —— 下一代容器镜像的探索实践

Nydus 镜像加快插件迁入 Containerd 旗下

cgo 机制 – 从 c 调用 go

从规模化渠道工程实践,咱们学到了什么?