Nydus 容器镜像加速服务 – 架构设计与技术文档
目录
项目概览核心架构RAFS 文件系统存储子系统缓存机制Daemon 服务架构镜像构建流程性能优化技术安全与完整性
项目概览
1.1 Nydus 简介
Nydus 是一个高性能容器镜像加速服务,由 Rust 语言实现。它通过在 RAFS(Registry Acceleration File System)格式上实现内容寻址文件系统,显著提升容器启动速度、降低存储和网络带宽消耗。
核心优势:
快速启动:秒级容器启动,毫秒级函数计算代码包加载按需加载:以 chunk 为单位按需下载镜像数据节省资源:chunk 级别数据去重,跨层/跨镜像降低存储、传输和内存成本端到端安全:数据完整性验证,可检测供应链攻击
1.2 主要组件
| 组件 | 描述 | 路径 |
|---|---|---|
| nydusd | 用户空间守护进程,处理 FUSE/fscache/virtiofs 消息,服务 RAFS 镜像 | |
| nydus-image | 镜像构建工具,将 OCI 镜像层转换为 RAFS 格式 | |
| nydusify | 完整 OCI 镜像转换工具,支持 registry 集成(Go 实现) | |
| nydusctl | 守护进程管理和查询客户端 | |
| nydus-service | 服务框架库,可集成到其他项目 | |
核心架构
2.1 整体架构图
┌─────────────────────────────────────────────────────────────┐
│ 应用层 (Application) │
└─────────────────────┬───────────────────────────────────────┘
│
┌─────────────────────┴───────────────────────────────────────┐
│ 容器运行时 (Container Runtime) │
│ (containerd/CRI-O/Docker + nydus-snapshotter) │
└─────────────────────┬───────────────────────────────────────┘
│
┌─────────────────────┴───────────────────────────────────────┐
│ nydusd (用户空间守护进程) │
│ ┌──────────────┬──────────────┬──────────────┬──────────┐ │
│ │ FUSE Mode │ Virtiofs Mode│ FsCache Mode │ NBD Mode │ │
│ └──────────────┴──────────────┴──────────────┴──────────┘ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ RAFS Filesystem Layer (rafs/) ││
│ │ - Metadata Management - Inode Operations ││
│ │ - Chunk Deduplication - Prefetch Optimization ││
│ └─────────────────────────────────────────────────────────┘│
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Storage Subsystem (storage/) ││
│ │ ┌───────────────┬──────────────┬─────────────────────┐ ││
│ │ │ BlobDevice │ BlobCache │ Chunk Decompression │ ││
│ │ └───────────────┴──────────────┴─────────────────────┘ ││
│ │ ┌───────────────────────────────────────────────────┐ ││
│ │ │ Cache Layer (File/Blob/Fs Cache) │ ││
│ │ └───────────────────────────────────────────────────┘ ││
│ │ ┌───────────────────────────────────────────────────┐ ││
│ │ │ Backend Storage (backend/) │ ││
│ │ │ Registry │ OSS │ S3 │ LocalFS │ HTTP Proxy │ ││
│ │ └───────────────────────────────────────────────────┘ ││
│ └─────────────────────────────────────────────────────────┘│
└──────────────────────────────────────────────────────────────┘
2.2 Workspace 模块结构
nydus/
├── api/ # API 定义、HTTP 处理器、配置类型
├── builder/ # 镜像构建和转换逻辑
├── rafs/ # RAFS 文件系统实现(元数据、chunk、inode)
├── service/ # Daemon 服务框架(FUSE/virtiofs/fscache/NBD 服务器)
├── storage/ # 存储后端(Registry/OSS/S3/LocalFS)和缓存
├── utils/ # 通用工具、metrics、日志
├── clib/ # C 语言绑定
├── src/bin/ # 二进制可执行文件
│ ├── nydusd/ # 守护进程
│ ├── nydus-image/ # 镜像构建工具
│ └── nydusctl/ # 控制客户端
├── contrib/ # Go 工具(nydusify、nydus-overlayfs)
└── smoke/ # Go 实现的冒烟测试
2.3 关键抽象与 Trait
服务层 Trait (
nydus-service)
nydus-service
pub trait NydusDaemon {
// 生命周期管理
fn start(&self) -> Result<()>;
fn stop(&self);
fn wait(&self) -> Result<()>;
fn umount(&self) -> Result<()>;
// 状态管理
fn get_state(&self) -> DaemonState;
fn set_state(&self, s: DaemonState);
// 热升级支持
fn save(&self) -> Result<()>; // 保存状态
fn restore(&self) -> Result<()>; // 恢复状态
}
pub trait FsService {
// 文件系统后端实例管理
fn backend_collection(&self) -> Arc<FsBackendCollection>;
}
存储层 Trait (
nydus-storage)
nydus-storage
pub trait BlobBackend {
// 获取 blob 读取器
fn get_reader(&self, blob_id: &str) -> Result<Arc<dyn BlobReader>>;
fn shutdown(&self);
fn metrics(&self) -> &BackendMetrics;
}
pub trait BlobReader {
fn blob_size(&self) -> Result<u64>;
fn try_read(&self, buf: &mut [u8], offset: u64) -> Result<usize>;
fn read(&self, buf: &mut [u8], offset: u64) -> Result<usize>;
fn metrics(&self) -> &BlobReaderMetrics;
}
pub trait BlobCache {
fn blob_id(&self) -> &str;
fn blob_uncompressed_size(&self) -> Result<u64>;
fn blob_compressor(&self) -> compress::Algorithm;
// 数据读取
fn read(&self, iovec: &mut BlobIoVec, buffers: &[FileVolatileSlice]) -> Result<usize>;
// 预取支持
fn start_prefetch(&self) -> StorageResult<()>;
fn stop_prefetch(&self) -> StorageResult<()>;
fn prefetch(&self, cache: Arc<dyn BlobCache>, prefetches: &[BlobPrefetchRequest], bios: &[BlobIoDesc]) -> StorageResult<usize>;
}
构建层 Trait (
nydus-builder)
nydus-builder
pub trait Builder {
fn build(
&mut self,
build_ctx: &mut BuildContext,
bootstrap_mgr: &mut BootstrapManager,
blob_mgr: &mut BlobManager,
) -> Result<BuildOutput>;
}
RAFS 文件系统
3.1 RAFS 版本对比
| 特性 | RAFS v5 | RAFS v6 |
|---|---|---|
| 设计理念 | 融合文件系统元数据和 blob 管理元数据 | 独立的 blob 管理层 |
| 元数据大小 | 较大 | 优化更小(针对 EROFS 兼容性) |
| 内核支持 | FUSE/virtiofs | FUSE/virtiofs/EROFS (Linux 5.16+) |
| fscache 支持 | 部分 | 完整支持 (Linux 5.19+) |
| 典型场景 | 传统容器场景 | VM/轻量级虚拟化/内核挂载 |
3.2 RAFS Superblock 结构
RafsSuperMeta 主要字段
pub struct RafsSuperMeta {
// 基础信息
pub magic: u32, // 文件系统魔数
pub version: u32, // 版本号 (5 或 6)
pub sb_size: u32, // Superblock 大小
pub root_inode: Inode, // 根 inode 编号
// Chunk 配置
pub chunk_size: u32, // Chunk 大小(默认 1MB)
pub batch_size: u32, // 批处理 chunk 大小
// 统计信息
pub inodes_count: u64, // Inode 总数
pub chunk_table_entries: u32, // Chunk 表条目数
// 特性标志
pub flags: RafsSuperFlags, // 压缩、哈希、加密等特性
// 表偏移量
pub inode_table_offset: u64, // Inode 表偏移
pub inode_table_entries: u32, // Inode 表条目数
pub blob_table_offset: u64, // Blob 表偏移
pub blob_table_size: u32, // Blob 表大小
pub prefetch_table_offset: u64, // 预取表偏移
pub prefetch_table_entries: u32, // 预取表条目数
// RAFS v6 特有
pub meta_blkaddr: u32, // 元数据块地址
pub root_nid: u16, // 根节点 ID
pub chunk_table_offset: u64, // Chunk 表偏移
pub chunk_table_size: u64, // Chunk 表大小
}
RafsSuperFlags 特性标志
bitflags! {
pub struct RafsSuperFlags: u64 {
// 压缩算法
const COMPRESSION_NONE = 0x0000_0001;
const COMPRESSION_LZ4 = 0x0000_0002;
const COMPRESSION_GZIP = 0x0000_0040;
const COMPRESSION_ZSTD = 0x0000_0080;
// 哈希算法
const HASH_BLAKE3 = 0x0000_0004;
const HASH_SHA256 = 0x0000_0008;
// 加密算法
const ENCRYPTION_NONE = 0x0100_0000;
const ENCRYPTION_ASE_128_XTS = 0x0200_0000;
// 其他特性
const EXPLICIT_UID_GID = 0x0000_0010; // 显式 UID/GID
const HAS_XATTR = 0x0000_0020; // 扩展属性支持
const INLINED_CHUNK_DIGEST = 0x0000_0100; // 内联 chunk digest
const TARTFS_MODE = 0x0000_0200; // TARFS 模式
}
}
3.3 Inode 结构与操作
RafsInode Trait
pub trait RafsInode {
// 验证和 IO
fn validate(&self, max_inode: Inode, chunk_size: u64) -> Result<()>;
fn alloc_bio_vecs(&self, device: &BlobDevice, offset: u64, size: usize, user_io: bool) -> Result<Vec<BlobIoVec>>;
// POSIX 属性
fn ino(&self) -> u64;
fn get_attr(&self) -> Attr;
fn get_entry(&self) -> Entry;
// 文件类型检查
fn is_dir(&self) -> bool;
fn is_reg(&self) -> bool;
fn is_symlink(&self) -> bool;
fn is_hardlink(&self) -> bool;
// 扩展属性
fn has_xattr(&self) -> bool;
fn get_xattr(&self, name: &OsStr) -> Result<Option<XattrValue>>;
fn get_xattrs(&self) -> Result<Vec<XattrName>>;
// 目录操作
fn walk_children_inodes(&self, entry_offset: u64, handler: RafsInodeWalkHandler) -> Result<()>;
fn get_child_by_name(&self, name: &OsStr) -> Result<Arc<dyn RafsInodeExt>>;
fn get_child_by_index(&self, idx: u32) -> Result<Arc<dyn RafsInodeExt>>;
fn get_child_count(&self) -> u32;
// 文件数据
fn size(&self) -> u64;
fn get_chunk_count(&self) -> u32;
}
3.4 Chunk 管理
Chunk 的核心概念
Chunk:数据块,RAFS 的基本 I/O 单元(默认 1MB)内容寻址:每个 chunk 通过其内容的哈希值(digest)唯一标识去重:相同内容的 chunk 只存储一次,跨层/跨镜像共享压缩:Chunk 可以使用 LZ4/Gzip/Zstd 压缩加密:支持 AES-128-XTS 加密(实验性)
BlobChunkInfo Trait
pub trait BlobChunkInfo {
// 标识信息
fn chunk_id(&self) -> &RafsDigest; // 内容哈希
fn id(&self) -> u32; // Chunk 索引
fn blob_index(&self) -> u32; // Blob 索引
// 压缩数据位置
fn compressed_offset(&self) -> u64; // 压缩 blob 中的偏移
fn compressed_size(&self) -> u32; // 压缩大小
fn compressed_end(&self) -> u64; // 压缩数据结束位置
// 未压缩数据位置
fn uncompressed_offset(&self) -> u64; // 未压缩 blob 中的偏移
fn uncompressed_size(&self) -> u32; // 未压缩大小
fn uncompressed_end(&self) -> u64; // 未压缩数据结束位置
// 特性标志
fn is_compressed(&self) -> bool; // 是否压缩
fn is_encrypted(&self) -> bool; // 是否加密
fn is_batch(&self) -> bool; // 是否批处理 chunk
fn has_crc32(&self) -> bool; // 是否有 CRC32 校验
fn crc32(&self) -> u32; // CRC32 值
}
存储子系统
4.1 BlobDevice 架构
┌──────────────────────────────────────────────┐
│ BlobDevice (device.rs) │
│ 统一的 Blob 访问接口,管理多个 BlobCache │
└────────────┬─────────────────────────────────┘
│ Arc<ArcSwap<Vec<Arc<BlobCache>>>>
│
┌────────┴────────┬──────────┬──────────┐
│ │ │ │
┌───▼─────┐ ┌───────▼──┐ ┌───▼──────┐ ...
│BlobCache│ │BlobCache │ │BlobCache │
│ #0 │ │ #1 │ │ #2 │
└───┬─────┘ └───┬──────┘ └───┬──────┘
│ │ │
┌───▼───────────────────────────▼────────────┐
│ BlobCacheMgr (cache/) │
│ ┌──────────────┬───────────────────────┐ │
│ │ FileCacheMgr │ FsCacheMgr │ DummyMgr │ │
│ └──────────────┴───────────────────────┘ │
└───────────────┬────────────────────────────┘
│
┌───────────────▼────────────────────────────┐
│ BlobBackend (backend/) │
│ ┌───────┬──────┬────┬─────────┬────────┐ │
│ │Registry│ OSS │ S3 │ LocalFS │HttpProxy│ │
│ └───────┴──────┴────┴─────────┴────────┘ │
└────────────────────────────────────────────┘
4.2 存储后端实现
Backend 类型
| Backend | 描述 | 配置键 | 使用场景 |
|---|---|---|---|
| Registry | OCI/Docker Registry | |
标准容器镜像仓库 |
| OSS | 阿里云对象存储 | |
阿里云环境 |
| S3 | AWS S3 兼容存储 | |
AWS 或 S3 兼容服务 |
| LocalFS | 本地文件系统 | |
本地开发、测试 |
| LocalDisk | 本地磁盘/GPT 分区 | |
直接访问块设备 |
| HttpProxy | 本地 HTTP 代理 | |
缓存代理加速 |
BlobInfo 配置结构
pub struct BlobInfo {
// 基础信息
pub blob_index: u32, // Blob 索引
pub blob_id: String, // Blob ID(通常是 SHA256)
pub blob_features: BlobFeatures, // 特性标志
// 大小信息
pub compressed_size: u64, // 压缩大小
pub uncompressed_size: u64, // 未压缩大小
pub chunk_size: u32, // Chunk 大小
pub chunk_count: u32, // Chunk 数量
// 算法配置
pub compressor: compress::Algorithm, // 压缩算法
pub cipher: crypt::Algorithm, // 加密算法
pub digester: digest::Algorithm, // 哈希算法
// 预取配置
pub prefetch_offset: u32, // 预取起始偏移
pub prefetch_size: u32, // 预取大小
// RAFS v6: Chunk 信息数组元数据
pub meta_ci_compressor: u32, // CI 压缩算法
pub meta_ci_offset: u64, // CI 偏移
pub meta_ci_compressed_size: u64, // CI 压缩大小
pub meta_ci_uncompressed_size: u64, // CI 未压缩大小
// 加密对象
pub cipher_object: Arc<Cipher>, // 加密对象
pub cipher_ctx: Option<CipherContext>, // 加密上下文
// Fscache 支持
pub fs_cache_file: Option<Arc<File>>, // Fscache 文件对象
}
4.3 BlobIoVec – IO 描述符
数据结构
// 单个 IO 描述符
pub struct BlobIoDesc {
pub blob: Arc<BlobInfo>, // 关联的 blob
pub chunkinfo: BlobIoChunk, // Chunk 信息
pub offset: u32, // Chunk 内偏移
pub size: u32, // IO 大小
pub(crate) user_io: bool, // 是否用户发起的 IO
}
// IO 向量(scatter/gather list)
pub struct BlobIoVec {
bi_blob: Arc<BlobInfo>, // 目标 blob
bi_size: u64, // 总 IO 大小
pub(crate) bi_vec: Vec<BlobIoDesc>, // IO 描述符数组
}
IO 合并优化
// IO 合并状态机
pub struct BlobIoMerge {
map: HashMap<String, BlobIoVec>,
current: String,
}
impl BlobIoMerge {
// 追加 IO 向量
pub fn append(&mut self, desc: BlobIoVec);
// 获取当前元素
pub fn get_current_element(&mut self) -> Option<&mut BlobIoVec>;
// 清空并返回所有元素
pub fn drain(&mut self) -> Drain<'_, String, BlobIoVec>;
}
缓存机制
5.1 缓存层次结构
┌──────────────────────────────────────────────┐
│ Application Read │
└────────────────┬─────────────────────────────┘
│
┌────────────────▼─────────────────────────────┐
│ BlobCache Trait 实现 │
│ ┌──────────────────────────────────────┐ │
│ │ 1. 检查 ChunkMap 就绪状态 │ │
│ │ 2. 从缓存读取已就绪的 chunk │ │
│ │ 3. 从后端获取未就绪的 chunk │ │
│ │ 4. 解压缩/解密 │ │
│ │ 5. 验证 digest │ │
│ │ 6. 写入缓存 │ │
│ └──────────────────────────────────────┘ │
└──────────────┬───────────────────────────────┘
│
┌──────────┴────────┬────────────┐
│ │ │
┌───▼──────┐ ┌─────────▼─┐ ┌───────▼─────┐
│FileCacheMgr│ │FsCacheMgr │ │DummyCacheMgr│
│(文件缓存) │ │(fscache) │ │(无缓存) │
└───┬────────┘ └─────┬─────┘ └─────────────┘
│ │
│ │ (Linux 5.19+)
│ ▼
│ ┌──────────────┐
│ │ Kernel FsCache│
│ └──────────────┘
│
▼
┌──────────────────┐
│ Local Cache File│
│ /path/to/cache/ │
└──────────────────┘
5.2 缓存管理器类型
FileCacheMgr(文件缓存)
// 特点:
// - 用户空间缓存实现
// - 基于本地文件系统
// - 支持所有平台
// - 完全由 nydusd 管理
pub struct FileCacheMgr {
cache_dir: PathBuf, // 缓存目录
validate: bool, // 是否验证数据
// Chunk 就绪状态跟踪
chunk_map: Arc<dyn ChunkMap>,
// 后端读取器
backend: Arc<dyn BlobBackend>,
}
FsCacheMgr(内核 fscache)
// 特点:
// - 内核空间缓存(Linux 5.19+)
// - 与内核 fscache 子系统集成
// - 更高性能
// - 系统级共享缓存
pub struct FsCacheMgr {
// Fscache 文件对象
cache_file: Arc<File>,
validate: bool,
chunk_map: Arc<dyn ChunkMap>,
backend: Arc<dyn BlobBackend>,
}
DummyCacheMgr(无缓存)
// 特点:
// - 直接从后端读取
// - 无本地缓存
// - 适合只读场景或测试
pub struct DummyCacheMgr {
validate: bool,
backend: Arc<dyn BlobBackend>,
}
5.3 Chunk 状态管理
ChunkMap Trait
pub trait ChunkMap {
// 检查 chunk 是否就绪
fn is_ready(&self, chunk: &dyn BlobChunkInfo) -> Result<bool>;
// 设置 chunk 为就绪状态
fn set_ready(&self, chunk: &dyn BlobChunkInfo) -> Result<()>;
// 批量设置 chunks 就绪
fn set_ready_batch(&self, chunks: &[Arc<dyn BlobChunkInfo>]) -> Result<()>;
// 等待 chunk 就绪
fn wait_for_ready(&self, chunk: &dyn BlobChunkInfo, timeout: Duration) -> Result<()>;
}
5.4 预取策略
预取类型
静态预取列表
镜像构建时配置,记录在 prefetch table基于访问模式分析生成容器启动时自动预取
动态预取列表
命令行指定 优先级高于静态列表支持目录递归预取
--prefetch-files
按需预取
根据访问模式动态预取合并连续 chunk 请求后台异步执行
预取实现
impl RafsSuper {
pub fn prefetch_files(
&self,
device: &BlobDevice,
r: &mut RafsIoReader,
root_ino: Inode,
files: Option<Vec<Inode>>, // 动态预取列表
fetcher: &dyn Fn(&mut BlobIoVec, bool),
) -> RafsResult<bool> {
if let Some(files) = files {
// 动态预取
let mut hardlinks = HashSet::new();
let mut state = BlobIoMerge::default();
for f_ino in files {
self.prefetch_data(device, f_ino, &mut state, &mut hardlinks, fetcher)?;
}
// 提交所有预取请求
for (_id, mut desc) in state.drain() {
fetcher(&mut desc, true);
}
Ok(false)
} else {
// 静态预取(从 prefetch table)
if self.meta.is_v5() {
self.prefetch_data_v5(device, r, root_ino, fetcher)
} else {
self.prefetch_data_v6(device, r, root_ino, fetcher)
}
}
}
}
Daemon 服务架构
6.1 服务模式
nydusd 支持四种运行模式:
| 模式 | 描述 | 使用场景 | Linux 要求 |
|---|---|---|---|
| FUSE | 用户空间文件系统 | 标准容器、开发测试 | FUSE 内核模块 |
| Virtiofs | virtio-fs 服务器 | VM、Kata Containers | virtiofs 支持 |
| FsCache | 内核 fscache 客户端 | 高性能场景、EROFS | Linux 5.19+ |
| NBD | 网络块设备导出 | 块设备访问 | NBD 模块 |
6.2 Daemon 状态机
state_machine! {
derive(Debug, Clone)
pub DaemonStateMachine(Init)
Init => {
Mount => Ready, // 挂载文件系统
Takeover => Ready[Restore], // 热升级接管
Stop => Die[StopStateMachine], // 停止
},
Ready => {
Start => Running[StartService], // 启动服务
Stop => Die[Umount], // 卸载并停止
Exit => Die[StopStateMachine], // 退出
},
Running => {
Stop => Ready[TerminateService], // 停止服务
},
}
状态转换说明:
┌──────┐ Mount ┌───────┐ Start ┌─────────┐
│ Init ├─────────►│ Ready ├─────────►│ Running │
└──┬───┘ └───┬───┘ └────┬────┘
│ │ │
│ Stop │ Exit/Stop │ Stop
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────┐
│ Die │
└──────────────────────────────────────────┘
特殊转换:
Init --Takeover--> Ready (热升级接管)
6.3 DaemonController
pub struct DaemonController {
active: AtomicBool, // 活跃状态
singleton_mode: AtomicBool, // 单例模式
daemon: Mutex<Option<Arc<dyn NydusDaemon>>>, // Daemon 实例
blob_cache_mgr: Mutex<Option<Arc<BlobCacheMgr>>>, // 缓存管理器
fs_service: Mutex<Option<Arc<dyn FsService>>>, // 文件系统服务
waker: Arc<Waker>, // 唤醒器
poller: Mutex<Poll>, // 事件轮询器
}
impl DaemonController {
// 设置 daemon 实例
pub fn set_daemon(&self, daemon: Arc<dyn NydusDaemon>) -> Option<Arc<dyn NydusDaemon>>;
// 启动事件循环
pub fn run_loop(&self);
// 优雅关闭所有服务
pub fn shutdown(&self);
// 通知控制器关闭
pub fn notify_shutdown(&self);
}
6.4 热升级机制
┌────────────────────────────────────────────┐
│ Old Nydusd Instance (running) │
│ 1. Receive upgrade signal │
│ 2. daemon.save() - 保存状态 │
│ 3. Transfer state via Unix socket │
└───────────┬────────────────────────────────┘
│ State Transfer (Unix Socket)
│
┌───────────▼────────────────────────────────┐
│ New Nydusd Instance │
│ 1. Connect to upgrade socket │
│ 2. daemon.restore() - 恢复状态 │
│ 3. Trigger Takeover event │
│ 4. Take over FUSE fd / virtiofs │
└───────────┬────────────────────────────────┘
│
┌───────────▼────────────────────────────────┐
│ Old Instance exits gracefully │
│ - Close old connections │
│ - Release resources │
│ - Exit process │
└────────────────────────────────────────────┘
热升级步骤:
启动新 nydusd 实例,指定 新实例连接到旧实例的升级 socket旧实例序列化状态(FUSE fd、配置、挂载点等)新实例反序列化并接管服务旧实例优雅退出
--upgrade-sock
镜像构建流程
7.1 nydus-image 工作流程
┌─────────────────────────────────────────────┐
│ Input Sources │
│ - OCI Image Layer (tar) │
│ - Directory │
│ - Stargz Layer │
│ - Previous RAFS Bootstrap │
└──────────────┬──────────────────────────────┘
│
┌──────────────▼──────────────────────────────┐
│ nydus-image create │
│ 1. Parse source │
│ 2. Build inode tree │
│ 3. Deduplicate chunks (optional) │
│ 4. Generate blob file │
│ 5. Generate bootstrap file │
└──────────────┬──────────────────────────────┘
│
┌────────┴────────┐
│ │
┌─────▼──────┐ ┌──────▼──────┐
│ Bootstrap │ │ Blob File │
│ (meta) │ │ (data) │
│ .boot │ │ .blob │
└────────────┘ └─────────────┘
7.2 主要子命令
| 子命令 | 功能 | 输出 |
|---|---|---|
| create | 从源构建 RAFS | bootstrap + blob |
| merge | 合并多个 bootstrap 为分层镜像 | merged bootstrap |
| check | 验证 RAFS 元数据完整性 | 验证报告 |
| inspect | 交互式检查 RAFS 元数据 | 元数据详情 |
| stat | 生成统计信息 | 统计报告 |
| compact | 优化 blob 布局 | 压缩的 blob |
| optimize | 生成预取列表 | 优化的 bootstrap |
| unpack | 解包 RAFS 到 tar | tar 文件 |
| export | 导出为块设备镜像 | 块设备镜像 |
| chunkdict | 使用 chunk 字典去重 | 去重的 blob |
7.3 转换类型
nydus-image 支持 10+ 种转换类型():
--source-type
pub enum ConversionType {
DirectoryToRafs, // 目录 -> RAFS
TarToRafs, // Tar -> RAFS
EStargzToRafs, // eStargz -> RAFS
EStargzToRef, // eStargz -> RAFS (引用)
TargzToRafs, // tar.gz -> RAFS
TargzToRef, // tar.gz -> RAFS (引用)
TargzToStargz, // tar.gz -> Stargz
TargzToStargzIndex, // tar.gz -> Stargz Index
StargzIndexToRafs, // Stargz Index -> RAFS
// ... 更多类型
}
7.4 Chunk 去重策略
基于内容哈希的去重
// 1. 计算 chunk 的 digest (SHA256 或 Blake3)
let digest = calculate_digest(&chunk_data, digester);
// 2. 查询 chunk 字典
if let Some(existing_chunk) = chunk_dict.get(&digest) {
// 复用已存在的 chunk
return existing_chunk;
}
// 3. 新 chunk,添加到字典
chunk_dict.insert(digest, chunk_info);
ChunkDict 模式
# 1. 创建 chunk 字典
nydus-image create
--source-type directory
--blob /path/to/dict.blob
--bootstrap /path/to/dict.boot
--chunkdict-generated
/source/dir
# 2. 使用字典构建新镜像
nydus-image create
--source-type directory
--blob /path/to/new.blob
--bootstrap /path/to/new.boot
--parent-bootstrap /path/to/dict.boot
/source/new-dir
性能优化技术
8.1 I/O 合并优化
合并连续 Chunk 请求
// 配置参数
struct BlobIoMergeConfig {
max_comp_size: u64, // 最大合并压缩大小(默认 1MB)
max_gap: u64, // 允许的最大间隙(默认 64KB)
}
// 合并算法
fn merge_and_issue(bios: &[BlobIoDesc], config: &BlobIoMergeConfig) {
let mut state = BlobIoMergeState::new(&bios[0]);
for bio in &bios[1..] {
// 检查是否连续
if !prev_bio.is_continuous(bio, config.max_gap)
|| state.size() >= config.max_comp_size {
// 不连续或大小超限,发起当前请求
state.issue(config.max_gap);
}
state.push(bio);
}
state.issue(config.max_gap);
}
优化效果:
减少网络往返次数(RTT)提高网络带宽利用率特别适合高延迟网络(Registry/OSS/S3)
8.2 预取优化
Prefetch Table 生成
# 1. 分析容器访问模式
# 运行容器并记录文件访问
nydus-snapshotter --enable-nri-plugin
# 2. 生成优化的镜像
nydus-image optimize
--bootstrap /path/to/original.boot
--prefetch-list /path/to/access-pattern.json
--output /path/to/optimized.boot
预取策略配置
{
"prefetch": {
"enable": true,
"threads": 4, // 预取线程数
"batch_size": 1048576, // 批量大小 (1MB)
"bandwidth_limit": 10485760 // 带宽限制 (10MB/s)
}
}
8.3 压缩算法选择
| 算法 | 压缩率 | 速度 | CPU 使用 | 适用场景 |
|---|---|---|---|---|
| None | 1.0x | 最快 | 最低 | 已压缩数据 |
| LZ4 | ~2.0x | 很快 | 低 | 默认推荐 |
| Gzip | ~2.5x | 中等 | 中等 | 兼容 stargz |
| Zstd | ~3.0x | 较快 | 中等 | 追求压缩率 |
选择建议:
LZ4:默认选择,平衡性能和压缩率Zstd:存储受限场景,更好的压缩率None:数据已压缩(如 JPEG、视频),避免二次压缩
8.4 Batch Chunk 优化
// 小文件合并到批处理 chunk
// 优势:
// - 减少 chunk 元数据开销
// - 提升小文件访问性能
// - 降低存储碎片化
pub struct BatchChunkConfig {
enabled: bool,
min_file_size: u32, // 最小文件大小(默认 4KB)
max_batch_size: u32, // 最大批处理大小(默认 4MB)
}
8.5 Amplify IO 优化
{
"amplify_io": {
"enable": true,
"threshold": 65536, // 阈值 64KB
"max_amplify_rate": 4 // 最大放大倍数
}
}
工作原理:
小于阈值的请求会向前后扩展预先缓存相邻数据减少后续小IO请求
安全与完整性
9.1 数据完整性验证
Digest 验证层次
┌────────────────────────────────────────────┐
│ Level 1: Chunk Digest 验证 │
│ - 每个 chunk 都有 SHA256/Blake3 digest │
│ - 读取时可选验证 │
└────────────┬───────────────────────────────┘
│
┌────────────▼───────────────────────────────┐
│ Level 2: CRC32 快速校验 │
│ - 可选的 CRC32 checksum │
│ - 更快的完整性检查 │
└────────────┬───────────────────────────────┘
│
┌────────────▼───────────────────────────────┐
│ Level 3: Blob Digest 验证 │
│ - 整个 blob 的 digest │
│ - 供应链攻击检测 │
└────────────────────────────────────────────┘
配置验证策略
{
"rafs": {
"mode": "direct",
"validate": true, // 启用 digest 验证
"enable_crc": true // 启用 CRC32 校验
},
"cache": {
"type": "filecache",
"validate_on_write": true, // 写入缓存时验证
"validate_on_read": false // 读取缓存时不验证(已验证)
}
}
9.2 加密支持(实验性)
AES-128-XTS 加密
// Blob 加密配置
pub struct BlobCipherInfo {
cipher: crypt::Algorithm, // AES-128-XTS
cipher_object: Arc<Cipher>, // 加密对象
cipher_ctx: Option<CipherContext>, // 加密上下文(IV 等)
}
// 解密流程
fn decrypt_chunk(
encrypted_data: &[u8],
cipher_object: &Cipher,
cipher_ctx: &CipherContext,
chunk_info: &dyn BlobChunkInfo,
) -> Result<Vec<u8>> {
if !chunk_info.is_encrypted() {
return Ok(encrypted_data.to_vec());
}
crypt::decrypt_with_context(
encrypted_data,
cipher_object,
cipher_ctx,
true,
)
}
限制:
目前仅支持 AES-128-XTS实验性功能密钥管理需外部处理
9.3 供应链安全
端到端验证
┌────────────────────────────────────────────┐
│ 1. Image Build (nydus-image) │
│ - 计算每个 chunk 的 digest │
│ - 生成 bootstrap 和 blob │
│ - 签名镜像 manifest │
└────────────┬───────────────────────────────┘
│
┌────────────▼───────────────────────────────┐
│ 2. Registry Storage │
│ - 存储 bootstrap 和 blob │
│ - 保持 digest 不变 │
└────────────┬───────────────────────────────┘
│
┌────────────▼───────────────────────────────┐
│ 3. Runtime Verification (nydusd) │
│ - 验证 manifest 签名 │
│ - 验证 bootstrap digest │
│ - 验证每个 chunk digest │
│ - 检测任何篡改 │
└────────────────────────────────────────────┘
Digest 算法对比
| 算法 | 长度 | 速度 | 安全性 | 推荐场景 |
|---|---|---|---|---|
| Blake3 | 256 bits | 很快 | 高 | 默认推荐 |
| SHA256 | 256 bits | 中等 | 高 | 兼容性要求 |
9.4 认证与授权
Registry 认证
{
"backend": {
"type": "registry",
"config": {
"scheme": "https",
"host": "registry.example.com",
"repo": "myorg/myimage",
// 认证方式 1: Basic Auth
"auth": "base64(username:password)",
// 认证方式 2: Bearer Token
"registry_token": "Bearer eyJhbGc...",
// 认证方式 3: 动态刷新
"refresh_token_url": "https://auth.example.com/token"
}
}
}
环境变量覆盖
# 通过环境变量提供认证信息
export IMAGE_PULL_AUTH='{"username":"user","password":"pass"}'
nydusd fuse --bootstrap /path/to/bootstrap.boot
--config /path/to/config.json
--mountpoint /mnt/nydus
附录
A. 配置示例
ConfigV2 完整示例
{
"version": 2,
"id": "my-nydus-instance",
"backend": {
"type": "registry",
"config": {
"scheme": "https",
"host": "registry.example.com",
"repo": "myorg/myimage",
"auth": "base64_encoded_credentials",
"timeout": 30,
"connect_timeout": 5,
"retry_limit": 3,
"proxy": {
"url": "http://proxy.example.com:8080",
"fallback": true
}
}
},
"cache": {
"type": "filecache",
"config": {
"work_dir": "/var/lib/nydus/cache",
"disable_indexed_map": false
},
"prefetch": {
"enable": true,
"threads": 4,
"batch_size": 1048576,
"bandwidth_limit": 10485760
}
},
"rafs": {
"mode": "direct",
"validate": true,
"digest_validate": true,
"enable_xattr": true,
"amplify_io": {
"enable": true,
"threshold": 65536,
"max_amplify_rate": 4
}
},
"internal": {
"blob_accessible": true,
"batch_size": 1048576
}
}
B. 性能调优检查清单
压缩算法:根据场景选择 LZ4/Zstd Chunk 大小:默认 1MB,根据工作负载调整 预取配置:启用预取,调整线程数和带宽限制 缓存策略:选择 FileCacheMgr 或 FsCacheMgr IO 合并:配置 和
max_comp_size Amplify IO:小文件密集场景启用 Batch Chunk:大量小文件场景启用 验证策略:生产环境启用
max_gap,开发环境可关闭 Backend 配置:调整
validate、
timeout 并发控制:调整
retry_limit
prefetch.threads
C. 故障排查指南
常见问题
容器启动慢
检查预取配置是否启用检查网络延迟和带宽查看 chunk 缓存命中率
磁盘空间不足
检查缓存目录大小调整缓存清理策略使用 Batch Chunk 减少碎片
数据验证失败
检查 blob 是否损坏检查网络传输是否稳定验证 Registry 中的镜像完整性
热升级失败
检查 upgrade socket 权限确认新旧版本兼容性查看状态传输日志
D. 参考链接
官方文档:https://nydus.dev/GitHub 仓库:https://github.com/dragonflyoss/nydusNydus Snapshotter:https://github.com/containerd/nydus-snapshotterDragonfly 集成:https://d7y.io/docs/setup/integration/nydus性能基准测试:https://github.com/dragonflyoss/nydus/tree/master/smoke
适用 Nydus 版本:v2.2+
















暂无评论内容