At the Forge - 服务器迁移与灾难

作者:Reuven M. Lerner

在系统管理的世界中,经验至关重要。经历过糟糕的硬件、破坏性的软件问题和安全漏洞的系统管理员,更有可能制定有效的备份策略、安全策略和灾难恢复计划。问题不在于灾难是否会发生在您的服务器上,而在于灾难何时发生以及以何种形式发生。

我写这篇文章时是 2003 年 8 月中旬,距离我将自己的服务器 (lerner.co.il) 迁移到一个新的虚拟托管设施不到一周。而且,这篇专栏文章的大部分是在纽约市停电期间写的,我原本计划在那里参加几个小时的商务会议——结果却亲身体验了一场大规模的技术灾难。哦,当我不忙于迁移服务器或坐在黑暗中时,我还在芝加哥搬到了新公寓,因此有将近一周的时间没有互联网连接。

因此,本月,我们将暂时暂停讨论 Bricolage 和其他内容管理软件,转而考虑如何处理 Web/数据库站点的服务器迁移和灾难计划。当然,每个站点和服务器都是不同的,应该给予个别关注,以便进行最佳的规划。但是,只要稍加考虑,将您的服务器从一个位置移动到另一个位置、处理灾难性的硬件或软件故障,甚至像今年夏天美国东北部经历的那样,在大规模灾难面前运行,应该都不会太困难。

服务器迁移

在过去的几年里,我已经多次迁移我的服务器,每次的体验都比前一次更加顺利。老实说,迁移到新机器不需要困难或痛苦,但确实需要仔细计划。每一步都需要假设您在某个时候需要回滚。

从一台机器迁移到另一台机器的最简单服务器类型是静态网站或使用基本 CGI 程序的网站。在这种情况下,您只需要问几个问题

  • Apache 配置是否包含您使用的模块?如果您是 mod_rewrite 的重度用户,或者您喜欢 mod_speling(是的,只有一个 l)的好处,您应该仔细检查以确保这些模块可用。如果它们是静态编译到您的服务器中的,运行httpd -l会列出它们。但是,如果它们是作为动态模块 (DSO) 编译的,则应在 Apache 安装的 libexec 子目录中检查,其中放置了可用的 DSO。每个 DSO 都可以通过在 Apache 配置文件中包含适当的 LoadModule 指令来选择性地加载。

  • Apache 以什么用户和组运行?系统管理员对于 Apache 应该以什么用户和组 ID 运行有不同的看法。有些人使用默认设置,以 nobody 用户身份运行它。其他人(像我一样)更喜欢创建一个特殊的 Apache 用户和组,并在必要时将用户添加到 apache 组中。还有一些人使用 Apache 中的 suexec 功能,编译它使其可以作为一个或多个用户运行。在任何情况下,请确保您在新服务器上选择的 Apache 用户/组配置已在 /etc/passwd 和 /etc/group 以及 Apache 自己的配置文件中设置。

  • DocumentRoot 在哪里?默认情况下,Apache 假定 DocumentRoot 在 /usr/local/apache/htdocs 中。此默认值可以使用 Apache 配置文件中的 DocumentRoot 指令进行更改,具体取决于您运行的操作系统或发行版。如果您使用的是 RPM 版本的 Apache,就像 Red Hat 风格的发行版一样,DocumentRoot 可能在 /var/www 或另一个目录中。这不应影响您的程序和文档中的 URL,但在假设目标位置正确之前,您应该仔细检查要复制文件的目录。

  • 您的 CGI 程序依赖于哪些语言和模块?如果您的站点使用 CGI 程序,那么至少其中一个程序可能依赖于某种外部模块或库。CGI.pm,用于 CGI 程序的 Perl 模块,多年来已包含在 Perl 发行版中,但它仍在定期更新。因此,如果您依赖于最新版本的功能,则必须仔细检查。这适用于您使用的其他模块;我的一位客户正在使用旧版本的 Perl Storable 模块,并且(以惨痛的方式)发现升级到最新版本会在与旧系统通信时破坏兼容性。

DNS

任何服务器迁移的关键环节都是移动 DNS 记录的过程。虽然人们更喜欢使用名称,例如 www.lerner.co.il,但网络连接使用数字 IP 地址,例如 69.55.225.93。将人类可读的名称转换为计算机可用的数字是 DNS(域名系统)的作用。智能地操作 DNS 记录是任何服务器转移的关键部分。

