收起左侧

虚拟机共享宿主机文件夹,仅限Linux。

0
回复
23
查看
[ 复制链接 ]

概述

本教程介绍如何在 FnOS(飞牛NAS)上使用 virtio-9p(Plan 9)协议将宿主机目录共享到 KVM 虚拟机中。9p 是一种轻量级的文件共享协议,无需网络配置,通过 virtio 总线直接在宿主机和虚拟机之间传输文件,性能优于 NFS/Samba 等网络共享方案。

适用场景

  • 宿主机与虚拟机之间共享文件/模板
  • 虚拟机访问宿主机上的大容量存储
  • 多台虚拟机共享同一目录(如模板库、ISO 仓库等)

环境要求

项目 要求
宿主机 FnOS(基于 Debian 12)或其他支持 KVM/QEMU 的 Linux
虚拟机 需要内核支持 9p(Linux 内核 2.6.14+,主流发行版默认支持)
QEMU 支持 virtio-9p-pci 设备

操作步骤

第一步:确认宿主机共享目录存在

确保要共享的目录已创建,以 /vol1/1000/templates 为例:

ls -ld /vol1/1000/templates

如果目录不存在,先创建:

sudo mkdir -p /vol1/1000/templates

第二步:修复目录权限

QEMU 进程以 libvirt-qemu 用户运行,需要确保从根目录到共享目录的整条路径链都有可访问权限:

sudo chmod 755 /vol1 /vol1/1000 /vol1/1000/templates

⚠️ 关键:即使共享目录本身权限正确,如果上级目录(如 /vol1/vol1/1000)缺少 o+x 权限,QEMU 仍然无法访问,会报 Permission denied 错误。

第三步:关闭虚拟机

9p 设备需要在虚拟机配置中添加,修改配置前必须先关闭虚拟机:

sudo virsh shutdown <虚拟机名称>

如果虚拟机未响应 shutdown,可以强制关闭:

sudo virsh destroy <虚拟机名称>

确认已关闭:

sudo virsh list --all | grep <虚拟机名称>

第四步:添加 9p 共享设备(一键命令)

使用以下一键命令将 9p 文件系统设备注入到虚拟机 XML 配置中:

VM_NAME="ubuntu24-clone-01"
SHARE_DIR="/vol1/1000/templates"
SHARE_TAG="templates_share"

virsh dumpxml $VM_NAME > /tmp/${VM_NAME}.xml && \
sed -i "/<\/devices>/i \    <filesystem type=\"mount\" accessmode=\"passthrough\">\n      <driver type=\"path\"\/>\n      <source dir=\"${SHARE_DIR//\//\\/}\"\/>\n      <target dir=\"${SHARE_TAG}\"\/>\n    <\/filesystem>" /tmp/${VM_NAME}.xml && \
virsh define /tmp/${VM_NAME}.xml && \
rm -f /tmp/${VM_NAME}.xml

输出:

Domain 'ubuntu24-clone-01' defined from /tmp/ubuntu24-clone-01.xml

参数说明:

变量 说明 示例
VM_NAME 虚拟机名称 ubuntu24-clone-01
SHARE_DIR 宿主机要共享的目录路径 /vol1/1000/templates
SHARE_TAG 共享标签名(虚拟机内挂载时引用) templates_share

XML 配置解读:

添加到 <devices> 内的配置如下:

<filesystem type="mount" accessmode="passthrough">
  <driver type="path"/>
  <source dir="/vol1/1000/templates"/>
  <target dir="templates_share"/>
</filesystem>
属性 说明
type="mount" 挂载类型,将宿主机本地目录共享
accessmode="passthrough" 直接使用宿主机文件权限,性能最佳
<driver type="path"/> 使用路径驱动
<source dir="..."/> 宿主机上的共享目录路径
<target dir="..."/> 共享标签名,不是虚拟机内的挂载路径

第五步:启动虚拟机

sudo virsh start <虚拟机名称>

第六步:虚拟机内挂载共享目录

通过 SSH 或 VNC 进入虚拟机,执行以下操作:

1. 加载 9p 内核模块(通常已自动加载):

sudo modprobe 9p
sudo modprobe 9pnet
sudo modprobe 9pnet_virtio

2. 创建挂载点:

sudo mkdir -p /mnt/templates

3. 挂载共享目录:

sudo mount -t 9p -o trans=virtio,version=9p2000.L templates_share /mnt/templates

⚠️ 注意templates_share 是第四步中设置的 SHARE_TAG 标签名,必须与配置中的 <target dir="..."/> 完全一致,否则会报 no channels available 错误。

4. 验证挂载:

ls /mnt/templates
df -h /mnt/templates
mount | grep 9p

正常输出示例:

templates_share on /mnt/templates type 9p (rw,relatime,sync,dirsync,access=client,trans=virtio)

第七步:设置开机自动挂载(可选)

将挂载配置写入 /etc/fstab,实现开机自动挂载:

