高级主题

ZFS卷

ZFS卷是表示块设备的数据集。可以在/dev/zvol/{dsk,rdsk}/rpool目录中将ZFS卷定义为设备。
以下示例中,创建一个5GB的ZFS卷system1/vol
$ zfs create -V 5gb system1/vol
改变卷的大小时需要小心:缩小卷可能会发生数据损坏;如果创建大小发生变化的卷的快照,当尝试回滚快照或从快照创建克隆,可能会导致不一致。
因此,在创建卷时,保留会自动设置为卷的初始大小,以确保数据完整性。

使用zfs getzfs get all命令可以显示zfs卷的属性:
$ zfs get all system1/vol
如果输出结果中volsize后面跟了一个问号,则表示I/O错误造成无法获知正确值。例如:
$ zfs get -H volsize system1/vol
system1/vol        volsize ?       local 		
I/O错误通常表示池设备有问题。
如果使用安装了区域的Oracle Solaris系统,则无法在本机区域中创建或克隆ZFS卷。

用作交换或转储设备

在安装ZFS根文件系统或从UFS根文件系统迁移期间,将在ZFS根池中的ZFS卷上创建交换设备和转储设备。
以下例子展示如何显示交换设备和转储设备的信息:
$ swap -l
swapfile                     dev    swaplo   blocks     free
/dev/zvol/dsk/rpool/swap   253,3        16  8257520  8257520

$ dumpadm
Dump content: kernel pages
Dump device: /dev/zvol/dsk/rpool/dump (dedicated)
Savecore directory: /var/crash/
Savecore enabled: yes		

如果在安装系统后需要更改交换区域或转储设备,可使用swapdumpadm命令(FreeBSD中没有这两个命令)。
如果需要创建其他交换卷,可创建特定大小的ZFS卷,然后在该设备上启用交换,并在新设备的stab/vfstab中添加对应的条目。
例如:
$ zfs create -V 2G rpool/swap2
$ swap -a /dev/zvol/dsk/rpool/swap2
$ swap -l
swapfile                      dev  swaplo  blocks    free
/dev/zvol/dsk/rpool/swap    256,1      16 2097136 2097136
/dev/zvol/dsk/rpool/swap2   256,5      16 4194288 4194288		
不要在ZFS文件系统上使用交换文件。ZFS交换文件配置不受支持。

用作iSCSI LUN

作为iSCSI目标的ZFS卷与任何其他ZFS数据集一样进行管理,只是在ZFS卷作为iSCSI LUN共享时,不能重命名数据集、回滚卷快照或导出池。
如果试图执行这些操作,会收到类似以下的消息:
$ zfs rename system1/volumes/v2 system1/volumes/v1
cannot rename 'system1/volumes/v2': dataset is busy
$ zpool export system1
cannot export 'system1': pool is busy		
所有iSCSI目标配置信息都存储在数据集中。与NFS共享文件系统一样,在不同系统上导入的iSCSI目标也会相应地共享。
通用多协议SCSI目标(COMSTAR)软件框架使您能够将任何Oracle Solaris系统转换为可由启动器主机通过存储网络访问的SCSI目标设备。您可以创建和配置要作为iSCSI逻辑单元(LUN)共享的ZFS卷。
如何将ZFS卷用作iSCSI LUN
  1. 首先,安装COMSTAR包
  2. $ pkg install group/feature/storage-server
  3. 创建一个ZFS卷用于iSCSI目标
  4. $ zfs create -V 2g /system1/volumes/v2
  5. 创建SCSI-block-device-based LUN(基于SCSI块设备的逻辑单元号)
  6. $ sbdadm create-lu /dev/zvol/rdsk/system1/volumes/v2
    Created the following LU:
    
    GUID                    DATA SIZE           SOURCE
    --------------------------------  -------------------  ----------------
    600144f000144f1dafaa4c0faff20001  2147483648           /dev/zvol/rdsk/system1/volumes/v2
    $ sbdadm list-lu
    Found 1 LU(s)
    
    GUID                    DATA SIZE           SOURCE
    --------------------------------  -------------------  ----------------
    600144f000144f1dafaa4c0faff20001  2147483648           /dev/zvol/rdsk/system1/volumes/v2			
    
  7. 向所有ZFS客户端或选定的ZFS客户端共享LUN视图
  8. 以下示例中,LUN视图共享给所有ZFS客户端:
    1. 定义LUN GUID
    2. $ stmfadm list-lu
      LU Name: 600144F000144F1DAFAA4C0FAFF20001				
      
    3. 共享LUN视图
    4. $ stmfadm add-view 600144F000144F1DAFAA4C0FAFF20001
      $ stmfadm list-view -l 600144F000144F1DAFAA4C0FAFF20001
      View Entry: 0
      Host group   : All
      Target group : All
      LUN          : 0				
      
  9. 创建iSCSI目标
  10. 详见使用COMSTAR配置存储设备
