在 Linux 上部署 Squid 代理服务器
为了向 SAS Institute 欧洲、中东和非洲 (EMEA) 的用户提供互联网访问,已经在国家办事处级别和位于德国海德堡的 SAS 欧洲总部中心安装了许多代理服务器。
这些服务器运行 Squid 代理服务器软件;该软件根据 GNU 通用公共许可证提供。简而言之,Squid 提供了缓存和/或转发互联网对象的请求,例如通过 HTTP、FTP 和 gopher 协议可用的数据。然后,Web 浏览器可以使用本地 Squid 缓存服务器作为代理 HTTP 服务器,从而减少访问时间和带宽消耗。Squid 将这些对象保存在 RAM 或本地磁盘上。Squid 服务器可以分层安装,以便中央服务器可以构建可供层级较低的服务器使用的大型数据缓存。
Squid 已在 SAS EMEA 周围使用了一段时间,并且运行良好;该软件非常稳定,并为连接的客户端提供无缝的互联网访问。
最初的代理服务器安装在运行 HPUX 10.20 版本和 Squid 2.1 版本的 HP 工作站上。这在各种硬件上运行,但通常是配备 64MB 内存和大约 4GB 磁盘的 HP9000/720 工作站。这种配置难以支持;硬件已经老化,故障变得越来越常见,互联网使用量的增加以及办事处的增长使得配置显得性能不足。我们最近的主要问题是磁盘空间管理;访问模式的增加使得我们现有的 100MB 日志区域显得太小,而我们的实际缓存目录在 2GB 时也显得相当小。
因此,我们开始研究一些替代方案,以维持服务。由于我们对 Squid 软件本身感到满意,并且我们已经对配置有了很好的理解,因此我们决定继续使用 Squid,但要审查硬件基础。
由于 Squid 是一个开源项目,并且在 Linux 下得到很好的支持,因此探索使用基于 Linux 的解决方案(使用标准的 SAS EMEA Intel PC)似乎是个好主意。此配置是一台配备 256MB RAM、500MHz Intel Pentium 和内置 20GB IDE 磁盘的 Dell 台式 PC。由于 Dell 与 Red Hat 有合作关系,因此使用他们的发行版是有意义的。此外,SAS 最近发布了与 Red Hat 合作的 SAS 产品版本。
SAS EMEA 的原始架构使用了三个中央父 Squid 缓存,可以直接访问互联网,以及许多国家办事处的子 Squid 服务器。一些较小国家的业务运营仍然连接到中央总部缓存,我们认为使用更便宜的硬件将使我们有机会在这些办事处安装代理。此外,在许多国家业务运营中,SAS 的存在分散在通过 WAN 链路连接的多个办事处之间;同样,更便宜的硬件使我们有机会在这些办事处安装代理。这些部署应提高 Web 流量的响应时间,并有望减少 WAN 链路上的开销。
最后,我们对原始基础设施的弹性和可用性有一些保留意见,我们认为通过修改客户端和服务器配置,我们可以提高内部客户的服务水平。
我们的新架构在原则上没有太大改变;我们仍然有三个中央服务器,但它们现在运行 Linux。我们正在部署更多的子代理,并且在某些办事处需要三级层次结构。例如,一些国家/地区拥有卫星办事处,这些办事处仅通过单个 WAN 链路连接到国家/地区总部的 SAS 内网;在这些情况下,我们将在卫星办事处安装代理,并在国家/地区总部而不是欧洲总部设置首选父缓存。
我们架构的一个新增加部分是用于 HTTP 病毒扫描的 Trend Interscan Virus Wall 产品。我们还安装了三个运行 Red Hat Linux 的病毒扫描系统;这些系统位于当前 Squid 父缓存之后,在 Squid 缓存层级结构和外部互联网之间提供病毒扫描层。由于病毒扫描器本质上只是直通的,因此我们只需将我们的顶级 Squid 服务器配置为在它们之间“轮询”。
最初的 HP-UX 服务器是通过复制已知配置的磁盘映像来安装的。这是一种完全不能令人满意的方法,原因有很多,其中至少一个原因是难以为维护此映像以进行补丁或 Squid 的版本更新等做好准备。
我们的目标是脚本化和自动化安装,本地办事处的工作人员可以快速执行。我们对这个概念的实施感到满意,并且它在恢复和配置管理方面有一些有用的好处(见下文)。
我们制作了一个 KickStart 配置文件来构建机器。KickStart 是 Red Hat 提供的一种自动化系统安装的工具。基本上,我们可以告诉安装程序如何分区磁盘,要安装哪些软件包 (RPM),并通过 shell 命令包含一些本地配置步骤。我们的 KickStart 配置与普通的 Linux 启动实用程序一起放在软盘上,我们指示 KickStart 从 CD 执行安装。
这意味着对于新的代理服务器,我们可以安排运送一台看起来与我们预期的硬件配置相似的 PC,并运送一张 CD 和软盘,供远程办事处完成配置。
安装过程已自动化,但有三个例外:将提示用户输入主机名、IP 信息和键盘类型(我们的一些办事处对当地语言使用不同的键盘)。KickStart 硬编码所有其他选择;例如,安装语言始终为英语,软件包的选择始终相同,并且磁盘始终以相同的方式分区。
从将磁盘放入驱动器到使用新安装的操作系统重新启动的基本安装耗时不到十分钟。这比我们自己做要快得多,并且大大减少了执行 HP-UX 安装所需的时间。这显然对我们的备份和恢复程序有一些影响(见下文)。
我们在运行系统时遇到了常见的问题:配置文件需要更新,软件需要升级,日志文件需要轮换,进程需要监控。过去,曾经使用过一系列非常不一致的 shell 脚本和 cron 作业,或者更常见的是,配置已经允许分歧。我们已经用 rdist 作业替换了其中一些,但这并不完全足够,因此我们寻找了另一种工具。
最好的工具似乎是 cfengine。这使我们能够在中央位置构建工具和配置的通用定义,然后将其分发到我们所有的服务器。实施 cfengine 非常成功,尽管它确实需要仔细规划配置结构,并且需要相当仔细地阅读文档。
我们分发的一些文件是完全标准的,我们可以简单地让 cfengine 将它们“原样”发送到目标系统。但是,有些文件基于通用模板,需要针对每个系统进行修改。一个很好的例子是主要的 Squid 配置文件。在这种情况下,我们通过 cfengine 运送模板和一个知道如何进行转换的小脚本。我们使用 cfengine 中的一个功能,该功能允许在收到文件后运行命令,因此运行此 shell 脚本,然后向 Squid 发送信号以重新读取配置文件。这样,我们可以保持集中控制和协调的配置,并确切了解远程系统的状态。
反过来,我们的 cfengine 配置建立在我们维护的本地 NIS 映射之上;此 NIS 映射只是将主机名与功能索引起来。例如,关键字 SQUID-CHILD 用于标记机器是二级代理,而不是 SQUID-MASTER。处理此 NIS 映射以生成 cfengine 中使用的类;最终结果是配置信息集中存储,而不是在每台服务器上。
对我们来说更成问题的是已安装软件的维护。我们正在运行一个主要围绕 Red Hat 6.2 构建的系统,但自从安装了一些代理以来,Red Hat 发布了我们需要的更新。通常,安全问题是优先事项。我们还有一些本地派生的 RPM,并且使用更新版本的 Squid,其中包含 Red Hat 未包含的一些选项,并且我们使用本地构建版本的 gated 路由守护程序,其中包含对一些附加路由协议的支持。最后,我们还有一些从未在 Red Hat 发行版中的 RPM。
要采取的显而易见的步骤是构建一个 FTP 服务器以进行更新。我们在 Network Appliance Filer 上的内置 FTP 服务器上使用了该服务器,该服务器也包含我们来自 Red Hat 的发行版。我们有一个 FTP 镜像作业,可以从 Red Hat 镜像站点拉取最新更新。我们的 FTP 服务器还有一个用于我们本地 RRM 的树。
花了一些时间才能使更新 RPM 的过程正确,并且我们仍然不太满意。我们目前拥有的最佳工具是 autorpm。它配置为查看我们的 FTP 服务器并自动安装 Red Hat 更新,忽略我们一开始未安装的 RPM,并安装或更新我们本地树内的所有 RPM。
我们在这里的问题是 autorpm 无法处理某些 RPM 中包含的某些循环依赖关系。手动解决这个问题很容易,但我们更希望自动化此过程。这似乎不是 autorpm 的错,而更多是实际 RPM 的问题。
RPM 的这个问题也对我们的安装程序产生了影响。我们对安装时间在十分钟以下感到非常满意,并且仅需几分钟即可应用我们旧的 rdist 文件更新。但是现在,在某些站点上应用 RPM 更新需要十分钟以上,并且这是一个手动过程,需要登录系统才能完成。对于 Squid 软件来说,这非常关键,因为我们的 Squid 配置文件需要更新版本的 Squid。
现在我们在安装本身上也遇到了问题;如果我们更新了一些软件,则无法在本地完成安装而无需我们的干预。这对我们来说是一个相当重要的问题。有时远程办事处会遇到某种类型的故障,而我们无法提供帮助。在这些情况下,我们希望远程访问办事处以简单地重新安装他们的代理服务器,可能是在新硬件上。只有在我们不需要干预该过程的情况下,这才有效。
因此,我们回头重新考虑了最初的假设之一——我们说过我们将仅运送标准的 Red Hat CD,并使用 KickStart、cfengine 和 autorpm 对其进行自定义。现在我们决定制作我们自己的 Linux 发行版,该发行版主要基于 Red Hat 发行版,但包括我们新的和更新的 RPM 以及一些配置文件。现在的想法是,初始安装将生成一个可工作的代理,然后我们计划的自动化作业稍后会进行清理任何小问题。
制作我们自己的发行版非常成功;我们可以在大约一到两天内从新的 Red Hat 版本制作我们的发行版。我们采用基本的 Red Hat 发行版,并从树中删除许多 RPM。这不是一个非常科学的过程:我们不会删除每个 RPM,只删除占用最多空间的 RPM。然后,我们将我们自己的 RPM 添加到树中,修改树中的各种控制结构,并刻录 CD。
由于我们的新介质包含 cfengine 和 autorpm,因此我们可以配置 KickStart 过程的安装后步骤,以便在安装后的首次启动时运行这些过程。这应该使我们的新机器快速更新到我们当前的配置。
但是,当我们迁移到 Red Hat 6.2 时,我们在 KickStart 中遇到了一个有趣的问题:当 KickStart 文件中没有 IP 地址和其他网络信息时,新版本不一定会提示用户输入这些信息(当从 CD-ROM 安装时)。仔细阅读略有更新的文档表明,这是 Red Hat 故意的,但对我们来说是一个主要的难题。最终,我们重写了 Anaconda 安装程序中的代码部分,以恢复原始行为。
我们研究了各种备份和恢复选项,并决定使用可用的最简单的备份程序;即我们不备份机器。当我们查看代理时,很明显,只有日志数据和缓存结构对于任何机器来说都是唯一的。日志数据会定期复制到中央位置进行分析,而缓存虽然有价值,但可以清除并在一段时间后重建。
到目前为止,我们部署的 Linux 代理没有发生重大的服务中断或硬件问题,但如果我们确实遇到问题,我们建议重新安装远程系统。如果发生硬件故障,我们预计大多数远程办事处都能够找到备用 PC 并重复安装。
因此,我们不仅不进行备份,而且我们也不需要为弹性硬件或镜像等技术做任何准备。事实上,使用专用硬件会降低我们的可用性和弹性,因为我们没有远程办事处的备用硬件来进行更换,而我们有许多配置足够相似的标准台式 PC,我们的 KickStart 程序可以在这些 PC 上运行。
我们预计,如果 PC 可用,远程办事处可以在大约 20 分钟内恢复服务。我们已经尽力修改了客户端浏览器配置,以使桌面用户对此透明。这为我们提供了一个高可用的解决方案。
旧的代理配置依赖于客户端配置为显式使用命名的代理服务器。对于有多个代理服务器可用的站点,用于代理服务器的主机名在由 lbnamed 管理的域中。正在使用的版本已稍作修改,但仍不适合我们的使用。lbnamed 使用 rpc.rstatd 从池中的机器获取负载信息,然后根据权重,lbnamed 将返回不同的主机,从而创建一些有限的负载平衡。实际上,这并不能有效地分配,尽管它有一个有用的功能,即如果机器不可访问,它将从池中删除。不幸的是,这个有用的功能被这样一个事实破坏了:只有负载(在基本 Perl 版本中)用于对主机进行加权。如果我们的 Squid 服务器守护程序死掉,机器上的负载往往会降低,这可能会使发生故障的机器位于池的顶部。有一个 C 语言的实现可以查看除负载之外的其他因素,但对此进行的一些实验并没有取得成果。我们的总体印象是,与以前安装的一样,这比标准的 DNS 轮询更成功。
我们的测试是针对我们的三台新 Linux 代理服务器进行的,我们注意到的一个因素是,如果我们将 HTTP 查询发送到最有可能在缓存中包含对象的机器,则可以提高响应时间;当然,这似乎是一个相当明显的但不是立即有用的观察结果。
实际上,智能选择要查询的缓存的想法是一件非常简单的事情,可以使用大多数主流浏览器支持的代理自动配置 (PAC) 文件功能来实现。这基本上需要有一个 Web 服务器,该服务器可以在某处返回代理 PAC 脚本。
我们的任务变得更加容易,因为已经有人为 PAC 文件生成了一些示例代码,这些文件可以在多个服务器之间平衡查询。我们以 Sharp 在使用 URL 哈希的“超级代理脚本”方面所做的工作为基础。这是一个简单但巧妙的想法,它哈希正在请求的 URL,然后返回要使用的代理。就大量 URL 的负载分配而言,这在统计上是随机的,但对同一 URL 的重复查询将始终返回相同的代理。我们还利用 PAC 脚本中返回代理服务器数组的功能;效果是,如果第一个命名的代理失败,则客户端的查询将无缝路由到列表中的下一个代理。
在总部站点,我们根据园区位置返回基于两个或三个代理服务器的数组。对于只有一个代理可用的站点,我们不使用 URL 哈希,只返回一对代理,即本地代理服务器和一个中央服务器作为后备。
对于远程用户来说,使用中央后备是给我们带来最大弹性的功能。如果远程代理发生故障,该代理的远程客户端将检测到故障并使用中央主机,客户端将每 30 分钟(MSIE 和 Netscape)检查一次以确定原始服务器是否处于活动状态,并在活动状态时返回使用它。
事实上,由于我们有一些客户端使用 Microsoft Internet Explorer 5.0 版本,我们将 proxy.pac 脚本命名为 wpad.dat。这允许“未配置”的 IE5 客户端使用 WPAD 方法自动查找 wpad.dat 文件,WPAD 方法用于搜索 http://wpad.local.domain/wpad.dat 形式的 URL。WPAD 的使用对我们来说不是特别关键,但它是一个有用的功能。查看实施期间的日志表明,我们可能会为我们的帮助台节省一些来自移动用户的呼叫,否则这些移动用户在访问其他办事处时需要帮助手动设置他们的代理。
目前,我们使用 Apache Web 服务器返回 PAC 脚本,Apache 在本地代理主机或另一个本地可用的 Web 服务器上运行。可以使用精简的 Web 服务器之一,例如,有几个是用 Perl 实现的,这可能更安全并且代表更少的开销。我们尚未探索这种方法。
我们的 WPAD 服务器目前在 DNS 中有多个地址记录,因此如果单个 WPAD 服务器发生故障,我们会有一定的弹性。对于只有一个 WPAD 服务器的站点,我们依赖于使用先前缓存设置的新客户端会话。
这种方法存在一个小缺陷,即远程站点有多个代理:URL 哈希仔细选择要使用的本地代理,但随后代理只是在三个中央系统上轮询查询。我们可以使用 Squid 的一些功能来交换缓存摘要,以便本地代理将请求转发到最有可能生成命中的中央服务器,但在实践中,WAN 链路上的带宽成本使得这无效。相反,我们让轮询轮询任何中央服务器,然后让中央服务器使用缓存摘要交换来在可能的情况下生成命中。
我们预计我们将希望使我们的代理服务器保持最新状态,并使用相当新的 Red Hat 版本。虽然我们将依靠 cfengine 和 autorpm 对配置进行小的修改,但我们不希望通过网络升级整个操作系统对我们来说是真正可行的。
因此,相反,如果我们想升级,我们打算将我们的全新安装运送到远程办事处,并让他们执行新的安装。我们预计这种情况可能会每年发生三到四次。由于我们有如此干净的安装过程和对配置的严格控制,因此进行如此频繁的升级几乎没有损失。由于远程办事处将保留以前的介质,因此回退到早期版本也应该相当简单。
我们非常渴望进行这些频繁的更新,因为我们在 HP-UX 代理上遇到了许多与缺少软件和补丁更新直接相关的问题。例如,我们看到了 HP-UX 问题发生,这些问题有可用的补丁,并且有一个旧版本的 Squid 和许多我们尝试运行的工具,因为有旧版本的 Perl 可用。
升级可以在远程办事处的正常工作日期间完成,对于十分钟或二十分钟的停机时间,客户端将简单地回退到中央备用服务器,或者对于具有多个服务器的站点,他们使用自己的本地后备服务器。
出于规划目的,最有用的数据是缓存正在看到的活动的历史视图。我们使用 MRTG(多路由器流量图形器)和 Squid 中的内置 SNMP 代理收集此数据。这有点难以配置,但我们能够创建一些有用的代理性能图表。我们从内部网页上提供的代理收集许多指标。我们有一些代码,可以通过遍历我们的主机 NIS 映射(见上文)来生成所有服务器的索引页;此代码还包括一些关键指标的缩略图。我们特别感兴趣的是查看缓存命中和缓存未命中时间的趋势,以及跟踪请求的任何总体增长。
我们还使用 Calamaris 工具(见资源)来生成代理状态的快照以及日志的一些分析。
我们还拥有 HP OpenView 网络管理产品的副本。目前,我们仅使用它来监控机器的状态,但我们计划对其进行自定义以监控远程 Squid 软件的运行状况,以便在软件发生故障时简单地提醒我们。
我们还开始使用每五分钟从 cron 运行一次的 cfengine 来检查各种进程的运行状况,并尝试自动重启。
此外,我们还向当地办事处提供互联网使用情况报告。目前,我们将日志整理到 SAS 数据集中,并使用 SAS 报告工具生成报告,但我们也有 SAS IT Service Vision 和 SAS WebHound 等产品能够对流量进行类似的分析。这些都是功能强大的工具,我们可以使用它们来提供更全面的数据分析。
我们对我们的 Linux 解决方案的稳定性和性能感到满意。毫无疑问,硬件成本的降低使我们能够在以前不具有成本效益的位置安装代理,以便为其他位置构建更高的弹性。由于我们的新配置更具弹性,并且总的来说比以前的配置更好,因此我们遇到的问题比旧代理少。
到目前为止,我们看到的最糟糕的运营问题是文件系统损坏。我们有一个远程代理遭受电源故障,然后由于文件系统问题而无法启动。作为一项临时措施,我们修改了启动代码,使其更能容忍这些故障,但更长期的解决方案可能是使用正在变得可用的基于日志的文件系统之一。
我们开始看到越来越多的本地 ISP 链接正在我们的办事处部署。因此,我们将需要微调我们的配置,以支持在办事处级别进行 HTTP 病毒扫描以及从代理直接访问互联网。实际上,这仅仅意味着向 cfengine 和 autorpm 添加一些任务,以安装和配置新模块。
由于我们现在有一个程序来制作我们自己的 Linux 发行版介质,因此我们很可能会在内部审查更通用的 Linux 部署。无论如何,现在 SAS 产品在 Linux 上可用,这将在某种程度上发生;我们希望为内部使用制作标准发行版将为我们提供一些宽松的配置控制。我们可能会考虑哪些其他功能可以有效地在 Linux 上运行;例如,我们可能会将一些 DNS/BIND 功能迁移到 Linux。
