Two Pi R 平方:Web 服务器

作者:Kyle Rankin

在我上一篇文章中,我讨论了即使单个 Raspberry Pi 不是那么冗余,但两个 Pi 就是冗余的。我描述了如何使用 GlusterFS 集群文件系统将两个 Raspberry Pi 设置为容错文件服务器。现在我们有了跨两个 Raspberry Pi 共享的冗余、容错存储,我们可以将其作为构建其他容错服务的基础。在本文中,我将描述如何在我们已有的 Raspberry Pi 基础上设置一个简单的 Web 服务器集群。

以防您没有看过第一篇专栏文章,我将回顾上个月的设置。我有两个 Raspberry Pi:Pi1 和 Pi2。Pi1 的 IP 地址为 192.168.0.121,Pi2 的 IP 地址为 192.168.0.122。我已将它们设置为 GlusterFS 集群,它们之间共享一个名为 gv0 的卷。我还将此共享卷挂载到两台机器的 /mnt/gluster1 上,以便它们可以同时访问共享存储。最后,我进行了一些故障测试。我将此共享存储挂载到第三台机器上,并启动了一个简单的脚本,该脚本将日期写入共享存储上的一个文件。然后,我尝试分别关闭每个 Raspberry Pi 以确认存储保持运行。

现在我已经启动并测试了存储,我想将这些 Raspberry Pi 设置为容错 Web 集群。诚然,Raspberry Pi 没有快速的处理器或大量的 RAM,但它们仍然有足够的资源充当静态文件的 Web 服务器。虽然我将要给出的示例非常简单,但这是故意的——其想法是一旦您验证了简单的静态站点可以托管在冗余的 Raspberry Pi 上,您就可以自己扩展更复杂的内容。

安装 Nginx

虽然我也很喜欢 Apache,但对于资源有限的 Web 服务器服务静态文件,像 nginx 这样的东西具有正确的功能、速度和低资源消耗的结合,使其成为该站点的理想选择。Nginx 在默认的 Raspbian 软件包存储库中可用,所以我登录到集群中的第一个 Raspberry Pi 并运行


$ sudo apt-get update
$ sudo apt-get install nginx

安装 nginx 后,我在 /mnt/gluster1/cluster 中创建了一个新的基本 nginx 配置,其中包含以下配置


server {
  root /mnt/gluster1/www;
  index index.html index.htm;
  server_name twopir twopir.example.com;

  location / {
        try_files $uri $uri/ /index.html;
  }
}

注意:我决定将服务命名为 twopir,但您可以将其更改为您想用于该站点的任何主机名。另请注意,我将文档根目录设置为 /mnt/gluster1/www。这样,我可以将所有静态文件放在共享存储上,以便可以从任一主机访问它们。

现在我有了 nginx 配置,我需要将默认的 nginx 配置移开,并将此配置设置为默认配置。在 Debian 下,nginx 组织其文件的方式很像 Apache,带有 sites-available 和 sites-enabled 目录。虚拟主机配置存储在 sites-available 中,sites-enabled 包含指向您要启用的那些配置的符号链接。以下是我在第一个 Raspberry Pi 上执行的步骤


$ cd /etc/nginx/sites-available
$ sudo ln -s /mnt/gluster1/cluster .
$ cd /etc/nginx/sites-enabled
$ sudo rm default
$ sudo ln -s /etc/nginx/sites-available/cluster .

现在我有了配置,但没有文档根目录来提供服务。下一步是创建 /mnt/gluster1/www 目录并将默认的 nginx index.html 文件复制到其中。当然,您可能想要在此处创建您自己的自定义 index.html 文件,但复制文件是一个好的开始


$ sudo mkdir /mnt/gluster1/www
$ cp /usr/share/nginx/www/index.html /mnt/gluster1/www

文档根目录就位后,我可以重启 nginx 服务


$ sudo /etc/init.d/nginx restart

现在我可以转到我的 DNS 服务器,并确保我有一个指向我的第一个 Raspberry Pi(地址为 192.168.0.121)的 twopir 的 A 记录。当然,在您的情况下,您将使用您的主机名和 IP 更新您的 DNS 服务器。现在我将打开浏览器中的 http://twopir/ 并确认我看到了默认的 nginx 页面。如果我查看 /var/log/nginx/access.log 文件,我应该看到我访问过该页面的证据。