top

在已安装区域的Oracle Solaris系统上使用ZFS

Oracle Solaris操作系统中的Oracle Solaris区域功能提供了一个在系统上运行应用程序的隔离环境。
将ZFS数据集与区域关联时,应注意以下几点: Oracle Solaris内核区域使用存储的方式不同于本机Oracle Solaris区域。

通过使用fs资源添加ZFS文件系统,本机区域可以与全局或内核区域共享磁盘空间。
但是,区域管理员无法在基础文件系统层次结构中控制属性或创建新的文件系统。此操作与向区域添加任何其他类型的文件系统相同。
您应该将文件系统添加到本机区域,仅用于共享公共磁盘空间。

您还可以将ZFS数据集委托给本机区域,这样区域管理员就可以完全控制数据集及其所有子级。
区域管理员可以在该数据集中创建和销毁文件系统或克隆,以及修改数据集的属性。
区域管理员不能影响尚未添加到区域的数据集,包括超过在委派数据集上设置的任何顶级配额。

当源zonepath和目标zonepath都位于ZFS文件系统上且位于同一池中时,ZoneAdmin clone命令(而不是ZFS clone)将成为克隆分区的命令。
zoneadm clone命令创建源zonepath的ZFS快照并设置目标zonepath。

将ZFS文件系统添加到非全局区域

ZFS文件系统的mountpoint属性必须设置为legacy才能将其加入到本地区域。
例如:对于文件系统system1/zone/zion,可以在全局或内核区域使用以下命令:
global$ zfs set mountpoint=legacy system1/zone/zion
然后就可以使用zonecfg命令的add fs子命令将这个文件系统添加到本地区域。注意,要添加文件系统,要先确定它没有被挂载到其他地方
global$ zonecfg -z zion
zonecfg:zion> add fs
zonecfg:zion:fs> set type=zfs
zonecfg:zion:fs> set special=system1/zone/zion
zonecfg:zion:fs> set dir=/opt/data
zonecfg:zion:fs> end
以上操作将ZFS文件系统system1/zone/zion添加到已经配置过的zion区域,该区域挂载到/opt/data
区域管理员可以在这个文件系统中创建和销毁文件。
文件系统不能被挂载到其他地方。同样,区域管理员也不能更改文件系统上的属性,如atimereadonlycompression等。
全局区域管理员负责设置和控制文件系统的属性。
top

向非全局区域委托数据集

ZFS支持通过zonecfg add dataset命令将数据集添加到本机区域,以实现将存储管理委托给区域的目标。
下面例子中,全局区域管理员从全局区域或内核区域将一个ZFS文件系统委托给本机区域:
global$ zonecfg -z zion
zonecfg:zion> add dataset
zonecfg:zion:dataset> set name=system1/zone/zion
zonecfg:zion:dataset> set alias=system1
zonecfg:zion:dataset> end		
与添加文件系统不同,以上操作使ZFS文件系统system1/zone/zion在已配置的zion区域中可见。
zion区域中,这个文件系统不能被当作system1/zone/zion访问,但是会被当作名为system1的虚拟池。
委托的文件系统别名将原始池的视图作为虚拟池提供给区域。如果未指定别名,将使用与文件系统名称的最后一个组件匹配的默认别名。此例中,默认别名为zion
在委托的数据集中,区域管理员可以设置文件系统属性,以及创建子文件系统。
此外,区域管理员还可以创建快照和克隆,或者控制整个文件系统层次结构。
如果在委派的文件系统中创建ZFS卷,则这些卷可能与作为设备资源添加的ZFS卷冲突。 top

向非全局区域添加ZFS卷

可以向本地区域添加或创建ZFS卷,或者通过以下途径添加对本地区域卷中数据的访问: top

在区域内使用ZFS存储池

