第十一章:复杂安装

FreeBSD存储系统的强大之处不在于单个工具,而在于如何组合它们。

如果有很多FreeBSD机器要安装,可以转去PC-BSD安装程序。PC-BSD允许创建适合装配线部署的安装脚本。

本章适用于偶尔安装机器,并希望能够定制那些超出FreeBSD安装程序允许的安装。

安装到Gmirror

FreeBSD安装程序提供了手动分区硬盘的机会。我们以gmirror安装作为示例来演示。

先决条件

启动计算机必须找到操作系统内核,否则无法启动。BIOS在不熟悉的磁盘上找不到分区,可悲的是,很少有BIOS理解FreeBSD的GEOM类。至少,硬件的BIOS必须能够找到/boot分区并加载内核。

BIOS可以理解单磁盘和镜像磁盘,但无法识别RAID-3、RAID-5、RAID-10或其他更复杂的磁盘冗余协议。

为了克服这一限制,可以在镜像驱动器上放置/boot,然后将/、/usr和所有其他文件放在RAID-5上,或者以其他方式放置。我们将在本章稍后看到一个这样的例子。

FreeBSD安装程序不会为你镜像磁盘,必须自己做。

分区过程

启动安装程序,然后进入安装过程。指定主机名并选择要安装的软件。

在分区阶段,将有机会使用引导方法、手动方法或命令行。对于复杂的安装,需要进入命令行状态。

按以下步骤准备磁盘以成功安装:

分区挂载之后,可以让安装程序继续。安装过程的结尾,升级新的/boot/loader.conf文件使得系统启动时自动挂载gmirror内核模块。

分配分区方案

使用geom disk list或camcontrol devlist命令来识别所有的磁盘。

假设测试机器有两个磁盘,da0和da1。我想镜像它们。

先删除磁盘上的任何分区方案,并分配所需的方案:

现在磁盘准备好用于镜像了。

配置Geoms

现在在两个磁盘上创建一个镜像。这需要先加载gmirror模块,标识一个磁盘,然后插入另一块磁盘到镜像中。

镜像盘将开始同步。可以等它结束,也可以在安装过程结束后等待。或者可以忽略它,继续前进。

创建分区

我希望服务器上有分区,因此需要在镜像geom上有一个GPT表。

这台机器为引导加载程序获得一个512KB的分区,一个8GB的交换分区,5GB的根目录,1GB的/tmp和5GB的/var,其余分配给/usr。

我希望每个分区都有一个GPT标签,所有内容都以最接近的兆字节对齐。

现在可以在镜像中创建文件系统了。

注意,我们将这些分区放置在镜像上,而不是底层磁盘上。当写入镜像的分区表时,gmirror会将其传递到每一个单独磁盘上的相同分区表。

启动计算机在其中一个磁盘上找到GPT分区表,并使用它来查找内核。

即使机器进入单用户模式,镜像设备也会配置并准备就绪。

创建分区表

FreeBSD安装程序使用/tmp/bsdinstall_etc保存临时文件。其中一个临时文件是文件系统表/etc/fstab。

我建议在创建分区后立即创建文件系统表,以便它们在内存中保持新鲜。创建包含以下内容的/tmp/bsdinstall_etc/fstab:

还可以根据需求添加可移动媒体(标记为noauto)或其他设备,或加密交换空间,或网络共享设备。

当安装程序恢复时,它会把此文件复制到已完成的系统上。

启动器

镜像的两个驱动器都需要引导器,以放置其中一个发生故障。通常将此引导加载程序写入镜像,将其放在每一个磁盘上。

镜像将引导器和保护MBR直接复制到底层磁盘上。

创建文件系统

现在在分区创建需要的文件系统。我使用GPT标签取代完整的设备节点:

-j选项激活软更新日志,-L选项套用UFS标签。UFS标签于GPT标签相同。

临时挂载

安装程序希望目标文件系统安装在/mnt下。先挂载新的根分区。

为每个挂载点创建目录:

创建完目录后,将空的文件系统挂载到对应目录上:

至此自定义分区已经准备就绪。

在命令提示符下键入exit返回安装程序,安装程序会将FreeBSD解压缩到磁盘上。

安装后设置