一旦我验证了 Web 服务器在第一个 Raspberry Pi 上工作,就该在第二个 Raspberry Pi 上复制一些工作了。因为我将配置存储在共享的 GlusterFS 存储上,所以我真正需要做的就是安装 nginx,创建适当的符号链接以启用我的自定义 nginx 配置,然后重启 nginx


$ sudo apt-get update
$ sudo apt-get install nginx
$ cd /etc/nginx/sites-available
$ sudo ln -s /mnt/gluster1/cluster .
$ cd /etc/nginx/sites-enabled
$ sudo rm default
$ sudo ln -s /etc/nginx/sites-available/cluster .
$ sudo /etc/init.d/nginx restart
两个 DNS A 记录

所以,现在我有两个可以托管相同内容的 Web 主机,但此过程的下一步是使此设置冗余的重要部分。虽然您绝对可以设置像 heartbeat 这样的服务,并使用某种浮动 IP 地址,该地址根据哪个 Raspberry Pi 启动而从一个 Raspberry Pi 更改到另一个 Raspberry Pi,但更好的方法是为同一主机名使用两个 DNS A 记录,它们指向每个 Raspberry Pi 的 IP。有些人将此称为 DNS 负载均衡,因为默认情况下,对具有多个 A 记录的主机名的 DNS 查找每次发出请求时都会以随机顺序返回结果


$ dig twopir.example.com A +short
192.168.0.121
192.168.0.122
$ dig twopir.example.com A +short
192.168.0.122
192.168.0.121

由于结果以随机顺序返回,客户端应该在不同的主机之间均匀发送,实际上,多个 A 记录确实会产生一种负载均衡形式。然而,我对主机拥有多个 A 记录感兴趣的更多的是 Web 浏览器如何处理故障。当浏览器获得 Web 主机的两个 A 记录,并且第一个主机不可用时,浏览器几乎会立即故障转移到列表中的下一个 A 记录。这种故障转移速度非常快,在许多情况下用户感觉不到,并且肯定比您在传统 heartbeat 集群中可能看到的故障转移快得多。

因此,转到您用于添加第一个 A 记录的同一 DNS 服务器,并添加第二个记录,该记录引用相同的主机名,但引用不同的 IP 地址——集群中第二个主机的 IP 地址。保存更改后,执行像我上面执行的 dig 查询,您应该会得到两个 IP 地址。

一旦您设置了两个 A 记录,集群基本上就可以使用了,并且是容错的。打开两个终端并登录到每个 Raspberry Pi,然后运行 tail -f /var/log/nginx/access.log,以便您可以观看 Web 服务器访问,然后在 Web 浏览器中加载您的页面。您应该在一个服务器的访问日志中看到活动,但在另一个服务器的访问日志中看不到活动。现在刷新几次,您会注意到您的浏览器应该坚持使用单个 Web 服务器。在您确信您的请求已成功发送到该服务器后,在多次刷新网页的同时重启它。如果您看到任何闪烁,那也应该是短暂的,因为一旦 Web 服务器掉线,您应该会被重定向到第二个 Raspberry Pi,并且能够看到相同的索引页面。您还应该在访问日志中看到活动。一旦第一个 Raspberry Pi 从重启中恢复,您可能甚至无法从 Web 浏览器的角度注意到。

尝试一次重启一个 Raspberry Pi,您应该看到,只要您有一个服务器可用,站点就会保持运行。虽然这是一个简单的示例,但您现在要做的就是将您想要提供的任何其他静态 Web 内容复制到 /mnt/gluster1/www 中,并享受您的新型低成本容错 Web 集群。

Kyle Rankin 是 Linux Journal 的技术编辑和专栏作家,也是 Purism 的首席安全官。他是 Linux Hardening in Hostile NetworksDevOps TroubleshootingThe Official Ubuntu Server BookKnoppix HacksKnoppix Pocket ReferenceLinux Multimedia HacksUbuntu Hacks 的作者,也是许多其他 O'Reilly 书籍的贡献者。Rankin 经常就安全和开源软件发表演讲,包括在 BsidesLV、O'Reilly Security Conference、OSCON、SCALE、CactusCon、Linux World Expo 和 Penguicon 上。您可以在 @kylerankin 上关注他。

加载 Disqus 评论