最烦琐可怕的系统管理任务之一是系统升级。我们都知道新内核可能无法引导系统,但这是最小的问题。如果关键程序需要共享库的旧版本,该怎么办?也许新的终端模式与您的软件有点不兼容。或者,您的任务关键型软件可能会被新的链接器阻塞。
事情出了差错。有时,问题一开始并不明显,但只有在一两周后才会向你咆哮,这时回心转意变得更加困难。无论您采取什么预防措施或执行多少测试,任何升级都可能会失败。
我们开发了各种工具来解决糟糕的升级问题。引导加载程序帮助您快速从坏内核中恢复。备份有助于您从糟糕的用户环境中缓慢恢复。但这些都不能帮助您准确地理解出了什么问题,并复制问题。
除非您正在运行ZFS,否则就是这样。
通过组合快照和克隆,您可以创建操作系统内核和用户区的可引导备份。是否要升级?克隆操作系统数据集并继续。如果升级不顺利,请引导克隆。这将在使用 zfs diff 确定哪些文件已更改以及哪些文件出错时恢复服务。
您可以手动完成所有这一切,但FreeBSD将此功能捆绑到引导环境中。使用引导环境管理工具,您可以轻松创建、销毁和部署引导环境。每次您准备升级时,请创建一个新的引导环境。如果升级出现问题,无论是立即还是几周后,您都可以恢复到旧的操作系统版本。失败的版本仍然存在,因此您可以将其部署到另一台机器上,并准确地研究出了什么问题。
然而,要很好地使用引导环境,需要了解如何安装FreeBSD。
第一章:引导环境安装数据集使用引导环境查看引导环境创建引导环境激活引导环境重命名引导环境删除引导环境引导环境和 ZFS访问未使用的引导环境引导时的引导环境引导环境和应用程序移动应用软件数据创建新数据集磁盘加密和引导环境
在FreeBSD10.1及以后版本上,基于ZFS的安装创建了专门为引导环境设计的数据集。乍一看,这似乎有违直觉。看看默认安装上的一些数据集:
# zfs listNAME USED AVAIL REFER MOUNTPOINT…zroot/var 703K 188G 128K /varzroot/var/crash 128K 188G 128K /var/crashzroot/var/log 192K 188G 192K /var/logzroot/var/mail 128K 188G 128K /var/mailzroot/var/tmp 128K 188G 128K /var/tmp我们有 /var 的某些子目录的数据集:/var/crash、/var/log、/var/mail、/var/tmp 。但 /var 下的所有其他目录呢?/var/db 目录包含关键的系统信息,如包数据库。这至少跟 /var/tmp 一样重要吧?
默认安装不会根据目录中数据的重要性创建数据集。它创建数据集来分离数据。
现在检查 zfs mount ,看看这些数据集是如何挂载的:
xxxxxxxxxx# zfs mountzroot/ROOT/default /…zroot/var/crash /var/crashzroot/var/log /var/logzroot/var/mail /var/mailzroot/var/tmp /var/tmp请注意缺少的数据集:/var 。该数据集存在,但未挂载( canmount 属性设置为 no )。直接在 /var 中的文件实际上会以 root 身份挂载到数据集中,zroot/ROOT/default 。 /var 下有自己数据集的文件,如 /var/log/messages ,会放在一个单独的数据集中。在 /var 下但没有自己的数据集的文件,如 /var/db ,会进入根数据集。
数据的位置对于引导环境至关重要。可能受引导环境影响的数据放在根数据集上。您不想在引导环境中管理的数据将获得自己的数据集。
考虑 /var/db 。它包含关键信息,如包数据库、定位数据库、freebsd-update(8) 记录等。所有这些都与操作系统版本紧密相关。将主机升级到新的操作系统版本需要使用 freebsd-update ,这可能意味着在升级时更新加载项软件。如果必须还原升级,则也需要还原这些文件。
将其与 /var/log 进行比较。如果必须恢复升级,我特别不希望日志文件也回滚。日志不仅仅涵盖操作系统。类似地,/var/mail 中的主目录和邮件假脱机最好不要随操作系统回滚。
FreeBSD升级会影响特定目录。核心程序隐藏在 /bin 、/sbin、/usr/bin 和 /usr/sbin 中,库位于 /lib 和 /usr/lib 中。由于未装入 /usr 数据集,这些目录现在位于根数据集上。包安装在 /usr/local 下,但它也是根数据集的一部分。类似地,由于没有挂载 /var ,具有所有关键系统信息的 /var/db 目录也是根数据集的一部分。
不属于核心系统的文件(如日志、用户主目录等)具有自己的数据集。
这将核心系统和官方软件包与主机的其余部分隔离开来,让您可以将它们作为单个实体进行管理。FreeBSD开发人员正在打包基本系统和附加包,这可能需要重新访问这里讨论的系统。
ZFS的快照和克隆功能允许您保存、复制(copy)和复制(duplicate)文件系统。(我们在《FreeBSD Mastery:ZFS》中详细讨论了快照和克隆)。
使用ZFS,最好在执行系统维护(如升级)之前快照数据集。如果升级或更改失败,您可以回滚到上一个已知的工作版本。要调试失败的升级,请将快照复制到测试系统上并在那里进行调试,同时生产系统在稍旧的操作系统版本上继续运行。
引导环境——boot environment,将维护前快照打包为一个整洁的捆绑包,通常带有引导环境管理程序。在系统管理中使用快照不需要启动环境管理器,但管理器使维护所有这些快照变得容易得多。FreeBSD有一个引导环境管理器 beadm(8) ,专门设计为类似Solaris的beadm(8)。
使用 pkg 安装 beadm(8) 。
xxxxxxxxxx# pkg install -y beadm现在已经准备好使用引导环境了。
每个引导环境都是 zroot/ROOT 下的数据集。刚安装 beadm 的系统应该只有一个引导环境。使用 beadm list 查看所有引导环境。
xxxxxxxxxx# beadm listBE Active Mountpoint Space Createddefault NR / 649.9M 2016-02-15 14:47在 zroot/ROOT/default 之后,我们有一个名为 default 的环境。这是一个新安装的系统,因此这是您所期望的。
BE 列显示引导环境的名称,通常是 zroot/ROOT 数据集下面的名称。当前引导环境为 default ,它对应的数据集为 zroot/ROOT/default 。
Active 列显示此启动环境是否在使用中。
N 表示环境正在运行。R 表示重启时启动环境是否将被激活。重新启动时使用的引导环境来自池的 bootfs 属性。
Mountpoint 列显示引导环境的本地挂载点。所有活动的引导环境通常都挂载在/目录。如果一个引导环境未被使用,它通常没有挂载点,并且 canmount 属性给设置为 off 或 noauto 。你可以选择在其他地方挂载一个未使用的引导环境。
Space 列显示此数据集引用的磁盘空间量。
Created 列显示此引导环境创建的时间。在此例中,它是机器安装的日期。
在更改系统之前,让我们创建一个引导环境。
在现有安装或环境之后命名每个启动环境。如果正在创建引导环境以准备升级软件包,可附加当前日期或其他一些标识信息。使用 freebsd-version 检查当前运行的FreeBSD版本:
xxxxxxxxxx# freebsd-version10.3-RELEASE使用 beadm create 创建引导环境。Lucas太懒了,不想按 CAPSLOCK 键,因此引导环境名称完全是小写的。
xxxxxxxxxx# beadm create 10.3-releaseCreated successfully现在我们有两个相同的引导环境了:
xxxxxxxxxx# beadm listBE Active Mountpoint Space Createddefault NR / 650.1M 2016-02-15 14:4710.3-release - - 140.0K 2016-02-16 09:07我们当前正在使用 default 引导环境,并且相同的引导环境将在下次引导时启动。然而,10.3-release 的环境是可用的。在任何时候,您都可以告诉FreeBSD启动 10.3-release 的环境,并获得创建环境时的系统。
10.3-release 的环境与默认环境非常相似。请注意,它仅使用140 KB的空间。这足以标记快照,但由于我们尚未对文件系统进行任何更改,因此它几乎不占用任何空间。
在这里,我运行了 freebsd update ,将环境更新到最新的修补程序级别。default 引导环境获取修补程序。 10.3-release 环境保持不变。
如您所料,应用修补程序会更改引导环境的磁盘使用情况。
xxxxxxxxxx# beadm listBE Active Mountpoint Space Createddefault NR / 650.1M 2016-02-15 14:4710.3-release - - 69.7M 2016-02-16 09:0710.3-release 的引导环境突然使用69.7 MB的空间。这是 10.3-release 引导环境和当前引导环境 10.3-release-p13 之间应用的补丁程序所使用的空间。
假设你应用了最新的补丁程序,机器就疯了(goes bonkers)。您的服务器软件出现故障,或者内核恐慌(panics),或者小精灵(tiny gremlins)从USB端口跳出来,开始窃取您的勺子。通过激活引导环境并重新启动,回退到早期版本。使用 beadm activate 激活引导环境。
xxxxxxxxxx# beadm activate 10.3-releaseActivated successfully# beadm listBE Active Mountpoint Space Createddefault N / 308.1M 2015-06-19 10:0410.3-release R - 457.1M 2015-06-19 14:13default 引导环境将 Active 标志设置为 N ,这意味着它现在正在运行。10.3-release 的环境将 Active 标志设置为 R ,因此在重新启动后它将处于活动状态。
重新启动系统,然后突然恢复到运行 10.3-release 的引导环境,没有任何安全更新,并且具有最初安装在系统上的任何软件包。您已经回退到较旧版本的操作系统,风险比从备份中恢复低得多。
有时,您希望更改引导环境的名称。也许你选择的名字没有你想象的那么独特,或者你的一个爪牙(minions)想创建一个引导环境,但命名为 FeliciaGoesViking 。 beadm rename 命令允许重命名引导环境。给出两个参数:原始名称和新名称。
此主机具有名为 install 的引导环境。我将其改为 10.3-release ,就像我的其他主机一样。
xxxxxxxxxx# beadm rename install 10.3-releaseRenamed successfully该名称现在与我的其他主机一致。
如果您创建了一大堆引导环境,您将开始使用越来越多的磁盘空间。其中一些引导环境您将永远不会再使用。
xxxxxxxxxx# beadm listBE Active Mountpoint Space Createddefault NR / 3.6G 2015-04-28 11:53install - - 126.0M 2015-04-28 12:1910.3-p9 - - 209.0M 2015-05-14 08:0110.3-p10 - - 169.0M 2015-05-24 11:0210.3-p10-10Jun - - 150.0M 2015-06-10 14:2410.3-p10-13Jun - - 47.3M 2015-06-13 06:1910.3-p12 - - 7.7M 2015-06-19 07:06使用 freebsd-version 告诉我,这个特定的系统正在运行 FreeBSD 10.3-RELEASE-p13。可以想象,我可能想回到10.3-p12。但我不会回到p10或p9,特别是安装版本。消除这些引导环境将节省磁盘空间,并使我现有的引导环境更易于阅读和理解。
使用 beadm destroy 和引导环境名称来删除不需要的引导环境。
xxxxxxxxxx# beadm destroy 10.3-releaseAre you sure you want to destroy '10.3-release'?This action cannot be undone (y/[n]): yDestroyed successfully我的FreeBSD 10.3的原始安装现在已从此系统中删除。剩下的一切都以这种或那种方式修补。这可能会释放根池上的一些空间,而不是引导环境使用的所有空间,因为快照和克隆在需要块的最后一个快照被销毁之前不会释放空间。但你会得到一些回来。
引导环境利用ZFS快照和克隆。但他们到底是做什么的?查看我们首次安装的主机上的快照。
xxxxxxxxxx# zfs list -t snapshotNAME USED AVAIL REFER MOUNTPOINTzroot/ROOT/default@2016-02-16-08:35:22 25.9M - 479M -该主机有一个快照,以我创建的引导环境命名。默认的引导环境是当前正在运行的环境,因此它不需要快照。现在查看 zroot/ROOT 下的数据集。
xxxxxxxxxx# zfs list -r zroot/ROOTNAME USED AVAIL REFER MOUNTPOINTzroot/ROOT 765M 283G 96K nonezroot/ROOT/10.3-release 457M 283G 457M /每个引导环境都是 zroot/ROOT 下的一个数据集,从源快照克隆。引导环境 default 为 zroot/ROOT/default ,而 10.3-release 引导环境为 zroot/ROOT/10.3-release 。
虽然所有启动环境数据集的 mountpoint 属性都为 / ,但除活动数据集外的每个启动环境数据集中的 canmount 都设置为 off 。如果愿意,可以挂载这些数据集,但您需要指定新的挂载点。
销毁引导环境会销毁关联的快照和克隆。
访问未使用的引导环境的内容的一种方法是检查从中创建引导环境的快照。引导环境可以在隐藏的 /.zfs 目录中访问。这便于快速检查。
如果要以读写方式装载这些引导环境,请使用 beadm mount 命令和引导环境名称。引导环境将以读写方式装入 /tmp 下的位置。
xxxxxxxxxx# beadm mount 10.3-p19Mounted successfully on '/tmp/BE-10.3-p19.DmtRWZGf'操作完成后,可使用 beadm umount 卸载它:
xxxxxxxxxx# beadm umount 10.3-p19Unmounted successfully.可以使用 canmount 和 mountpoint 属性装载和卸载引导环境快照。然而,如果操作不正确,则会将旧的引导环境挂载到正在运行的引导环境的顶部。虽然FreeBSD文件系统是可堆叠的,但更改正在运行的系统上的所有系统二进制文件可能会使您陷入困境。想象一下,由于二进制文件无法与正在运行的内核对话,无法运行 reboot(8) !
注意安全。使用 beadm(8) 中内置的快照装载和卸载功能。
因此,您已经真正地清洗了操作系统。忘记进入多用户模式吧,即使是单用户模式也会溶解为一系列错误消息,这些消息非常模糊,甚至FreeBSD最有经验的内核黑客都认为您的硬件受到了散热器的影响。FreeBSD 10.3及更高版本允许您在加载程序提示符处更改引导环境。这需要控制台访问,但任何其他让您走出这个漏洞的方法也是如此。
引导主机。您将得到一个类似于此的加载程序菜单,以及一些图形。
xxxxxxxxxx +============Welcome to FreeBSD===========+ | | | 1. Boot Multi User [Enter] | | 2. Boot [S]ingle User | | 3. [Esc]ape to loader prompt | | 4. Reboot | | | | Options: | | 5. [K]ernel: kernel (1 of 2) | | 6. Configure Boot [O]ptions... | | 7. Select Boot [E]nvironment... | | | | | +=========================================+选择第七项就会得到一个新的菜单:
xxxxxxxxxx +============Welcome to FreeBSD===========+ | | | 1. Active: | | 2. bootfs: zfs:zroot/ROOT/default | | 3. [P]age: 1 of 1 | | | | Boot Environments: | | 4. 10.3-release | | 5. default | | | +=========================================+选择首选的引导环境。菜单将更新,在空间1中显示所选的环境(标记为 Active)。按 1 返回主菜单,或按 ENTER 启动。您的系统将恢复到已知的工作引导环境,让您有机会了解为什么一切都偏离了正轨。
在过去的几十年里,FreeBSD开发了许多传统做法,特别是使用附加软件包。其中一些是基于FreeBSD敏感性的:MySQL将数据存储在 /var/db/mysql 中。一些基于软件的首选项:PostgreSQL将其记录保存在 /usr/local/pgsql 中。所有这些都可能在使用引导环境时带来问题。
让我们以MySQL为例。目录 /var/db/mysql 是根数据集的一部分。它包含在引导环境中。如果将数据库数据存储在引导环境中,则回退到较旧的引导环境也会将数据库数据恢复到较早的版本。这可能不是你想要的。
其他服务器软件也有同样的问题。
处理这一点并不困难,但它需要您了解您的软件。您有两个选择:更改应用程序数据位置,或在旧的应用程序目录中创建数据集。一旦你了解了自己的需求,两者都会很好地工作。
移动应用程序数据需要为应用程序数据创建数据集,并通知应用程序使用该位置。在这里,我决定将MySQL数据放在 /var/mysql 中。
xxxxxxxxxx# zfs create zroot/var/mysql我现在必须告诉MySQL使用这个数据目录。检查 /usr/local/etc/rc.d/mysql-server 中的变量告诉我,我需要 /etc/rc.conf 中的 mysql_dbdir 选项。
xmysql_dbdir="/var/mysql"我必须将任何现有的数据和配置文件从 /var/db/mysql 移动到 /var/mysql ,然后重新启动服务器。
引导环境仅影响根文件系统数据集。如果要将应用程序数据保留在通常的位置,则必须为该数据创建新的数据集。让我们以PostgreSQL为例。PostgreSQL将其数据存储在 /usr/local/pgsql 中,因此您可以只创建该数据集。
xxxxxxxxxx# zfs create zroot/usr/local/pgsqlcannot create 'zroot/usr/local/pgsql': parent does not exist如果没有 /usr/local 数据集,则无法创建 zroot/usr/local/pgsql 。但如果创建标准的 /usr/local 数据集,则可以将 /usr/local 中的文件从引导环境中拉出,或者将空文件系统覆盖在填充的 /usr/local 目录之上。与 /usr 一样,解决方案是创建一个将 canmount 属性设置为 off 的文件系统,然后创建子数据集。
xxxxxxxxxx# zfs create -o canmount=off zroot/usr/local# zfs create zroot/usr/local/pgsql现在,您有了 /usr/local/pgsql 作为自己的数据集,并且可以在引导环境中安全地运行PostgreSQL。
这两种解决方案都不能解决像Apache这样混乱的软件包。例如,Apache2.4将许多内容粘贴在 /usr/local/www 和 /usr/local/etc/apache24 中。系统管理员应该编辑其中的一些文件,但不是所有文件。这使得ZFS数据集的分离变得复杂。对于Apache和类似的程序,我通常创建一个全新的数据集,如 /var/www ,并将活动网站文件放在那里。
标准 beadm 引导环境管理器仅适用于单个根文件系统数据集。GELI加密磁盘的FreeBSD安装与 beadm 不兼容。
将带有ZFS的默认FreeBSD安装到加密磁盘设备上需要一个未加密的小分区来存储引导内核。默认安装程序为此创建池 bootpool ,并将 /boot 放在 bootpool/boot 中。在正在运行的系统上,/boot 是指向另一个池的符号链接。系统的其余部分进入 zroot 池。
可以在加密磁盘上使用引导环境。您只是没有获得启动环境管理器的便利。在升级系统之前拍摄快照。克隆该快照以创建旧环境。为每个引导环境保留内核的副本。使用 zroot 池的 bootfs 属性更改FreeBSD用作根文件系统的环境。
然而,引导内核需要一个完全不同的过程。在修补内核之前,必须创建以引导环境命名的内核副本。在从10.3-RELEASE升级到10.3-p5之前,您需要将10.3-RELEESE内核从 /boot/kernel 复制到 /boot/kernel.10.3R 。如果必须恢复引导环境,请在加载程序菜单中选择旧内核。
PC-BSD 10确实支持在GELI加密磁盘上使用引导环境,但它们使用GRUB引导加载程序和一些特殊的技巧。
FreeBSD 11.0预计支持从GELI加密的ZFS引导,而无需单独的 bootpool ,从而允许引导环境像在未加密磁盘上一样工作。截至本书出版日期,该功能尚未登陆。
对于大多数FreeBSD ZFS用户,引导环境节省了许多麻烦。让我们继续讨论其他省去你麻烦的方法。