不能在本地区域内创建或修改ZFS存储池。委托管理模型集中控制全局集内核区域内的物理存储设备,并控制本地区域的虚拟存储。
尽管可以将池级数据集添加到本地区域,但不允许从本地区域内执行任何修改池物理特性的命令,如创建、添加或删除设备。
即使使用zonecfg add device命令将物理设备添加到本地区域,或使用文件,zpool命令也不能在本地区域创建任何新池。

内核区域在数据存储管理方面更强大、更灵活。设备和卷可以委托给内核区域,就像全局区域一样。此外,还可以在内核区域中创建ZFS存储池。
top

在区域内管理ZFS属性

将数据集委托给区域后,区域管理员可以控制特定的数据集属性。
将数据集委托给区域后,其所有祖先都将作为只读数据集可见,而数据集本身以及其所有后代都是可写的。
例如,考虑以下配置:
global$ zfs list -Ho name
system1
system1/home
system1/data
system1/data/matrix
system1/data/zion
system1/data/zion/home		
如果使用默认的zion别名将system1/data/zion添加到一个区域,每个数据集将拥有以下属性:
数据集 是否可见 是否可写 不变属性
system1 No - -
system1/home No - -
system1/data No - -
system1/data/zion Yes Yes zoned, quota, reservation
system1/data/zion/home Yes Yes zoned
注意:system1/zone/zion的每个父级都是不可见的,所有子级都是可写的。区域管理员无法更改分区属性,因为这样会暴露下一节所述的安全风险。
区域中的特权用户可以更改任何其他可设置属性,quotareservation除外。此行为允许全局区域管理员控制本地区域使用的所有数据集的磁盘空间消耗。
此外,该份额也有所下降。将数据集委托给本地区域后,全局区域管理员无法更改share.nfsmountpoint属性。 top

了解被分区域的属性

将数据集委托给本地区域时,必须对数据集进行特殊标记,以便某些属性不会在全局区域或内核区域的上下文中进行解释。
将数据集委托给本地区域并由区域管理员控制后,其内容将不再受信任。
与任何文件系统一样,可能存在setuid二进制文件、符号链接或其他有问题的内容,这些内容可能会对全局或内核区域的安全性产生不利影响。
此外,不能在全局或内核区域的上下文中解释mountpoint属性。否则,区域管理员可能会影响全局或内核区域的命名空间。
为了解决后者,ZFS使用zoned属性指示数据集在某个时间点已委托给本地区域。

zoned属性是一个布尔值,在首次启动包含ZFS数据集的区域时自动启用。区域管理员不需要手动设置此属性。
如果设置了zoned属性,则无法在全局或内核区域中挂载或共享数据集。
以下示例中,system1/zone/zion已委托给某个区域,但system1/zone/global还没有委托:
$ zfs list -o name,zoned,mountpoint -r system1/zone
NAME                  ZONED   MOUNTPOINT              MOUNTED
system1/zone/global     off   /system1/zone/global        yes
system1/zone/zion        on   /system1/zone/zion          yes
$ zfs mount
system1/zone/global           /system1/zone/global
system1/zone/zion             /export/zone/zion/root/system1/zone/zion


root@kzx-05:~# zonecfg -z sol info dataset                                                
dataset:
    name: rpool/foo
    alias: foo
root@kzx-05:~# zfs list -o name,zoned,mountpoint,mounted -r rpool/foo                     
NAME       ZONED  MOUNTPOINT                  MOUNTED
rpool/foo     on  /system/zones/sol/root/foo      yes
root@kzx-05:~# zfs mount | grep /foo                                                      
rpool/foo                       /system/zones/sol/root/foo		
从区域中删除数据集或销毁区域时,zoned属性不会自动清除。
此行为将避免与这些任务相关的固有安全风险。因为不受信任的用户可以完全访问数据集及其子体,所以mountpoint属性可能设置为错误值,或者文件系统上可能存在setuid二进制文件。

为了防止意外的安全风险,如果要以任何方式重用数据集,则必须由全局区域管理员手动清除分区属性。
在将zoned属性设置为off之前,请确保数据集及其所有子体的mountpoint属性设置为合理的值,并且不存在setuid二进制文件,或者关闭setuid属性。

验证没有留下任何安全漏洞后,可以使用zfs setzfs inherit命令关闭分区属性。
如果在区域内使用数据集时关闭zoned属性,则系统可能会以不可预知的方式运行。
只有在确定数据集不再由本机区域使用时,才更改属性。

