Nydus 容器镜像加速服务 – 架构设计与技术文档

Nydus 容器镜像加速服务 – 架构设计与技术文档

目录

项目概览核心架构RAFS 文件系统存储子系统缓存机制Daemon 服务架构镜像构建流程性能优化技术安全与完整性


项目概览

1.1 Nydus 简介

Nydus 是一个高性能容器镜像加速服务,由 Rust 语言实现。它通过在 RAFS(Registry Acceleration File System)格式上实现内容寻址文件系统,显著提升容器启动速度、降低存储和网络带宽消耗。

核心优势:

快速启动:秒级容器启动,毫秒级函数计算代码包加载按需加载:以 chunk 为单位按需下载镜像数据节省资源:chunk 级别数据去重,跨层/跨镜像降低存储、传输和内存成本端到端安全:数据完整性验证,可检测供应链攻击

1.2 主要组件

组件 描述 路径
nydusd 用户空间守护进程,处理 FUSE/fscache/virtiofs 消息,服务 RAFS 镜像
src/bin/nydusd/
nydus-image 镜像构建工具,将 OCI 镜像层转换为 RAFS 格式
src/bin/nydus-image/
nydusify 完整 OCI 镜像转换工具,支持 registry 集成(Go 实现)
contrib/nydusify/
nydusctl 守护进程管理和查询客户端
src/bin/nydusctl/
nydus-service 服务框架库,可集成到其他项目
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
)

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
)

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
)

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
backend-registry
标准容器镜像仓库
OSS 阿里云对象存储
backend-oss
阿里云环境
S3 AWS S3 兼容存储
backend-s3
AWS 或 S3 兼容服务
LocalFS 本地文件系统
backend-localdisk
本地开发、测试
LocalDisk 本地磁盘/GPT 分区
backend-localdisk-gpt
直接访问块设备
HttpProxy 本地 HTTP 代理
backend-http-proxy
缓存代理加速
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 实例,指定
--upgrade-sock
新实例连接到旧实例的升级 socket旧实例序列化状态(FUSE fd、配置、挂载点等)新实例反序列化并接管服务旧实例优雅退出


镜像构建流程

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

max_gap
Amplify IO:小文件密集场景启用 Batch Chunk:大量小文件场景启用 验证策略:生产环境启用
validate
,开发环境可关闭 Backend 配置:调整
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+

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
璇璇别烦恼的头像 - 鹿快
评论 抢沙发

请登录后发表评论

    暂无评论内容