xfyyzy

摘要

核心结论

在阿里云 V 代及以上实例运行 FreeBSD (13+),必须在 /boot/loader.conf 中配置 kern.maxphys="65536"。

该配置用于限制单次物理 I/O 请求最大为 64KB,以解决 virtio-blk 驱动与底层虚拟化后端的兼容性问题,防止系统在启动阶段卡死。

原因分析

  • FreeBSD 机制:FreeBSD 13+ 默认的 maxphys 较大,virtio-blk 驱动会根据此值设定 DMA 请求大小。
  • 平台限制:阿里云 KVM/virtio 后端对单次 I/O 请求大小有特定限制,超出限制会导致请求失败或系统挂起。
  • 对比 Linux:Linux 内核能动态协商设备队列参数(如 max_sectors_kb),自动适配后端限制,因此无需手动配置。

多系统对比

  • FreeBSD: 需手动设置 loader tunable kern.maxphys="65536"。
  • OpenBSD: 内核默认 MAXPHYS 即为 64K,无需配置
  • illumos: 可在 /etc/system 中设置 set maxphys = 0x10000。

阿里云 FreeBSD 镜像关键配置

在阿里云 V 代及以上实例上制作或运行 FreeBSD 镜像时,loader.conf 中有一项至关重要的配置,缺失该配置极易导致系统在启动或挂载 root 阶段卡死(特别是自制镜像或从 FreeBSD 12 升级到 13+ 时)。

核心结论:必须在 /boot/loader.conf 中添加以下配置。

# /boot/loader.conf
kern.maxphys="65536"

阿里云官方 FreeBSD 文档明确指出,在 FreeBSD 13 及以上版本中,该内核参数由于 virtio 驱动兼容性原因成为必选项。

1. 配置详解

1.1 必需配置:kern.maxphys

对于 FreeBSD 13 及以上版本(含 14.x) 运行在阿里云 V 代及以上实例:

尽管 FreeBSD 13+ 已经整合了用于阿里云 V 代机型的 virtio 内核补丁(virtio_pci_legacy 系列),但仍需在 /boot/loader.conf 中显式设置 kern.maxphys=65536 才能保证系统正常运行。

  • FreeBSD 社区说明MAXPHYS 已演变为可调内核全局变量 maxphys,通过 loader tunable kern.maxphys 在引导阶段设定,用于限制“单次物理 I/O 请求最大大小”。
  • 技术背景:在 VMware ESXi、阿里云等使用 virtio-blk 的环境中,若不将 kern.maxphys 降至 65536,virtio-blk 可能因单次 I/O 请求过大而导致启动阶段卡死。此时可能需要在 loader 提示符下手动执行 set kern.maxphys=65536; boot 才能临时进入系统。

1.2 旧版本(FreeBSD 11/12)的情况

对于 FreeBSD 11/12,在 V 代及以上实例上运行的核心障碍在于 virtio 驱动本身的不兼容

  • 解决方案:必须应用阿里云提供的 0001-virtio.patch 补丁并重新编译内核。
  • 官方镜像:阿里云官方公共镜像已预置该补丁。
  • 自制镜像/升级:若自行制作镜像或使用 freebsd-update 升级内核而未打补丁,系统将无法启动。此时仅调整 loader.conf 无法解决问题。

建议:在回溯移植 FreeBSD 13+ 的 tunable 支持时,也可以顺手加上 kern.maxphys=65536 以增强兼容性。

1.3 可选性能调优配置

以下配置并非阿里云强制要求,但在特定网络环境(如部分防火墙或隧道场景)下,禁用 LRO/TSO/CSUM 可能有助于解决兼容性或性能问题:

hw.vtnet.lro_disable="1"
hw.vtnet.tso_disable="1"
hw.vtnet.csum_disable="1"

这属于网络层面的调优,通常不影响系统启动。

2. 机制分析:为何 Linux 不需要?

核心差异在于 I/O 最大请求大小的处理方式

FreeBSD 的处理方式

  • 内核拥有全局的“最大物理 I/O 大小”变量 maxphys
  • 从 FreeBSD 13 开始,maxphys 变为 loader tunable,且默认值较大以适应 ZFS 和大块 I/O。
  • virtio-blk 等存储驱动在挂载(attach)时,会直接参考该值决定单次 DMA 请求的尺寸。

error 触发机制

  • 阿里云底层的 KVM + virtio 后端对单次 I/O 请求大小较为敏感。
  • 当 Guest OS (FreeBSD) 发出超过后端限制的请求时,会引发设备错误或挂死。
  • maxphys 限制为 64 KiB(65536 字节),实际上是将所有设备的最大 I/O 请求强制限制在安全范围内。

Linux 的处理方式

  • Linux 的 blk 层和 virtio-blk 驱动能够根据设备队列属性(如 max_sectors_kb, max_segment_size动态协商最大 I/O 大小。
  • 云厂商通常对 Linux 内核提供了长期的测试和针对性补丁,使其能自动适配底层存储后端的限制。

总结:Linux 通过驱动层面的自动协商解决了问题,而 FreeBSD 在阿里云环境下则需要通过 loader tunable 配合少量内核补丁来进行手动限制和兜底。

3. 其他操作系统的等效配置

制作“阿里云友好”的镜像时,通常需要关注 virtio 驱动支持I/O 请求大小限制(64K)

3.1 OpenBSD

OpenBSD 内核中的 MAXPHYS 是编译时常量,其默认值即为 64K

  • 配置无需额外的 loader 配置
  • 兼容性:OpenBSD 的 vioblkvioif 驱动在 KVM 环境中表现良好,不需要手动干预 I/O 大小。
  • 注意:制作镜像时应确保 root 盘使用 vioblk,并配置串口控制台(stty, set image 等)以便调试。

3.2 illumos / Solaris

illumos 系系统中,等价的 tunable 为 maxphys

  • 配置:在 /etc/system 中添加如下配置:
    * /etc/system
    set maxphys = 0x10000     * 0x10000 = 65536
    
  • 说明:这是为了兼容性牺牲部分大块 I/O 性能的保守配置。

3.3 通用建议 Checklist

  1. 驱动:确保磁盘使用 virtio-blk/virtio-scsi,网络使用 virtio-net。
  2. I/O 限制
    • FreeBSD: kern.maxphys=65536
    • OpenBSD: 默认支持
    • illumos: set maxphys=0x10000
  3. 控制台:配置串口控制台以便在启动失败时排查故障。

参考资料