Two Pi R
虽然很多人对 Raspberry Pi 的硬件破解可能性感到兴奋,但最让我感兴趣的事情之一是,它本质上是一个小型低功耗 Linux 服务器,我可以用来替换我已经在家中使用的其他 Linux 服务器。在之前的专栏中,我谈到了使用 Raspberry Pi 来替换控制我的啤酒冰箱的服务器,以及在奥地利托管 Raspberry Pi。在奥地利托管 Raspberry Pi 之后,我开始思考使用如此多单点故障的设备作为我依赖的服务器的优点和缺点,所以我开始思考处理单点故障的方法。当您看到 “Two Pi R” 时,您可能会认为 R 代表圆的半径。对我来说,它代表冗余。我的结论是,虽然一个 Pi 不是冗余的,但两个 Pi 是冗余的。
因此,在本文中,我将为使用一对 Raspberry Pi 设置冗余服务构建基础。我首先使用 GlusterFS 设置基本的集群网络文件系统。在后续文章中,我将继续介绍如何利用此共享存储来设置其他冗余服务。当然,虽然我在本文中使用的是 Raspberry Pi,但这些相同的步骤也应该适用于其他硬件。
配置 Raspberry Pi首先,我准备了两张 SD 卡,并从官方 Raspberry Pi 下载页面下载了最新版本的默认 Raspberry Pi 发行版,即基于 Debian 的 Raspbian,加载到 SD 卡中。我按照文档设置了镜像,然后在连接到电视的情况下启动了两个 Raspberry Pi,以确保操作系统启动并且 SSH 设置为默认启动(应该是这样的)。您可能还需要使用 raspi-config 工具来扩展根分区以填充 SD 卡,因为您会希望所有额外的空间都用于冗余存储。在我确认可以远程访问 Raspberry Pi 后,我将它们从电视旁边移开,放到交换机旁边,并在未连接显示器的情况下重启了它们。
默认情况下,Raspbian 将通过 DHCP 获取其网络信息;但是,如果您想要设置冗余服务,您会希望您的 Raspberry Pi 每次启动时都保持相同的 IP。在我的例子中,我更新了我的 DHCP 服务器,以便每次 Raspberry Pi 启动时都为其分配相同的 IP,但您也可以编辑 Raspberry Pi 上的 /etc/network/interfaces 文件并更改
iface eth0 inet dhcp
改为
auto eth0
iface eth0 inet static
address 192.168.0.121
netmask 255.255.255.0
gateway 192.168.0.1
当然,请修改网络信息以匹配您的个人网络,并确保每个 Raspberry Pi 使用不同的 IP。我还更改了每个 Raspberry Pi 的主机名,以便我在登录时可以区分它们。为此,只需以 root 身份编辑 /etc/hostname,并将主机名更改为您想要的名称。然后,重启以确保每个 Raspberry Pi 都使用正确的网络设置和主机名启动。
配置 GlusterFS 服务器GlusterFS 是一个用户空间集群文件系统,我选择它用于此项目是因为它使配置共享网络文件系统变得非常简单。首先,选择一个 Raspberry Pi 作为您的主节点。您需要做的少量初始设置将从主节点完成,即使一旦设置好,节点应该会自动故障转移。以下是有关我的环境的信息
Master hostname: pi1
Master IP: 192.168.0.121
Master brick path: /srv/gv0
Secondary hostname: pi2
Secondary IP: 192.168.0.122
Secondary brick path: /srv/gv0
在执行任何其他操作之前,请登录到每个 Raspberry Pi,并安装 glusterfs-server 软件包
$ sudo apt-get install glusterfs-server
GlusterFS 将其文件存储在它所谓的 brick 中。brick 是服务器上的一个目录路径,您将其预留给 gluster 使用。然后,GlusterFS 组合 brick 以创建客户端可访问的卷。GlusterFS 可能会将卷的数据条带化到多个 brick 中,因此,虽然 brick 可能看起来像一个包含文件的标准目录,但一旦您开始将其与 GlusterFS 一起使用,您将希望仅通过客户端修改它,而不是直接在文件系统本身上修改。在 Raspberry Pi 的情况下,我决定在两个 Raspberry Pi 上都创建一个名为 /srv/gv0 的新目录作为我的第一个 brick
$ sudo mkdir /srv/gv0
在本例中,我将共享我的标准 SD 卡根文件系统,但在您的情况下,您可能需要更多存储空间。在这种情况下,将 USB 硬盘驱动器连接到每个 Raspberry Pi,确保磁盘已格式化,然后将它们挂载在 /srv/gv0 下。只需确保您更新 /etc/fstab,以便它在启动时挂载您的外部驱动器。brick 不一定需要在相同的目录路径上或具有相同的名称,但一致性并没有坏处。
在每个 Raspberry Pi 上都提供 brick 目录并且已安装 glusterfs-server 软件包后,请确保两个 Raspberry Pi 都已通电。然后,登录到您认为是主节点的任何节点,并使用 gluster peer probe
命令告诉主节点信任您传递给它的 IP 或主机名作为集群的成员。在本例中,我将使用我的辅助节点的 IP,但如果您很高级并且设置了 DNS,您也可以使用其主机名代替
pi@pi1 ~ $ sudo gluster peer probe 192.168.0.122
Probe successful
现在我的 pi1 服务器 (192.168.0.121) 信任 pi2 (192.168.0.122),我可以创建我的第一个卷,我将其命名为 gv0。为此,我从主节点运行 gluster volume create
命令
pi@pi1 ~ $ sudo gluster volume create gv0 replica 2
↪192.168.0.121:/srv/gv0 192.168.0.122:/srv/gv0
Creation of volume gv0 has been successful. Please start
the volume to access data.
让我们稍微分解一下这个命令。第一部分 gluster volume create
告诉 gluster 命令我将要创建一个新卷。下一个参数 gv0
是我想为卷分配的名称。该名称是客户端稍后将用来引用卷的名称。之后,replica 2
参数配置此卷使用复制而不是在 brick 之间条带化数据。在本例中,它将确保任何数据都复制到两个 brick 上。最后,我定义了我想用于此卷的两个单独的 brick:192.168.0.121 上的 /srv/gv0 目录和 192.168.0.122 上的 /srv/gv0 目录。
现在卷已创建,我只需要启动它
pi@pi1 ~ $ sudo gluster volume start gv0
Starting volume gv0 has been successful
卷启动后,我可以使用任一节点上的 volume info
命令查看其状态
$ sudo gluster volume info
Volume Name: gv0
Type: Replicate
Status: Started
Number of Bricks: 2
Transport-type: tcp
Bricks:
Brick1: 192.168.0.121:/srv/gv0
Brick2: 192.168.0.122:/srv/gv0
配置 GlusterFS 客户端
现在卷已启动,我可以从任何支持 GlusterFS 的客户端将其挂载为 GlusterFS 类型的文件系统。但是,首先,我希望从我的两个 Raspberry Pi 上挂载它,因为我希望它们能够自己写入卷。为此,我将在每个 Raspberry Pi 上的文件系统中创建一个新的挂载点,并使用 mount 命令将卷挂载到其上
$ sudo mkdir -p /mnt/gluster1
$ sudo mount -t glusterfs 192.168.0.121:/gv0 /mnt/gluster1
$ df
Filesystem 1K-blocks Used Available Use% Mounted on
rootfs 1804128 1496464 216016 88% /
/dev/root 1804128 1496464 216016 88% /
devtmpfs 86184 0 86184 0% /dev
tmpfs 18888 216 18672 2% /run
tmpfs 5120 0 5120 0% /run/lock
tmpfs 37760 0 37760 0% /run/shm
/dev/mmcblk0p1 57288 18960 38328 34% /boot
192.168.0.121:/gv0 1804032 1496448 215936 88% /mnt/gluster1
你们中更吹毛求疵的读者可能会对自己说,“等一下,如果我在这里指定了一个特定的 IP 地址,当 192.168.0.121 宕机时会发生什么?” 事实证明,此 IP 地址仅用于拉取卷中使用的 brick 的完整列表,从那时起,将使用冗余 brick 列表来访问卷。
挂载文件系统后,尝试创建文件,然后查看 /srv/gv0。您应该能够看到(但再次强调,不要触摸)您从群集中两个节点上的 /srv/gv0 brick 上的 /mnt/gluster1 创建的文件
pi@pi1 ~ $ sudo touch /mnt/gluster1/test1
pi@pi1 ~ $ ls /mnt/gluster1/test1
/mnt/gluster1/test1
pi@pi1 ~ $ ls /srv/gv0
test1
pi@pi2 ~ $ ls /srv/gv0
test1
在您满意可以挂载卷后,通过将以下条目添加到 Raspberry Pi 上的 /etc/fstab 文件使其永久化
192.168.0.121:/gv0 /mnt/gluster1 glusterfs defaults,_netdev 0 0
请注意,如果您还想从网络上的其他客户端访问此 GlusterFS 卷,只需为您的发行版安装 GlusterFS 客户端软件包(对于基于 Debian 的发行版,它被称为 glusterfs-client),然后创建一个挂载点并执行与我上面列出的相同的 mount 命令。
测试冗余现在我已经有了一个冗余文件系统,让我们对其进行测试。由于我想确保我可以关闭两个节点中的任何一个节点,并且仍然可以访问文件,因此我配置了一个单独的客户端来挂载此 GlusterFS 卷。然后我在卷内创建了一个名为 glustertest 的简单脚本
#!/bin/bash
while [ 1 ]
do
date > /mnt/gluster1/test1
cat /mnt/gluster1/test1
sleep 1
done
此脚本在无限循环中运行,只是将当前日期复制到 GlusterFS 卷中的一个文件中,然后将其 cat 回屏幕。一旦我使文件可执行并运行它,我应该看到大约每秒钟弹出一个新日期
# chmod a+x /mnt/gluster1/glustertest
root@moses:~# /mnt/gluster1/glustertest
Sat Mar 9 13:19:02 PST 2013
Sat Mar 9 13:19:04 PST 2013
Sat Mar 9 13:19:05 PST 2013
Sat Mar 9 13:19:06 PST 2013
Sat Mar 9 13:19:07 PST 2013
Sat Mar 9 13:19:08 PST 2013
我注意到偶尔输出会跳过一秒,但在这种情况下,我认为这只是 date 命令并非每次都精确地每秒执行一次的功能,因此偶尔运行循环所需的额外亚秒会累积起来。
在我启动脚本后,我登录到第一个 Raspberry Pi 并键入 sudo reboot
以重启它。脚本继续运行良好,如果在此过程中有任何小故障,我也无法将其与我之前看到的偶尔跳过一秒的情况区分开来。一旦第一个 Raspberry Pi 重新启动,我在第二个 Raspberry Pi 上重复了重启,只是为了确认我可以丢失任一节点并且仍然可以正常工作。考虑到这仅用了几个命令,这种冗余还不错。
就这样,您现在已经为跨两个 Raspberry Pi 的冗余文件存储奠定了基础。在我的下一篇专栏文章中,我将在此基础上构建一个新的冗余服务,该服务将利用共享存储。