第二章:委托和Jails

减少工作量的最好方法之一就是让别人来完成工作。

ZFS有一个功能齐全的委托系统,允许指定用户或用户组可以在每个数据集上使用哪些命令和功能。

可以允许用户创建和销毁自己的快照、创建子数据集、生成空间销毁报告或控制数据集的属性。ZFS基于委托功能和jail提供特殊支持。

ZFS委托

ZFS允许根据每个数据集的每个属性和每个命令将管理任务委托给用户。

可以让数据库管理员完全控制数据库池,或者让web服务器管理员控制网站数据集上的快照。

使用zfs allow命令委派权限。

以上示例获取remotepool池的权限列表。

此池只有一个用户复制器的权限条目。此用户有权使用zfs的压缩和挂载点属性,以及创建、销毁、挂载和接收子命令。

应用程序和用户可以定义自己的属性。像zfstools这样的程序创建属性来管理快照。

还有一个特殊权限userprop,允许用户创建用户定义的属性。

用户定义的属性被分配为单个权限:不能单独分配不同的用户定义属性。

root用户不会列出任何权限,但root却可以做任何事情。因为它是root。

添加权限

使用-u选项指定要委派的用户,或使用-g选项指定要委派的组:

查看数据集权限时,将显示分配的两个权限:

委托会自动继承。当用户获得为主目录创建快照能力时,他也获得了对主目录中所有子数据集的许可。

创建新数据集需要挂载它们,销毁数据集显然应该包括卸载数据集。

要使用clone、create和destroy命令都需要mount权限。以下命令委托销毁和挂载权限给用户:

现在查看一下权限:

用户有权销毁他的主目录数据集。

你可以授予用户创建和挂载数据集的权限,但操作系统在这里也有发言权。

FreeBSD使用sysctl vfs.usermount来确定用户是否可以挂载分区。将此sysctl设置为1,以允许用户挂载分区。

即使有了sysctl,允许普通用户挂载文件系统也会附带一条安全带(safety belt),以防止用户误操作。

用户必须拥有他想要挂载任何东西的目录。这可以防止用户将新数据集挂载为/etc并劫持系统。数据集可能具有限制权限,但拥有挂载点并具有mount权限的用户可以挂载它。

要允许普通用户在其主目录中创建、克隆、挂载数据集,应设置sysctl并确保他拥有相应的控制目录:

使用普通登录并检查:

记得添加vfs.usermount=1行到/etc/sysctl.conf文件。

取消权限

使用zfs unallow从数据集中删除权限。此命令遵循与zfs完全相同的语法。

以下示例取消了lucas创建子数据集的权限:

权限也可以使用-r选项递归删除,若某个子数据集被手动设置过权限,也会被删除。

委托继承

ZFS的委托权限会自动继承。zfs allow命令还以限制权限继承。

继承的权限可以是本地的,也可以用于后代。

本地权限仅适用于指定的数据集。以下示例允许用户快照他的主目录,但不快照子数据集。

-l选项将权限设置为仅本地权限(不能被继承)。

-d选项则与-l选项相反,它仅允许对子数据集进行委托。

以下示例中,我想允许lucas销毁他创建的快照,但不要销毁他的整个主目录。我使用-d指定这些权限仅适用于他的主目录的子数据集,而不适用于主目录本身。我在他的主目录中保留了快照和回滚命令的权限,这样如果他没有搞砸,他就可以自救了。

测试一下:

只有系统管理员才能在Lucas主目录上运行zfs destroy。

create time权限

ZFS允许在今天为未来时间不存在的数据集创建权限。

create time权限应用于创建数据集的用户。使用-c定义。

对这类权限的一个常见愿望是将权限授予每个人,而不是指定系统上的每个用户或定义一个包括所有用户的组。使用-e选项表示所有人(所有用户),而不是-u或-g表示某个人或组。

-l选项设置父数据集的权限。假设我们有一个可供所有人使用的临时数据集,比如/tmp。

我们需要每个人都能在这个空间创建和挂载数据集,但不能访问整个数据集。这些权限必须限制到该数据集,并且不能由新的子数据集继承。

现在使用-c指定分配给新创建的数据集的创建时间权限:

检查您的工作将显示创建时间权限作为权限集。

当然,真正的测试是以普通用户的身份运行这些命令。让lucas在mypool/strack下创建一些数据集。

现在,lucas,而且只有lucas,可以创建和销毁他的数据集的快照。其他用户可以创建只有他们才能访问的自己的数据集。

更改权限的权限

有权访问allow命令的用户可以委派他已经拥有的任何其他权限。这使您能够让团队负责人或项目经理负责其团队的权限。

考虑前面的划痕数据集示例。假设lucas想允许liz用户在他的新scratch数据集上创建快照。

首先,通过允许lucas使用zfs-allow命令,赋予他委派权限的能力。

Lucas现在可以将他拥有的任何权限委托给liz帐户。通过以他的身份登录来测试这一点。

但Lucas不能放弃他没有的权限:

系统管理员可以将权限委托给用户,并让用户负责进一步委托自己的数据集。

权限集

运行zfs allow命令会显示一个列表,其中包含可以授权给用的60多个权限。可以单独授予对每个zfs子命令以及每个池和数据集属性的访问权限。