当设置了root密码、配置了时区并添加了初始用户,FreeBSD会询问是否想在系统中打开一个shell进行任何最终的手动更改,回答是。

现在处于已完成安装的chroot中。新机器的根目录不再是/mnt,而是/。

进入/boot目录并创建loader.conf文件,其中应包含以下行:

验证镜像是否已完成同步,然后重启系统。

手动安装FreeBSD

如果在命令行中手动分区磁盘并创建了文件系统,可以选择自己安装FreeBSD文件,而不通过安装程序。

安装内核

FreeBSD需要的文件都在安装介质的/usr/freebsd-dist目录中。现在我们安装base和kernel到新根文件系统中,它挂载在/mnt上。

base和kernel是唯一必须的组件,但可以根据需要从该目录安装其他组件。

在amd64上,建议安装32位库(lib32.txz)。

新安装需要文件系统表,/etc/fstab。建议在创建分区时创建文件系统表。如果是手动安装FreeBSD,则必须将文件系统表复制到新安装中:

或者直接在/mnt/etc/fstab中创建它。

系统现在拥有从硬盘启动所需的一切。它没有用户,没有root密码,也没有配置。这对很多人来说已经足够了,但我们可以做到更好。

高级配置

如果你想让手动安装的机器启动到一切都设置好的状态,可以编辑一些文件,比如/etc/rc.conf文件(安装过程中,它可能位于/mnt/etc/rc.conf)。

有些命令只能在运行中的系统上才能正常工作,比如adduser,它只将用户添加到/etc的密码文件中。这就是调用chroot魔力的时候:

现在已经进入新安装,允许adduser会影响新安装,而不是安装介质。

键入exit退出chroot,然后重新启动以进行新安装。

脚本安装

FreeBSD安装程序使脚本磁盘分区和安装后设置变得相当简单。它仍然需要一些手动步骤和人工交互,但您可以编写复杂的脚本并减少用户错误。同样,如果你有很多服务器要安装,PC-BSD有一个完整的FreeBSD安装自动化工具。

脚本安装带来了两个小挑战:让网络运行和创建实际的脚本。两者都不难。

通过安装介质联网

启动安装介质,当遇到选择执行安装还是转到shell时,请选择shell。这将启动命令提示符。

将安装脚本安装到计算机上的最简单方法是通过网络。这意味着需要一个解析器配置/etc/resolv.conf。安装介质的/etc目录是只读介质,因此无法直接创建。

使用mount_unionfs将目录覆盖在另一个目录上。创建一个/mnt/etc目录,并将其挂载到现有/etc目录上:

现在可以创建/tmp/etc/resolv.conf文件并配置名称服务器(nameserver),它将会出现在/etc目录中。

联网之后使用fetch命令获取安装脚本:

现在,你所需要的就是一个安装脚本了。

安装脚本

安装脚本包括创建geom和文件系统,并将FreeBSD解压到其中所需要的所有命令的列表。下面显示了一个示例脚本。

第一行的-x可以使shell在运行命令时显示信息。

虽然此脚本满足一些人的需求,但可以根据实际环境对齐自定义。

此脚本做的最后一件事时打印镜像状态,提醒我们在重启之前让镜像磁盘完成同步。

此脚本不会添加本地用户或设置root密码,不能在脚本执行到一半时运行chroot命令,然后让脚本继续运行。

如果有必要,可以编写第二个脚本,将其复制到/mnt中,chroot到新系统中,然后运行该脚本。

安装脚本还可以将关键文件系统复制到服务器,以配置SSH和LDAP等服务。

完整的磁盘加密

无法完全加密计算机上的所有内容。每个系统都需要足够的未加密代码来告诉它如何解密加密的驱动器。

在FreeBSD上,使用GELI进行加密,需要一个未加密的/boot目录,其中包含内核和GELI密钥文件。

可以在只读介质(如CD)、可移动介质(如U盘)或主硬盘上的小分区上进行启动。可以加密此启动介质之外的所有内容。

FreeBSD安装程序运行使用主硬盘上的一个小分区,使用单个大型文件系统创建加密的ZFS安装。

如果你需要的不是安装程序给你的东西——比如你想要UFS,或者你想要一个细粒度的ZFS安装——你必须手动安装。

