Skip to content

网络与存储

概述

Cube Hypervisor 提供多种网络和存储设备模型,满足不同场景的性能和功能需求。

网络设备

Virtio-net

Virtio-net 是标准的半虚拟化网络设备:

配置示例

json
{
  "net": [
    {
      "tap": "tap0",
      "ip": "192.168.1.1",
      "mac": "00:11:22:33:44:55",
      "mask": "255.255.255.0",
      "num_queues": 2,
      "queue_size": 256
    }
  ]
}

源码结构

rust
// virtio-devices/src/net.rs
pub struct Net {
    common: VirtioCommon,
    net: NetQueuePair,
    ctrl_queue: Option<CtrlQueue>,
    taps: Vec<Tap>,
    config: VirtioNetConfig,
}

pub struct NetQueuePair {
    tap: Tap,
    rx: RxVirtio,
    tx: TxVirtio,
    counter: NetCounters,
}

Vhost-user-net

Vhost-user-net 将网络后端运行在独立进程中:

配置示例

json
{
  "net": [
    {
      "vhost_user": true,
      "socket": "/tmp/vhost-net.sock",
      "mac": "00:11:22:33:44:55"
    }
  ]
}

TAP 设备管理

rust
// net_util/src/lib.rs
pub struct Tap {
    tap_file: File,
    if_name: String,
    // ...
}

impl Tap {
    pub fn new(name: &str) -> Result<Tap> {
        // 打开 /dev/net/tun
        let tap_file = OpenOptions::new()
            .read(true)
            .write(true)
            .open("/dev/net/tun")?;
        
        // 配置 TAP 设备
        let ifr = IfreqBuilder::new(name)?
            .iff_flags(IFF_TAP | IFF_NO_PI)
            .build();
        
        unsafe {
            ioctl::tun_set_iff(tap_file.as_raw_fd(), &ifr)?;
        }
        
        Ok(Self { tap_file, if_name: name.to_string() })
    }
    
    pub fn set_ip(&self, ip: Ipv4Addr) -> Result<()> {
        // 设置 IP 地址
        // ...
        Ok(())
    }
    
    pub fn set_netmask(&self, mask: Ipv4Addr) -> Result<()> {
        // 设置子网掩码
        // ...
        Ok(())
    }
}

存储设备

Virtio-blk

Virtio-blk 是标准的半虚拟化块设备:

配置示例

json
{
  "disks": [
    {
      "path": "/path/to/rootfs.ext4",
      "readonly": false,
      "direct": true,
      "io_uring": true,
      "queue_size": 128
    }
  ]
}

源码结构

rust
// virtio-devices/src/block.rs
pub struct Block {
    common: VirtioCommon,
    disk_image: Box<dyn DiskFile>,
    disk_path: PathBuf,
    rate_limiter: Option<RateLimiter>,
    read_only: bool,
    serial: Vec<u8>,
    config: VirtioBlockConfig,
}

impl Block {
    pub fn new(
        disk_path: PathBuf,
        read_only: bool,
        direct: bool,
        io_uring: bool,
        rate_limiter: Option<RateLimiter>,
    ) -> Result<Self> {
        // 检测磁盘格式
        let image_type = detect_image_type(&disk_path)?;
        
        // 创建磁盘文件
        let disk_image: Box<dyn DiskFile> = match image_type {
            ImageType::Raw => {
                if io_uring && block_io_uring_is_supported() {
                    Box::new(RawFileDisk::new(file, direct))
                } else {
                    Box::new(RawFileDiskSync::new(file, direct))
                }
            }
            ImageType::Qcow2 => {
                Box::new(QcowDiskSync::new(file))
            }
            ImageType::FixedVhd => {
                if io_uring {
                    Box::new(FixedVhdDiskAsync::new(file))
                } else {
                    Box::new(FixedVhdDiskSync::new(file))
                }
            }
            ImageType::Vhdx => {
                Box::new(VhdxDiskSync::new(file))
            }
        };
        
        Ok(Self {
            disk_image,
            read_only,
            // ...
        })
    }
}

Vhost-user-blk

Vhost-user-blk 将块设备后端运行在独立进程中:

Virtio-fs

Virtio-fs 允许 Guest 直接访问 Host 文件系统:

配置示例

json
{
  "fs": [
    {
      "tag": "shared",
      "socket": "/tmp/virtiofs.sock",
      "shared_dir": "/path/to/shared",
      "cache": "auto",
      "xattr": true
    }
  ]
}

源码结构

rust
// virtio-devices/src/fs.rs
pub struct Fs {
    common: VirtioCommon,
    fs: PassthroughFs,
    cache: CachePolicy,
    thread_pool_size: usize,
    xattr: XattrMap,
    config: VirtioFsConfig,
}

pub struct PassthroughFs {
    inodes: RwLock<InodeStore>,
    handles: RwLock<HandleStore>,
    mountinfo: MountInfo,
}