ZFS允许定义权限集,而不是必须向每个用户授予一长串权限,并且不可避免地会忘记或记错一个。

使用-s选项并给出一个以@符号开头地权限集名称,然后列出该集中地权限以及该权限集有效的数据集的名称。

以下示例创建一个名为@dataset的权限集,包括管理数据集的权限,并将其应用于mypool/teams数据集上:

以下是一个名为@replication的权限集,它提供了在同一数据集上进行复制所需的特权:

@billing权限集授予对数据集上通常无法访问的userused和pgroupused属性的访问权限:

以下是一个@quotas权限集,允许某人管理数据集空间配额:

最后,这里有一个权限集,可以让人们调整一些基本的数据集属性。据推测,系统管理员将这些设置为合理的默认值,但用户可能具有特殊要求的特定数据集:

一旦建立了权限集,就可以将它们分配给用户和组。此例中,managers组可以访问其数据集中的@dataset和@basic_properties集中的权限:

然后,我们允许运行计费系统(billing system)的billbot用户访问在mypool/teams上设置的billing权限:

运行zfs allow命令显示数据集上的权限集和分配的权限:

ZFS委托可能很快变得复杂。与许多其他权限方案一样,使用组可以帮助简化管理。

仅在需要时分配权限,而不是因为你认为你知道系统如何发展。

委托和Jails

FreeBSD支持一种称为jail的轻量级虚拟化方法。FreeBSD的ZFS实现对jail有特殊的支持。

数据集可以被标记为只能在jail中使用。jail中的root用户可以完全控制数据集。

无法在主机系统上挂载jail数据集。jail数据集不受信任,并且可能具有与主机不兼容或对主机充满敌意的属性设置。

举个例子,jail可能有一个挂载点为/etc的数据集。记住,BSD文件系统是可堆叠的。如果主机挂载了jail数据集,jail的/etc将堆叠在主机的/etc上。主机将突然拥有jail的/etc/password、rc.conf、sshd_config和其他重要的文件系统。最坏的情况是,jail的系统管理员可以声称控制主机。最好的情况是,主机的系统管理员会度过非常不愉快的一天。

据jail的root用户所知,他几乎完全控制了数据集。他唯一不能改变的属性是配额。编辑配额可能会让他比分配给他的系统管理员更多的访问权限。

然而,jail的root用户可以看到它存在于jail中。root账户可以看到其数据集的每个父数据集,直到池的根。如果你有一个jail池,并且jail存在于例如jails/ccustomers/lucas中,则root用户可以看到该路径。然而,它们看不到在jail外任何数据集。其他客户数据集是不可见的。

Jailing 一个数据集

将数据集的jailed属性设置为on,主机将无法再挂载这个数据集。

以下示例为Lucas创造一个jail,创建一个新的数据集作为他的jail的根,在这里,我们使用zroot/jails/lucas/jail数据集作为jail数据集:

一旦有了数据集,就在这个数据集中建立一个临时的jail:

现在进入jail:

当我们进入到jail后,可以创建一个新的数据集:

新的数据集和jail的父数据集都是可见的:

zroot/jails中是否还有其他数据集,或实际上,在这个jail的主机中是否有其他数据集?jail里的用户永远不会知道。

用户lucas现在可以设置挂载点、创建和销毁数据集、将数据集委托给jail内的普通用户等等。要是能让lucas用户在现实世界中不破坏东西就好了。

创建一个ZFS委托jail

你的jail用户可能不想要如上所述的简陋jail。他们可能想要一个真正的用户区,有程序和运行服务的能力。

这意味着在jail数据集上安装FreeBSD。

首先,创建一个jail数据集:

现在在该数据集上安装操作系统。可以直接从FTP站点安装:

如果打算安装多个jail,请下载对应版本的base.txz,并在每个jail中提取它:

将操作系统复制到jail数据集中后,将该数据集标记为不受信任。这使得主机无法访问数据集:

现在有了数据集,在jail配置文件/etc/jail.conf中为no.gelato.for.michaelwlucas.com这个jail创建一个条目:

有了jail.conf条目,我们可以使用标准的FreeBSD工具启动jail:

最后一段设置需要在jail内进行。或者,在安装操作系统时,可以做一些疯狂的事情,比如提前计划,但这会让事情失去乐趣。让我们进入jail,看看我们的数据集:

这个新jail在rc.conf中没有启用ZFS,因此默认情况下不会挂载新数据集。启用ZFS并重新启动jail:

更改配置后,重新启动并重新进入jail:

将看到新创建的数据集:

jail管理员必须使用完整路径,包括jail外的部分,来创建新的数据集。

定义限制和安全带

对于充满好奇心或又菜又爱玩的用户,ZFS提供了snapshot_limit和filesystem_limit属性,可以限制在特定数据集下可以创建的快照或子文件系统的数量。

将这些属性设置为大于你希望用户创建的快照数或数据集的数量。也就是说,将snapshot_limit设置为10,则用户可以创建9个快照,第十个会产生错误。

为了遏制某些用户存粹的邪恶,将他可以创建的快照数量限制为两个:

只读的filesystem_count和snapshot_count属性允许快速查看存在多少个文件系统或快照,并将该数字于限制进行比较。