第一个问题时,你希望将未加密的启动驱动器放在哪。可以使用主硬盘上的的小分区或独立的设备,如U盘。1GB未加密的驱动器就够了。

如果想把/boot分区放在只读介质上,比如CD,则需要一些额外的步骤。安装程序需要将文件写入/boot,但不能写入CD-R。如果打算使用只读介质保存/boot,请先使用/boot的闪存驱动器进行安装,完成后再将闪存驱动器上的文件复制到可引导CD上。

假设测试系统有个一256GB驱动器。需要一个4GB交换分区,引导分区未使用的任何剩余空间用于运行加密的FreeBSD安装。

首先从FreeBSD安装介质启动,然后选shell。

独立驱动器分区

测试系统有一个256GB的主硬盘(da0)需要被加密,和另一个8GB的第二个硬盘(da1)不需要被加密。

首先销毁驱动器上所有分区,然后创建新的方案:

现在驱动器已经清除了所有以前的文件系统,并准备好进行GPT分区。

接下来我们将在每个分区上创建两个新分区。未加密的驱动器需要一个引导分区和一个FreeBSD UFS分区。(即使使用ZFS作为主磁盘,/boot也很小,而且大多是静态的,所以这样做没有多大意义。)

使用gpart show命令核查结果。应该有一个引导加载器分区和一个用于未加密文件系统的分区。

现在安装PMBR和GPT引导加载器:

至此,引导驱动器完成了分区。接下来对主驱动器进行分区。

此例中分区3作为交换分区,分区4作为加密设备。分区1和分区2未使用。

现在我们有四个GPT分区分别位于这两个磁盘上:

单磁盘分区

要将所有内容放在一个磁盘上,必须创建四个分区:引导代码分区、/boot分区、加密交换分区、加密文件系统分区。

首先销毁磁盘的现有分区,并为GPT分区做准备。

我们再次使用这个265GB磁盘。

系统需要一个未加密的启动器,包含PMBR和GPT启动代码。

为/boot创建分区2。这个分区只需要1GB空间。我们使用1MB对齐,以便在磁盘的开头有一点额外的空间。

特别希望/boot位于分区2。分区3有4GB空间,用于交换。其余部分用GELI加密。

此时这个磁盘有四个分区:

da0p1——启动分区,标记为boot

da0p2——/boot分区,标记为clear

da0p3——交换分区,标记为swap

da0p4——GELI加密的分区

安装/boot

设置的其余部分归结为配置引导驱动器、配置GELI、创建文件系统以及在磁盘上安装FreeBSD。

我们将首先创建引导驱动器,这样就有了一个放置关键文件的地方。在/media上挂载新分区,并将安装/boot目录复制到其中。

现在应该有了一个填充的/mnt/boot目录。进入该目录,创建一个以你要加密的分区命名的密钥文件:

现在在/mnt/boot/loader.conf中配置启动器。必须告诉启动器加载GELI内核模块并附加GELI设备。

还需要在loader.conf中添加一条。FreeBSD默认从加载内核的任何分区加载根文件系统,但可以覆盖此设置。告诉FreeBSD使用vfs.root.mountfrom可调参数从/dev/daop4.eli上的UFS文件系统挂载其根文件系统:

未加密分区已经完成。一旦启动系统,并且知道一切正常,就可以将这些文件复制到ISO中并刻录到CD上。

安装加密分区

现在有了一个引导分区,可以在加密设备上安装FreeBSD。首先随机化GELI分区的内容,这样入侵者就无法轻易确定哪些块是加密的,哪些块是随机垃圾:

初始化GELI设备,并将密钥文件附加到未加密的分区上,使用-b选项告诉GELI它应该以单用户模式连接此设备。

现在在加密设备上创建一个文件系统,并将其挂载到/mnt上:

现在有了文件系统,可以在上面安装FreeBSD文件。参阅本章前面的“手动安装FreeBSD”。

与未加密的系统一样,加密的根分区需要一个文件系统表/etc/fstab。

文件系统表必须列出当前根分区、交换分区以及(可选)挂载未加密分区的位置。

如果你想将未加密的驱动器挂载到某个地方,请为它创建一个目录,此处我们将其挂载在/clear。也可以将其挂载到/boot,或者将/boot设置为符号链接。