DNS 的主要问题不是主机到 IP 的转换,而是 DNS 结果会被缓存的事实。毕竟,您希望避免有人发出的每个 HTTP 请求都向您的服务器发出 DNS 请求。此类请求将给您的服务器带来不必要的负载,并会不必要地延迟 HTTP 请求的服务。

因此,当您发出 DNS 请求时,您实际上并不是向原始的权威服务器询问答案。相反,您是在向本地 DNS 服务器询问答案。如果它可以从其最近结果的缓存中提供答案,它将这样做,而无需转向主服务器。换句话说,nslookup www.lerner.co.il对您的 ISP 的 DNS 服务器执行 DNS 请求。该服务器可能会从其缓存返回结果,或者它可能会转向 lerner.co.il 域的权威服务器。

因此,当您将服务器从一台机器移动到另一台机器时,您需要将 DNS 服务器上的 TTL(生存时间)设置降低到一个较低的数字,以便缓存此信息的 DNS 服务器不会返回错误的答案。我发现将 TTL 降低到 300 秒(五分钟)就足够了。一旦系统完全迁移完成,您可以将 TTL 增加到一个更典型的值,例如六个小时,以减少 DNS 服务器上的负载。

如果您要将 HTTP 服务器从一个提供商迁移到另一个提供商,以下是您可以执行的成功迁移的概要

  • 确保您的新提供商的 DNS 服务器能够并且愿意使用您当前的 IP 地址和主机名提供 DNS 服务(正向和反向)。也就是说,您的新提供商的 DNS 服务器应该将人们指向您的旧提供商。将 TTL 设置为五分钟。

  • 更新您域名的 WHOIS 记录,表明您的新提供商是权威 DNS 服务器。这可能需要一两天才能在整个 DNS 系统中传播。如果您的新 DNS 服务器提供的结果与旧服务器相同,则判断事情是否奏效的唯一方法是执行 WHOIS 查询或使用nslookup -type=ns yourdomain.com.

  • 一旦 WHOIS 记录更新,就开始迁移。确保您需要的所有软件都已正确配置,所有模块都已正确设置,并且 DNS 服务器已更新。如果您的新 DNS 服务器没有响应对您域名的查询,当 WHOIS 记录指向新服务器作为权威时,您将陷入困境。

  • 当一切看起来都相同时(从旧系统到新系统运行 rsync 是确保它相同的好方法),切换 DNS 定义,使主机名解析为新的 IP 地址,而不是旧的 IP 地址。

根据您运行的服务器类型,您可能需要关闭旧系统上的 HTTP 服务器,以减少切换可能造成的混乱。例如,在切换 DNS 之前关闭旧的 HTTP 服务器可确保日志文件没有任何重叠,从而允许您将它们附加在一起并使用 Webalizer 或 Analog 进行适当的查看。

在这个阶段,一切都应该在新系统上正常工作。但是,您应该尽可能多地检查链接,尤其是那些调用 CGI 程序、服务器端包含和非标准模块的链接,或者那些需要不寻常权限的链接。与往常一样,您的 HTTP 服务器的错误日志是您在此过程中最好的朋友;如果事情出错,您可以查阅错误日志以查看发生了什么。

数据库

当然,以上所有假设都基于您正在处理一个相对简单的站点。然而,大多数现代网站都在某个地方包含关系数据库,原因有很多。它们用于一致性和灵活性,以及开发速度和易于调试和使用的常用范例的结合。

关系数据库将信息存储在一个或多个表中,通常分组到一个数据库中。(是的,说一个数据库服务器包含一个或多个数据库,而每个数据库又包含一个或多个表,这有点令人困惑,但事实就是如此。)要将数据库从一个系统移动到另一个系统,您需要移动数据库模式(表、视图和函数定义)和数据本身。当然,数据库通常由特定的数据库用户(通常与 UNIX 用户不同)拥有,并且对其设置了特定的权限。

如果您的网站包含数据库,那么您需要将该数据库从旧系统移动到新系统,包括所有者和权限相关的信息。您如何做到这一点取决于您使用的数据库以及是否涉及任何技巧。

使用 ISAM/MyISAM 表(默认且仍然是最流行的选项)的 MySQL 数据库可以简单地从一个 MySQL 系统复制到另一个 MySQL 系统。通常,与数据库关联的所有文件都位于 /var/lib/mysql 下以数据库名称命名的目录中。因此,您可以通过将目录 /var/lib/mysql/foo(包括它可能包含的任何文件)复制到新系统上的 /var/lib/mysql/foo 来复制 foo 数据库。(确保在执行此操作之前关闭数据库。)在新系统上启动服务器,它应该可以正常工作。