Pmem (持久内存)

Pmem 将 Host 文件映射为 Guest 的持久内存:

json
{
  "pmem": [
    {
      "file": "/path/to/pmem.img",
      "size": 1073741824,
      "iommu": false
    }
  ]
}

磁盘格式支持

支持的格式

格式说明特性
Raw原始格式简单、高性能
QCOW2QEMU 格式压缩、快照、加密
VHD虚拟硬盘动态扩展
VHDXVHD 扩展更大容量、日志
VMDKVMware 格式兼容性

格式检测

rust
// block_util/src/lib.rs
pub fn detect_image_type(path: &Path) -> Result<ImageType> {
    let mut file = File::open(path)?;
    let mut header = [0u8; 4];
    file.read_exact(&mut header)?;
    
    match header {
        // QCOW2 魔数
        [0x51, 0x46, 0x49, 0xFB] => Ok(ImageType::Qcow2),
        // VHD 魔数
        [0x63, 0x6F, 0x6E, 0x65] => Ok(ImageType::FixedVhd),
        // VHDX 魔数
        [0x76, 0x68, 0x64, 0x78] => Ok(ImageType::Vhdx),
        // 默认为 Raw
        _ => Ok(ImageType::Raw),
    }
}

I/O 优化

io_uring

io_uring 是 Linux 的异步 I/O 接口,提供更低的延迟:

rust
// block_util/src/raw_async.rs
pub struct RawFileDisk {
    file: File,
    io_uring: IoUring,
}

impl AsyncIo for RawFileDisk {
    fn push_request(&mut self, request: Request) -> Result<()> {
        // 提交 io_uring 请求
        let entry = IoUringEntry {
            opcode: IORING_OP_READ,
            fd: self.file.as_raw_fd(),
            addr: request.addr,
            len: request.len,
            offset: request.offset,
        };
        
        self.io_uring.submit(entry)?;
        
        Ok(())
    }
    
    fn pop_request(&mut self) -> Result<Option<CompletedRequest>> {
        // 获取完成的请求
        self.io_uring.complete()
    }
}

直接 I/O

直接 I/O 绕过页缓存,减少内存拷贝:

rust
// block_util/src/raw_sync.rs
pub struct RawFileDiskSync {
    file: File,
    direct: bool,
}

impl RawFileDiskSync {
    pub fn new(path: &Path, direct: bool) -> Result<Self> {
        let file = OpenOptions::new()
            .read(true)
            .write(true)
            .custom_flags(if direct { libc::O_DIRECT } else { 0 })
            .open(path)?;
        
        Ok(Self { file, direct })
    }
}

限流器

Rate Limiter

Rate Limiter 限制设备的 I/O 速率:

rust
// rate_limiter/src/lib.rs
pub struct RateLimiter {
    ops: TokenBucket,
    bytes: TokenBucket,
}

pub struct TokenBucket {
    size: u64,
    one_time_burst: u64,
    refill_time_ms: u64,
    budget: u64,
    last_update: Instant,
}

impl RateLimiter {
    pub fn new(
        ops_limit: u64,
        bytes_limit: u64,
    ) -> Self {
        Self {
            ops: TokenBucket::new(ops_limit),
            bytes: TokenBucket::new(bytes_limit),
        }
    }
    
    pub fn consume(&mut self, ops: u64, bytes: u64) -> bool {
        // 检查是否有足够的 token
        if self.ops.consume(ops) && self.bytes.consume(bytes) {
            true
        } else {
            // 回滚
            self.ops.rollback(ops);
            self.bytes.rollback(bytes);
            false
        }
    }
}

配置示例

json
{
  "disks": [
    {
      "path": "/path/to/disk.img",
      "rate_limiter": {
        "ops": {
          "one_time_burst": 1000,
          "refill_time": 100,
          "size": 100
        },
        "bytes": {
          "one_time_burst": 1048576,
          "refill_time": 100,
          "size": 1048576
        }
      }
    }
  ]
}

性能对比

网络性能

设备类型吞吐量延迟CPU 开销
Virtio-net
Vhost-user-net
VFIO NIC极高极低极低

存储性能

设备类型IOPS延迟CPU 开销
Virtio-blk
Vhost-user-blk
VFIO NVMe极高极低极低

最佳实践

  1. 选择合适的设备类型

    • 通用场景使用 Virtio
    • 高性能场景使用 VFIO
    • 自定义后端使用 vhost-user
  2. 启用异步 I/O

    • 使用 io_uring 提升性能
    • 启用直接 I/O 减少拷贝
  3. 配置限流器

    • 防止单个 VM 独占资源
    • 设置合理的限流阈值
  4. 选择合适的磁盘格式

    • 生产环境使用 QCOW2 或 VHD
    • 高性能场景使用 Raw 格式

下一步