安装后设置和管理

可以引导到加密的文件系统,但系统没有用户,也没有配置。

可以像其他手动安装一样,自己手动完成所有操作。必须从头开始创建/etc/rc.conf,并运行adduser来创建用户账户。

使用只读介质运行/boot会使系统维护复杂化。FreeBSD的升级工具,如freebsd-update和make installkernel,不能写入只读介质。系统从未加密的驱动器启动内核,而不是GELI分区/boot/kernel中的内核。

建议将只读介质挂载到/boot以外的位置。这可以使升级正常工作。

当更改内核时,无论是通过构建自定义内核还是升级,都必须手动更新启动介质。

这种加密程度将保护数据在偶然被盗的情况下不被泄露。如果需要更强的保护,请参阅第七章。

扩展虚拟磁盘

大多数虚拟化系统都有扩展提供给访客的虚拟磁盘的选项。

首先备份系统。任何时候,当你摆弄磁盘或文件系统时,数据丢失都是非常真实的风险。

以下示例:

这个VM在磁盘尾部有320GB的剩余空间。但为什么扩展磁盘1会损坏GPT表呢?

GPT将分区表存储在磁盘的前面。它还在磁盘末尾保留一个备份副本。

移动磁盘末端不会破坏备份副本,但会将其丢弃在错误的位置。

使用gpart recover创建新的磁盘末端(end-of-disk)备份:

这将放置一个新的备份副本并清除损坏的警告。

现在决定如何处理这个空间。

最简单的方法是在该空间中创建一个新分区并将一些文件移动到其中。

首先,决定这些分区的排列方式。这个系统有三个分区:引导分区、根分区和交换分区。磁盘扩展后还是这三个分区,以及磁盘末尾的320GB空白空间。

无法将根分区扩展到空白空间,因为交换空间挡在中间。

常见的建议是把交换空间放在磁盘的前部,因为那里是磁盘上最快的部分。但这个常见的建议无关紧要。虚拟化系统不在意底层磁盘,甚至完全不知道磁盘上最快的那部分实际上在哪里。

最简单的方法是将交换空间移动到磁盘的末尾,并扩展根分区以填充空白的空间,最终得到:

gpart命令不允许在磁盘末尾创建分区。

每个新分区都会直接出现在任何现有分区之后。但它允许创建一个无实际意义的填充分区。

新的空白分区显示为320GB,但这里是四舍五入的。在空白空间中创建一个315GB的临时分区,并给它一个易识别的标记:

现在使用剩余空间创建一个交换分区:

此时磁盘结构看起来是这样的:

编辑/etc/fstab使用新的交换分区替代旧的:

可以重启以激活新的交换空间。也可以使用以下命令启用它:

系统交换空间看起来像这样:

旧交换空间是/dev/label/swap0,以GEOM标签标记;新交换空间是/dev/gpt/swap0,以GPT标签标记。

名称无所谓,关键是不要搞混。

现在关闭旧的交换空间:

旧的交换空间不用了,所以可以把它解脱出来。仔细检查gpart show,确定哪个是要删除的。然后删除掉不用的分区:

再次检查:根文件系统是否还在?FreeBSD有防止删除挂载分区的保护措施,但无论如何都要检查。

交换空间位于磁盘尾部,符合预期。中间有317GB自由空间,位于根文件系统之后。

再次检查你的备份,确定你有重建此服务器所需的一切。然后使用gpart resize扩展根文件系统,不用指定大小,新分区将扩展以填充所有可用的连续空间:

现在看看都有啥:

根分区现在是635GB,成功了。

嗯,接近成功。分区更大,但分区上的文件系统还是只有318GB。

扩展UFS文件系统,使用growfs命令填充其分区。

在FreeBSD9及更早版本中,growfs仅适用于未安装的文件系统。在FreeBSD10及以后的版本中,growfs适用于启用了软更新的已挂载文件系统。

通过设备节点或GPT标签标识文件系统:

如果分区没有使用软更新,请重启到单用户模式,并在挂载之前扩展文件系统。

扩展文件系统后,重新应用GPT标签:

到此应该已经设置好了,但建议重启系统,以确保没有任何损坏。

现在分区看起来应该像这样:

所有可用磁盘空间现在都在使用中,任务完成。