返回首页

Samba、ZFS、VirtioFS:设置具有 ACL 和 XATTR 的文件服务器

详细指南:在 KVM 上通过 VirtioFS 将 Samba 与 ZFS 集成,解决 Windows 兼容访问权限和影子副本的 ACL 和 xattr 问题。

Samba、ZFS 和 VirtioFS:NAS 中 ACL 和 xattr 问题的深入分析
Advertisement 728x90

Samba、ZFS 与 VirtioFS 整合:攻克 ACL 和 XATTR 难题

在 KVM 虚拟化环境中,利用 VirtioFS 部署基于 ZFS 存储的高性能 SMB 文件服务器,会面临一些独特的挑战,尤其是在正确处理访问控制列表 (ACL) 和扩展属性 (xattr) 以确保与 Windows 客户端兼容性方面。本文将详细介绍配置过程以及如何克服关键障碍,从而确保文件共享的完整功能和稳定运行。

选择 VirtioFS 进行存储虚拟化

当基于 ZFS 构建网络附加存储 (NAS) 并通过 Samba 设置共享文件夹时,需要一种高效的方法将 ZFS 存储池连接到虚拟机 (VM)。最初考虑了多种方法,包括 NFS,但 KVM 虚拟机监控程序提供的直接目录直通功能引起了特别关注。在 virtio-9pVirtioFS 等可用选项中,最终选择了后者。

virtio-9p 因其不稳定、POSIX 支持有限和性能不佳而被排除,不适用于关键的文件服务器任务。相比之下,VirtioFS 凭借其架构展现出更大的潜力,它允许虚拟机以高性能直接访问宿主机的文件系统。

Google AdInline article slot

然而,尽管 VirtioFS 具有明显的优势,它也存在一些特殊之处。标准的 virt-manager 设置没有提供启用扩展属性 (xattr) 和访问控制列表 (ACL) 支持的选项,而这些对于 Samba 与 Windows 客户端的正常工作至关重要。扩展属性允许存储额外的文件信息,而 ACL 则定义了用户和组的详细访问权限,构成了 Windows 中 NTFS 权限的基础。如果没有这些功能,Samba 和 ZFS 的完全集成将无法实现。

配置 VirtioFS 以支持 ACL 和 XATTR

主要的挑战是确保在宿主机上运行的 virtiofsd 守护进程能够以必要的 --xattr--posix-acl 参数启动。通过 libvirtQemu 直接编辑 VM 的 XML 配置被证明是无效的,因为无法正确传递 virtiofsd 启动所需的所有参数。

解决方案是使用一个包装器——一个简单的脚本,它以所需的标志启动 virtiofsd。这种方法绕过了 libvirt 的限制,并确保了对直通目录的完整 ACL 和 xattr 支持的激活。创建和应用包装器的过程包括以下步骤:

Google AdInline article slot
  • 创建包装器脚本:

创建一个文件 /usr/libexec/virtiofsdfix,内容如下:

```bash

#!/bin/bash

Google AdInline article slot

exec /usr/libexec/virtiofsd "$@" --xattr --posix-acl --sandbox none

```

--sandbox none 参数是在实验过程中添加的,旨在禁用隔离,这在某些情况下可能很重要。

  • 设置权限:

授予脚本执行权限,并从原始 virtiofsd 守护进程复制安全上下文:

```bash

sudo chmod +x /usr/libexec/virtiofsdfix

sudo chcon --reference=/usr/libexec/virtiofsd /usr/libexec/virtiofsdfix

```

  • 修改 VM 配置:

在虚拟机的 XML 配置中(通过 virt-managervirsh edit),将创建的包装器脚本路径指定为主要的 VirtioFS 模块。

完成这些步骤后,VirtioFS 将正确地将宿主机的文件系统直通到虚拟机中,并激活 xattr 和 POSIX ACL 支持。这为与 ZFS 和 Samba 的进一步集成奠定了基础。

ZFS 配置以实现正确的 ACL 操作

即使 VirtioFS 已正确配置以传递扩展属性和 POSIX ACL,ZFS 文件系统仍需要特定的配置才能完全支持这些功能。为了使 ZFS 数据集能够正确处理类似于 Windows 中使用的 ACL(NTFS ACL),必须设置几个关键属性:

  • zfs set acltype=posixacl pool/smbfs

此属性为指定的数据集启用标准 Linux POSIX ACL 支持。它允许 getfaclsetfacl 等命令正常工作,这是 Samba 的先决条件。

  • zfs set aclinherit=passthrough pool/smbfs

此属性定义了 ACL 继承行为。passthrough 值确保当在数据集中创建新文件或目录时,它们会自动继承父目录的访问权限。这对于在文件结构中保持一致的权限至关重要,尤其是在 Windows 共享的上下文中。

  • zfs set aclmode=passthrough pool/smbfs

此属性将 ZFS 的 ACL 非干预模式设置为 passthrough。在此模式下,ZFS 不会尝试解释或修改 ACL,而是按原样传递它们。这确保了与 Samba 等管理自身 ACL 的外部系统的最大兼容性。

配置 ZFS 和 VirtioFS 后,唯一剩下的步骤是在客户机 VM 中挂载直通目录。这可以通过在 /etc/fstab 中添加相应行来完成:

fs   /fs   virtiofs   rw,noatime,_netdev,nofail

执行 mount -a 后,ZFS 目录将在 VM 的 /fs 处可访问,并可供 Samba 使用。

Samba 在 acl_xattrsecurity.NTACL 方面的问题