top

复制区域到其他系统

当需要将一个或多个区域迁移到另一个系统时,请使用Oracle Solaris Unified Archives,它管理操作系统中的所有克隆和恢复操作,并在全局、本机和内核区域上运行。
如果一个系统上的所有区域都需要移动到另一个系统上的另一个ZFS池,可以考虑使用复制流,因为它保留快照和克隆。
pkg updatebeadm createzoneadm clone命令广泛使用快照和克隆。

以下例子中,sysA的区域安装在rpool/zones文件系统中,需要复制到newpool/zones文件系统里的sysB
以下命令创建快照并使用复制流复制数据去sysB:
sysA$ zfs snapshot -r rpool/zones@send-to-sysB
sysA$ zfs send -R rpool/zones@seand-to-sysB | ssh sysB zfs receive -d newpool
top

使用具有备用根位置的ZFS池

池本质上与主机系统相连。主机系统维护有关池的信息,以便在池不可用时进行检测。
虽然这些信息对正常操作很有用,但当您从备用介质引导或在可移动介质上创建池时,这些信息可能会成为一种障碍。
为了解决这个问题,ZFS提供了一个备用根位置(alternate root location)池功能。
备用根池位置不会在系统重新启动时保持不变,并且所有装载点都会修改为相对于池的根。

创建具有备用根位置的ZFS池

在备用位置创建池的最常见原因是用于可移动介质。在这些情况下,用户通常需要一个文件系统,并且希望将其装载到目标系统上他们选择的任何位置。
使用zpool create –R选项创建池时,根文件系统的装入点将自动设置为/,这相当于备用根值。

下面例子中,创建一个名为morpheus的池,挂载到/mnt上作为备用根位置:
$ zpool create -R /mnt morpheus c0t0d0
$ zfs list morpheus
NAME                   USED  AVAIL  REFER  MOUNTPOINT
morpheus              32.5K  33.5G     8K  /mnt		
注意,单个文件系统morpheus,其挂载点时池的备用根位置/mnt
存储在磁盘上的挂载点时/,并且/mnt的完整路径仅在池创建的初始上下文中解释。
然后,可以使用-R alternate-root-value语法在不同系统上的任意备用根位置下导出和导入此文件系统。
$ zpool export morpheus
$ zpool import morpheus
cannot mount '/': directory is not empty
$ zpool export morpheus
$ zpool import -R /mnt morpheus
$ zfs list morpheus
NAME                   USED  AVAIL  REFER  MOUNTPOINT
morpheus              32.5K  33.5G     8K  /mnt		
top

导入具有备用根位置的池

也可以使用备用根位置导入池。
此功能允许恢复情况,其中不应在当前根装入点的上下文中解释装入点,而是在可以执行修复的某个临时目录下解释装入点。
如前一节所述,在安装可移动介质时,也可以使用此功能。

在下面的示例中,一个名为morpheus的池被导入,其中/mnt作为备用根装入点。本例假设morpheus以前已导出。
$ zpool import -R /a pool
$ zpool list morpheus
NAME   SIZE   ALLOC  FREE    CAP  HEALTH  ALTROOT
pool  44.8G    78K  44.7G     0%  ONLINE  /a
$ zfs list pool
NAME   USED  AVAIL  REFER  MOUNTPOINT
pool  73.5K  44.1G    21K  /a/pool		
top

导入具有临时名称的池

除了在备用根位置导入池外,还可以导入具有临时名称的池。
在某些共享存储或恢复情况下,此功能允许同时导入具有相同持久名称的两个池。必须使用临时名称导入其中一个池。

在以下示例中,rpool池在备用根位置导入,并使用临时名称。由于永久池名称与已导入的池冲突,因此必须通过池ID或指定设备导入。
$ zpool import
pool: rpool
id: 16760479674052375628
state: ONLINE
action: The pool can be imported using its name or numeric identifier.
config:

rpool     ONLINE
c8d1s0  ONLINE
$ zpool import -R /a -t altrpool 16760479674052375628
$ zpool list
NAME      SIZE  ALLOC  FREE  CAP  DEDUP  HEALTH  ALTROOT
altrpool   97G  22.4G   74G  23%  1.00x  ONLINE  /a
rpool     465G  75.1G  390G  16%  1.00x  ONLINE  -		
还可以使用zpool create -t选项使用临时名称创建池。

top