PostgreSQL 的情况并非如此简单,它以低级二进制格式跟踪数据库模式和数据。使用 tar 或 rsync 复制 PostgreSQL 数据库极不可能奏效——即使奏效,也可能涉及大量数据损坏,甚至可能导致后端数据库服务器崩溃。相反,您应该使用 pg_dump 工具,该工具允许您将 PostgreSQL 数据库转换为纯文本格式的一组 CREATE、INSERT 和 COPY 语句。例如

pg_dump -U mydb mydb > /tmp/mydb-dump.txt

命令-U mydb部分表示我们要使用 mydb 数据库用户。您可能需要替换不同的用户名。然后,您可以使用以下命令将转储的输出放入工作数据库中

$ createdb -U mydb mydb2
$ psql -U mydb mydb2 < /tmp/mydb-dump.txt

执行这两个命令后,将有两个数据库(mydb 和 mydb2)可用,都由 mydb 用户拥有。

MySQL 使处理这种情况变得容易,因为它内置了主/从系统。一个数据库可以是主数据库,接受所有 SQL 命令和查询,另一个数据库可以跟随,允许您在发生灾难性故障时用从数据库替换主数据库。

停电情况...

正如我之前提到的,我很“幸运”地在今年 8 月美国和加拿大发生大规模停电期间身处纽约市。具有讽刺意味的是,停电发生在我参观一位潜在客户的服务器机房大约一个小时后,他在那里演示了他的公司如何将其所有数据备份到康涅狄格州的远程位置。(毕竟,纽约市和康涅狄格州都受到影响的可能性有多大?至少,那是我在停电前一小时点头表示赞同时的想法。)

如果您像我一样,停电不会影响您的服务器,因为它们位于纽约市以外。大多数托管设施都有备用发电机,可以在紧急情况下处理设施的大部分或全部电力需求。

但是,如果您的服务器位于您的办公室中,或者您仅使用简单的 UPS 来确保它们继续运行,那么服务器可能会在像我们在 8 月中旬看到的那种停电期间不可用,这种停电在东北部某些地区持续了 48 小时以上。如果您的服务器对您的业务至关重要,您可能需要认真考虑将其迁移到托管设施。

但是即使是托管服务器也会崩溃并离线;在过去的几年里,我可以从个人经验中告诉你这一点。这意味着如果您依赖于您的服务器,您应该定期备份它。此外,您应该将其持续迁移到另一个物理位置的服务器,最好由不同的公司托管。但是,差异应该仅限于此——您希望软件配置尽可能相似。如果您对服务器上的所有 HTML 页面、模板、软件库和 CGI 程序使用 rsync,并类似地自动化第二个服务器上的数据库转储和还原,那么第二个服务器应该与第一个服务器几乎完全相同,并且应该随时可以上线。

您甚至可以更进一步,同时使用两个服务器。当然,这是一项更加困难的任务,因为它要求您要么使用单个数据库服务器(创建一个单点故障),要么以频繁的间隔同步数据库。但这是完全有可能的,尤其是在主要为静态的站点上,正如我们从 Akamai 的成功中知道的那样,Akamai 在世界各地拥有庞大的冗余服务器阵列。站点越静态,复制和保持运行就越容易。

这仍然是 Oracle 等商业数据库软件相对于 PostgreSQL 和 MySQL 的一个优势。尽管后者在不同程度上提供了主/从复制,但同步既不像 Oracle 提供的那么先进,也不那么健壮。然而,随着时间的推移,我预计这种情况会发生变化,因为这种架构变得越来越普遍。

结论

搬到新的地方很困难,将您的服务器移动到新的位置或计算机也很困难。但是,通过制定良好的迁移计划,逐步迁移并在每个阶段使用 nslookup、dig、telnet 以及 Perl 的 LWP(或执行类似操作的 curl 工具包)附带的 HEAD 和 GET 程序等工具检查您的工作,您可以实现平稳而简单的迁移。

只需进行少量更改,迁移计划也可以用作备份计划,确保您的服务器即使在发生重大灾难后也能继续工作并可访问。您无法计划每个潜在的陷阱,但如果您的组织依赖于其网站,那么值得投入时间和金钱来确保其保持在线。

Reuven M. Lerner,一位长期的 Web/数据库顾问和开发人员,现在是西北大学学习科学项目的一年级研究生。他与妻子和两个年幼的女儿住在伊利诺伊州芝加哥市。您可以通过 reuven@lerner.co.il 联系他。

加载 Disqus 评论