在完成基本的 VirtioFS 和 ZFS 设置后,下一步是 Samba 配置。本地目录的典型设置,包括 vfs objects = acl_xattr,工作完美,允许 Samba 写入扩展属性,包括用于 Windows ACL 的属性。然而,当尝试将此配置应用于通过 VirtioFS 直通的目录时,出现了一个问题:Samba 拒绝写入 XATTR 属性,特别是 security.NTACL

问题表现为 POSIX ACL 的标准 setfacl 命令在本地磁盘和 VirtioFS 上都能正常工作,但写入 Samba 特定的属性(如 security.NTACL)却失败了。这阻碍了 Windows 权限的完整功能,因为 Samba 无法保存必要的安全描述符信息。即使在宿主机上禁用 SELinux 也未能达到预期效果。

使用 setfattr 模拟 Samba 属性写入的测试揭示了一个关键问题。当尝试以域用户身份写入 security.NTACL 属性时,操作在本地文件和 VirtioFS 上的文件都失败了。然而,当以超级用户 (root) 身份执行相同的操作时,在本地磁盘上写入 security.NTACL 成功,但在 VirtioFS 上仍然失败。

这表明扩展属性的处理方式存在根本差异:

  • security.NTACL:此属性位于 security 命名空间中,Samba 用它来存储 Windows 权限 (NTFS ACL)。写入此命名空间受到严格限制,需要 CAP_SYS_ADMIN 权限,相当于 root 权限。普通用户,即使是文件所有者,也无法直接修改或删除此属性。
  • user.NTACL:此属性位于 user 命名空间中。任何对文件具有写入权限的用户都可以修改此命名空间中的属性。

VirtioFS 失败的主要原因是,即使使用了 --sandbox none 参数并尝试以 root 身份(通过 sudo)写入,VirtioFS 在内核层面或其自身实现中,似乎阻止了对 security.NTACL 命名空间的写入。这阻止了 Samba Windows 权限的正确保存。

解决方案:将 security.NTACL 重定向到 user.NTACL 并集成 ZFS 快照

由于 Samba 无法通过 VirtioFS 将属性正确写入 security.NTACL 命名空间,唯一可行的解决方案是将这些属性重定向到 user.NTACL 用户命名空间。虽然这是一种权宜之计,而非 VirtioFS 根本问题的完整解决方案,但它允许 Samba 存储所有必要的 Windows 权限信息。需要注意的是,当用户仅通过 SMB 与服务器交互,并且无法直接访问宿主机或客户机 VM 的文件系统时,这种方法是可接受的。

要实现此解决方案,必须将以下参数添加到 Samba 配置文件 (smb.conf) 中:

[VirtioFS]
    path = /fs
    writable = yes
    admin users = "domain\admin-domain" "superadmin"

    vfs objects = acl_xattr shadow_copy2

    # user.NTACL
    acl_xattr:security_acl_name = user.NTACL
    acl_xattr:ignore system acls = yes


    shadow:basedir = /fs
    shadow:snapdir = .zfs/snapshot
    shadow:format = GMT-%Y.%m.%d_%H.%M.%S
    shadow:sort = desc
    shadow:localtime = yes

其中,关键行是:

  • acl_xattr:security_acl_name = user.NTACL:指示 Samba 使用 user.NTACL 而非 security.NTACL 来存储安全描述符。
  • acl_xattr:ignore system acls = yes:此参数告诉 Samba 忽略系统 ACL,转而依赖其自身的机制来存储权限。

将 ZFS 快照与 Samba 集成

为了向 Windows 客户端提供卷影副本功能,允许用户恢复以前的文件版本,使用了 shadow_copy2 模块。它与 ZFS 的快照功能集成。在提供的配置中:

  • vfs objects = acl_xattr shadow_copy2:激活 shadow_copy2 模块。
  • shadow:basedir = /fs:指定卷影副本的基目录。
  • shadow:snapdir = .zfs/snapshot:定义 ZFS 存储其快照的子目录。为了正常运行,ZFS 存储池必须设置 listsnapshots=on 属性(例如,zpool set listsnapshots=on pool_name),这允许 Samba 发现并显示可用的快照。
  • shadow:formatshadow:sortshadow:localtime:配置快照的显示格式和排序方式。

因此,尽管最初在 security.NTACL 方面遇到了困难,此配置仍允许通过 VirtioFS 在 ZFS 上创建功能完善的 Samba 文件服务器,确保 Windows ACL 和卷影副本的正常运行。

关键要点

  • VirtioFS 与 ACL/xattr: 为了通过 VirtioFS 实现 Samba 与 Windows ACL 的完整功能,virtiofsd 守护进程必须以 --xattr--posix-acl 参数启动,这通常需要一个包装器脚本。
  • ZFS 配置: 用于 Samba 共享的 ZFS 数据集必须配置 acltype=posixaclaclinherit=passthroughaclmode=passthrough 属性,以正确处理 ACL。
  • security.NTACL 问题: Samba 默认尝试将 Windows 安全描述符写入 security.NTACL,这需要 root 权限,并且可能被 VirtioFS 阻止。
  • 通过 user.NTACL 解决: 一个有效的变通方法是通过 acl_xattr:security_acl_name = user.NTACL 参数,将 Samba 重定向到使用 user.NTACL 来存储安全属性。
  • ZFS 快照与 Samba: 通过 Samba 中的 shadow_copy2 模块实现 ZFS 快照与 Windows 卷影副本的集成,这需要适当的 ZFS 存储池属性配置。

— Editorial Team

Advertisement 728x90

继续阅读