echo 'templates_share /mnt/templates 9p trans=virtio,version=9p2000.L,_netdev 0 0' | sudo tee -a /etc/fstab

验证 fstab 配置是否正确(不会实际挂载,只检查语法):

sudo mount -a

fstab 参数说明:

参数 说明
templates_share 设备名(即共享标签)
/mnt/templates 虚拟机内的挂载点
9p 文件系统类型
trans=virtio 使用 virtio 传输层
version=9p2000.L 使用 Linux 扩展的 9p 协议
_netdev 延迟挂载,确保 virtio 设备就绪后再挂载

accessmode 模式对比

模式 权限映射 性能 适用场景
passthrough 直接使用宿主机 UID/GID ⭐⭐⭐ 最优 QEMU 以 root 运行,或路径链权限已正确配置
mapped-xattr 通过扩展属性映射权限 ⭐⭐ 良好 QEMU 以非 root 用户运行,文件系统支持 xattr
mapped-file 通过隐藏文件映射权限 ⭐ 一般 文件系统不支持 xattr 时的备选方案

如果使用 passthrough 模式遇到权限问题,可以切换为 mapped-xattr

VM_NAME="ubuntu24-clone-01"

virsh dumpxml $VM_NAME > /tmp/${VM_NAME}.xml && \
sed -i 's/accessmode="passthrough"/accessmode="mapped-xattr"/' /tmp/${VM_NAME}.xml && \
virsh define /tmp/${VM_NAME}.xml && \
rm -f /tmp/${VM_NAME}.xml

共享多个目录

可以同时共享多个目录,每个目录使用不同的标签名。重复第四步,修改变量即可:

# 共享第二个目录
VM_NAME="ubuntu24-clone-01"
SHARE_DIR="/vol1/1000/isos"
SHARE_TAG="isos_share"

virsh dumpxml $VM_NAME > /tmp/${VM_NAME}.xml && \
sed -i "/<\/devices>/i \    <filesystem type=\"mount\" accessmode=\"passthrough\">\n      <driver type=\"path\"\/>\n      <source dir=\"${SHARE_DIR//\//\\/}\"\/>\n      <target dir=\"${SHARE_TAG}\"\/>\n    <\/filesystem>" /tmp/${VM_NAME}.xml && \
virsh define /tmp/${VM_NAME}.xml && \
rm -f /tmp/${VM_NAME}.xml

虚拟机内挂载:

sudo mkdir -p /mnt/isos
sudo mount -t 9p -o trans=virtio,version=9p2000.L isos_share /mnt/isos

删除 9p 共享

如果不再需要共享,执行以下步骤:

1. 虚拟机内卸载:

sudo umount /mnt/templates

如果设置了自动挂载,还需删除 fstab 中对应行:

sudo sed -i '/templates_share/d' /etc/fstab

2. 宿主机上移除 9p 设备:

VM_NAME="ubuntu24-clone-01"

virsh dumpxml $VM_NAME > /tmp/${VM_NAME}.xml && \
sed -i '/<filesystem type="mount"/,/<\/filesystem>/d' /tmp/${VM_NAME}.xml && \
virsh define /tmp/${VM_NAME}.xml && \
rm -f /tmp/${VM_NAME}.xml

⚠️ 注意:上面的命令会删除所有 9p 共享。如果只想删除特定的共享,建议使用 virsh edit 手动编辑。


常见问题

Q1: 挂载时报 no channels available for device xxx

原因:标签名不匹配或拼写错误。

解决:确认虚拟机 XML 中 <target dir="..."/> 的值与 mount 命令中的设备名完全一致:

# 查看配置中的标签名
virsh dumpxml <虚拟机名称> | grep "target dir"

Q2: 启动虚拟机报 Permission denied

原因:QEMU 进程无权访问共享目录或其上级目录。

解决:确保整条路径链都有可执行权限:

sudo chmod 755 /vol1 /vol1/1000 /vol1/1000/templates

或者改用 mapped-xattr 模式(参见上方 accessmode 模式对比章节)。

Q3: 虚拟机内无法写入共享目录

原因passthrough 模式下,虚拟机内用户的 UID/GID 需与宿主机上文件的权限匹配。

解决方案

  • 方案一:在宿主机上对共享目录设置宽松权限 chmod 777
  • 方案二:确保虚拟机内用户 UID 与宿主机目录 owner 一致
  • 方案三:改用 mapped-xattr 模式

Q4: 9p 性能不如预期

优化建议

  • 挂载时添加 cache=loose 选项提升读取性能(适合只读场景):
    sudo mount -t 9p -o trans=virtio,version=9p2000.L,cache=loose templates_share /mnt/templates
    
  • 挂载时添加 msize=262144 增大传输块大小:
    sudo mount -t 9p -o trans=virtio,version=9p2000.L,msize=262144 templates_share /mnt/templates
    

收藏
送赞
分享
https://www.xiaozhuhouses.asia/欢迎访问我的博客
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则