摘要
核心结论
在阿里云 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 tunablekern.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 的
vioblk和vioif驱动在 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
- 驱动:确保磁盘使用 virtio-blk/virtio-scsi,网络使用 virtio-net。
- I/O 限制:
- FreeBSD:
kern.maxphys=65536 - OpenBSD: 默认支持
- illumos:
set maxphys=0x10000
- FreeBSD:
- 控制台:配置串口控制台以便在启动失败时排查故障。