5 分钟
Nydus 核心二进制使用和性能测评
简介
Nydus 采用了一种创新的文件系统设计,将元数据(目录结构)与文件内容分离,从而实现了高效的只读文件系统格式。通过这种设计,用户只需预先下载元数据即可完成文件系统的挂载,而文件内容则在实际使用时按需加载。这种机制显著提升了远程文件系统挂载的速度。
Nydus 的主要应用场景是容器化环境,特别适用于加速 OCI 镜像(如 Docker 镜像)的挂载过程。社区提供了对 Kubernetes、Docker 等主流容器运行时的无缝集成支持,使其在容器生态中具有广泛的适用性。
本文将介绍如何利用 Nydus 提供的核心工具构建 Nydus 镜像,并在 Linux 系统中完成镜像的挂载操作。此外,本文还将浅析 Nydus 的技术原理及其基础性能评估结果。
通过本文,方案设计者可以获取足够的信息来评估是否采用以及何时采用 Nydus 技术。需要注意的是,本文不涉及在 Kubernetes 等容器平台中深度集成 Nydus 的具体实现细节,如需了解相关内容,请参考官方文档。
测试环境
- AWS us-east-1 t2.micro:
- CPU: 1 vCPU
- RAM: 1 GiB
- Disk: gp3, 3000 IOPS, 125 MiB/s
- 操作系统: Amazon Linux 2023 (fedora)
- 用户: root
- Nydus 版本: v2.3.0
- 测试目录
/root/nydus-demo
Nydus 核心工具安装
wget https://github.com/dragonflyoss/nydus/releases/download/v2.3.0/nydus-static-v2.3.0-linux-amd64.tgz
tar -zxvf nydus-static-v2.3.0-linux-amd64.tgz
chown -R 0:0 nydus-static
mv nydus-static/nydus* /usr/local/bin
rm -rf nydus-static nydus-static-v2.3.0-linux-amd64.tgz
基本使用
准备 mock 的根目录
mkdir -p 01-basic
cd 01-basic
mkdir -p origin-root-dir
mkdir -p origin-root-dir/dir_1 origin-root-dir/dir_2
mkdir -p origin-root-dir/dir_1/subdir_a origin-root-dir/dir_1/subdir_b
echo 'file_a' > origin-root-dir/dir_1/subdir_a/file_a
echo 'file_b' > origin-root-dir/dir_2/file_b
echo 'file_c' > origin-root-dir/file_c
ln -s file_c origin-root-dir/file_c_ln
tree origin-root-dir
# origin-root-dir
# ├── dir_1
# │ ├── subdir_a
# │ │ └── file_a
# │ └── subdir_b
# ├── dir_2
# │ └── file_b
# ├── file_c
# └── file_c_ln -> file_c
从目录构建 Nydus 镜像
nydusify --debug build --name image-basic-01 --source-dir origin-root-dir --output-dir image-store/
# DEBU[2025-02-24T12:48:02Z] Command: /usr/local/bin/nydus-image create --bootstrap image-store/image-basic-01.meta --log-level warn --whiteout-spec oci --output-json image-store/output.json --blob image-store/image-basic-01.blob --fs-version 6 --compressor zstd --chunk-size 0x100000 origin-root-dir
mv image-store/image-basic-01.blob image-store/$(cat image-store/output.json | jq -r '.blobs[0]')
du -ah --max-depth 1 image-store/
# 16K image-store/image-basic-01.meta
# 4.0K image-store/output.json
# 8.0K image-store/58048df580011d3a700076d8a1ec9ccaee6881f7feb8352aa298959ee8866f28
# 28K image-store/
挂载本地的 Nydus 镜像
mkdir -p mnt-local
tee nydusd-config.localfs.json > /dev/null << EOF
{
"device": {
"backend": {
"type": "localfs",
"config": {
"dir": "image-store"
}
},
"cache": {
"type": "blobcache",
"config": {
"work_dir": "cache"
}
}
},
"mode": "direct",
"digest_validate": false,
"iostats_files": false,
"enable_xattr": true
}
EOF
nydusd --config nydusd-config.localfs.json --mountpoint mnt-local --bootstrap image-store/image-basic-01.meta --log-level info
# 打开新终端,切换到该目录,观察 mnt-local 目录
cd /root/nydus-demo/01-basic
tree mnt-local/
# mnt-local/
# ├── dir_1
# │ ├── subdir_a
# │ │ └── file_a
# │ └── subdir_b
# ├── dir_2
# │ └── file_b
# ├── file_c
# └── file_c_ln -> file_c
du -ah --max-depth 1 cache/
# 4.0K cache/58048df580011d3a700076d8a1ec9ccaee6881f7feb8352aa298959ee8866f28.blob.data.chunk_map
# 0 cache/58048df580011d3a700076d8a1ec9ccaee6881f7feb8352aa298959ee8866f28.blob.data
# 8.0K cache/58048df580011d3a700076d8a1ec9ccaee6881f7feb8352aa298959ee8866f28.blob.meta
# 28K cache/
cat mnt-local/dir_1/subdir_a/file_a
# file_a
cat mnt-local/dir_2/file_b
# file_b
cat mnt-local/file_c
# file_c
cat mnt-local/file_c_ln
# file_c
du -ah --max-depth 1 cache/
# 8.0K cache/58048df580011d3a700076d8a1ec9ccaee6881f7feb8352aa298959ee8866f28.blob.data.chunk_map
# 12K cache/58048df580011d3a700076d8a1ec9ccaee6881f7feb8352aa298959ee8866f28.blob.data
# 8.0K cache/58048df580011d3a700076d8a1ec9ccaee6881f7feb8352aa298959ee8866f28.blob.meta
# 44K cache/
过程分析
- 镜像构建:
nydusify
工具 指定镜像名、源目录、输出目录。nydusify
工具解析命令行参数,并调用nydus-image
工具create
子命令构建 Nydus 镜像,参数如下:--bootstrap
: 生成的 Nydus 镜像的元数据文件路径。--log-level
: 日志级别,可选值:trace
,debug
,info
,warn
,error
。--whiteout-spec
: whiteout 规范,可选值为oci
,overlayfs
,none
。--output-json
: 输出 JSON 文件,包含构建一些元信息,比如 blob 文件 ID。--blob
:生成的 Nydus 镜像的 blob 文件路径。--fs-version
:Nydus 镜像的文件系统版本,默认值为 6,可选值:5
,6
。--compressor
: 压缩算法,可选值:none
,lz4_block
,zstd
。--chunk-size
: 压缩块大小,默认值为0
,可选范围:0
或0x1000-0x1000000
。path/to/source
: 源目录路径。
nydus-image
会生成 3 个文件分别是--bootstrap
、--output-json
和--blob
。--bootstrap
文件是 Nydus 镜像的元数据文件,包含了镜像的目录结构和文件信息。
- Nydus 定义了一套元数据(目录结构)与文件内容分离的,文件系统格式 Rafs,大致原理如下:
- Image MetaData 对应
--bootstrap
文件。 - Share Data Layer 对应
--blob
文件。 - 更多详见: 官方文档
- Image MetaData 对应
- 镜像挂载:通过
nydusd
工具通过 fuse 挂载 Nydus 镜像。--config
:指定 Nydus 镜像的 blob 存储位置(支持 oss、s3、本地文件)、 cache 配置、以及文件系统参数。--mountpoint
:指定挂载点,须确保目录存在。--bootstrap
:指定挂载的 Nydus 镜像的元数据文件路径。--log-level
:指定日志级别。--digest-validate
:是否开启校验。--iostats-files
:是否开启 IO 统计。- 除了 FUSE 方式外,还支持 EROFS、VirtioFS 方式挂载,详见下文。
使用场景
单层镜像构建和懒挂载
下面将介绍如何使用 Nydus 构建单层镜像,并将其上传到 s3 上,然后在本地通过 Fuse 方式懒挂载该镜像。
构建单层镜像并上传到 s3
mkdir -p 01-basic
cd 01-basic
# https://github.com/dragonflyoss/nydus/blob/v2.3.0/contrib/nydusify/pkg/packer/backend.go#L60-L70
tee backend-config.s3.json > /dev/null << EOF
{
"endpoint": "s3.us-east-1.amazonaws.com",
"scheme": "https",
"access_key_id": "xxx",
"access_key_secret": "xxx",
"bucket_name": "xxx",
"meta_prefix": "nydus-demo/meta/",
"blob_prefix": "nydus-demo/blob/",
"region": "us-east-1"
}
EOF
nydusify --debug build --name image-basic-01-s3 --source-dir origin-root-dir --backend-push --backend-type s3 --backend-config-file backend-config.s3.json
# INFO[2025-02-26T08:51:53Z] found 'nydus-image' binary at /usr/local/bin/nydus-image
# INFO[2025-02-26T08:51:53Z] start to build image from source directory "origin-root-dir"
# DEBU[2025-02-26T08:51:53Z] Command: /usr/local/bin/nydus-image create --bootstrap .nydus-build-output/image-basic-01-s3.meta --log-level warn --whiteout-spec oci --output-json .nydus-build-output/output.json --blob .nydus-build-output/image-basic-01-s3.blob --fs-version 6 --compressor zstd --chunk-size 0x100000 origin-root-dir
# INFO[2025-02-26T08:51:53Z] rename blob file into sha256 csum
# INFO[2025-02-26T08:51:53Z] start to push meta and blob to remote backend
# INFO[2025-02-26T08:51:53Z] push blob 58048df580011d3a700076d8a1ec9ccaee6881f7feb8352aa298959ee8866f28
# DEBU[2025-02-26T08:51:53Z] uploaded blob nydus-demo/blob/58048df580011d3a700076d8a1ec9ccaee6881f7feb8352aa298959ee8866f28 to s3 backend, costs 30.159619ms
# DEBU[2025-02-26T08:51:53Z] uploaded blob nydus-demo/meta/image-basic-01-s3 to s3 backend, costs 60.856919ms
# INFO[2025-02-26T08:51:53Z] successfully built Nydus image (bootstrap:'https://xxx.s3.us-east-1.amazonaws.com/nydus-demo/meta/image-basic-01-s3', blob:'https://xxx.s3.us-east-1.amazonaws.com/nydus-demo/blob/58048df580011d3a700076d8a1ec9ccaee6881f7feb8352aa298959ee8866f28')
通过 Fuse 懒挂载 S3 的单层镜像
tee nydusd-config.s3.json > /dev/null << EOF
{
"device": {
"backend": {
"type": "s3",
"config": {
"endpoint": "s3.us-east-1.amazonaws.com",
"scheme": "https",
"access_key_id": "xxx",
"access_key_secret": "xxx",
"bucket_name": "xxx",
"meta_prefix": "nydus-demo/meta/",
"blob_prefix": "nydus-demo/blob/",
"region": "us-east-1"
}
},
"cache": {
"type": "blobcache",
"config": {
"work_dir": "cache"
}
}
},
"mode": "direct",
"digest_validate": false,
"iostats_files": false,
"enable_xattr": true
}
EOF
# 下载元数据
time wget https://xxx.s3.us-east-1.amazonaws.com/nydus-demo/meta/image-basic-01-s3
# real 0m0.162s
# user 0m0.073s
# sys 0m0.042s
# 挂载
mkdir -p mnt-s3
nydusd \
--config nydusd-config.s3.json \
--mountpoint mnt-s3 \
--bootstrap image-basic-01-s3 \
--log-level debug
# 打开新终端,切换到该目录,观察 mnt-s3 目录
cd /root/nydus-demo/01-basic
tree mnt-s3/
# mnt-s3/
# ├── dir_1
# │ ├── subdir_a
# │ │ └── file_a
# │ └── subdir_b
# ├── dir_2
# │ └── file_b
# ├── file_c
# └── file_c_ln -> file_c
cat mnt-local/dir_1/subdir_a/file_a
# file_a
cat mnt-local/dir_2/file_b
# file_b
cat mnt-local/file_c
# file_c
cat mnt-local/file_c_ln
# file_c
通过基于 fscache 的内核文件系统 EROFS 懒挂载 S3 的单层镜像
详见: Nydus EROFS fscache user guide
转化和挂载 OCI 镜像(多层)
在 Docker/K8s 中,使用 Nydus 加速镜像拉取,本质上是:
- 将标准的 OCI 镜像的每一层,通过上述单层镜像的方式,转化为 Nydus Blob 文件和元数据文件,并存储在 OCI Register,创建一个 Nydus 格式的镜像。
- 在启动容器,从 OCI Register 获取该镜像,并对每一层通过上述单层镜像的方式进行只读挂载,然后,通过 Overlayfs 构造出容器的 rootfs。
具体命令本文不再赘述,可以参考:
此外 Nydus 为了支持标准 OCI,除了标准的 Rafs 格式外,还提供了 Zran 格式以节省 OCI 镜像转换、Push 耗时以及 Register 存储成本,详见: Nydus zran artifact user guide。
性能测评
测试单层 Nydus 镜像挂载后文件系统性能。
基本信息如下:
- 镜像信息:
- 大小 2.3G(挂载后 du 统计)
- 文件数 134567
- 目录数 67678
- 磁盘性能:
- IOPS 3000
- 吞吐量 125M
测试结果:
- 元数据文件大小: 140M
- 数据(blob)文件大小: 811M
- 挂载速度: 0.029989s (不包含元数据文件下载)
- 递归 Copy 整个文件系统到本地磁盘(rsync -av –progress):
- localfs 挂载,开启缓存,首次 copy: 2m12.346s
- localfs 挂载,开启缓存,二次 copy: 1m52.521s
- s3 挂载,开启缓存,首次 copy: 3m13.644s
- s3 挂载,开启缓存,二次 copy: 1m49.133s
- 本地裸目录(基准): 2m53.854s