Linux-管理最佳实践-全-
Linux 管理最佳实践(全)
原文:
annas-archive.org/md5/0ee032b8a98d994ca98c6a4bd4d654be译者:飞龙
前言
Linux 管理最佳实践 是一本帮助理解业务基础设施中最关键职能之一——系统管理——的指南。操作系统级别的管理仍然是通信和基础设施的基石。Linux 目前仍然是最受欢迎的操作系统家族,并且越来越受欢迎,这使得拥有训练有素、深具知识的 Linux 管理团队变得更加重要。
本书适合的人群
本书面向那些使用 Linux 或作为系统管理员工作的 IT 专业人员,旨在帮助他们将技能提升到更高的水平。本书关注最佳实践,因此我们着重于系统管理员的角色和思维方式,而不是单纯学习个别任务。本书将挑战你如何思考以及如何看待系统管理。它不会教你系统管理的具体任务,但会教你如何像职业管理员一样思考。
本书涵盖内容
第一章**,系统管理员的角色是什么?,阐述了系统管理员职能的实际角色和任务,并说明如何将其应用到你自己职业和组织中的角色上。
第二章**,选择你的发行版和版本模型,介绍了如何为你的组织选择合适的 Linux 变种(Linux 有许多不同的版本和风格),并理解版本模型的重要性。
第三章**,系统存储最佳实践,旨在通过高层次的方法,将你从初学者带到存储领域的专家,这也是系统管理中最难理解的领域之一。
第四章**,设计系统部署架构,讲解了评估部署方法以及不同模型何时适用于你的情况。
系统并非孤立存在,它们通常与其他系统一起部署,并且经常需要互操作以实现功能或冗余。以有意义的方式组合系统是复杂的,并且可能是反直觉的。
第五章**,补丁管理策略,探讨了补丁和更新,虽然听起来可能很平凡,但它们是任何系统任务列表的核心,并且通常比我们意识到的更复杂。良好的补丁管理将帮助你和你的组织防范意外和恶意的灾难。
第六章**,数据库,深入探讨了数据库概念以及它们如何应用于系统领域,从而帮助你为数据库用户提供更好的支持和指导。虽然技术上它不属于操作系统的一部分,但数据库管理历来由系统管理员负责。
第七章**,文档、监控与日志技术,探讨了手动和自动化过程跟踪我们系统的期望状态和当前状态的策略。
第八章**,通过脚本和 DevOps 实现自动化以提高管理成熟度,探讨了多种不同的自动化方法,考虑了实践性和现实需求,而不仅仅是完美的理论方法。每个人都在谈论系统任务的自动化,但许多组织却未能实现这一点。
第九章**,备份与灾难恢复方法,超越了传统的智慧,以全新的眼光和现代化的视角来探讨灾难恢复,提供了比通常更简便、更有效的备份方法。系统管理中最重要的任务就是保护数据。
第十章**,用户与访问管理策略,探讨了维护用户的最佳实践,讨论了决策和用户管理方法,并研究了远程访问操作系统的架构。如果没有人能访问系统,那这个系统还有什么用?
第十一章**,故障排除,探讨了采取计划性、故意的故障排除方法如何提高解决速度,减少压力,并可能发现那些原本可能被隐藏的问题。当出现问题且压力山大时,最难的就是弄清楚该做什么。
如何充分利用本书
预计您具有 Linux 和操作系统的基本知识。我们假设您有在生产环境和商业环境中操作系统的经验。本书侧重于高层次概念而非技术流程,因此具备 Linux 和操作系统的工作知识将非常有益。
本书所涵盖的软件是基于 Linux 的操作系统,如 Ubuntu、Fedora、Red Hat Enterprise Linux 和 Suse。
使用本书不需要运行中的系统。本书侧重于高层次概念,尽管了解 Linux 和操作系统非常有用,但在阅读本书时无需亲自操作运行中的系统。
下载彩色图片
我们还提供了一个 PDF 文件,其中包含本书中使用的截图/图表的彩色图片。您可以在这里下载:static.packt-cdn.com/downloads/9781800568792_ColorImages.pdf。
使用的约定
本书中使用了若干文本约定。
文字中的代码:表示文本中的代码字、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 账户名。例如:“System 是指 操作系统,并表示角色的范围:管理应用程序运行的平台。”
任何命令行输入或输出都写作如下:
$ lvcreate -l 100%FREE -n lv_data vg1
粗体:表示新术语、重要词汇或屏幕上显示的词汇。例如,菜单或对话框中的词汇会以这种形式出现在文本中。示例:“随着我们对Linux 系统管理的探索逐步深入,关于角色和职能的帽子理论会变得更加清晰。”
提示或重要说明
以这种方式出现。
联系我们
我们总是欢迎读者的反馈。
一般反馈:如果你对本书的任何部分有疑问,请在邮件主题中提及书名,并通过电子邮件联系我们:customercare@packtpub.com。
勘误表:尽管我们已尽力确保内容的准确性,但仍然可能发生错误。如果你在本书中发现了错误,我们将不胜感激你能向我们报告。请访问 www.packtpub.com/support/errata,选择你的书籍,点击“勘误提交表格”链接,并填写相关信息。
盗版:如果你在互联网上发现我们作品的非法复制品,我们将不胜感激你能提供位置地址或网站名称。请通过 copyright@packt.com 联系我们,并提供材料的链接。
如果你有兴趣成为作者:如果你在某个主题上有专长,并且有兴趣写作或为书籍做贡献,请访问 authors.packtpub.com。
分享你的想法
一旦你读完了 Linux 管理最佳实践,我们很想听听你的想法!请 点击这里直接进入亚马逊书评页面 并分享你的反馈。
你的评论对我们和技术社区非常重要,它将帮助我们确保提供优质的内容。
第一部分:理解 Linux 系统管理员的角色
第一部分的目标是帮助你理解系统管理员职能的范围、责任、角色和任务。我们将读者引导超越任务的概念,深入探讨该角色的目的和价值。
本书的这一部分包括以下章节:
-
第一章,系统管理员的角色是什么?
-
第二章,选择你的发行版和发布模型
第一章:系统管理员的角色是什么?
在我们的行业中,很少有事情听起来比这个更简单,更容易回答的问题:什么是系统管理员?然而,询问任何人,你会得到很多不同的意见。似乎每个人对系统管理员这个头衔或角色都有自己的看法,包括那些为自己使用此头衔或从公司颁发此头衔的人,可能是最多变的人!
欢迎来到系统管理,特别是Linux 管理的最佳实践。在本章中,我们将深入了解一个真正的系统管理员的工作、角色和职能,并尝试理解我们在这一角色中如何适应组织中的位置。
处理这本书时,对我来说,写作中的一个清晰的过程是必要的,但对你来说,理解这本书是否适合你,或者掌握我试图涵盖的范围,清晰地定义什么是系统管理员对我来说也是必要的。
准确理解一个真正的系统管理员应该具备的能力将成为将该角色定义应用于适用于系统管理和特别适用于Linux 管理的最佳实践的基础。
在本章中,我们将涵盖以下主要主题:
-
现实世界中的系统管理员在哪里
-
戴上管理员和工程师的帽子
-
在商业生态系统中理解系统
-
学习系统管理
-
介绍 IT 专业人员
现实世界中的系统管理员在哪里?
我认为尝试理解系统管理员是什么的最具挑战性的事情之一,源于系统管理员这个称号经常被公司随意颁发,几乎没有理解信息技术(IT)、系统或管理,并将其视为 IT 角色的通用填充物,他们不理解或不知道如何命名。它还很容易在没有给予薪资加薪或晋升的情况下,以此激励初级员工留在一个其他方面无法奖励的工作中,希望一个令人印象深刻的头衔将帮助他们在以后的职业生涯中。因此,实际上,作为系统管理员工作的人数与拥有这一头衔的人数相比非常少。事实上,可以毫不夸张地猜测,拥有系统管理员头衔的普通人从未思考过这一头衔的含义,也许对这一角色的预期有很少的了解。
如果单从职位来看,系统管理员无处不在。但他们大多存在于那些规模小到根本没有系统管理员的公司里。系统管理作为一项专职工作几乎仅限于大公司。大多数公司需要有人来做系统管理的工作,但通常只是作为其整体职责的一部分,而且往往只是其中很小的一部分。IT 的特点是,在小型和中型公司中,通常有一些通才身兼多职,做着各种必要的 IT 工作,而几乎没有时间专注于某一具体职能。相反,在大型企业中,你通常会看到专注的角色,通常被划分到专门的部门,只做一项 IT 工作:比如系统管理员。但即使在一些企业中,你也会发现部门像是独立的小型企业,仍然有通才负责许多不同的任务,而不是将职责分配给多个专门的人。
当然,这没有什么不对。完全可以预期。这就像是,作为一个房主,你常常会自己做很多房子的工作,或者你可能会雇一个修理工,他几乎可以做任何需要做的事情。你可能需要做一些水管工作、油漆、木工、电线安装等。不论是你自己做,还是你雇的修理工做,你都不会称自己或他为水管工、油漆工、木工等。你只是一个万能修理工,或者你雇佣的那个人是。你依然能意识到,专职、全职并专注于某一领域的水管工、油漆工、木工或电工是一个专业化的角色。你偶尔会做这些工作,甚至可能做得很好,但这并不等于这是你的全职职业。如果你声称自己是这些角色,朋友们很快就会指出你显然不是这些专业人士。
系统管理员就像水管工。每个拥有房屋的人至少会做一点水管工作。一个专门从事家居维护的修理工可能会做相当多的水管工作。但他们都不是水管工。一个非常大的住宅开发项目,或者一个建筑队可能会雇佣专职水管工。甚至可能不止一个。而几乎每个房主都需要时不时地聘请一个水管工。如果你像我一样,可能还需要经常找。大多数水管工要么为需要持续水管服务的大公司工作,要么为水管承包公司工作,享受同行和导师的帮助,帮助他们提升自己的专业知识。
几乎每个企业,无论规模大小,都需要完成系统管理任务。对于非常小的企业来说,这些任务通常每年不超过几个小时,并且在需要时,任务安排通常是不可预测的,很多时候一次性需要大量时间,而在其他时间可能什么也不需要。对于大型企业来说,可能每周需要数万小时的系统管理任务,并且需要整个部门的专职专家。因此,像水管工一样,小企业通常雇佣 IT 通才(类似于房主的杂工)或将系统管理任务外包给外部公司,如托管服务提供商(通常称为MSP),或者保留顾问;而大型公司则通常雇佣全职专门的系统管理员,专门从事这一工作,只为该公司服务。
系统管理任务存在于每个企业、每个行业,并构成了我认为是 IT 领域中最具回报性的角色之一的基础。通过掌握系统管理技能,你可以自主规划进入大型公司、成为顾问、加入服务提供商,或者通过提升其他技能成为更好、更高级的专家。如果没有坚实的系统管理基础,通才将缺乏最核心的技能,甚至在通才的行列中也难以晋升。而在通才领域的顶端,真正的 CIO 角色主要从那些具备广泛系统管理理解的人中选拔。
到目前为止,我们已经了解了系统管理员是什么,在哪些行业和企业中可以找到他们,以及为什么你可能希望将系统管理作为职业方向,或者作为拓展通才职业的一项技能。现在我们可以深入了解系统管理员到底做些什么!
戴上管理员和工程师的帽子
在本节中,我们将探讨两个部分:
-
管理和工程有什么不同。
-
如何识别你正在执行的角色。
系统管理员这个名字本身应该能给我们提示,说明这个角色应该包括哪些内容。这个职称并不是为了混淆或掩盖真正的职责。然而,许多人认为它是一种技巧。如果你在小型企业环境中工作足够长的时间,你可能甚至会发现许多专业的 IT 人员都不相信真正的系统管理员存在!
系统是指操作系统,并指明了该角色的范围:管理应用程序运行的平台。这将系统管理员的角色与例如数据库管理员(通常称为DBA)区分开来,后者管理的是数据库本身(运行在操作系统之上),或者应用程序管理员(管理操作系统之上的特定应用程序),或者平台管理员(管理操作系统运行的虚拟化平台),或者网络管理员(管理网络本身)。被称为系统管理员应该意味着该人的主要工作重点几乎完全围绕操作系统的维护与管理。如果你的一天并不完全围绕操作系统展开,那么你就不是真正的系统管理员。也许系统管理是你职责的一部分,但如果你以系统管理员为职称,那可能不太准确。
管理员这个词告诉我们,这个角色是负责管理某物的。管理员的直接对立面是工程师。工程师规划和设计某物;管理员运行和维护某物。我常常将这些角色称为A&E角色,通常这些职称被根据说话者的感觉随意使用,意义不大。但当准确使用时,它们有非常明确的含义,在 IT 领域的每个领域(系统、平台、网络、数据库、应用程序等)中,你都会看到它们相辅相成地工作。当然,在一个组织内,通常会有一个人既充当工程师又充当管理员,这两个角色的技能和知识有着广泛的重叠,并且必须密切合作才能有效地完成工作。
管理员角色和工程师角色之间的区别
然而,这两种角色之间有一个关键的区别,影响着组织和从业者的方式,这个区别非常重要,值得讨论,因为否则我们可能会觉得将这两种角色区分开来不过是装腔作势或是语义上的游戏。这个区别在于我们如何衡量绩效或成功。
工程角色通过吞吐量或完成的工作总量来衡量。它关注的是生产力——工程团队在给定时间内可以设计或构建多少系统。
在这种情况下,管理员角色是没有意义的。管理员管理的是已经运行的系统,而不是实现新的系统。管理员是通过可用性而不是生产力来衡量的。听起来可能有些奇怪,但这主要是因为大多数组织对管理工作理解不多,从未考虑过如何衡量一个管理部门的有效性。
角色定位
我花了很多时间谈论“帽子”。理解“帽子”很重要。
这里所说的“帽子”,指的是我们承担的不同工作角色,并理解何时我们正在执行某个角色的任务——即所谓的戴上某顶帽子。例如,如果我在餐馆工作,有一天我可能担任服务员,这时我们就会说我戴上了服务员的帽子。第二天,我可能在厨房做沙拉,这时我就戴上了短时间厨师的帽子。
这听起来可能有点傻,但它很重要。帽子这一术语有助于我们更好地理解作为某个角色和执行与该角色相关的任务之间的区别。我们都知道,做一名水管工需要什么,但大多数水管工都会开车去工作现场。这是否意味着他们是卡车司机?开卡车的技能是否是水管工技能的一部分?不,它不是。但这无疑是一个有用的辅助技能。然而,一家大型的水管公司可能会考虑聘请专业司机,专门负责将水管工从一个工作地点送到另一个工作地点,以保持每个人专注于他们的专业工作,降低保险成本,增加水管工作的计费小时,甚至允许聘用那些可能根本没有驾驶执照的优秀水管工!
在 IT 行业,常常会被要求承担许多不同角色和职能的职责,以至于我们常常忘记自己在做这些事情。IT 专业人员通常被视为全能型人才,能够做各种事情,通常这也成了事实,因为人们最初进入 IT 行业的原因往往是多才多艺。但当我们区分我们的预定角色、专长、培训以及我们因何获得薪水时,这对于理解我们是如何在做事情非常有帮助——而不是仅仅因为我们具备技能、灵活性或愿意帮助别人而做其他领域的工作。
随着我们深入探索Linux 系统管理,帽子概念以及深入挖掘工作角色和职能将变得越来越清晰。将我们的职能视为在特定时间佩戴特定的帽子,是理解的有力工具,更重要的是,它有助于我们向他人以及最终向我们自己传达我们的角色、需求、能力、期望和责任。在现实世界中,几乎没有公司或角色能够真正将系统的工程和管理方面分开。这有其好处,也有其后果。但值得一提的是,许多大型公司确实将这两种角色分开——有时甚至将它们安排在不同的部门,并拥有独立的管理团队。将这两者分开有许多好处,主要是因为系统的两个方面所需的软技能通常是对立的。
工程师受益于强大的软技能——优秀的规划能力。工程学几乎完全是关于规划的。你可以花时间思考系统将如何使用,并围绕这种未来需求进行设计。你的工作是防止紧急情况发生,而不是应对它们。
管理员受益于强大的软技能——优秀的感知能力,也就是实时响应事件,而不是提前规划。管理员的任务是管理实时运行的系统,这意味着他们的主要挑战是实时呈现的,能够进行急诊处理、优先排序并在压力下工作至关重要。
擅长工程的人很少同时擅长管理,反之亦然。尽管技术技能几乎完全重叠,但人际技能却截然相反,只有极少数人能在规划和急诊处理中都能做到得心应手。那些在管理方面非常有技能的人,通常也会自然地将工程工作放在次要位置,因为他们知道即使计划不充分,他们也能有效地应对。
这里还有其他语言可以为我们提供指导。工程师通常在一个以项目为导向的世界里工作。每个项目都有一个目标,一个工作交给管理员时的终点。管理则是在一个稳定、持续支持的世界中工作,几乎没有明确的起点或终点,项目这个词对他们来说是没有意义的。他们管理的是公司所需的系统,直到这些系统被替换,通常是由管理员以相同的方式管理一个新的工作负载。管理员可能需要向项目经理提供意见,因为项目可能需要报告其长期管理影响,或者获得管理部门的支持,确认他们愿意在项目交接后接手结果。但项目本身,按照定义,始终是由工程角色完成的。
知道自己何时戴上工程师的帽子,何时戴上管理员的帽子,能帮助我们有效地理解如何发挥作用,以及如何向组织的其他成员传达我们的需求和能力。大多数组织对这些工作角色的心理和表现后果视而不见,需要我们主动提供这种理解。我们越能准确识别自己的角色和需求,就越能做好准备,尝试将这些传达给管理层。
强求 IT 人员同时扮演工程师和管理员角色,常常会导致职业倦怠。作为管理员,通常意味着忙于处理请求,且总是当问题发生时第一个被召唤:系统运行缓慢、电脑崩溃、发现新的 bug、需要修补程序等。管理员不仅倾向于长时间工作,而且还需频繁待命。能够在可用的时间中休息是他们能否长期保持在这个角色中的关键。
工程师不需要待命,也不是在紧急情况或问题发生时负责的角色。然而,工程师不被期望需要特别的休息时间来弥补他们日程和时间的极大需求。他们不会被打断,不需要随身携带寻呼机(尽管如今几乎没人还携带寻呼机了),他们也不必错过孩子的学校剧,或者在登机前的几秒钟内回答问题,或在家庭聚餐时匆忙离开去远程指导别人解决问题。他们的生活是可以按计划进行的,可以像普通工作一样休息。那种 IT 人员疲惫不堪、永无休止地被要求为公司牺牲一切、生活在承诺中(这些承诺往往从未实现过,承诺他们未来能有休息的机会)的形象,几乎是所有系统管理员的共同写照。没有任何其他角色在最关键时刻承担如此多的责任。
将这两个角色结合在一起意味着,不仅一个身兼两职的人可能会面临随时待命、全天候处理问题的风险,还需要在每一个可能剩余的时间里,填充工程角色的项目工作,而这个角色又要求他们有足够的时间去做这些工作。试图在有截止日期的项目中保持生产力,同时还要应对每个问题、工单或故障,最终可能导致职业倦怠,甚至更糟。
如果我们能够向管理层传达管理职能与工程职能之间的区别,我们就可以开始对话,探讨如何使我们的工作更加可持续,这最终会让双方的情况变得更好。过度施压会导致生产力下降、错误、疏忽和员工流失。
十五分钟规则
在软件开发领域,所有的工作都是工程性任务,没有行政管理。一个标准的经验法则是,任何需要工程师集中注意力的中断,都会让工程师浪费掉中断的时间,再加上额外十五分钟的时间来重新恢复到中断前的工作状态。很容易看出,若一天中有几个中断,工程师的有效工作时间几乎会归零。他们可能整天都在努力工作,坐在办公桌前试图集中精力完成任务,消耗着有限的时间,但如果不断受到中断,他们只会原地踏步,感到越来越疲惫和沮丧,因为他们既无法休息,也无法有效工作,无法看到努力带来的成果。
这个十五分钟法则被称为任务切换开销。
管理员的角色几乎是充满了中断。需要监控系统,看是否出现故障,警惕新的补丁需要他们关注,回应其他团队的工单或问题等等。管理员当然也会受到十五分钟法则的影响,和工程师一样。但与工程师不同的是,管理员通常在解决一个问题或请求,而最糟糕的情况是一个小的、原子化的任务,在下一次中断之前完成。当一个任务完成,或者故障解决后,接下来要处理的任务会是不同的,无论它是否已经排好队,或者稍后才会到来。管理员无论如何都必须在每个问题之间进行任务切换,因此这种开销是不可避免的。
任务切换开销不仅帮助我们解释和理解为什么管理员和工程师需要分开工作,或者需要极端的支持,而且还帮助我们解释了为什么所有员工都需要安静、有效的工作环境这一更广泛的需求。中断不仅来自系统紧急情况,还可能来自会议、水冷机旁的闲聊、随便走过来的同事、办公室噪音、消防演习,等等。
用于衡量管理员或工程师技能的工具
如果我们处于一个较大的组织,能够将这些角色区分开来,我们就能展示出通过各自的独特利益来衡量每个部门,如何使每个部门变得更好。如果我们处于一个较小的组织,且不得不从一个角色切换到另一个角色,我们需要能够与组织有效协作,展示我们的需求,并与管理层合作,制定工作计划或额外资源,以提高我们的工作效率。
我见过的一个最好的工具,用于理解管理员与工程师之间的软技能差异,就是迈尔斯·布里格斯类型指标中的判断和感知。迈尔斯·布里格斯是一个行业标准的心理学考试,我认为如果处理得当,它对于帮助我们理解自己的自然优势和劣势非常有帮助。
以下是根据迈尔斯·布里格斯(Myers-Briggs)模型,不同人格类型及其认知功能的概述:

图 1.1 – 迈尔斯·布里格斯人格类型的认知功能
工程师通常需要较强的判断型特征,而管理员则需要较强的感知型特征。判断在此有效等同于规划,而感知大致等同于反应或执行初步处理的能力。几乎没有人能同时擅长规划和响应。了解自己的优势让你能专注于能让你快乐并表现出色的工作,而了解自己的劣势则能让你(和你的组织)相应地做出调整。
职责的奇妙多样性
这本书的一大挑战在于,系统管理员的角色,即使我们对系统管理员的定义达成一致,其职责差异之大,使得在一家公司的角色与在另一家公司执行相同角色时,可能看起来像是完全不同的职业道路!我们很容易找到那些几乎整天都在手动部署软件的系统管理员,他们从不进行性能调优;另一些系统管理员可能除了做性能调优几乎什么都不做;还有些人可能专注于管理系统应用或数据库;有些人会管理大量打印机,但大多数管理员永远不会管理一台打印机;另一些人负责管理用户及其存储问题,而大多数人根本不会管理用户。这些系统管理员可能永远不会遇到另一个做着类似工作负载的系统管理员,也很少有人会在同一领域找到第二份工作,要求他们再做一次相同的任务。每个系统管理员的职位实际上都是独一无二的,几乎可以说是荒谬的。
更为极端的是,很多人仅把系统管理视为服务器管理,当然,这个称谓通常也只用于服务器,但实际上在桌面、设备乃至物联网领域也有相关职业。Linux 在桌面和笔记本电脑领域可能仍然是一个相对小的角色,但各类公司在生产环境中部署它,并需要理解操作系统与终端设备相关方面的系统管理员。不要轻视桌面管理这一系统子集,它其实并没有那么不同。虽然桌面管理通常不像服务器管理那样压力大或至关重要,但它通常更为多样和复杂,且经常面临一些独特且极端的技术挑战。
在本书中,我会尽量从高层次来看待系统管理,并提供适用于几乎所有人的洞察和指导——无论你是全职系统管理员、希望有一天成为系统管理员的学生,还是将系统管理作为日常任务的一部分的 IT 通才。我觉得,太多的系统管理指南都采取了目光短浅的方法,试图仅从一两个方面来看待这个领域,完全忽略了大部分人根本不会遇到他们所学的大部分内容。
这里有一张图片,带给你关于“万事通”和“一专多能”的趣味:

图 1.2 – 通才与专家
系统管理方面有三种基本类型的书籍,具体如下:
-
第一种类型采用较高的层次,并试图展示行政管理的领域。
-
第二种类型深入探讨详细且高度具体的任务。
-
第三种类型侧重于教授认证考试所需的技能。
这三种风格的书籍或资源都非常有价值。在本书中,我们将着重于第一种类型,至于详细的命令、语法、工具和其他深入细节的实现问题,我们会留给那些已经专注于这些内容的优秀书籍。我也会尽量保持建议不偏向特定发行版。Linux 几乎是独一无二的,它是一个庞大而多样的生态系统,而不是单一的产品。谈到最佳实践时,我们可以自然地避开深入探讨某个特定的基于 Linux 的操作系统,但仍然有很大诱惑力去过度依赖某一两个流行的实现版本。
另外,区分 Linux 本身、基于 Linux 构建的操作系统(稍后会详细说明)、系统管理与单纯的惯例或假设之间的区别也很重要。在阅读本书时,我们可以朝着多个方向去探讨,并且我会尽量澄清什么时候是单纯的惯例,什么时候才是真正必须这样做的。
很好,现在我们知道了成功进行系统管理所需的能力和心理素质,也了解了这个角色有多么令人激动。我们正在清晰地勾画出系统管理员的目的。接下来,我们需要了解这个角色如何适应 IT 部门和整个业务。
理解商业生态系统中的系统
系统,即 IT 基础设施中的操作系统层,在 IT 和业务中扮演着至关重要的角色。在大多数企业中,IT 功能的最关键方面通常由系统角色来监督。系统管理员通常肩负着处理安全性、性能、数据完整性、存储、规划、访问控制、备份、创新、设计、咨询等许多任务的责任。没有其他角色需要像他们一样承担所有这些职能。
出于多种原因,系统管理员通常是 IT 部门基础设施的支柱。操作系统由于与存储和网络的深度关联,以及与数据和应用程序的紧密联系,处于在整个 IT 组织中具有最大控制和可见性的位置。系统管理员可能与终端用户的直接接触很少,但他们通常是几乎所有基础设施和支持部门集中关注和依赖的核心。
系统管理通常被认为是集中在技术角色范围内的最大一群 IT 专业人员,至少在纯技术角色的范围内是如此。像帮助台或桌面支持这样的终端用户接触职位可能涉及更多的人员,但这些职位中的许多工作通常涉及客户服务或终端用户培训,占用了他们大部分的日常时间。在网络、存储、应用程序、数据库等技术领域中,系统很可能代表着你团队中的最大部分,并涵盖最广泛的技能。
由于其如此核心、重要且通常规模庞大,你可以把系统看作是 IT 部门的“粘合剂”,或者把系统看作是所有其他 IT 学科都趋向于连接的中心枢纽。下图展示了这一点:

图 1.3 - 系统在 IT 生态系统中的核心位置
与网络专业人员可能对系统一无所知不同,系统专业人员不能不熟悉网络概念,甚至是非常详细的概念。再比如,数据库管理员通常可以假设其他人会妥善处理备份,而系统管理员通常是与所有通讯的综合点,必须了解数据库是如何与存储通信的,存储是如何冻结数据的,备份是如何与系统解耦的。正如操作系统本质上是工作负载的通讯枢纽,系统管理员自然也成为了对工作负载的整体理解和管理的核心。
根据我的经验,系统管理往往被期望作为一个完全的咨询同行与其他团队合作。我见过应用程序、数据库和网络团队都在寻求更广泛的经验时转向系统部门。系统管理员不仅需要深入了解自己的领域,还要深入了解所有相邻领域,这种特性使得他们能够像 IT 为整个业务提供咨询一样,为其他部门提供咨询。
自然地,从 IT 角度来看,系统管理能获得对企业整体运作的最全面理解,因为它涉及到业务的几乎每个方面,这使得它通常是对一个组织的最重要视角之一。这也使得系统管理员在组织内扮演关键角色,向业务领导汇报并可能提供建议,讨论问题和机会。在 IT 的所有专业角色中,系统管理员最有可能大规模地与业务进行互动。
现在我们已经对我们的角色如何融入 IT 部门和业务有了一个较为清晰的认识。接下来,我们将学习如何从头开始学习这个角色。
学习系统管理
如果你还没有担任系统管理员的职位,可能会觉得获得必要的经验和培训以成为一名系统管理员会很困难。事实上,情况并非如此。事实上,比起几乎任何其他 IT 领域,你可以在家庭实验室中以非常低的成本,几乎实践系统管理的每一个方面。系统管理虽然有许多方面,并且偏向于那些具有深厚知识的人,但最终它也是对那些愿意付出努力的人可及的。
在接下来的章节中,我将描述一些你可以开始学习如何成为系统管理员的方法。
构建家庭实验室
很少有人像我一样,坚定支持建立家庭实验室。我个人的家庭实验室经验是我职业生涯中最宝贵的经历之一。作为一名招聘经理,无论某人有多少办公室经验,我总是想知道他们在自己的时间里做些什么。家庭实验室展示了专注、兴趣、热情,并提供了独特的机会,真正从头到尾学习一个过程。在我几十年的系统管理经验中,我发现实际上很少有管理员能够真正积累从头到尾运行一个系统的经验,并理解一个系统和工作负载的生命周期是什么样的。即使这段经验仅仅是在家里获得,它也能成为面试或工作中的一个重要差异化点。它很可能是让你脱颖而出的关键因素。
虚拟化技术使得家庭实验室的成本和复杂度,从上世纪 90 年代末的沉重负担,转变为 2020 年代几乎不值一提的轻松选项。实验室的资源需求通常非常小,而大多数计算机的空闲资源相对来说则非常充足。更何况我们还没有考虑到云计算和如今可以按需使用云资源进行实验室工作的能力。尽管云计算并非完全免费,但作为家庭实验室可以部署的另一种资源,云计算通常是非常经济实惠的,可以进一步扩展学生的实践经验。充分利用这两者,你的简历和面试时可以谈论的内容将更多。
当然,为了让这个体验更有价值,你必须真正投入大量的努力——这与在付费工作中处理生产系统时所需的投入是一样多,甚至更多。花时间去自动化、保护、监控、更新和维护实际工作负载,即使你只是把它们用于家中。无论是网页服务器、家庭 VoIP 电话 PBX、电子邮件、即时消息、数据库、媒体服务器、远程访问服务器、DNS 过滤器等等,你可以在自己的实验室中运行许多类似,甚至相同,或者更好,甚至超越常见商业环境中的工作负载。不要害怕利用你的实验室为家人和朋友做一些有趣和有创意的项目。
让家人和朋友参与其中
只为自己建立家庭实验室可能具有挑战性,因为你永远看不到自己的环境被实际使用。若有可能,我强烈建议招募朋友和家人一起参与。这让你能够获得最终用户的反馈,并体验到更接近实际使用的系统。仅仅为自己运行系统,远远无法获得与商业环境中实际操作相匹配的经验。
当我第一次运行自己的家庭实验室进行系统管理时,我运行了一个家庭网站,一个电子邮件服务器,可能最有趣的是一个完整的 PBX。家庭的VoIP PBX(或语音 IP 专用分支交换机)非常好,因为与大多数家庭风格的工作量相比,它倾向于更为复杂,可以完全真实地作为您家庭通信平台的有价值部分,并且很少有经验丰富的 IT 专业人员自己使用过它们。
在 PBX 的例子中,您可以通过在多个房间设置分机并向家庭成员提供分机来进行接近。利用 PBX 为家庭建立一个免费通话机制,以便轻松保持家庭成员之间的联系,可以在提供 IT 经验之外真正实用。构建能够提供真实价值并得到真正使用的东西不仅会使您的项目更加愉快,还会使教育经验更像真实世界。
利用家庭实验室经验的秘诀之一不仅是像在最好的企业中那样做每件事情,还要准备好详细讨论和解释你所做的事情以及如何满足甚至超越了从更典型的工作环境中获得的经验。突出最佳实践、整体管理、实验和有机会使用最新技术的机会,可以使面试者对家庭经验的忽视变得不重要,因为他们可能觉得自己的员工可能因为你更广泛的经验基础和更为更新的知识库而无法胜任面试!
从通才开始,逐步成为系统管理员领域的专家
超越你的家庭实验室,还有其他方法可以在尝试跳入大企业世界之前积累经验,在那里系统管理员最有可能被发现。当然,一个常见的路径是在小公司中作为通才工作,其中系统管理是工作的一部分。这种方法确实有效,但通常情况下不如预期的那样有效。从小企业通才到大企业专家的跃升几乎和一次性从学生跃升到大企业专家一样具有挑战性。因此,我们需要探讨一些直接到达目标或帮助过渡的方式。
为非营利组织或非商业组织做义工
另一个选择是志愿服务。非营利组织和其他非商业性组织通常需要资源,而他们无法找到、吸引或支付。在这些类型的组织中做志愿者是获得生产经验和展示您对专业的执着的好方法。他们很少能提供任何形式的指导或指导,这是一个重要的负面因素,但他们也通常不提供多少监督或结构,并且会赞赏您的努力,给予您更多自由选择有利于您个人经验的方法。作为志愿者,您会很容易发现,您可以花更多时间专注于为组织找到真正的解决方案,而不需要“玩政治”或试图取悦经理,因为您是无偿工作,没有工作需要捍卫或晋升需要争取。
在我系统管理职业生涯的早期,做出的一个较好决定是利用业余时间,在一所 K-12 学校作为唯一的 Linux 环境系统管理员志愿者工作了几年。学校几乎没有现有的计算机设备,当然也没有网络或互联网接入,我能够发挥工程师的能力,设计整个环境,包括桌面、服务器、电话、网络、打印等。一旦实施完成,我又能够转换为管理员的角色,独自管理从 Linux 系统搭建起来的整个桌面、服务器、电话和存储环境。我能够全权处理所有事务,并且独立完成所有工作。作为工程师的疏忽让我作为管理员付出了代价。我看到了最初的成本和设计考虑以及它们如何影响最终用户。我处理从采购初始硬件、安装软件、配置、部署、培训到支持的工作负载。这种经历不仅在短期内推动了我的职业发展,甚至在我职业生涯晚期,成为高级企业 CIO 级别面试的重要话题。
在财富 100 强企业的面试中展示这种经验非常容易。展示我理解决策的过程和后果是很棒的。能够展示从服务器安装到系统生产支持的每个步骤的能力是独特的。在企业中,这些技能很少存在,因为通常不同的团队经常处理流程的不同部分。能够展示对整个过程的整体监督为我带来了很多优势。这种广泛和多样的经验是其他候选人所没有的,极大地改变了我的职业发展轨迹。
不要忽视为朋友和家人提供一些小型技术支持。几乎每个人都认识需要家庭技术支持的人,而人们在家里最需要的恰恰是系统管理支持!这不言而喻,这主要是桌面支持,而非服务器支持。现实世界中的桌面支持经验无疑比没有经验要好。积累多种不同类型的经验是展示最全面的个人能力组合的最佳方式。
自学
学习系统管理的好处之一是市场上有许多优质资源可供利用,从书籍、认证到在线社区和视频应有尽有。无论是结构化材料还是非结构化材料都非常丰富,成千上万的热情专业人士时刻在线,愿意在社区中回答问题并帮助他人。
寻找课程或如今流行的训练营来学习 IT 技能,尤其是系统管理,的确是很有吸引力的选择,但在大多数情况下,我会建议避免这种做法。尤其是训练营,它们的目的是教你一些非常具体的技能,帮助你迅速入门并通过特定流程的面试,但无法花足够的时间深入教授相关主题。这是危险的,并且常常导致长期的职业失败。更加正式的传统课堂教育可能会更好,有些人尤其通过这种方式学得更好,但也有一些需要注意的事项。
通常,课堂学习的进度非常缓慢,而且不够灵活,无法适应你的时间表。虽然这并不是一个很大的问题,但你会失去在最短时间内专注于最重要内容的机会。很少能找到既及时又相关的课堂教育。虽然有可能,但几乎没有听说过,而且很少有有效的检查和监督机制来验证所教授内容的实用性或准确性。最重要的是,课堂学习不是一种可持续的方法。一旦你开始在职场工作,你将没有时间持续上课以保持知识更新,也很难找到能满足下一个项目或挑战需求的课程。课堂学习本质上只是一个特殊的情况,仅适用于职业生涯前的阶段。在持续发展的过程中,它并不是一个有效的方法。因此,课堂学习并不能展示适用于职场的实际技能。
相反,通过书籍、文章、实验、在线社区和其他自主学习的方式教授自己,表明你能够在没有他人帮助的情况下学习是至关重要的,因为几乎永远不会有人在你之前知道你需要知道的一切,并准备好教给你,并且因为你将在整个职业生涯中不断需要保持更新和学习新技术和技巧。任何严肃的专业都涉及终身学习,但几乎没有一个像 IT 行业那样需要。展示出能够自学所需的一切对潜在雇主来说非常重要。
学会自学能让你拥有更广泛的学习机会,更灵活地选择学习时间和方式,有可能随时开始学习,并能够以最快的速度前进。当然,作为本书的读者,你已经至少迈出了这一步,寻求正式、自主学习。
年龄并不重要
也许你会想知道何时考虑开始学习系统管理的初步研究。这是你在大学开始的事情吗?在转移到系统之前,你是否需要在网络或帮助台工作几年?你是否需要先运行桌面支持,然后才能切换到服务器?
很好的问题,我很高兴你问。答案实际上是:你可以在任何年龄开始! 是真的,我是认真的。虽然 landing a big corporate job 对于几乎任何高中生来说可能是不可及的,但获得实际经验和系统教育却不然。高中生在书籍、在线视频、文章、家庭实验室、志愿机会,有时甚至是与较小公司的实际薪酬工作之间,有着许多潜在途径来建立简历、面试并把脚搁在象征性的门上,以至于任何人开始学习成为系统管理员的最佳时机总是今天。
与大多数其他领域相比,IT 的一个重要优势是我们拥有许多行业认可的证书,这些证书可以在职业生涯的早期阶段为简历建设做出很大贡献,几乎没有一个需要先前行业经验或特定年龄或学位的。事实上,许多高中行业项目专门旨在帮助学生在高中获得他们的第一个行业认证。一个积极进取的学生可以远远超越任何普通学校项目所能提供的,并很快地建立起经验和证书的简历。
获得一份好工作可能需要等到十八岁,才能真正开始申请,但有可能一个高中生可以利用自己的学业年限积累一个令人印象深刻的学术背景,并几乎立即进入一个好的起始岗位,并迅速晋升。如果一个学生从中学开始就朝着 IT 职业发展,并且坚持了四到六年,获得的实际经验可能比许多中年职场人士还要多。并不是每个公司都会热衷于聘用这么年轻的人,不管他们能为公司带来什么,但我们并不需要每个职位,我们要的是那个特定的职位,而一个真正重视 IT 的公司可能会把这样的候选人视为最具竞争力的人选。
实习
在传统的行业环境中,获得经验的标准方式是通过实习。今天这种方式变得不那么普遍,但它仍然存在。大多数实习都是无薪的。实习可能非常有价值,尤其是对于年轻学习者,通常是高中或大学年龄的学生,因为它们可以提供进入传统企业的机会,而非非营利组织或慈善机构,并且通常会有导师来指导你学习。即使是有薪实习,也被认为薪水非常低,因此通常很难让学生以外的成年人考虑。
在接触公司讨论实习时要保持警惕。大多数提供实习机会的公司认为他们在获取低成本劳动力,而实习的目的应该是回馈行业和社区。在这种情况下,我们经常看到没有导师或指导。实习生只是被用来做一些不需要技能的工作,并没有学到任何东西。在那些至少试图妥善对待实习的公司中,通常会发现公司缺乏技能或资源来指导实习生,最终无法提供有效的指导。最糟糕的结果可能是被一个没有接受过良好培训的导师指导,实习生学到的东西完全不正确,结果比入职时还要缺乏技能!
不要因此而放弃寻找实习的机会。实习经历在简历上非常有分量,哪怕是糟糕的经历,也可以用来在面试中作为很好的谈资。如果你被教错了所有的东西,也许你可以通过示例呈现一个不该做的事!只要保持警惕,不要认为所有的实习都会很糟糕,或者需要做低级劳务工作,或者没有导师指导。真正的实习是通过导师提供教育,导师能够向你展示如何在现实世界中完成工作。这不是为了获得廉价劳动力的借口。并不意味着在实习期间你就不会做任何工作。你很可能会做一些工作,而且在真实环境中动手实践是实习的一个重要目标。但真正的实习生是来学习的,而不是单纯地工作本身。
现在我们已经有了一个很好的思路,了解如何将自己定位为系统管理角色,并如何解决持续终身学习的问题。现在我们可以在整个业务的背景下,来看 IT 专业人员的角色。
介绍 IT 专业人员
如果我不稍微停顿一下,讨论一下IT 专业人员在更广泛意义上的角色,我将感到有些遗憾。在谈论 IT 中的系统管理时,太容易就假设你拿起这本书是因为你是一个经验丰富的 IT 专业人员,想要磨练自己的技术,调整自己的技能,或者可能是希望进入Linux 管理路径,很多人可能正是这样做的。但也有一些人可能是该领域的新手,想要知道是否特别是 Linux 管理,或者更广义的系统管理,才是你希望专注的方向。
首先,我必须说,在这个领域工作超过三十年后,很少有其他行业能像 IT 一样带来如此广泛的回报。IT 不仅是一个拥有无数机会的巨大领域,而且它还提供地理上的机会,能让你探索任何业务市场(金融、制造、保险、医疗保健、兽医、酒店业、研究、政府、军队、新闻媒体、软件、旅游、营销等等),并在这个领域内有无数不同的角色。每个人的 IT 之旅都是独一无二的,IT 行业为你的职业提供了比几乎任何其他行业都更高的回报和激动人心的机会。IT 不仅是一个技术领域,也是一个客户服务领域,但最重要的是,它是核心业务功能。IT 建立和维护业务基础设施。因此,我们在每个企业的内部方面都是关键参与者,甚至在考虑到我们参与所有企业之前!
正如我们之前提到的,系统管理员在某些方面是IT 中的 IT,是 IT 部门中最核心、最广泛涉及的角色,类似于元 IT角色,通常结合或连接其他所有角色。
然而,IT 领域中我认为值得特别提及的一个话题是信息技术和IT 专业人员的通用职称。让我们仔细看看这两者:
-
首先是信息技术。毫无疑问,这就是IT的含义,但实际上,IT 并不仅仅是技术。它关乎信息、通信、存储、安全和业务的效率——即业务基础设施。因此,技术自然而然地被认为是其中的一部分,但有时 IT 也可能是关于白板、便签以及为组织带来良好的决策和常识。我常常将 IT 与法律和会计部门进行比较:每个部门都有自己的重点,但它们也只是业务的一部分。
-
第二,我们自称为专业人士,因为,坦率地说,这听起来很棒。每个人都希望被称为专业人士。这让我们与医生、律师、土木工程师等职业相联系。但事实上,这些职业并不是我们在 IT 行业中所做工作的良好类比。所有这些领域都有严格的认证要求,遵循精确的规则,如果把它们的方法应用到 IT 行业,结果只是按部就班。IT 认证几乎专注于产品而非角色,正是因为概念上给 IT 角色认证并不太合理。这是为什么呢?
IT 角色无法以有意义的方式进行认证,因为如果你能将 IT 编码化,你就可以自动化 IT,但实际上做不到。IT 主要是创造性的,并且作为业务功能的角色更像是 CEO,而非其他任何部门。IT 的工作是通过改善和良好的业务基础设施决策来最大化企业的利润,这是一项极其广泛的任务。CEO 也有相同的任务,只不过他们的任务不局限于基础设施。你永远不会认证某人作为CEO 专业人士,那太疯狂了。CEO 完全是创造性的、狂野的、独特的。IT 也是如此,或者应该是如此。我们永远不会接受一个只是按别人做的 CEO,因为这样的人不会带来任何价值。像 CEO 或 IT 部门这样的商业专业人士需要处理大量信息和培训,加入常识、经验和创造力,然后将这些全部应用到一个独特的商业环境中,结合它的客户、市场、法规和竞争。几乎在这些角色中,没有什么是可以大规模复制的。
毕竟,无论是只有一个人,还是十万人,IT 部门的唯一功能就是帮助公司最大化利润。为了实现这一目标,我们必须全面了解业务,理解商业的总体概念、技术、决策、风险与回报等等。如果你受到与专业人士相关的限制,你就无法做出这种类型的商业决策,也无法承担这种类型的利润风险。
以医生为例,他们需要遵循很多严格的规则,所有的核心都围绕着他们的认证过程,他们的总体关注点是避免错误。医生会优先考虑通过不作为而导致的任何死亡,而不是亲自造成死亡。专业的做法是在战术层面避免错误,同时避免战略层面的考虑。
IT,像任何业务职能一样,应该采取相反的思路。我们必须进行全面的风险评估,计算潜在的回报,并做出在数学上对业务利润有意义的决策。作为 IT 的专业人员,偶尔失去一个患者并非不可接受,但如果我们从不失去一个患者,那么很可能我们过于规避风险,无法做出好的决策。IT 永远不应该是避免任何失败的代价(甚至是非理性的代价),而是根据情况的数学和逻辑,选择一个明智的风险水平。因此,我常常称我们领域的人为 IT 从业者,因为这个称呼更能反映我们在公司中代表 IT 部门时应具备的正确心态(而且,间接地,意味着公司重视自身)。
成功无论代价的谬误
我从一些企业中听到的一个观点,应该立刻在每个高管和经理的脑海中引起警觉,那就是类似于我们不能容忍服务器停机,绝不允许停机的概念。这通常出现在风险评估和发现的过程中。系统工程师询问一个系统的价值,以便衡量风险缓解的需求,结果常常得到类似于停机不是选择或者我们必须保持百分之百的运行时间,不惜一切代价的回答。
当然,如果我们真正花时间思考,就会发现他们只是在通过说些荒谬的话来回避问题。这样我们就无从着手,也不知道该如何接近系统设计。没有任何系统能够做到零故障,这是不可能的。说我们必须以任何代价防范所有可能的故障,意味着为了满足这一需求,我们必须将组织可以提供的所有资源完全用于风险缓解。任何 IT 部门如果真诚地执行这一指令,最终都会让公司破产。显而易见,在任何情况下,没有任何工作负载值得如此代价。然而,令人惊讶的是,公司管理层往往期望 IT 在缺乏其他指引的情况下,决定哪些工作负载该获得何种程度的保护。
了解业务、财务以及 IT 在业务中的位置,是当 IT 必须迫使企业采取理性有效行动时必不可少的。
不要感到惊讶,在你作为 IT 从业者的角色中,尤其是在系统管理领域,你将扮演着在许多不同的商业职能中引导和建议公司的重要角色。虽然我们希望其他角色,如 CEO 和 CFO 能够在商业实践方面接受更广泛的培训,但商业的严酷现实是,成为这些角色往往比没有商业培训的有效系统管理员更容易。处于决策或影响层面的 IT 角色需要大量的商业知识和实际商业思维,才能在一定程度上成功地完成工作,因此我们常常必须充当整个业务层级的顾问,因为在组织的其他地方往往缺乏商业经验。
总结
希望到此为止,你已经对“系统管理员”和“Linux 管理员”这两个概念有了坚实的理解,并且知道这些角色如何潜在地融入组织。我们将把本书的剩余部分视为在系统领域内同时处理管理和工程,并着眼于 Linux 作为我们选择的系统家族所独特的需求。
我们已经了解了什么是系统,以及它们如何融入 IT 部门的服务中。我们看过了角色的工程和管理方面。我们分析了一个角色如何是专职的,或只是专业人士戴上的许多“帽子”之一。我们甚至深入了解了 IT 作为一个通用领域的更多内容,以及我们如何去获得教育,让我们能够转行进入 IT 职业。
此时,我认为我们已经准备好开始解决 Linux 管理的具体最佳实践了!
在下一章,我们将从审视系统管理员的含义转移,按照相同的方式关注Linux 操作系统的含义,并探讨 Linux 如何融入技术生态系统,谁是关键参与者,以及我们如何为我们的工作负载选择 Linux。
第二章:选择你的发行版和发布模型
当我们谈论Linux 系统管理时,我们可能会迅速跳到我们将要讨论的 Linux 版本问题。这通常是我们与企业主或其他非技术部门人员进行即使是随意交谈时首先想到的话题。我们很少花时间考虑的是发布和支持模型,以及它们如何影响我们的规划、风险和支出模型。
四分之一世纪前,我们曾经定期接受关于不同软件许可模型的优缺点和运作方式的教育。今天,像开源这样的术语被广泛使用,几乎没有人对这些术语感到惊讶,但正如所有技术领域的事物一样,随着一个术语的普及率增加,其一般理解可能会降低。因此,我们需要探讨一些许可的细微差别,因为它在操作系统如何与外界互动(至少从法律角度来看)中起着重要作用。
本章将涵盖以下主要主题:
-
理解生产环境中的 Linux
-
Linux 许可
-
了解主要厂商和产品
-
理解发布和支持模型:快速发布、长期支持和滚动更新
-
选择你的发行版
理解生产环境中的 Linux
Linux如今被广泛应用于商业和生产系统的各个方面。仅仅因为是基于 Linux 的系统,实际上并不能告诉我们设备可能在做什么或如何使用。与 macOS 不同,macOS 基本上可以保证其用途是桌面设备或笔记本电脑,或者与 Windows Server 不同,Windows Server 几乎可以保证系统是一个基础设施或业务线(LOB)服务器。系统基于 Linux 构建并不能为我们提供很多线索来判断该系统的预期用途。Linux 被应用于服务器、虚拟化、桌面、笔记本电脑、平板电脑、路由器、防火墙、手机、物联网设备、电器等多个领域。Linux 无处不在,几乎承担着任何可以做的事情。几乎没有 Linux 没有覆盖的角色,至少在某些时候是这样。
在本书的Linux 管理上下文中,我们假设讨论的是基于标准的GNU/Linux体系结构,使用行业标准的基础工具集,并且是在多用户环境中。我们几乎会专注于 Linux 在服务器上的应用,但也会考虑到桌面和笔记本电脑等终端用户设备作为有效的硬件候选。我们讨论的许多内容,当然,也适用于安卓设备或甚至非 Linux 系统。Linux 本身是一个几乎无限广泛的主题,但有一个广泛接受的人们理解的 Linux概念,我们将基于这个概念进行讨论。因此,我们不会讨论 Android、Chrome OS 等。
Linux 本身是一个内核,而不是操作系统。但作为内核,它已经形成了多个相关UNIX操作系统的核心部分(且只是一个小的公共组成部分)。
Linux 是 UNIX 吗?
在你的 Linux 学习过程中,你可能会听到人们说 Linux 不是 UNIX。从某种程度上来说,他们是对的,但并不是他们通常所说的那种方式。Linux 只是一个内核,是 UNIX 操作系统的一部分。但基于 Linux 构建的操作系统在大多数情况下是 UNIX——至少根据最权威的来源,Dennis Ritche,他是 UNIX 的创始人之一。Linux 实现了 UNIX 的方法和生态系统,以及 UNIX 接口。它是 UNIX,就像 FreeBSD 和其他操作系统一样。UNIX 既是一个标准,也是一个商标。但这两者并不一定是一起维护的。这里的水有点混乱。不过,标准的 Linux 系统,我们在本书中讨论的所有系统,都实现了 UNIX 标准(最初称为 POSIX,现在是 POSIX 的超集,称为 SUS)。因此,它们是 UNIX 的变体或衍生物,正如 Dennis Ritchie 在 1999 年所说的那样。他当时也对 BSD 操作系统家族说了同样的话。
但事情比这稍微复杂一些。虽然大多数基于 Linux 构建的操作系统从未花费过任何费用来获得 UNIX 认证,但其中一个最近做到了:华为的 EulerOS,它基于 CentOS,而 CentOS 又基于 Fedora。只有 EulerOS 作为产品正式拥有 UNIX 商标认证,但它显示出更广泛的生态系统正在符合这些规范。认证过程的特点是,它使得像 AIX 或 macOS 这样的商业化支持的大型专有 UNIX 项目容易且显而易见地获得认证。但在 Linux 领域,由于每个发行版都算作一个独立的操作系统,而且通常很难明确区分一个操作系统与另一个操作系统的不同(比如 Kubuntu 是否包含在 Ubuntu 内?Ubuntu 是否包含在 Debian 内?),而且许多项目通常是志愿者的工作,无法提供收入来支付一个无意义的认证过程,因此几乎不可能通过一个复杂且昂贵的认证过程对其进行认证,尤其是当这个过程没有价值时。实际上,Linux 和 BSD 生态系统已经证明了 UNIX 认证过程的实用性已经走到了尽头,且该过程对行业有害,已无任何意义。最终,与 UNIX 兼容是毫无价值的,Linux 和 BSD 才是其他系统想要保持兼容的对象。
微软在过去几年中完美地展示了这一点,他们将其传统的 UNIX 兼容层 Windows SFU(Windows Subsystem for UNIX)重新构建并更名为 WSL(Windows Subsystem for Linux),并故意使其与 Linux 完全兼容,以便能够在 Windows 内核上运行基于 Linux 的操作系统。微软,曾是传统 UNIX 系统最大的制造商之一,其 Xenix 产品如今只看重 Linux 兼容性。
如果曾经真的发生过操作系统之战,那么 UNIX 完全赢得了胜利。在 UNIX 之中,Linux 胜出。
因此,我们不断被挑战,去精确定义我们所说的 Linux 到底是什么。每个人都有自己的定义,无论是有意的,还是仅仅因为没有理解内核与操作系统之间的关系,或者没有理解 Linux 发行版的作用。事实上,在企业中使用 Linux 不久后,你会对人们讨论时所指的 Linux 有个大致的了解。然而,尽管没有正式的定义,我们已经设法在业内达成了一种标准。当我们说一个系统是 Linux 还是不是 Linux 时,知道在谈论系统管理时不包括Android 或 Chrome OS,但在讨论 Linux 在桌面端的采用时要包括它们。这个概念充满了细微差别,没有可靠的方式来完全确定别人是指这个意思还是那个意思,我们可以假设,随着时间推移,这些定义会逐渐变化,因为它们实际上并没有基于任何坚实的基础,且并不准确。
正因为这种奇怪的 Linux 命名惯例——没有正式定义,我们依靠上下文线索来判断所指的内容——我们实际上使用了像 从 Chrome OS 切换到 Linux 桌面 这样的短语,这本不应该有意义,因为 Chrome OS 和任何其他基于 Linux 的操作系统一样,都是 Linux。
现在,在最高层次上,我们应该对 Linux 有一个基本的了解,更重要的是,当人们谈论某物是 Linux 或甚至是 UNIX 系统时,他们通常指的是什么。我们也已经准备好在下次的系统管理鸡尾酒会中辩护,说明为什么 Linux 绝对是 UNIX 家族的真正成员!接下来是许可证问题,但不用担心,因为 Linux 宇宙让许可证管理变得轻松至极。
Linux 许可证
很少有关于 Linux 的讨论不提到 许可协议。这种情况通常出于几个原因:因为 Linux 许可协议 与几乎所有竞争对手的许可协议都大相径庭,因此在商业决策中占有重要地位;因为它是市场上最大的、最突出的开源产品,无论在哪个类别中;而且因为它与开源软件运动的兴起一同流行起来,迅速成为了这一运动的代表作。大多数人一提到开源软件,就立刻会联想到(甚至会混淆)Linux,这导致了很多混乱,因为市场上有数百万个同样是开源的软件包,而在提到闭源软件时,没有人会跳出来立刻联想到某个具体的代表软件包并认为我们指的就是它。无论出于何种原因,Linux 的讨论方式、命名和思考方式总是与市场上几乎任何其他产品不同。
Linux 本身的许可协议是 GNU 通用公共许可证(也称为 GPL),也被称为 CopyLeft,是所有开源许可证中最著名的。这种许可证为我们使用 Linux 提供了许多优势。
作为最知名的开源许可证,这本身就是一个显著的优势。关于此许可证如何应用于组织的理解广泛,相关的许可资源也比比皆是。将此许可证应用于组织是行业标准知识,且由于几乎全球所有公司都在至少某种程度上使用 GPL 许可的软件,如果不是广泛使用,那么关于许可证的任何问题都必须解决,原因多种多样。虽然其他开源许可证,如 BSD 或 MIT 许可证,可能从最终用户 IT 部门的角度看被认为更优,但它们的知名度肯定不如 GPL。
GPL 保证了每个人都可以免费、随时访问 Linux 的源代码。这为组织提供了重要的保护。它通过允许任何感兴趣的人进行代码审查来提高安全性,像 Linux 这样的大型产品,进行审查的政府、大型企业、安全研究公司以及开发人员的数量极其庞大。Linux 可以说是历史上最受审查的代码。此类开源软件在保留闭源软件所有安全优势的同时,还增加了至关重要的公共审查选项,并且更重要的是,增加了公共问责制。
开源代码的自由获取也确保了使用 Linux 的公司,即使发生供应商中断的情况(比如破产,或供应商突然决定改变战略,放弃产品或将产品推向不受欢迎的方向),也能通过多种方式进行缓解。例如,另一家供应商可能会接手该产品并提供替代的支持和生产路径,甚至是客户自己来完成。最重要的是,原始供应商不能通过改变定价、许可或产品的可用性来真正将客户“扣为人质”。客户和市场始终保有选项,只要产品具有价值。
这种开源软件的一个伟大特点是,每个客户都能从许可证的保护、安全性和灵活性中受益,即使他们没有像自己审核代码或分叉产品以制作自己版本那样做。
然而,理解开源并不意味着或暗示是免费的这一点至关重要。在开源社区中,有一个著名的表达方式是 自由如同自由,而非免费如同啤酒 来解释这一点。意思是代码是免费的,但由代码制成的产品可能是免费的,也可能不是。作为供应商,您完全可以根据许可证使用免费的开源代码,编译一个需要付费购买的产品。许多 Linux 操作系统供应商采用这种做法。这并不会削弱代码是开源的好处,它只是意味着您在与 Windows 或 AIX 等操作系统合作时,需要像追踪其他操作系统的许可证和费用一样,跟踪开源代码的许可证和费用。
然而,大多数基于 Linux 的操作系统是完全免费的,这在行业中具有非常大的意义。完全免费的好处是显而易见的,但这些好处也可能具有误导性,因为没有前期成本使得销售人员容易用情感上混淆的说法 你得到的就是你付出的 来攻击消费者,我们都知道这个说法本质上是错误的,并没有现实或逻辑基础,但它经常被重复,且容易让人觉得有道理。我们可以立即反驳这一点:你可以为 Linux 自愿支付任何金额,没有供应商会拒绝捐赠的选项,然而,那是否意味着你因为自愿支付更多而让价值增加呢? 当然不是,这一概念完全荒谬。然而,这也是一个常见的论点,认为仅仅将钱投入产品就是它的回报。
除了避免前期购买成本,免费的软件,尤其是操作系统软件,对于企业来说能够提供很多帮助。可能最大的好处就是灵活性。有了免费的 Linux 选项,你可以根据需要在组织内的任何地方部署软件,无需管理许可证、获得预算批准,或是需要与供应商协调购买事宜。实际上,在非免费操作系统的部署中,许可证的开销往往会超过技术的开销!在云计算和DevOps领域,随着部署可能变得自动化、透明且不可预测,这个问题会变得更加严重。
免费还意味着员工、子公司、员工候选人、合作伙伴公司、客户,甚至任何人,都可以自由部署相同的系统,用于兼容性、教育、标准化、测试、预演等各种目的。在某些情况下,专有许可甚至不允许实现所需的场景,或者在允许时,也可能是繁琐且负担重的。当然并非所有情况都如此,但在大多数关键的实际场景中,确实如此。值得注意的是,BSD 系列操作系统也是开源且通常免费的(例如,FreeBSD、NetBSD、OpenBSD 和 Dragonfly BSD),除了它们之外,Linux 发行版的其他市场竞争者并没有以一种能够轻松用于家庭实验室、测试、合作伙伴环境,或是在多种硬件平台上的形式存在。比如,macOS 只限于Apple Mac终端硬件,而 Windows 只在AMD64 架构硬件上有意义,并且它的许可复杂、令人困惑且昂贵。AIX和Solaris仅限于来自少数供应商的极为小众的高端服务器硬件,并需要昂贵的许可。Linux 和 BSD 系列操作系统在可以几乎在任何可想象的场景中免费部署这一点上是独一无二的。
就这样,Linux 许可的要点总结完毕。到目前为止,你应该已经有信心能够在你的企业中部署 Linux 解决方案,并理解许可证如何影响你,何时需要付费,以及你可能会为哪些内容支付。你已经准备好将许可和支持等概念区分开来,并在合理的地方进行投资。
提示
如果你发现这个话题非常有趣,我推荐一些经典书籍,它们更深入地探讨了开源许可的话题,比如 Sam Williams(2002)的《自由即自由》以及 Eric S. Raymond(2001)的《教堂与集市》。这些书籍是开源革命巅峰时期的关键著作,并且在 Linux 管理领域被认为是几乎接近经典的必读书目。阅读它们能帮助你更好地了解 Linux 管理员所属于的“圈子”。
现在我们已经讨论完了 Linux 层面的概念,我们需要从五万英尺的高度转向更接近一万英尺的视角,开始谈论 Linux 领域中的真实厂商和具体产品。
关键厂商和产品
与 Linux 的主要竞争对手(如微软的 Windows、苹果的 macOS、甲骨文的 Solaris 或IBM的 AIX)不同,Linux 没有单一的厂商代表它,而是有很多厂商各自提供产品、支持和 Linux 的不同方式。这当然使得讨论 Linux 变得非常困难,因为 Linux 不是一个单一的事物,而更像是一个概念:一系列相关的事物,通常有许多共同点,但不一定都相同。
描述 Linux 家族操作系统是一项相当艰巨的任务,因为它比仅仅几个兄弟操作系统要复杂得多。实际上,Linux 是一个复杂的树形结构,包括根和衍生发行版,衍生版的衍生版,以及来自树上各个层级的操作系统,随着时间的推移,它们的影响力不断变化。幸运的是,我们可以忽略 Linux 仅是 UNIX 家族树中的一个分支这一事实!分析整个 UNIX 谱系将需要一本专门的书,坦率来说,这需要的研究量超出了我认为合适的范围。可以说,UNIX 是一个庞大的话题,主要是历史上的兴趣,对于我们来说,深入探讨并不会带来太多价值。
那 BSD 呢?
在系统管理的背景下提到 Linux 家族操作系统时,我们也需要讨论其精神上的兄弟家族——BSD。BSD 在很多方面与 Linux 相似。像 Linux 一样,BSD 是开源的;像 Linux 一样,BSD 代表着一个相似且密切相关但最终独特的操作系统家族;像 Linux 一样,BSD 几乎总是免费的;并且像 Linux 一样,至少有一个 BSD 家族成员已完全认证为 UNIX,而所有成员在任何有意义的方式上都是 UNIX。
本书中我们将要讨论的几乎所有内容都同样适用于 Linux 和 BSD 家族,在很多情况下,甚至适用范围更广。BSD 与 Linux 并不完全相同,它确实有一些差异,就像其他任何操作系统一样。从高层次来看,一些关键的差异包括 BSD 使用 BSD 许可证,而 Linux 使用 GPL 许可证,另外,BSD 指的是围绕内核的生态系统,而不是内核本身,Linux 则指的是内核,无论其周围的生态系统如何。因此,在这方面,它们是完全相反的术语。实际上,BSD 更像是 GNU 这个术语,而不是 Linux。
BSD 真正代表了一种 Linux 替代品,既不共享代码,也没有共同的许可协议,但在几乎所有方面,它们在精神上是紧密相关的。两者几乎在相同的时间段开始,都是为了在 UNIX 占主导地位但又昂贵且难以获得访问权限的时期,试图复制 UNIX。今天,两者几乎运行相同的应用程序,方式也非常相似,通常被视为彼此在几乎所有领域的直接替代品,包括云计算、服务器、虚拟化、桌面、笔记本、移动设备,甚至是物联网!
同样,像 Linux 一样,BSD 也发生了分裂或分叉,形成了许多不同的产品。在服务器领域有四个关键的 BSD 家族成员:FreeBSD、OpenBSD、NetBSD 和 DragonFly BSD,其中 FreeBSD 是最具主导地位的。在桌面和移动端,BSD 与 Linux 有很大不同,主要产品几乎都是非免费的,且几乎完全来自单一供应商——苹果公司。苹果的 macOS、iOS、iPadOS 等都源自 FreeBSD,并且仍然是 BSD 家族中的商业成员,这使得 BSD 的可见度和实用性远远超出了人们的认知。
尽管追踪和理解市场上任何操作系统的主导地位非常困难,因为没有确凿的手段来了解哪些操作系统在实际使用中,更别提哪些操作系统正在被使用或新部署与旧部署的比较,如何计算主要设备与闲置的辅助设备等,一般来说,人们普遍认为 Linux 是今天最具主导地位的操作系统家族,而且可能,虽然这一观点不那么广泛接受,BSD 排在第二位,主要是因为移动终端用户设备,但它在服务器领域也有着非常强的存在,并且 macOS 突然也成为了桌面领域的重要力量。此时,微软的 Windows NT 家族是与 Linux 和 BSD 在市场上最为严肃的竞争者,尽管它在桌面和笔记本电脑上仍占有主导地位。
Linux 家族树的根基上有几个根。这些是基于 Linux 内核构建的操作系统发行版,配备了所有相关的工具和组件,以组装成一个完整的操作系统。在这个层级上可能有数百个发行版,但真正重要的只有几个,我们会提到的有Debian、Red Hat和Slackware。这些都代表着各自的基础操作系统,你可以部署它们,每一个也代表着基于初始操作系统核心工作所派生出的数百个甚至数千个操作系统。
我们这里只讨论服务器操作系统的选择。如果我们开始列举重要的桌面 Linux 发行版,列表将会是原来的三倍以上,而且它将从一个多年来变化极少的 厂商 和 产品 的稳定列表,变成一个每年或两年都会发生巨大变化、关键产品进出市场的列表。选择一个合适的桌面操作系统相比于服务器选择的 纯粹以业务为导向的决策过程,是一个更具个人色彩的选择。最终用户或管理层看起来好、用起来顺手的东西,往往才是最重要的,因为它是终端用户的界面系统。然而,服务器没有用户界面,因此我们的决策方式截然不同。
Debian
让我们首先来看 Debian。它是 Linux 发行版中最大且最具趣味性的家族之一,也是最古老的之一,1993 年首次发布。Debian 本身就非常知名,许多 IT 部门将 Debian 作为其主要的服务器发行版,很多应用也以它为主要开发目标。Debian 以其开放性和缺乏商业监督而著称,通常被认为是大型发行版中 最自由 的。正因为如此,Debian 更多地作为其他发行版的基础,而非作为独立部署的发行版。Linux 世界中有更多的部分是基于 Debian 构建的,而非其他任何来源。
Debian 完全免费,甚至不提供任何付费服务,也不包含任何专有组件或驱动程序。这使得它成为构建其他发行版的理想基础或 种子 系统,但也常常意味着公司在选择 Debian 作为直接安装的操作系统时会有所顾虑,因为没有原厂支持选项。因此,评估 Debian 的流行度有些复杂,因为作为基础系统,它几乎无处不在,但原生安装的情况却很少。
Debian 以其轻量、稳定和保守著称。它不是最受欢迎的部署系统,但作为一个选择,它是一个可靠的选择。
Ubuntu
Debian 最著名的衍生版发行版,也是基于 Linux 的服务器上部署最多的发行版,便是 Ubuntu。Ubuntu 可以说几乎是一个行业巨头,尽管它在 Linux 世界中进入较晚,2004 年才首次发布,而当时几乎所有其他发行版都已经建立多年。Ubuntu 在桌面领域迅速崛起,几乎定义了 Linux 桌面的面貌,短短几年内就成为最受欢迎、应用最广泛的 Linux 发行版之一,并且至今保持着领先地位,且没有任何放缓的迹象。如果有的话,Ubuntu 的采用率还在不断增加,既因为 Linux 本身的普及,也因为 Ubuntu 在 Linux 领域内的份额相较于其他 Linux 发行版继续增长。
Ubuntu 是基于 Debian 构建的,但增加了更多功能和优化,最重要的是,它有一个商业供应商支持:Canonical。通过 Canonical,您可以选择为 Ubuntu 获得主要供应商支持,这意味着许多需要主要供应商支持的组织可以选择 Ubuntu,而在 Debian 不适用于他们的情况下。Ubuntu 与 Debian 本身有许多不同之处,包括一些非开源软件包的添加,但对许多人来说,它基本上是一个由供应商支持的、业务就绪的 Debian 版本。
目前,Ubuntu 在各种部署类型上领先。它在桌面、传统服务器、云服务器等领域都占据领先地位。在有限的范围内,甚至可以在一些手机、平板电脑、像 Raspberry Pi 这样的单板计算机和物联网设备上找到 Ubuntu 的身影!Ubuntu 无处不在,几乎每个人都在考虑 Ubuntu。
在早期,Ubuntu 非常注重桌面功能,并将自己营销为对 Linux 新手更加友好。无论这是否属实,这使得 Ubuntu 在获得许多开发人员和其他非 IT 采纳以及使得许多 IT 专业人士愿意尝试 Linux 方面受益匪浅。这也给 Ubuntu 带来了一些时间上的负面印象,需要一些时间来克服。如今,这些都已成为历史,关于易于使用或专注于桌面的讨论早已不复存在。
IBM Red Hat Enterprise Linux (RHEL)
另一个早期的Linux 供应商,Red Hat 也像 Debian 一样,在 1993 年进入市场,并在其整个历史中一直是最大和最有影响力的供应商之一。2019 年,IBM 收购了 Red Hat。自 2002 年起,Red Hat 的旗舰 Linux 发行版被称为Red Hat Enterprise Linux,但由于名称过长,业界称其为RHEL。
在 Linux 领域,RHEL 几乎是独一无二的一个不免费的发行版。当然,由于其基于 GPL 许可的 Linux 和其他组件构建,Red Hat 要求其操作系统的源代码是开放和免费的,但 GPL 对编译后的最终产品没有此类限制。这使得 RHEL 作为单独使用的产品受到了很大的限制。它始终与供应商支持捆绑在一起。
因此,RHEL 被视为 Linux 的大型商业解决方案,长期以来一直是仅有的两家专注企业产品的大厂之一,另一家是SUSE。在大部分历史中,Red Hat 一直是市场领导者,而 SUSE 则紧随其后。但近年来,Ubuntu 在市场份额上取得了领先地位,尽管在盈利方面并非如此。
RHEL 被视为极为保守的发行版,在标准安装中比大多数竞争对手稍微重一些。RHEL 经常受到最多的安全关注和审查,并且拥有最强大的支持供应商支持。
RHEL 的替代品
当本书出版时,Red Hat 的世界正在发生巨大的变化。多年以来,CentOS 是一款尽可能接近 RHEL 的 Linux 发行版,它是通过重新编译 RHEL 的源代码制作的,同时去除了任何商标名称、徽标等内容,制作出一个与 RHEL 完全兼容的免费二进制发行版,几乎等同于 RHEL,仅仅在名称上有所不同。Red Hat 最终收购了 CentOS,但在一段时间内仍按原样运营。然而,就在本书写作之前,Red Hat 宣布停止了 CentOS,使市场陷入混乱。直到那时,CentOS 是 Red Hat 生态系统中的主要产品,许多以某种方式使用 RHEL 的公司实际上是在使用 CentOS,这是一款免费的、没有支持的版本。突然取消这一产品,使得该市场的部分领域陷入了混乱。
在这一公告发布后,出现了其他一些即时的选择。其中之一是 Rocky Linux,它本质上是 CentOS 项目的重新创建,由其原始创始人主导,使命保持不变。另一个选择是 Oracle Linux,它的构建方式与 CentOS 相同,采用 RHEL 的源代码重新编译而成,由 Oracle(一个主要的行业供应商,也是 Solaris 操作系统的创建者)提供,并且仍然免费提供,但也提供可选的 Oracle 供应商支持,并且具有一些 RHEL 本身没有的额外功能。
由于市场对 CentOS 突然停产的强烈反应,以及显而易见的市场趋势转向其他非 IBM 供应商,Red Hat 宣布了一项计划,向小型企业或需要学习操作系统的 IT 专业人士免费提供有限数量的 RHEL 许可证。
未来几年这一局面如何发展将会非常有趣,但也很难预测。但无需多言,RHEL 强大的市场地位和长期存在的可能性,已不像几个月前我们曾认为的那样是接近确定的。
这也突显了一个商业中的普遍规则:来自大型专有供应商的产品通常是最具风险的,这与大多数商业所有者的情感反应相反,因为这些产品的方向由董事会、投资者和市场机会决定,使得即使产品在市场上表现良好,也很容易被突然抛弃或停止。通常,专注于某一领域的小型供应商实际上在稳定性方面能更好地满足客户需求。它们依赖于保持现有产品的生命力,无法承担停产主要产品线或疏远用户基础的风险。
Fedora
Fedora 是商业 Linux 领域中的一个有趣的参与者。从技术上讲,Fedora 是 Red Hat 的一部分,而 Red Hat 又是 IBM 的一部分。Fedora 的运作方式类似于一个独立的非营利组织,但它本身并不是一个法律实体。因此,许多人认为它是一个独立的公司,实际上并非如此。Fedora 最初是一个独立的项目,直到 2002 年与早期的 Red Hat Linux 产品合并。
作为一个产品,Fedora 在本书的目标中扮演着两个关键角色。首先,它生产了一个完全免费的 Linux 发行版,简单地称为 Fedora,旨在既能作为桌面发行版,也能作为服务器发行版使用。其次,Fedora 专注于创新,他们的工作成为了 CentOS Stream 和 RHEL 的基础。
最初,Red Hat 是种子发行版,Fedora 从其代码中开发并进行了扩展。但经过多年发展,Fedora 现在已经成为基础种子发行版,RHEL 就是从其中派生出来的。从这个角度来看,Fedora 在某种程度上类似于 Debian 与 Ubuntu 之间的关系,不过这里是 RHEL 而非 Ubuntu。像 Debian 一样,Fedora 不提供供应商支持。而且,同样像 Debian,Fedora 的下游子产品(RHEL 和 CentOS)比其母体(Fedora)更为人熟知。
然而,在其他方面,我们发现在实践中,Fedora 和 Ubuntu 在总体上更为相似,两者在多个不同的使用场景上有着类似的关注点,都是许多其他产品的基础,并且共享相似的设计策略。遗憾的是,没有完全对应的类比。
Fedora 面临的最大挑战来自于其缺乏主要供应商的支持选项。它还受到许多软件厂商未将其视为顶级发行版的困扰。这些厂商通常将目标定在 Ubuntu 和 RHEL 上,而 Fedora 经常只是作为一种附带考虑或因为其与 RHEL 高度兼容而获得支持。
OpenSUSE 和 SLES
最后一大“老牌”Linux 供应商,SUSE 于 1994 年发布了其第一个产品,但早在 1992 年,它就作为 SLS 和 Slackware 等较老发行版的支持商提供支持,而这些发行版当时并没有自己的支持供应商。Linux 本身可以追溯到 1991 年,SUSE 通常被认为是 Linux 的第一个商业支持供应商。SUSE 最初以其他发行版为基础开发 Suse Linux,但其底层项目在 1990 年代逐渐消失,自 2000 年以来,SUSE Linux 一直是独立的根发行版,并且从自身中衍生出其他发行版。
SUSE 的产品和公司名称一直让人感到困惑。SUSE 主要以OpenSUSE这个名称推出其核心产品。这些产品是免费的,而且非常受欢迎。此外,SUSE Linux Enterprise Server 是 OpenSUSE 某个版本的商业支持副本。它与 Red Hat/Fedora 生态系统或 Debian/Ubuntu 生态系统并没有直接的对比。三大主要生态系统的运作方式各不相同。
OpenSUSE 的 Linux 发行版在欧洲非常受欢迎,尤其是在其总部所在地德国。在北美市场,它们的普及程度远低于欧洲。
深入挖掘发行版历史
追溯 Linux 作为内核的真正历史,并试图追踪它多年来衍生出来的所有发行版及它们之间的关系,既容易又有趣。许多发行版已经出现并消失,许多基金会和指导组织曾试图控制或监管 Linux 或 Linux 发行版的不同方面,但大多数都已逐渐消失在历史的尘埃中。
如果你想更有趣一点,可以回过头来,尝试追溯 1960 年代开始的 UNIX 历史,看看如今市场上的产品从哪里来!到现在,UNIX 已经超过五十年历史,而 Linux 今年满三十岁,2021 年!这些都是拥有丰富历史的老系统,而且由于 UNIX 和 Linux 至少部分根植于开源,它们衍生出了许多不同的故事,这些故事都源自一个起点。与像 Windows 这样的产品相比,UNIX 并不是单一供应商的产品,它本身也并不算是一个单一的产品。因此,我们今天所拥有的故事非常复杂。
尽管这一历史很有趣,但很难说它今天还有多大的实际价值。随着历史的积累和今天的产品与过去的供应商之间的广泛脱节,了解我们如何走到今天更像是一个派对技巧,而不是实用的 IT 知识。了解当前供应商和发行版的基础知识非常重要,但了解谁先出现,谁更老,谁的工作是基础等等,则显得平淡无奇。今天所有的主要供应商都已接近二十岁或更长时间,因此所有参与早期的人都已经不在了。即使是这些供应商 themselves,现在也很难追溯到他们产品的历史了。
其他 Linux 发行版
有许多潜在的Linux 发行版可供选择,如果你在桌面环境下工作,完全可以选择许多小众或未经验证的系统,因为在桌面上处理不稳定性或支持问题的能力通常是相当灵活的。在桌面 Linux 的世界里,许多最流行的替代桌面环境都是建立在主要发行版的基础上,例如ElementaryOS、Zorin OS和Linux Mint,它们都是基于 Ubuntu(而 Ubuntu 又建立在 Debian 之上)之上的额外层。一些发行版如 Solus 则从零开始,没有借用任何其他的种子发行版。
如果我们在看服务器,我们将难以为任何非主流发行版辩护。主流发行版会获得更多的厂商支持、更多的测试、更广泛的第三方支持,涵盖软件和硬件兼容性等等。但除此之外,较大的发行版也有更好的社区文档、更多的操作指南以及更多具备特定操作系统经验的专业人士。在决定安装哪个操作系统时,我们必须考虑所有可能性,这包括寻找额外的系统管理资源或替代资源。如果我们有能力提前雇佣,并有足够的时间进行培训,那么任何优秀的系统管理员都可以轻松上手,即使是完全冷门和不常见的操作系统,因为基本概念始终保持不变。然而,能够在危机时刻找到一个有经验、熟悉并且可以随时支援的人,这意味着我们必须坚持使用那些广为人知的发行版。
随着时间的推移,新的发行版将会崛起,而旧的发行版会逐渐消失。变化是不可避免的。在这种情况下,最佳实践是评估行业现状,并根据当前的因素来判断本书中的建议是否仍然适用,或者是否某个发行版已经失去人气、遇到支持问题,或者是否有一个具备出色功能和强大行业支持的新发行版崛起,需要考虑。没有什么是静止不变的,尤其是在 IT 领域。我在这里尽力为你提供一个选择发行版的良好起点,但永远不要犯认为这份列表是神圣不可更改的错误。IT 要求我们必须考虑所有相关因素,应用我们所知道的,并根据当前的实际情况做出最好的判断。我希望我的指南能帮助你理解我如何看待这些发行版,以及为什么在写作时我特别关注这些发行版。
流行度的迷思
我们必须平衡这种想法:即仅仅因为某个东西很流行,就认为市场上会有大量的支持资源可用,与此同时,我们也要考虑实际支持的概念。仅仅因为某个产品很流行或有很多人提供支持,并不意味着这些支持在实际操作中更好或更容易获得。
多年来,我们一直在讨论 Windows 和 Linux 操作系统的问题。市场上有更多的 Windows 系统管理员在营销自己,而 Linux 管理员则相对较少。但经验告诉我们,当招聘 Linux 管理员时,至少能找到一些相对合格的候选人。进行一系列面试,几乎每个候选人都能完成工作,尽管可能做得不好。但是,如果你进行类似的面试,寻找的是 Windows 管理员而不是 Linux 管理员,那么你可能会收到两倍或三倍数量的候选人,但能做到与 Linux 候选人同等水平工作的,只有极少数。
为什么会这样呢?我们可以假设有许多原因。首先,大多数 Windows 系统允许或要求通过图形用户界面(GUI)完成工作,而不是通过命令行。这意味着,大多数从未做过某项任务的人,只需随便摸索一下,运用一些基本常识,阅读屏幕上的内容,便能在表面上看起来像是在做系统管理工作,尽管他们可能从未见过服务器。但是,几乎所有 Linux 系统都不允许在服务器上使用 GUI,当有时确实有 GUI 时,管理工具通常也不在 GUI 中,所有工作都必须通过命令行完成,这使得单纯的“瞎摸索”变得更加困难。熟悉命令和结果非常重要。基本上,虚张声势是非常困难的。这并不是说 Linux 更难,根本不是。
这种情况源于 Linux 世界中,服务器上不接受 GUI 的文化,而 Windows 世界则有完全相反的文化。在早期的 1990 年代,Linux 没有 GUI,所有操作都必须通过命令行完成,而同时 Windows 则是完全基于 GUI 的,直到几十年后才增加了完整的命令行能力。这种情况开始形成了一种趋势,至今依然存在。如果你和一个 Linux 管理员交流,他们通常会认为所有操作只能通过命令行完成;而与 Windows 管理员交流时,他们虽然也熟悉命令行,但几乎所有人都会认为命令行只是与 GUI 配合使用的一个部分工具。当然,如果你今天想完全通过 PowerShell 来管理 Windows,是完全可以做到的,而且效果非常好。同样,如果你真的想的话,Linux 也可以通过 GUI 进行管理。虽然没人这么做,因为那是一个糟糕的主意,但确实是可能的。
另一个因素是小型 Windows 商店随处可见,并倾向于在几乎没有或没有真正进行过管理工作的情况下授予系统管理员的头衔。在上世纪 90 年代末和 21 世纪初,我们面临一个问题,即微软和其他认证供应商像万圣节一样发放认证,许多人(可能大多数人)通过脑筋急转弯或速成班获得认证,而且对 Windows 或系统管理可能没有经验,甚至没有知识。这些所谓的纸管理员的使用,威胁到许多认为他们可以轻易雇用却没有进行任何验证的 IT 商店,并最终导致产业发展出一种 IT 通常缺乏知识或培训的文化,鉴于 IT 人员处于关键位置,这给公司带来了严重风险,但由于 IT 非常复杂,公司通常无法识别过程的失败,甚至事后很少有公司对招聘过程进行事后剖析。大多数公司甚至不知道如何或从何处开始评估决策过程的效力,因此他们只能忽视它。
无论出于何种原因,找到自称是 Windows 管理员的人很容易,但找到真正有实际知识水平的人却相当困难。Linux 的情况稍有不同,声称自己是管理员的人数较少,能够雇佣能够为您提供良好结果的人相对容易。这只是一个例子,并不是由 Windows 或 Linux 固有的任何原因引起的,只是许多历史因素的结果,因此不要试图在其中读出任何不存在的东西。这个例子的唯一目的是表明,市场上资源的普及或丰富并不等同于具有有用的支持。
使用多个发行版
新系统管理员通常认为他们需要为整个组织选择一个单一的发行版,并在各种情况下坚持使用它。这被称为同质环境,具有许多明显的优势。它更容易学习,更容易自动化,更容易测试,更容易监视并保持对最新新闻和变化的了解。当然,要考虑同质环境可能适合您的组织。
有许多原因我们可能需要考虑异构环境,即存在多个 Linux 发行版(更广义地说,可能还有其他操作系统,如 Solaris、AIX、macOS、FreeBSD,甚至 Windows!)。无论他们偏爱 Windows、Linux 还是其他,几乎没有任何规模的公司能够真正实现同质化。如今,大多数 IT 商店被迫在服务器、桌面、笔记本电脑甚至手机等设备上使用各种系统。
这种多样性不仅在软件中迅速传播,在硬件中也同样如此。在过去的几年里,替代 CPU 架构开始逐渐占据一席之地。这种情况其实在行业的前几十年一直存在,直到大约十五年前。在 2000 年代中期,行业大规模地统一在了 AMD64 架构上(虽然一直存在一些替代架构的小众市场,但它们在很多年里确实是小众的),所有其他主要竞争者要么完全失败,要么被 relegated 到非常专业的角色。然而到了 2020 年左右,非 AMD64 架构的受欢迎程度迎来了如此大的跃升,以至于我们不得不重新考虑异构硬件环境。
硬件架构看似无关紧要,但其实并非如此。每个操作系统和每个 Linux 发行版仅针对有限数量的硬件架构进行开发。这意味着你选择的操作系统将决定你的硬件选项,或者你选择的硬件将决定你能使用的操作系统选项。理想情况下,关于这个问题的决策应该是全面考虑所有软件和硬件需求,做出一个能够产生最佳结果的设计决策,而不是将两者割裂开来,单纯希望达成一个不考虑实际结果的工作妥协。
一般来说,我的建议是避免在组织内出现不必要的操作系统蔓延。很容易就会出现多个不同的操作系统,每个系统都执行一个特定的任务,每个系统都需要一些与其他系统不同的特殊维护。然而,这并不是说你应该追求完全的统一,除非你没有选择。对于你来说,总会有一种合理的平衡方式。试图保持完全统一几乎肯定会是一项无果的努力,最终只会带来不必要的困扰。而放任不管地扩展操作系统则几乎肯定会导致环境过于复杂。对于新事物的选择要慎重,但不要畏惧它。
做出选择
了解可能的 Linux 发行版范围,并理解我们的设计原则,以合理的方式避免操作系统蔓延,我们应该如何做出最终的操作系统选择决策?
简单的答案是考虑所有因素。说起来容易做起来难。对我来说,当我准备部署一个新的工作负载时,我的第一个问题是关于工作负载本身的。其供应商支持在哪些发行版上运行?其供应商推荐在哪些发行版上运行?当前的支持路径和未来的支持路径分别是哪些发行版?
与其对抗,不如与工作负载应用程序供应商合作,这可能非常重要。选择错误的发行版可能会导致性能不佳、安装问题,甚至长期的稳定性问题。供应商通常会官方支持更多的操作系统,而不仅仅是他们定期进行测试的操作系统。例如,供应商可能在他们的开发实验室中使用 Debian,并对每个版本进行测试,但可能每年只测试一次 Fedora,即使 Fedora 在他们的支持列表上。如果你选择了 Fedora,认为供应商支持它,可能会在供应商发现之前就遇到 Fedora 上的部署或稳定性问题,而供应商可能没有准备好支持他们不了解的内容。这是供应商的错误,他们没有明确说明他们的支持并非全部平等,但这是一个非常常见的情况。即使是那些在支持和测试多个发布目标方面做得非常出色的供应商,也通常会有一两个他们测试得更频繁或更深入的目标。通常来说,这就是他们开发人员使用的操作系统。
不同的操作系统也会有不同的性能特征。通常,在不同的 Linux 发行版之间,这种差异是微不足道的。例如,Linux 和 Windows 之间,即使是非常简单的应用程序,也可能会有很大的差异。在 Linux 发行版之间,我们最可能看到的性能差异并非来自核心特性,如内核配置或系统库,而是更多来自于编程语言版本的不同,这些差异通常会因发行版的治理方式而在后台产生多种变化,导致不同发行版之间存在较大差异。
一旦我们了解了我们的发行版将如何影响我们的工作负载,我们就可以与其他因素一起考虑,比如哪些发行版已经在我们的组织中使用或是未来规划的一部分、成本、现有知识、支持选项等等,从而确定适合我们的发行版。在理想的世界里,操作系统和硬件的考虑应该在最初选择工作负载时就起到作用,但现实中,组织很少会全面考虑整个业务,通常会孤立地做出决定,比如选择部署哪些应用程序,而不考虑这些决定会如何影响整体业务。作为系统管理员,我们往往对将要支持的工作负载没有太多发言权,因此我们必须尽可能地做出反应以适应它们。
好了,这就是我们对流行 Linux 厂商和产品的调查。我知道,这些信息有点多。使用 Linux 通常意味着你需要了解许多厂商和发行版,通常会定期试用不同的版本。从职业发展的角度来看,掌握这些知识非常重要。你知道的越多,雇主就越看重你,职业机会也会更多。
在下一部分,我们将看看 Linux 常见的支持和发行模型,并观察我们刚才学习的厂商和发行版的实际示例。
发行版和支持:LTS、当前版和滚动版
选择厂商可能看起来能帮助你完成 Linux 部署的所有准备工作,但并非如此。我们仍然需要将发行管理作为我们选择发行版计划的一部分来考虑。
发行模型或发行制度是一种更新发行版的方法。几乎所有厂商都遵循三种标准模型:滚动发行版、短期发行版和长期发行版。
不是所有厂商都提供所有不同的模型,每个厂商的支持方式也不同。我们会尽力做出有用的一般性总结,但当你做出决定时,你需要考虑潜在厂商当前提供的策略,并且要考虑它们提供的支持质量。
还有一个常常与发行模型混淆的因素,那就是支持周期。两者有一定关系,但厂商可以将更新和支持紧密结合,或者可能完全没有关系。在现实世界中,几乎所有厂商都倾向于遵循几个常见模型,像微软这样的厂商,传统上并不遵循这些模型,但它们已经改变,开始与大型 Linux 发行版的模型相匹配。
更复杂的是,每个厂商提供的不同模型采用完全不同的命名规范,因此一旦你了解了一个厂商的做法,你就无法更好地理解下一个厂商可能采用的方式。
我们将首先探讨每种发行模型,然后再尝试解读每个厂商为这些模型提供的支持。我们还应该讨论补丁和发行版之间的区别。
发布是操作系统的新版本。我们经常谈论主要版本和次要版本。但和这个话题中的其他内容一样,这一切都是约定俗成的。如果你熟悉 Windows 世界,主要版本可以类比为 Windows 2000、XP、Vista 等。次要版本被称为服务包。因此,Windows XP 是一个主要版本,介于 Windows 2000 和 Windows Vista 之间,而 Windows XP SP2 是一个次要版本,介于 Windows XP SP1 和 Windows XP SP3 之间。Red Hat 遵循了一个类似且易于理解的模型,主要版本如 RHEL 7 和 RHEL 8,次要版本则是 RHEL 7.2 和 RHEL 7.3。
主要版本发布的理念是,某一主要版本的软件可能与之前的主要版本不兼容。主要版本旨在为软件供应商或项目提供一个稳定的目标,供其编写和测试,以确保他们开发的软件在整个生命周期内都能在某一主要版本上正常运行。因此,大多数软件会指定与其已知兼容的主要版本,例如兼容 RHEL 8或为 Windows 7 构建。
次要版本发布旨在进行重要的更改,同时保持向后兼容。理论上,只要主要版本没有变化,你应该能够将系统从其初始的次要版本更新到最终的次要版本,而不会出现软件兼容性问题。当然,在实际操作中,每当发生任何变化时,无论多么微小,总是存在某些兼容性发生变化的风险。次要版本发布的目的是提供新的功能和更大的更新,这些更新可能会影响培训、最终用户、性能和其他因素,但不会阻止软件正常运行,也不需要额外的测试。
并非所有供应商都遵循主要/次要版本发布系统。在 Linux 世界中,主要的商业供应商 Red Hat 和 Suse 使用主要/次要版本系统,但 Canonical(Ubuntu 的开发商)则不使用。传统上,微软采用了主要/次要版本系统,但这一做法随着 Windows 10 的发布而结束。需要注意的是,Red Hat 在 RHEL 中使用了主要/次要版本系统,但在 Fedora 中并没有这样做。
Canonical 开创了现在标准的基于日期的命名约定,Ubuntu 采用了完全不同的版本命名方式。Ubuntu 的发布按年份和月份编号,并且通常有一个稍显随意的名字,方便记忆(或者说,老实讲,数字真的很容易记,而基于动物的名字一点也不容易记)。微软在推出 Windows 10 时复制了这一做法。Fedora 做了类似的事情,但采用简单的递增数字,既不基于日期,也不基于动物。
基于底层方法的极端差异,再加上命名约定的不同,使得理解不同供应商或产品的更新周期变得棘手。我们将在本书中讨论一些,但这些内容当然是会发生变化的,所有三大供应商过去都有改变过这些(微软也是如此),并且未来可能会再次发生变化。唯一一个几十年来始终坚持相同命名约定的大型供应商是苹果公司,他们的 macOS 和 iOS 产品,尽管如此,这些产品仍然在某些地方有一些营销上的变化,让我们保持警觉。
最佳实践是花一些时间学习你所使用的供应商的当前发布模式、约定、名称和版本,并保持与这些内容的同步更新。这是每个使用软件的人都需要了解和掌握的知识。
补丁也可以有发布计划
讨论补丁发布计划可能看起来很疯狂。如果软件存在漏洞且补丁已经发布,显然我们需要立刻获得该补丁,应该没有故意的等待或发布计划安排。大多数情况下,供应商确实是如此运作的,补丁会在可用时持续发布,版本更新会按照产品的发布计划进行。
众所周知,微软并没有遵循这一策略,他们的“补丁星期二”非常有名。除了最关键的补丁,微软长期坚持每月只发布一次预定的补丁更新!
支持到底是什么意思?
如果你说你的软件有可用支持或者是受支持的,我们几乎都会立刻想到相同的事情。然而,“支持”这个术语在不同的情境下意味着完全不同的东西,仅仅说某个东西“受支持”并不足以让它真正有意义。
单独来看,“支持”这个术语字面上毫无意义,但它在听到的人脑海中引发了保障的联想,这使得它成为一个强有力的营销术语。提供的支持让我们安心,而缺乏支持则让我们感到恐慌。没有哪个公司会在没有支持的情况下使用软件,对吧?嗯,既对也不对。这到底意味着什么?一切都取决于你当时的具体意思,支持有时存在,有时又不存在。
在讨论支持时,或者说管理者最关注的点,通常是操作系统的主要供应商是否继续提供安全补丁或稳定性补丁,以修复发现的问题。软件是一个动态的存在,定期修补是我们最需要供应商提供的服务之一。这种支持是我们绝对必须依赖软件供应商的地方。没有其他渠道能合理地处理这个问题,而这正是操作系统发布的根本目的。
在打补丁之后,我们往往认为供应商声称产品得到支持意味着他们会提供更新和咨询支持,以应对操作系统出现的任何问题。实际上,这并不是铁板一块,在某些方面,像微软这样的大供应商实际上并未在所谓的支持中包括这一点。在 Linux 世界中,大多数主要供应商确实为遇到问题或需要帮助的用户提供了某种程度的支持,这可能非常有价值。但实际上,这是 Linux 在某些方面超越其他领域的地方,它可以代表一个显著的卖点,当然前提是在付费支持的情况下,因此许多公司选择不采用这种支持方式。
我们通常将这种顶级支持称为可以向操作系统供应商提交支持票证并期望获得快速响应以帮助我们解决几乎任何实际问题,从操作系统本身的问题到简单的配置或使用问题,甚至可能是培训的问题,作为有偿供应商支持。有些公司完全依赖这种类型的支持,而有些公司从未使用过,甚至有些公司对其存在并不了解。
支持也可以意味着第三方支持。这可以来自大供应商,如提供 RHEL 的 Oracle 的第三方供应商支持,或者来自小型咨询公司,如托管服务提供商(MSPs)。几乎任何产品都可以通过第三方获得某种程度的支持,这可能会导致支持情况不明朗,因为有些产品期望支持来自第三方,而其他产品则期望支持来自第一方。
然后是社区支持,这个术语用于描述来自在线论坛和社区等地方的任何支持。这在 Linux 领域往往受到很多关注,而在其他领域则很少。所有操作系统或 IT 产品都确实有这种类型的支持。Linux 得到更多关注,很可能是因为该领域的知识更为丰富,而且开源的性质使得很少有东西被供应商隐瞒。封闭源软件得到的社区支持较少,因为细节必须要么靠运气发现,要么由供应商发布。社区支持往往会被管理层低估,但实际上它是 Linux 生态系统强大的重要标志之一:供应商将所有信息公开,并有专业社区成员互相支持。在许多情况下,社区支持非常重要,它完全可以改变我们对产品的看法,实际上可能比供应商支持还要好。
基本上,“支持”意味着许多不同的事情,每个人对它的定义也各不相同。我们需要广泛考虑我们组织的支持需求,以及不同的方式会对我们产生什么影响。许多大型组织由于内部政治原因,需要主要供应商支持并签订服务水平协议。仅仅让系统保持健康运行,通常只需要基本的安全补丁和适度的社区支持。评估你自己的需求,摒弃情感,别以为“支持”意味着更多的东西。
我们现在已经明确了这些术语的含义,以及发布和支持是如何相互关联并提供的。这为我们提供了一个框架,用来探索来自实际产品和供应商的真实世界模型。
发布模型:快速发布
最为人所知且 arguably 最重要的发布模型没有官方或标准的名称。你会听到像“快速发布”、“短期支持”、“当前版本”以及类似的名称,但通常它被视为一种标准,用来衡量其他模型的优劣。它是各类模型中的中庸之道。
主要产品包括:
-
Fedora
-
Ubuntu
我们从快速发布模型开始讨论,因为这是大多数人认为的发布标准或基准方法。即使它不是最常用的发布方式,这也是最为人所知和理解的发布方式。近年来,它们变得越来越受欢迎。
快速发布(也可以称为标准或常规发布)模型的惯例是大约每六个月发布一个新版本,但当然,每个供应商可以自由选择他们想要的时间框架。我们通常会认为,如果一个版本的发布间隔至少为两个月,但不超过一年,那么它就属于这个类别。
最为人所知且最容易解释的产品是 Fedora,它由 IBM 的 Red Hat 部门开发。Fedora 每大约六个月发布一个新的主版本,并且没有次要版本。Fedora 对每个版本进行顺序编号,以便尽可能简化变更跟踪。没有复杂的数字需要记住,没有小版本发布,也没有跳跃的版本号。只是 Fedora 1、2、3... 30、31、32、33 等等。每个 Fedora 版本的支持期大约为十三个月。所以,在任何给定时间,至少最新的两个版本(如果不是三个版本)都会处于支持状态。
我们必须提到,Fedora 没有任何付费的主要供应商支持。Fedora 中的“支持”指的是 Red Hat 对更新和安全补丁的支持。当然,Fedora 的第三方支持非常广泛。
主流的 Ubuntu 产品同样采用快速发布模式,但其命名约定比 Fedora 更加复杂。像 Red Hat 的 Fedora 一样,Ubuntu 每六个月发布一次。Ubuntu 的支持期限为从初始发布起九个月,这意味着新版本发布日期到 Ubuntu 对旧版支持承诺结束之间仅有三个月的重叠期。
不同于仅提供软件层面支持的 Fedora,Canonical 为 Ubuntu 的快速发布选项提供了完整的首要厂商付费支持。
这些较短的支持时间框架可能会给人带来困扰,正是由于在选择快速发布产品时,总会有一种情感上的压力,认为每九到十三个月就需要找到一个新解决方案来避免 支持结束 的局面。这也是为什么许多公司会选择其他模式,避免需要定期寻找新解决方案的原因。这种做法不合逻辑,因为它基于一个错误的假设——认为更新系统是不可选的。
快速发布支持在大多数情况下可能是 短期 的,但这只是其中一种看法。在这里提到的两个例子(以及我所知的所有其他案例)中,获得 永久支持 很简单,只要在合理的时间范围内保持系统更新。对于 Ubuntu 来说,这意味着至少每九个月更新到当前版本,而对于 Fedora 来说,则是每十三个月更新一次。在这两种情况下,以及大多数正常情况下,更新是通过几个简单的命令来完成的,而不是替换一个解决方案。虽然我们可能称这些为短期支持方式,但实际上它们恰恰相反。这是行业标准的做法,通过这种方式,系统始终保持合理的最新状态并且持续得到支持。
发布模型:LTS
主要的 LTS 产品包括:
-
Red Hat 企业版 Linux(RHEL)
-
OpenSuse Leap
-
Ubuntu LTS
-
Debian
LTS 可能是长期支持的标准,但大多数人理解 LTS 更多的是与其发布计划相关。虽然没有硬性规定什么算作 LTS,除了厂商指定外,我们通常认为 LTS 版本之间的间隔至少为两年。理想情况下,厂商应该将发布命名规则与支持模式分开,以便让这一点更加清晰,但很少有厂商这样做。
从技术上讲,LTS 版本意味着该版本将获得 长期 支持,但具体含义因厂商而异。LTS 是一个营销术语,更多的是为了激发客户的即时信心,因此经常被用作这一目的。
LTS 发布的基础理论目标是提供一个稳定的产品,能够在长期内得到支持(我们在这里必须多加一些引号),从而使软件供应商能够轻松地开发在该产品上运行的应用,而无需持续维护更新。这使得它们在软件供应商中非常受欢迎,因为它们需要更少的工作来进行支持。它们通常也受到 IT 部门的青睐,因为 LTS 发布的主要风险可能在数年甚至数十年后才会显现,因此选择 LTS 发布的负面后果往往最终会成为别人的问题。
仅仅用一般性说法是远远不够的。请注意,供应商可以采用任何他们想要的模型,并且随时可能改变,同时可以在没有任何实质性支持变化的情况下使用 LTS 这个术语。如果整体支持不符合你的需求,请不要因为 LTS 这个术语而情绪化地偏向某个 LTS 发布。
Red Hat 的 LTS 产品是 RHEL。所有版本的 RHEL 都是 LTS。RHEL 的主要版本发布周期比较不固定,最初大约每两年发布一次,随着时间的推移,发布间隔逐渐变长,现在大约是五年一次,我们猜测未来的发布间隔可能会继续缓慢增长。
Red Hat 为每个版本提供大约十年的支持。如你所见,支持周期和发布周期都是长期的,但它们并不直接相关。支持周期是发布周期的两到五倍,因此,它既是一个长期发布(也叫慢节奏发布),又是一个长期支持的模型。
RHEL 本身除非在特定情况下是免费的。许多 RHEL 的克隆版本存在,其中大多数是免费的,并且没有官方供应商支持,但会接收补丁更新,因此在某种程度上也是得到支持的。传统上,CentOS 是主要的免费 LTS 版本,镜像 RHEL 的功能。随着 CentOS 的停用,像RockyLinux、Oracle Linux和AlmaLinux等项目接替了它们,覆盖了相同的领域。我们完全可以合法地称它们为 LTS 版本,因为它们会长时间保持补丁级别和更新支持。
Suse 的 LTS 产品是 SUSE Linux Enterprise Server,或称SLES。该产品采用与 Red Hat 几乎相同的主/次版本和支持模型,并且一直被视为最直接的竞争对手。SLES 每三到五年发布一次新的主要版本,发布周期比较不规则,通常是根据他们认为自己已经准备好发布的时机。像 Red Hat 一样,每个主要版本的官方支持期大约为十年。所以,像 RHEL 一样,SLES 也是一个慢节奏的发布,并且有长期支持的模型。
和 RHEL 一样,SLES 本身并不是免费的……嗯,不能完全这么说。在 SLES 品牌下,SLES 并不免费。但是 SUSE 提供了一个免费的 SLES 版本,叫做 OpenSuse Leap。这可能有点让人困惑,因为 Leap 是 SLES 的免费版本,但它带来了语言和逻辑上的挑战,因为我们必须说 SLES 不是免费的,而 Leap 是 SLES 的免费版本。基本上,当使用 SLES 名称时,它不是免费的,但使用 Leap 名称时,它是免费的。困惑吗?你最好相信,这的确让人困惑。
SLES 和 OpenSUSE Leap 都是慢速发布和 LTS 版本。两者的支持时长相同,但 SLES 提供的支持更加深入。
Canonical 在 Ubuntu 上采用了非常不同的方法。与 Red Hat 和 SUSE 每个都推出多个产品不同,Canonical 只推出一个产品:Ubuntu。如上所述,Ubuntu 每六个月定期发布一次。Canonical 并没有为其 LTS 版本单独推出一个产品,而是将其快速发布产品中的每第四个版本指定为 LTS 版本。因此,每两年就会发布一个特别的 Ubuntu 版本,获得大约八年的支持。所以,Ubuntu 只有一个产品,且仅有一个发布周期(每六个月一次),但有两个支持周期。虽然这种方式最难解释,但它带来了最灵活、最直接的产品开发、测试和使用方式。
Debian 采取了另一种方法。记住,Debian 从不提供付费的厂商支持选项,仅提供安全性和软件支持。这影响了它的支持模型。Debian 大约每两年发布一次新版本,因此它是一个慢速发布的产品。然而,官方仅完全支持当前版本。非官方情况下,他们通常会继续支持之前的版本。这就造成了一个奇怪的情况,发布周期相对较慢,但支持机制却非常激进,期望所有使用 Debian 的人几乎立即更新到最新版本,这实际上削弱了大多数公司选择慢速发布产品的初衷。所以,Debian 发布缓慢,但其支持却远非长期支持。
发布与支持计划的相互关系:重叠
单独的发布和支持计划提供了有限的信息。真正能让我们理解如何看待一个发行版的是将两者结合起来看。例如,Ubuntu LTS 的发布周期为两年,这意味着我们可以以一种速度更新平台,而它的长期支持周期为八年,意味着我们可以选择不更新,甚至可以有好几个周期不更新而不失去厂商支持。大多数人提到 LTS 模式时,都期望这种行为,但实际上这种行为并不意味着所有 LTS 版本都表现如此。
Debian 的两年发布周期几乎与 Ubuntu LTS 相同,但由于官方支持在最新版本发布时结束,实际上的支持保障低于 Ubuntu 过渡版本周期的支持,后者在新版本发布和旧版本支持结束之间提供三个月的重叠。
这种重叠,尽管几乎没人提及,却是最重要的因素之一,值得讨论——如果我们真的相信可以单独从某个方面有意义地分析某个因素的话。重叠告诉我们,不仅是作为系统管理员,我们更新系统的机会窗口,还包括我们的第三方软件供应商有多长时间进行测试并发布他们的新产品,同时保持与操作系统供应商的支持。这个重叠数字从最低的 0 年到最高的 10 多年不等。没有哪个数字是更好或更差的。重叠过大可能会引发严重问题,重叠过小则可能使得系统维护变得困难。
更复杂的是,有一个志愿者开发团队与 Debian 合作,为每个 Debian 发布提供非官方的长期支持。因此,虽然 Debian 团队的官方支持极为有限,但在实践中和非官方上,对旧版本的支持非常广泛,甚至可能超越任何其他支持供应商。这种情况导致 Debian 被视为稳定、保守、得到良好支持且非常稳固,但同时缺乏任何付费的主要供应商支持或官方 LTS 选项!
发布模型:滚动发布
关键的滚动产品包括:
-
Fedora Rawhide
-
OpenSUSE Tumbleweed
滚动发布意味着系统更新会立即提供。我们通常认为这意味着它们会按可用性发布,这可能意味着它们随时会发布,无论白天还是晚上,甚至可能一天发布多次。更新不会按照预定的时间表发布。一旦准备好,便会发布。当然,作为系统管理员,你可以控制它们何时应用。仅仅因为发布了更新,并不意味着它们会自动应用。
滚动发布是最为罕见的,正如你能想象的那样,它在与应用供应商的协调方面可能会遇到一些困难。该产品是一个不断变化的目标,几乎没有任何能力来指定兼容性。
滚动发布有一些有趣的现象需要考虑。首先,它们非常棒,因为你可以尽快获得所有最新的特性。无需等待发布周期的到来。如果操作系统中的一个组件产品的新特性发布就在你的快速发布准备上市的第二天,你将至少要等六个月才能通过任何主要产品将其引入。如果你使用的是慢速发布版本,可能要等两到五年!如果这是一个对你来说重要的特性,这可能是相当长的等待。
一个著名的等待新特性发布的例子发生在PHP 7发布时,它承诺通过更好的性能和特性彻底振兴 PHP 生态。坚持使用慢速发布产品的公司等待了多年才获得性能升级,而快速和滚动发布的分发在基准测试中已经超越了他们。在一个特性往往包括改进的安全功能的世界里,等待新特性可能也意味着安全风险。
为什么不手动更新包呢?
支持长期支持和慢速发布的分发者通常会声称,为了解决 LTS 生态系统显而易见的不足,我们可以以某种方式获取所需的包,并单独更新它们。一个很好的例子就是我提到的 PHP 案例。
这完全是可能的,而且人们经常这样做。但仅仅因为它可以做到,并不意味着它在逻辑上有意义。获取一个慢速发布、长期支持的操作系统的目的,字面上的整个目的,就是你希望有一个可以预测且得到支持的目标平台来运行应用程序。除此之外,LTS 版本的所有内容对客户组织来说都是负面的。
如果我们以一个假设的前提或者愿意的态度来对待 LTS 发布,简单地拆解操作系统并修改其中的部分以获取更新的特性,我们就在破坏它的功能。操作系统供应商将不再提供支持,或无法像以前那样了解完整的技术栈,应用程序供应商也将面对一个未知的目标平台。在这种情况下,我们实际上承担了慢速发布分发的所有复杂性、开销和风险,同时还承担了快速或滚动发布分发的问题和风险,并且额外增加了我们自己在供应商视野之外操作所带来的额外开销和风险。
这一切都是完全可行的,并且会顺利运行。但它能够工作并不应该让我们认为这是一个好主意。相反,它应该暴露出,如果我们并不真正相信 LTS 版本的价值,固守 LTS 版本的想法是多么根本上的愚蠢!
更好的方法是选择一个更快的发布发行版,它能够恰当地满足我们的需求,同时提供我们所需的支持级别,并获得更完整的支持和更新体验,减少我们重建厂商已经完成的工作的负担,同时避免离开经过测试的应用目标,自己去无缘无故地构建一些东西。
最佳实践:按工具的设计使用,不要试图绕过设计来满足情感或政治上的需求,比如在工具不能满足需求时坚持使用长期支持版本。
我们通常看到的根本错误是失去了目标的方向。假设一个企业的目标始终是最大化利润。出于实际原因,我们常常需要使用中介目标来精细化实现我们的主要目标。这样一来,我们可能将目标的一部分提炼为最大化厂商支持,这本身就是一个危险的中介目标。那么,许多组织在此过程中所做的,就是拿着这个值得怀疑的中介目标,尝试通过使用 LTS 版本来实现第一个中介目标,却忽略了一个事实:仅仅因为一个版本被指定为 LTS,并不意味着它一定提供更好的支持,或者满足我们的需求,完全错过了一个关键点——如果我们不按设计使用它,它就不再是真正的 LTS 版本,至少在实际意义上是这样的。
滚动发布比其他类型的发布更少见,既因为较少的厂商生产它们,又因为较少的公司部署它们。最著名的滚动发布是 OpenSUSE Tumbleweed。Tumbleweed 得到了如此多的关注,以至于 OpenSUSE 实际上大多数时候将其作为他们的主要产品进行推广。它绝不是二等公民。Red Hat 的滚动发布是 Fedora Rawhide。
滚动发布的支持引发了有趣的讨论,因为在其他发布中,我们会根据自初始发布以来的时间来考虑支持和支持时长。但对于滚动发布来说,并没有发布版本,因此在某种程度上,支持通常被认为只有一天,或者永远有效,这取决于你如何看待它。
很难理解或表达滚动发布如何提供支持的原因,不是因为滚动发布很复杂,而是因为它们非常简单,以至于没有掩盖我们尝试通过其他发布模型解决的真正问题:希望在避免更新的同时保持厂商支持。
无论采用哪种发布模型,如果我们保持系统持续更新,我们始终能够得到厂商的支持。改变的不是是否能够获得支持,而是为了获得支持,我们需要做什么。对于 LTS 发布版本,我们接受每五到十年就必须更新(或直接替换)系统。而对于快速发布,我们接受每六到十三个月就必须更新一次系统。至于滚动发布,我们只需要接受更新是一个日常的过程。只要我们接受这些要求,所有的方式都能在厂商支持产品的任何形式下提供永久支持。
选择适合我们工作负载的发布模型
既然我们已经理解了发布和支持模型,我们就需要思考如何将它们应用到我们自己的决策中。我们主要的需求将由我们的工作负载来定义,这一点一直如此。但当我们有选择时,我们需要做好准备,做出深思熟虑和战略性的决策。
总的来说,大多数人倾向于选择 LTS 发布版本,往往是出于不理性的选择,无法指出这种方式的任何实际好处。这种情感负担很可能源于早期 IT 时代,当时操作系统只有长期发布版本,而更新常常出现问题,且不稳定,往往导致系统崩溃。这个问题非常严重,以至于我们通常认为更新操作系统是无法完成的任务。这种情形(并且至今仍然存在)在 Windows 世界尤为显著,因为操作系统的主版本更新之间,确实经常发生大范围的系统崩溃,每次更新几乎都带来不可忽视的后果,而很少能安全地就地更新系统。这个假设已经成为了普遍观念,并且持续至今:升级操作系统时,我们需要部署新的系统,并将工作负载迁移过去。
这在 1990 年代及更早的 UNIX 世界中也大体成立,但由于接口标准的普及和缺乏基于 GUI 的应用程序,情况从未像现在这样严重。UNIX 系统上的工作负载类型通常能够在多个不同的系统上运行,因此相比之下,单一操作系统的版本差异显得微不足道。这种对旧系统,特别是 Windows 系统,无法优雅地处理更新的恐惧,不幸地影响了许多管理者,Linux 的决策常常因为这一点而建立在错误信息上。
这个问题还由于两个关键因素而加剧。首先,像 RHEL 和 Ubuntu LTS 这样慢发布的系统,更新周期很长,通常需要几年才会进行一次更新,在这段时间里,许多组件会发生变化。因此,LTS 更新通常会因为这个原因而带来一些复杂性。此外,许多选择 LTS 发布的 IT 部门还倾向于避免其他形式的更新,或者不及时更新 LTS 版本(有时导致一次更新多个版本),这样更新就会变得非常可怕。
当然,我们可以通过正确对待 LTS 版本并尽可能快速地更新它们来解决一些问题,但我们永远无法完全消除它们所带来的额外开销。相比之下,我们应该看看像 Fedora 或 Ubuntu 这样的快速发布产品,它们在其关联的 LTS 发布更新一次期间,发布大约四到六次。从表面上看,如果你害怕将更新视为一次可怕的经历,那么多次更新而不是一次更新听起来简直让人畏惧。然而,这其实是对概念的误用。
在大多数情况下,像 Ubuntu 这样介于 LTS 发布之间的中间版本本质上是增量发布。LTS 发布会获得所有相同的更改,但它会一次性获得许多更改。这使得更新变得更加可怕和复杂。将这些相同的更改拆分成四个较小的发布通常能让我们更早、更优雅地处理任何兼容性破坏问题。
滚动发布从逻辑上讲,进一步扩展了这些好处,并将每次更新的系统更改减少到最小的可能量。然而,这样做会产生一个新问题,那就是我们失去了为测试确定一个特定目标版本的能力。我们因此面临的风险是,当供应商在软件中进行测试时,它可能永远不会出现在我们的系统上,我们也会失去一些可预测性。实际上,滚动发布通常运行得相当顺利,并且在生产环境中完全有效,但它们确实通过失去可预测性和对第三方产品的集中测试增加了一些风险。
如果我们需要的系统本质上只由操作系统组件构成,那么滚动发布在支持、安全性和功能方面很容易处于领先地位。如果我们需要在操作系统之上支持第三方应用程序,那么我们大多数情况下会倾向于快速发布。
只有操作系统
不久前,我们还会笑话那个想法:我们可以部署一个桌面或服务器操作系统,然后不再在其上部署其他应用程序,只运行操作系统本身包含的组件。如果你来自 Windows 世界,那么考虑这个概念可能特别奇怪,因为操作系统本身几乎不包含额外的组件。
在 Linux 世界中,操作系统往往包含了很多附加组件。在我的桌面设备上,几乎每一个我使用的工具都包含在我的操作系统中。实际上,Chromebook 生态系统完全围绕这个概念设计。在 Linux 服务器中,我们也经常看到这种情况,许多组件,从 web 服务器到数据库,都包含在操作系统中。
当前运行的第三方应用程序的总体数量和脆弱性与十年前,甚至二十年前大不相同。另一个减少慢速发布发行版好处的因素。
理解支持和发布模型并非一项琐事,令人惊讶的是,几乎没有系统管理员真正花时间去了解它意味着什么。现在你已经了解了每种模型的含义,你将能够应用来自潜在新供应商的未来产品,并用它来为你的组织做出决策。你已经领先于行业中许多人,这些人往往忽视或忽略这些决策,仿佛它们微不足道,而实际上如果选择错误,它们可能带来重要的影响。
现在,我们已经深入探讨了许多关于 Linux 发行版的不同细节,接下来我们将把所有这些不同的方面和关注点结合起来,尝试制定一个全面的决策策略,以帮助我们为任何可能考虑的工作负载选择合适的发行版。
选择你的发行版
出人意料的是,选择哪个发行版,或者在 Linux 世界中通常所说的distro,可能比看起来要更具挑战性。你可能会是幸运的,所在公司已经有了预先确定的 Linux 发行版标准,且你只需遵循,这个问题对你来说早已解决。然而,随着公司逐渐意识到根据实际使用场景选择正确的发行版所带来的好处,以及意识到系统标准化并不像以前认为的那样能从保持系统一致性中受益,这种情况变得越来越少见。尽管如此,这种做法依然存在。
归根结底,优先考虑操作系统而非工作负载的选择基本上是没有意义的。强迫选择特定操作系统并基于此做出应用选择的价值相对较小。当然,在理想的世界里,各种因素都会被考虑和权衡,许可、支持知识、标准化及其他对操作系统选择有重大影响的因素将起作用,但与应用选择因素相比,它们通常显得较为微不足道。而且,假设我们正在考虑 Windows、macOS 和某些Linux 变种;如果仅仅是关于一个 Linux 选项与另一个的选择,那么各个发行版之间的差异就会大大减少。
当然,如果你处在一个拥有成千上万RHEL 服务器的环境中,并且有冲动为特定工作负载安装一个单独的 Ubuntu 服务器,那么根据我们所谈论的标准化规模,想方设法让工作负载在 RHEL 上运行,或者考虑其他工作负载可能是合理的。然而,IT 部门通常很少能处于拥有成百上千个同质操作系统镜像的情况。这是一个非常边缘的案例。
使用我们的工作负载来告诉我们现实选项的分布情况,然后应用任何同质性因素,我们可以考虑最适合应用和业务需求的发布和支持模型。当然,风险规避和偏好是一个重要因素。
不要害怕风险
每个业务,每个决策都有风险。在信息技术领域,我们最重要的工作之一就是评估风险,并将这些风险与机会和回报进行平衡。将风险因素简化为纯数学可能很难,甚至是不可能的,但即使我们不能简单地通过数字来显示任何给定决策中的风险和回报水平,这也不应改变我们目标的根本事实——那就是运用数学和逻辑来判断最佳的行动方案。
一个真正威胁到企业的因素,并且经常导致企业失败的,是风险规避。听起来似乎有些违背直觉,但其实并不然。如果风险规避或真正保守的商业实践是基于理性和逻辑的,那么这应当增加企业存活的机会。然而,情况通常并非如此。大多数风险规避是情绪化且不合逻辑的,而情绪化的决策,尤其是在面对风险时,几乎总是会导致更多的风险,而非减少,无论预期结果如何。就像在危险情况下恐慌反应很少能救你一样,情绪化的恐慌式商业决策几乎完全剥夺了你做出正确决策的能力。
作为 IT 专业人员,与企业合作,了解风险评估、因素和偏好水平,是我们为组织创造价值的重要部分。选择操作系统可能是一个单独的小组件,但它却是了解企业决策过程的常见途径。如果一个企业需要昂贵的供应商支持,或者因为害怕风险而延迟发布周期,而不是基于经过计算的风险评估,这就能告诉我们很多关于企业如何看待决策过程的信息。
最佳实践:企业应该让员工对决策过程的质量负责,而非决策结果。
这一最佳实践适用于组织的各个方面,绝不局限于选择 Linux 发行版或工作负载。这正是最佳实践的特点——非常普遍且广泛适用。
总结
在这一章节中,我们涵盖了很多内容,包括一些看似不重要的因素,而我相信,这些因素实际上在系统管理中往往是非常重要的。我们了解了 Linux 如何融入现代组织以及它的历史来源,这也许能帮助我们了解它未来的发展趋势。我们还深入探讨了开源许可协议以及软件许可如何影响我们与操作系统的工作方式。
我们已经了解了今天市场上的主要供应商以及他们的核心产品。接着,我们调查了发布和支持模式,既包括一般性的模式,也特别分析了今天市场上主要供应商的情况。然后,我们尝试将所有这些因素结合起来,形成一个决策过程,帮助我们选择适合工作负载的最佳发行版。
在我们的下一章中,我们将告别那种万尺高空的视角,深入探讨非常技术性的系统存储最佳实践领域。这是我最喜欢的系统管理领域之一!
第二部分:Linux 技术的最佳实践
第二节的目标是向你介绍技术最佳实践,并对系统管理功能核心的难度较大的技术概念的工作原理进行高层次的理解。我们将探讨设计元素和架构,这些内容很少被涉及,但对 Linux 来说至关重要。
本书的这一部分包括以下章节:
-
第三章,系统存储最佳实践
-
第四章,系统部署架构设计
-
第五章,补丁管理策略
-
第六章,数据库
第三章:系统存储最佳实践
系统管理中可能最复杂且最难理解的部分涉及存储领域。存储往往被忽视,极少教授,且常常被当作神话看待而非科学。存储也是最令人恐惧的领域,因为在存储中,我们的错误可能导致数据丢失,而没有什么比数据丢失更严重的失败了。
存储决策影响性能、容量、寿命,最重要的是耐用性。存储是我们误差最小的领域,也是我们能产生最大影响的地方。在其他规划和设计领域,我们通常能够获得相当大的容错空间,错误往往表现得比较优雅,比如系统没有达到预期的速度,或者成本略高于必要,但在存储领域,过度建设可能会使总成本翻倍,错误也很容易导致系统无法正常运行。失败通常远非优雅。
我们将讨论如何在 Linux 系统中查看和理解存储,并揭开存储的神秘面纱,让你能够以系统化和经验主义的方法进行操作。在本章结束时,你应该能够根据工作负载的所有需求,决定最适合的存储产品和设计。
在本章中,我们将探讨以下关键主题:
-
探讨存储中的关键因素
-
了解块存储:本地和 SAN
-
调查文件系统和网络文件系统
-
了解逻辑卷管理(LVM)
-
利用 RAID 和 RAIN
-
了解本地存储的复制
-
分析存储架构和风险
探讨存储中的关键因素
在考虑系统管理中的存储时,我们关注的是成本、耐用性、可用性、性能、可扩展性、可访问性和容量。在面对如此多的因素时,存储会让人感到不知所措,这也让它成为一个风险点,我们可能会忽视我们真正想要实现的目标。在每个存储决策中,我们需要始终关注这些因素。最重要的是,关注所有这些因素。我们很容易只关注其中几个,从而失去对整个图景的把握。
在大多数情况下,如果你研究那些未能满足业务需求的存储系统的事后分析,你几乎总是会发现,设计阶段忘记了一个或多个这些因素。很容易只专注于一两个关键因素,而忽视其他因素,但我们必须始终关注所有因素,才能确保存储的成功。
我们应该从单独分析每个因素开始。
成本
也许你会觉得,存储的成本不可能被忽视,但相信我,这种情况确实存在,并且发生得很频繁。通常,IT 是一个业务职能,所有的企业本质上都是为了赚钱,提供基础设施的成本必须始终考虑到利润。因此,基于这一点,IT 中的任何决策(或任何企业中的决策)都不应该在没有考虑成本的情况下做出。我们绝不应该让成本被遗忘,或者更糟的是,允许有人说成本不是问题,因为那永远不可能成立,完全没有意义。成本可能不是最主要的关注点,预算限制可能具有一定灵活性,但成本始终是重要的。
存储通常是生产系统中最昂贵的组成部分之一,因此,在处理存储时,我们往往比处理其他物理系统设计部分(如 CPU 和内存)时更加敏感成本。存储也通常是通过简单地投入更多资金来解决的,因此许多人在硬件规划时,倾向于过度建设,因为这比较容易。当然,我们可以始终这样做,只要我们足够了解自己的存储需求以及存储的工作原理,它就能正常工作,但不会过于昂贵。不过,当然,如果我们不具备成本效益,作为系统管理员就很难有效工作——这两者是相辅相成的。
耐用性
在存储方面,没有什么比耐用性更重要了:即存储机制抵抗数据丢失的能力。耐用性是可靠性的两个方面之一。对于大多数工作负载和大多数系统场景,耐用性是最为关键的。我们很少需要存储那些即使检索缓慢、延迟或昂贵,也无法可靠地恢复的数据。诸如数据可用性或性能等概念在数据丢失的情况下毫无意义。
耐用性还指的是数据能够抵抗损坏或衰退。在存储中,我们必须担心数据集的某些部分可能会失去完整性,而这可能是我们能够或无法检测到的。仅仅因为我们能检索到数据,并不能告诉我们我们所检索的数据是否完全符合预期。数据损坏可能意味着文件无法读取,数据库无法访问,操作系统无法启动,甚至更糟糕,它可能意味着会计应用中的一个数字变成了另一个不同但有效的数字,而这种变化几乎不可能被检测到。
可用性
传统上,我们主要从数据可用性的角度考虑数据的可靠性,尤其是在检索数据时。可用性通常被称为正常运行时间,如果存储不可用,那么你的工作负载也无法使用。因此,尽管可用性通常会让位于耐用性,但它仍然极为重要,是整体存储可靠性的两个关键方面之一。
有时可用性和性能会交织在一起。有些情况下,存储性能会显著下降,导致数据实际上变得无法使用。可以想象一下淋浴水滴每隔几秒才滴落一次,从技术上讲,水仍然存在,但它流经管道的速度太慢,无法有效使用。
我们稍后会深入讨论 RAID,但可用性和性能是很好的现实例子。一个著名的情况是,当一个或两个硬盘出现故障并被替换后,RAID 6 阵列仍然在线,并且正在进行主动重建(即通过元数据重新计算丢失的数据的过程)。RAID 系统常常因处理和写入的数据量过大而不堪重负,虽然阵列从技术上讲是在线且可用的,但其速度非常慢,以至于无法以任何有意义的方式使用,操作系统或应用程序试图使用时,由于极端的慢速,不仅无用,甚至可能因响应时间过长而错误报告存储设备已离线。可用性可能变得模糊不清,如果我们不小心的话。
性能
对于 21 世纪的计算机来说,存储几乎总是我们系统中最重要的性能瓶颈。CPU 和 RAM 几乎总是需要等待存储,而不是反过来。现代采用固态技术的存储设备在缩小存储系统与其他组件之间的性能差距方面做出了很大贡献,但这一差距依然相当大。
性能可能很难衡量,因为有许多不同的视角,而不同类型的存储介质通常具有截然不同的性能特性。比如延迟(数据检索开始前的时间)、吞吐量(也称为带宽,衡量数据流的速度)以及每秒输入输出操作数(IOPS,表示在特定时间内可以执行的存储相关活动次数)。大多数人仅从吞吐量的角度考虑存储,但传统上,IOPS 是大多数工作负载下衡量性能的最有用指标。
总是很容易将因素简化为一些易于理解和比较的内容。但是如果我们拿汽车做比较,我们可以将三种车辆进行对比:一种加速快但最高速度低,一种加速慢但最高速度高,另一种是拖车,虽然加速慢且最高速度低,但一次可以搬运大量物品。如果我们只关心延迟:即第一个数据包到达的时间,那么第一辆车会脱颖而出。如果我们关心如何快速地将一个小的工作负载从一个地方移动到另一个地方,第二辆车则表现得最好,这最像是在测量 IOPS。拖车则在我们关心的是在系统之间传输的数据量时无可匹敌,这就是我们的吞吐量或带宽。对于汽车,大多数人认为快车是指最高速度最快的车,但在存储领域,大多数人认为拖车的例子是他们想要衡量的目标,而不是在使用时感觉快的东西。实际上,性能是一个视角问题,不同的工作负载对性能的感知是不同的。
例如,备份涉及到稳定、线性的数据显示,并且最受益于以吞吐量为设计核心的存储系统。因此,磁带在备份性能方面表现优异,也解释了为什么旧的光学介质如 CD 和 DVD 曾经可以接受。但其他工作负载,比如数据库,则非常依赖于 IOPS 和低延迟,并且很少受益于总体吞吐量,因此更适合使用固态存储。其他工作负载,如文件服务器,通常需要性能和容量的平衡,使用旋转硬盘就可以很好地满足需求。你必须了解你的工作负载,才能设计出合适的存储系统来支持它。
当我们开始考虑突发性与持续性速率时,性能变得更加复杂。需要考虑的因素非常多,而且你无法绕过这个过程。
可扩展性
典型的物理系统部署如今预计在生产中使用四到八年,且听说有些系统的使用寿命远超这个范围也并不罕见。只要在 IT 行业工作一段时间,你很可能会遇到一些仍在运行并对公司成功至关重要的系统,这些系统已经连续使用了二十年甚至更久!由于存储系统预期拥有如此长的使用寿命,我们必须考虑该系统在这一潜在时间段内如何能够增长或变化。
大多数工作负载随着时间的推移会出现容量增长需求,设计一个可以根据需要扩展容量的存储系统,对于应对未知的挑战非常有益,同时也能让我们在前期投资较少,仅在需要和当额外容量变得必要时才增加支出。一些存储系统也可能在性能方面进行扩展。这种情况较少见,也较少被认为是关键需求,但即便是一个工作负载仅仅增加了容量需求,而不是性能需求本身,仅仅是更大的容量也可能要求提升性能,尤其是处理备份等任务时,因为大容量意味着更长的备份和恢复时间。
理论上,你也可能遇到一种情况,其中对可靠性的需求(持久性、可用性或两者)可能随着时间的推移而增加。这种情况是可能的,但往往会更加复杂。
存储是一个在灵活调整配置方面通常最难、但也是最重要的领域。我们无法总是预见到未来的需求。我们需要尽力规划,以便在可能的情况下留有调整的灵活性。
容量
最后,我们来看看容量,系统中可以存储的数据量。容量看似简单,但有时也会令人困惑。即使是简单的磁盘阵列,我们也必须考虑原始容量(所有设备容量的总和)和结果容量(可用于存储目的的可用容量)。许多存储系统有冗余设计,以提供可靠性和性能,而这会消耗原始容量。因此,我们必须了解存储配置如何影响最终结果。存储管理员会同时讨论原始容量和可用容量。
现在我们已经掌握了存储方面的关键要素,接下来我们可以深入学习存储组件如何组合成企业存储子系统。
理解块存储:本地存储和 SAN
我们今天会遇到的任何标准存储机制的根本概念是块设备。块设备是允许存储非易失性数据并可以按任意顺序存储和检索的存储设备。从实际意义上讲,标准块设备可以理解为硬盘。硬盘是典型的块设备,我们可以将任何其他块设备视为像硬盘一样工作。我们也可以将其称为实现驱动接口或外观。
许多设备都是块设备。传统的旋转硬盘、固态硬盘(SSD)、软盘、光盘、DVD-ROM、磁带驱动器、RAM 磁盘、RAID 阵列等都是块设备。从计算机的角度来看,所有这些设备都是一样的。这使得作为系统管理员的工作变得简单:一切都建立在块设备之上。
从系统管理员的角度来看,我们通常简单地将块设备称为磁盘,因为从操作系统的角度,我们无法准确识别设备,只知道我们正在使用块存储。这种块存储可能是物理磁盘,是建立在多个磁盘之上的逻辑设备,或者是建立在内存之上的抽象,磁带驱动器,或者远程系统,你可以随意猜测。我们其实无法真正分辨出来。对我们来说,它只是一个块设备,而由于块设备通常代表磁盘,我们称它们为磁盘。这虽然不一定准确,但却很有用。
本地附加块存储
最简单的块存储设备类型是那些物理附加到我们系统的设备。比如,我们对标准的内部硬盘就比较熟悉。如今,本地块设备通常通过 SAS、SATA 和 NVMe 连接。近年来,并行 SCSI(当时仅称为SCSI)和并行 ATA(即PATA,当时仅称为ATA或IDE)是标准。这些技术,以及一些较为冷门的技术,允许物理块设备直接附加到计算机系统上。
这是一种本地附加存储,我们大部分时间都会使用它。所有块设备都必须以某种方式本地附加才能被使用。所以这种技术始终具有相关性。
本地附加的块设备相较于其他替代方案有很多固有的优势。由于本地附加,它具有天然的性能和可靠性优势:系统尽可能简单,这意味着出错的机会较少。其他条件相同的情况下,简单的总是优于复杂的。存储就是一个很好的例子。更少的运动部件和更短的连接路径意味着我们能够获得最低的延迟、最高的吞吐量和最高的可靠性,同时成本最低!
当然,本地附加存储也有一些限制,否则没人会选择其他方案。本地附加存储的缺点是灵活性。确实有一些场景是本地附加存储无法满足的,因此我们有时必须选择其他替代方案。
存储区域网络(SAN)
本地附加设备的逻辑替代方案是远程附加设备,虽然我们可能会认为我们会简单地以这种方式称呼这些类型的块设备,但实际上并不是这样。远程附加设备使用网络协议将远程性的概念引入存储,而远程设备所使用的网络被称为存储区域网络,因此,常见的术语通常将所有远程块存储称为SAN。
SAN 的可怕术语
从技术角度讲,存储区域网络(SAN)应该是指一个专用网络,用于传输块设备流量,在非常专业的圈子里,这个术语是这样使用的。SAN 上的设备可以是直接的块设备、磁盘阵列以及其他类似的网络上的块设备。SAN 是网络,而不是一个你可以买到的东西。
然而,在日常用语中,通常将任何提供存储、实现块设备接口并连接到网络而非直接连接到计算机的设备称为 SAN。你每天都会听到这样的表达,比如你买了 SAN 吗?、我们需要一个 SAN 工程师、我和我们的 SAN 供应商谈过了、我们应该升级 SAN 吗?以及我们的 SAN 在哪里?去最近的 IT 硬件供应商那里,问他们卖不卖 SAN,他们会毫不犹豫地卖给你,这个术语已经如此标准,以至于可以打赌,如果你试图把 SAN 当成不是硬件设备的东西,他们会完全困惑,而这种设备是你放入硬盘并通过某种电缆连接到网络的设备。
由于存储既复杂又令人困惑,而且令人害怕,存储区域网络又在基础之上增加了额外的复杂性,这整个领域迅速被视为充满魔法和术语的黑匣子,术语也迅速恶化,大多数关于 SAN 的认知都基于误解和神话。常见的误区包括一些不可能的想法,比如 SAN 不可能出现故障、SAN 比没有网络层的相同技术更快、SAN 是其他技术的必需品等等。
只有当我们理解技术如何工作并避免陷入神话(和市场营销)时,才能成为有效的系统管理员。例如,如果我们认为某个设备是魔法般的,而不考虑其实际的风险状况,我们就无法做出有意义的风险分析或性能决策。
理论上,SAN 是一个非常简单的概念。我们将任何块设备,无论是像实际硬盘这样的物理设备,还是像磁盘阵列这样更复杂的概念,都将其封装在标准块设备协议(如 SCSI 或 ATA)中,并通过网络协议(如 TCP/IP、以太网或FiberChannel)传输。网络协议充当了一个简单的隧道,将块协议传输到远距离。就这么简单。归根结底,它仍然只是一个基于 SCSI 或 ATA 的设备,但现在可以在远距离使用。
当然,我们刚刚增加了一些复杂性,因此 SAN 自然比本地存储更脆弱。所有本地存储的风险和复杂性仍然存在,并且还增加了网络层和设备带来的复杂性和风险。风险是累积的。而且,额外的网络层、处理和距离都必然会给存储事务增加额外的延迟。
正因为这些因素,基于 SAN 的存储总是比其他相同配置的本地存储要慢且更脆弱。大多数神话所用来宣传 SAN 的那些因素,正是它们的弱点。
当然,SAN 的做法是有其优势的,否则它就没有存在的意义了。SAN 提供了三个关键特性:距离、整合和共享连接。
距离可以是从几英尺到跨越全球的任何距离。当然,距离越远,延迟越高,而存储通常对延迟非常敏感,因此远程块存储在超出本地连接技术范围的情况下很少有用。如果你必须通过广域网(WAN)获取块存储数据,你可能会遇到至少导致严重性能问题的延迟,并且通常会面临不可承受的带宽限制。典型的生产级块存储假定吞吐量是每秒多个 GB(大写 B,而不是小写 b)且延迟在毫秒级别,但 WAN 连接通常连一个 Gb/s 都难以达到,即便是最好的延迟通常也会是几毫秒,甚至几十毫秒以上!
整合曾是 SAN 的传统驱动力。因为许多系统可以通过单一网络连接到一个存储阵列,这使得第一次可以投资一个昂贵的存储系统,让多个物理分离的计算机系统同时使用。设备上的存储会被切分,每个连接到它的设备都能看到属于自己的独特存储部分。
当本地存储不再是本地存储
在 IT 领域,接口、抽象和不准确的术语层出不穷,这使得我们在很多时候很容易迷失,不清楚到底发生了什么。SAN 就是这样一个很容易让人感到困惑的地方。SAN 的特点是,它将远程的块设备呈现给计算机时,仿佛这个设备是本地的。但它也可以把本地设备表现为本地设备,尽管实际上它是远程的。我刚才说的是什么意思?
最好的例子就是外部 USB 硬盘。我们都在使用它们,它们非常常见。去任何本地的商场,你都可以买到。或者在线上订购。你大概在某个架子上放了五个,已经忘记了它们。虽然 USB 硬盘是外部的,但显然它仍然是本地的,对吧?
其实,说起来并不那么简单。没错,它在物理上是很接近的。但在技术术语中,远程意味着某个东西是通过网络连接的,而本地则是不通过网络连接的。无论某个东西有多远,决定本地和远程的因素是网络方面。否则,我位于德克萨斯的桌面和位于纽约的爸爸的桌面之间就因为有一整条电缆连接而被认为是物理连接的。
这带来了一个有趣的挑战,因为你看,USB 实际上是一个非常简单的网络协议,IEEE 1394 和 Thunderbolt 也是如此。如果你物理地解剖一个外部硬盘,你可以在某种程度上看到这一点。它们由标准硬盘组成,通常带有 SATA 接口,以及一个微型网络适配器,将 SATA 协议封装成 USB 网络协议并通过网络传输(通常只需两英尺的总距离)。
USB 及其类似设备可能不会让你觉得它是一个网络协议,但它确实是。它是一个二层网络协议,与以太网竞争,能够将多个设备连接到多个计算机,并且甚至能使用类似交换机的设备。它是一个真正的网络平台,这意味着通过 USB 连接的外部硬盘实际上是微型 SAN!这很难相信,但确实如此。考虑一下,你的思维可能会被震撼。
存储是大多数系统中最大的一笔开销,能够更高效地共享和切割存储降低了部署新物理计算机系统的成本。例如,硬盘可能有 1TB 的容量,但单个系统可能只需要 80GB 或 300GB,或者其他容量,而通过共享 SAN,数百台计算机系统可能共享一个存储阵列,并且每台计算机只使用它所需要的部分。今天,通过虚拟化,我们主要通过本地存储来实现这种效率,但在虚拟化广泛普及之前,只有像 SAN 这样的系统才能解决这个成本节省问题。因此,在 SAN 的早期,重点是成本节省,其他特性则是在后期才出现的。如今,这一价值大多已发生反转,因此通常比过度配置的本地存储更昂贵,但在某些情况下仍然存在。
最后一个价值是共享连接。这是指两个或多个计算机访问同一设备上相同存储部分的情况——看到相同的数据。这可能听起来有点像传统的文件共享,但实际上完全不是那样。
在文件共享中,我们习惯于计算机拥有一个智能的门控设备,用于调解对文件的访问。而在 SAN 中,我们必须记住,这是一个无脑的块设备,没有自己的逻辑。使用 SAN 将两个或多个计算机系统连接到单个逻辑块设备,意味着每台计算机都把存储看作是自己的私有、完全隔离的系统,并且对可能也连接到它的其他系统一无所知。这可能导致各种问题,从丢失的更改到损坏的文件,再到摧毁的文件系统。当然,有一些机制可以用于实现共享存储空间,但按照定义,它们并非由 SAN 实现,必须在计算机系统的更高层次提供。
共享 SCSI 连接
在 SAN 之前,或者说在 SAN 尚未普及和广泛应用的日子里,还有另一种技术允许两台计算机共享同一硬盘池:共享 SCSI。
使用这种技术,一根单独的 SCSI 带状电缆(通常可以连接八个、十六个,甚至三十二个设备。一个设备需要是控制器,通常在计算机的主板上。其他连接用于连接硬盘。但另一个连接器可以连接到另一台计算机上的控制器,两个计算机可以同时看到并访问相同的硬盘。
由于需要在两台物理计算机之间共享一根带状电缆的限制,这种技术非常有限且笨拙,但仍然可行。这种设置的主要价值在于允许一台计算机系统故障时,另一台计算机可以接管,或者将分配给单一数据集的 CPU 和 RAM 资源加倍,超出单一服务器机箱的容量。但存储组件的可靠性和性能限制使得该系统通常不够实用,因此这种技术在实际中很少实施。但从历史角度来看,它非常重要,因为它是现代共享块存储的基础,它曾是 1990 年代末期系统培训中的标准知识,也有助于我们理解今天 SAN 的工作方式——更优雅、更灵活,但本质上仍然相同。
今天,共享块存储连接的最大使用场景是为集群系统提供支持,这些系统设计用来将这种存储作为虚拟化的共享后端存储。大约在 2010 年时,这一方式最为流行,但如今已经被其他方法取而代之,来解决这种需求。现在这会是一个相对特殊的系统设计。然而,我们很快会看到,这里使用的技术将被改造用于其他存储模型。
SAN 的世界有许多流行的连接技术。有些超简单的 SAN 传输,简单到没有人认为它们是 SAN,包括 USB、Thunderbolt 和 IEEE1394/Firewire。然后是一些常见的企业级 SAN 协议,如 iSCSI(通过 IP 的 SCSI)、光纤通道、FCoE(以太网光纤通道)、FC-NVMe(光纤通道上的 NVMe)等。每种 SAN 协议都有其自身的优点和挑战,通常供应商只提供他们自己设备中的一小部分选择,因此选择供应商通常会限制你的 SAN 选项,而选择 SAN 选项则会限制你的供应商选择。理解所有这些协议将我们从系统世界带入网络世界。作为系统管理员,你很少有机会选择或影响 SAN 设计中的选择,通常这将由存储、网络和/或平台团队为你决定。如果你确实能够在这个领域产生影响,那么就需要对这些技术、它们的优点以及它们如何适应你的工作负载进行深入研究,但这远远超出了本书的范围。
块存储并不会消失。尽管我们对新的存储技术(如对象存储)感到兴奋,但块存储仍然是所有其他存储类型的基础。我们必须在物理上和逻辑上了解块设备,因为在我们的存储平台的各种方式中,我们将使用它们作为构建块。块存储功能强大且普遍存在。它代表了我们在工程阶段中与之交互的大多数存储,并且预计将在未来几十年内继续保持核心地位。
当决定使用本地存储还是远程块存储时,有一个有用的经验法则:在本地存储能够满足需求之前,您总是希望使用本地存储。或者在没有其他选择之前,您从不想使用远程存储。
调查文件系统和网络文件系统
在块存储的顶部,我们通常找到一个文件系统。文件系统是计算机系统上主要(我指的是,它们构成了 99.999%或更多用例的)最终数据存储的方式。文件系统是我们所知的,在计算机存储中保存文件的工具。
文件系统是一种位于块存储之上的数据组织格式,提供了一种使用文件类比来组织、识别、存储和检索数据的机制。您每天在所有设备上都在使用文件系统。即使在您看不到它们的情况下,无论是在您的桌面、手机甚至 VoIP 电话或微波炉上!文件系统无处不在。
文件系统实际上是数据库。
如果你想和我一起稍微“极客”一下,并且诚实地说,你正在阅读一本关于系统管理最佳实践的书,所以我们都知道你喜欢深入了解一些严肃的细节,我们可以看看文件系统的真正含义。在其核心,文件系统是一个 NoSQL 数据库,具体来说是一个文件数据库(本质上是一种专门的文档数据库),它使用原始块设备作为其存储机制,只能存储和检索文件。
还有其他专业数据库直接使用块设备(在处理数据库术语时通常称为原始存储),但它们很少见。文件系统是一种如此常见的数据库类型,比所有其他数据库类型加起来都要常见,以至于没有人谈论或认为它们实际上是数据库。但在幕后,从各个方面来看,它们都是真正的数据库。
为了进行直接对比,无论类型如何,标准数据库都有标准化的存储格式、检索格式、数据库引擎(驱动程序),并且在某些情况下,还会有数据库管理层(它通常允许在同一系统接口中使用多个数据库工程师),以及用于访问数据的查询接口。无论你比较 MongoDB 还是 MS SQL Server,你会发现它们的文件系统行为是一样的。磁盘上选择的文件系统格式就是存储格式,检索格式就是 文件,数据库引擎就是文件系统驱动,Linux 中的数据库管理系统是虚拟文件系统(我们稍后会讨论),查询语言是实现于 C 语言中的一系列底层 POSIX 命令(同时我们还可以使用一些简单的基于 Shell 的抽象命令来提高便利性)。与标准数据库相比,根本无法区分它们!非常酷的技术。
一旦计算机系统部署完成,几乎所有从存储角度做的操作都涉及到文件系统的操作。在工程阶段,我们往往会过多关注块存储,而在运维阶段,则会更多关注文件系统。但显然,在将系统部署到生产环境之前,我们必须妥善规划文件系统。文件系统的正确规划其实是一个常被忽视的环节,很多人只是接受默认设置,很少考虑文件系统的设计。
大多数操作系统都原生支持几种不同的文件系统。在大多数情况下,一个操作系统有一个明显标准的主文件系统,并且还会有一些特殊的文件系统,这些文件系统通常用于特殊硬件设备,或者是为了兼容其他系统。例如,Apple macOS 在执行所有正常功能时使用 APFS(Apple 文件系统),但在处理光盘时使用 ISO 9660,在与 Windows 存储设备(如 USB 存储棒或外部硬盘)兼容时使用 FAT32 和 exFAT。Windows 操作系统也类似,不过它使用的是 NTFS,而不是 APFS。最近,Windows 添加了一个替代文件系统 ReFS,用于特殊需求,但它并不常见,且使用者不多。
然而,在 Linux 中,我们有多个主要的文件系统选项和数十种专用文件系统选项。我们无法在此一一介绍它们,但我们将讨论几个最重要的文件系统,因为理解它们的存在意义以及选择合适文件系统的时机非常重要。幸运的是,在生产环境中,我们实际上只需要关注几个关键的文件系统。如果你对文件系统感兴趣,可以深入研究许多 Linux 文件系统选项,以了解更多关于文件系统设计和历史的信息,或许你还会找到一个适合特殊用途的文件系统!
目前我们需要关注的关键 Linux 文件系统有:XFS、EXT4、ZFS 和 BtrFS。这四种文件系统几乎涵盖了我们日常使用的所有操作。还有一些不那么流行,但已经很好集成并且工作非常稳定的文件系统,如 JFS 和 ReiserFS,虽然它们几乎不会在生产环境中出现。还有一些较旧的文件系统,如 EXT2 和 EXT3,已被更新版本所取代。另有一些标准文件系统,如 Windows 的 NTFS 或 BSD 系列的 UFS,可以在 Linux 上使用。还有像 ISO 9660 和 FAT32 这样的标准小众文件系统,我们之前提到过。Linux 在每个方面都提供了选择,文件系统的选择便是其灵活性的一个典型例子。
EXT:Linux 文件系统家族
几乎每个操作系统都有自己的、独特的文件系统,作为其本地或默认使用的文件系统,并且与操作系统紧密相关,Linux 也不例外……开个玩笑,实际上 Linux 正是一个例外,这一点令人惊讶,因为 Linux 在文件系统选项上的强大远超其他任何操作系统。Illumos 有 ZFS,FreeBSD 有 UFS,Windows 有 NTFS,macOS 有 APFS,AIX 有 JFS,IRIX 曾有 XFS,等等。Linux 确实没有属于自己的文件系统,但它几乎包含了所有其他系统的文件系统。
大多数人都把 EXT 文件系统家族看作是 Linux 的本地文件系统,确实没有其他文件系统能与之相提并论。在 Linux 开发初期,早在任何人实际运行它之前,MINIX 文件系统被移植到 Linux 上,成为默认的文件系统,随着这个新操作系统的崛起而广泛使用。但是,正如名字所示,MINIX 文件系统原本是 MINIX 的本地文件系统,早于 Linux 出现。
就在 Linux 发布的第一年,EXT 文件系统(或 MINIX 扩展文件系统)应运而生,它以 MINIX 文件系统为基础,并且如你所料,加入了许多新特性,主要集中在时间戳处理上。
随着 Linux 的发展,EXT 文件系统也在不断发展,仅仅在 EXT 发布一年后,它的继任者 EXT2 就作为一次重要的升级发布,将 Linux 的文件系统生态系统从一个爱好型系统转变为一个严肃的企业级系统。EXT2 从 1993 年推出开始,几乎独占了 Linux 生态系统,直到 2001 年 Linux 经历了一次文件系统革命。EXT2 是如此重要的进步,以至于它被回移植到 MINIX 本身,并且出现了 Windows 和 macOS 等其他操作系统的驱动程序。可能没有任何文件系统比 EXT2 更加标志性地与 Linux 相关联了。
到了 2001 年,许多操作系统开始寻求更先进的文件系统技术,以在市场中获得竞争优势,Linux 通过引入更多的文件系统选项,并且在 EXT2 上添加日志功能,将其版本更新为 EXT3,从而实现了这一点。这为 EXT 文件系统家族带来了急需的稳定性。
又过了七年,我们对 Linux 的准原生文件系统进行了一个重要的升级,推出了 EXT4。令人惊讶的是,EXT3 和 EXT4 的主要开发者表示,尽管 EXT4 是一个巨大的进步,但它本质上仍然是 1980 年代技术的权宜之计,主要是在原有基础上进行改进。文件系统设计原则在 2000 年代初期有了飞跃发展,而 EXT 系列很可能已经走到了发展的尽头,但它仍然具有很长的使用寿命。
我将深入探讨每种主要文件系统选项的一些细节,但需要明确的是,这只是一个粗略的了解。文件系统的细节会迅速变化,并且在不同版本或实现中有所不同,因此对于最大文件大小、文件数量、文件系统大小等非常具体的细节,请参阅 Wikipedia 或文件系统的文档。你不需要记住这些细节,也很少需要了解它们。在 1990 年代,文件系统的限制非常明显,你必须时刻警惕并在每个环节绕过这些限制。如今,我们将使用的任何文件系统几乎都能应对我们遇到的任何挑战,因此我们真正需要理解的是不同产品的优缺点,以及何时在高层次上选择使用哪一个。
EXT4
Linux 作为一个类别,并没有像其他操作系统那样有默认的文件系统,但如果你今天想要主张某个文件系统应当被称为默认文件系统,那么这个荣誉应该归于EXT4。目前,部署最广泛的 Linux 操作系统选择 EXT4 作为默认文件系统,而不是其他任何文件系统。但这种情况正在开始发生变化,因此 EXT4 在未来几年内保持主导地位的可能性不大。
EXT4 的速度合理,可靠性强,灵活性高,广为人知,能够满足几乎任何部署的需求。它是 Linux 文件系统中的全能选手。对于典型的部署,EXT4 的表现相当不错。
EXT4 是我们所说的纯文件系统,这意味着它仅仅是一个文件系统,不做其他任何事情。这使得它更易于理解和使用,但也使得它的功能更加有限。
XFS
与 EXT 系列一样,XFS 源自 1990 年代初期,来自 Linux 的竞争者——SGI 的 IRIX UNIX 系统。它具有悠久的历史和强大的稳定性,并且在 2001 年被移植到 Linux,这与 EXT3 发布的年份相同。二十年来,EXT3/4 和 XFS 一直在 Linux 管理员(以及 Linux 发行版的开发者)中竞争,争夺默认文件系统的位置。
XFS 也是一个纯文件系统,并且非常常用。XFS 以其极高的性能和可靠性而著称。有时,高性能应用程序(如数据库)会特别推荐使用 XFS,以保持它们在高峰期的运行。
当系统管理员故意选择文件系统而不是简单地接受默认设置时,XFS 可能是部署最多的文件系统,也可能是应用程序供应商最推荐的文件系统,而且它是我自己在大多数存储需求非凡的工作负载中的个人选择。
多年来,EXT4 和 XFS 在流行度上一直在交替变化。我个人的观察是,XFS 在这些年中逐渐领先。
与 EXT4 相比,XFS 常被引用的一个警告是 EXT4 能够在部署后对卷进行缩小或扩展。XFS 可以扩展,但不能缩小已经部署的卷。然而,在一个正确部署的生产系统中,缩小文件系统几乎是闻所未闻的,因此这通常被视为琐事,与文件系统决策无关(尤其是在薄配置块存储出现之后)。
ZFS
ZFS 于 2006 年发布给 Solaris,ZFS 通常被认为是现代文件系统设计的基础。当 ZFS 的开发工作在 2001 年开始时,业界已经开始非常认真地对待文件系统设计,并且许多新的概念定期被引入,但 ZFS 确实将这些设计范式提升到一个新的高度,至今 ZFS 仍在许多领域中处于领先地位。
ZFS 其实有三个高层次的领域,它试图彻底颠覆文件系统行业。首先是容量:ZFS 能够解决比任何之前的文件系统多几个数量级的存储容量。其次是可靠性:ZFS 引入了比其他文件系统更强大的数据保护机制,使其能够以显著的方式防止数据丢失。第三是集成性:ZFS 是第一个真正的非纯粹文件系统,它代表了一个文件系统、一个 RAID 系统和一个逻辑卷管理器,三者都集成在一个单一的文件系统驱动程序中。我们将在本章后面详细讨论 RAID 和 LVM。这个集成性非常重要,因为它使得存储层能够像从未有过的那样相互通信和协调。像 EXT4 和 XFS 这样的纯文件系统可以使用这些技术,但通常是通过外部组件而非集成的方式。
虽然 ZFS 并不新颖,它至少在生产系统中已经使用了十五年,但对于 Linux 的发布而言,它是相当新的。在为 Linux 提供 ZFS 移植版本之前,花费了多年时间,而且又有许多年因许可问题,ZFS 没有以可消费的格式发布给 Linux。如今,唯一一个正式支持并打包 ZFS 的主要 Linux 发行版是 Ubuntu,但 Ubuntu 在市场上的主导地位使得 ZFS 自动广泛可用。目前,距离 ZFS 可以用于 Ubuntu 上可引导的根文件系统还不到两年。因此,ZFS 在生产环境中的 Linux 系统中仍然是以一种广泛可访问的方式相当新的。现在,由于 ZFS 已经可用,它的使用似乎正在迅速增长。
ZFS 代表了截至目前 Linux 平台上最先进、最可靠、最具可扩展性的文件系统。需要注意的是,从纯粹的文件系统性能角度来看,ZFS 并不是以性能突出而闻名。虽然存储性能调整在文件系统层面上很少被认为是有价值的,但当它成为必要时,现代文件系统由于其额外的可靠性,通常无法与较旧、更基础的文件系统竞争。必须指出这一点,因为人们常常默认现代系统也会自动更快,但实际上情况并非如此。
BtrFS
读作Butter-F-S,BtrFS是当前 Linux 本地文件系统的重要尝试(在 2000 年代初曾有过一次名为 ReiserFS 的尝试,虽然取得了一些进展,但由于非技术原因最终失败)。BtrFS 旨在模仿 ZFS 的工作方式,但它是本地化的 Linux 文件系统,并且具有兼容的许可证。
BtrFS 在许多特性上落后于 ZFS,许多功能仍未实现,但工作仍在继续。BtrFS 依然充满活力,越来越多的 Linux 发行版开始支持它,甚至选择将其作为默认文件系统。BtrFS 似乎是 Linux 长期未来中最有可能的选择。
像 ZFS 一样,BtrFS 是一个现代化、深度集成的文件系统,开始包含存储堆栈中 RAID 和 LVM 层的功能。当前,BtrFS 的性能是其最弱的环节。
Stratis
鉴于其行业支持,我们需要提到 Stratis。Stratis 本身并不是一个文件系统,本质上它更像是一个文件系统。Stratis 试图利用现有的 XFS 和标准 Linux LVM 层,构建集成(或卷管理文件系统)功能,如 ZFS 和 BtrFS。
在早期的 IRIX 上,XFS 设计用于与 IRIX 的本地 LVM 一起使用,两者自然地集成,提供的功能与今天的 ZFS 或 BtrFS 非常相似。当 XFS 被移植到 Linux 时,关联的 LVM 层并没有被移植,而是使本地的 Linux LVM 与其兼容。XFS + LVM 一直是业界的标准做法,而 Stratis 仅仅是试图提供一种更易于访问的方式,同时整合最佳实践和简化管理。
这总结了你可能遇到或需要选择的四种当前生产环境中的文件系统选项。请记住,你可以在单一系统上混合使用不同的文件系统。事实上,使用 EXT4 作为基本操作系统功能的启动文件系统,同时依赖 XFS 作为高性能数据库存储文件系统,或者依赖 BtrFS 作为大文件服务器的文件系统,这种情况非常常见。根据每个文件系统层的工作负载选择最合适的文件系统。不要觉得你只能在所有系统上使用同一个文件系统,更不要觉得在一个系统内必须统一使用一个文件系统!
文件系统的许多技术细节都涉及到处理在块设备上查找和存储数据的算法。这些算法的细节远远超出了本书以及系统管理的范围。如果你对文件系统感兴趣,学习数据是如何存储、保护和从磁盘中检索的,可以说是非常迷人的。对于系统管理任务而言,理解文件系统的高层次内容就足够了。
可惜的是,没有办法提供一个关于文件系统选择的真正最佳实践。你不太可能在生产环境中需要认真考虑使用这里未提到的任何稀有文件系统,但这里列出的四个文件系统都有有价值的使用案例,所有这些都应该考虑。通常,文件系统的选择并不是孤立做出的,除非你在处理一个非常特定的产品,该产品需要或推荐使用某个特定的文件系统以支持某个功能。相反,文件系统的选择通常会依赖于许多其他存储决策,包括 RAID、LVM、物理支持需求、驱动介质等。
集群文件系统
到目前为止我们讨论的所有文件系统,无论它们多么现代,都是标准文件系统或非共享文件系统。它们仅在访问保证仅来自单一操作系统时才可行。在几乎所有情况下,这样是完全足够的。
然而,回想一下我们在讨论 SAN 时提到的,我们提到过有些使用场景可能需要多个计算机系统能够同时读取和写入同一区域的存储。集群或共享存储文件系统就是能实现这一点的机制。
集群文件系统的工作原理与传统文件系统相同,但它们具有额外的功能,能够将锁定和共享信息写入文件系统,使多个计算机系统能够协调它们之间连接的节点使用文件系统。在标准文件系统中,只有一台计算机在访问文件系统,因此知道哪个文件已打开、文件何时已更新、写入何时被缓存等都在内存中处理。如果两台或更多计算机尝试共享来自传统文件系统的数据,它们不能在内存中共享这些数据,因此不可避免地会因为相互覆盖对方的更改、未能检测到更新的文件,以及各种由于过时的写缓存导致的糟糕情况而导致数据损坏!
由于这些系统唯一共享的组件是文件系统,因此所有访问文件系统的节点之间的通信必须在文件系统内部进行。实际上,除非使用一种不再是共享存储而是共享计算的机制,否则没有其他可行的方法,而这种机制要复杂得多,成本也更高。
为了简单描述集群文件系统的工作原理,我们可以将每台计算机视为通过文件系统得知,某个块设备(硬盘)上的特定区域被严格格式化并预留出一个固定大小的空间,用于记录节点与文件系统交互的当前状态。如果节点 A 需要打开文件 X,它会在该区域记录下它正在保持该文件打开的状态。如果节点 B 删除一个文件,它会在该区域记录下它正在删除该文件,并会在文件删除后进行更新。节点 C 通过读取文件系统中的这一小部分内容,能够知道正在进行什么操作。所有连接的节点都知道不缓存该区域的数据,记录它们计划执行的任何操作,并记录它们所做的任何事情。如果有任何节点行为不当,整个系统会崩溃,数据将丢失。
当然,正如你所看到的,这至少会带来很大的性能开销。而且这个系统必然需要所有连接节点之间的绝对信任,因为访问控制和数据完整性控制完全依赖于各个节点。没有,也不可能有任何机制强制节点正常工作。节点必须自愿遵守规则。这意味着,代码中的任何 bug、内存故障、任何拥有 root 权限的管理员、任何能够访问单个节点的恶意软件等等,都可以绕过任何和所有控制,读取、修改、销毁、加密等,任意程度地进行操作,并且我们通常认为能够保护我们的所有安全控制都不存在。共享存储非常简单,但由于我们习惯了存储抽象,反而变得难以想象任何存储系统会如此简单。
和常规文件系统一样,Linux 有多个集群文件系统,这些文件系统我们经常会见到。最常见的是 GFS2,其次是 OCFS2。
和 SAN 一样,集群文件系统也遵循相同的规则:你不会想要使用它们,除非你必须使用。
网络文件系统
网络文件系统总是有点难以描述,但从你看到的时候就知道了的现象来看,它们能很好地被理解。与常规文件系统不同,常规文件系统依赖于块设备并提供以文件形式访问存储的方式,而网络文件系统则将文件系统扩展到网络上。这听起来很像 SAN,但它们实际上非常不同。SAN 是通过网络共享一组块设备,而网络文件系统则是通过网络共享文件系统。
网络文件系统非常常见,你可能每天都会看到它们,但我们常常没有意识到它们到底是什么。我们通常把网络文件系统称为共享或映射驱动器,而标准的协议有 NFS 和 SMB(有时也叫 CIFS,这其实并不完全准确)。实现网络文件系统的服务器被称为文件服务器,如果你将文件服务器做成设备,它叫做 NAS(网络附加存储)。正因如此,网络文件系统也常常被认为是NAS 协议,就像块级网络协议被认为是SAN 协议一样。
与共享块协议不同,网络文件系统是智能的,共享存储的机器拥有一个它理解的本地文件系统,并且对涉及的文件有一定的智能,这样像文件锁定、缓存、文件更新等概念就可以通过一个单一的守门员来处理,该守门员能够执行安全性和完整性验证,而且不需要信任访问节点。关键的区别在于,SAN 只是盲目地连接到网络的存储,它可以简单到只是一个硬盘上连接的网络适配器(实际上它通常就是这样)。而实现网络文件系统的设备,则是一个服务器,要求有 CPU、内存和操作系统才能工作。共享块存储几乎只在少数受控的服务器上使用。网络文件系统可以在几乎任何 SAN 可以使用的地方使用,但它们也常用于直接向最终用户设备共享存储,因为它们的强大安全性、易用性和对终端节点信任的缺乏,使它们在 SAN 无法部署的地方变得非常有用。
网络文件系统作为一个额外的网络启用层运行在传统文件系统之上,并不取代我们已经拥有的磁盘上的文件系统。在谈到接口时,我们会描述网络文件系统为消耗文件系统接口,同时也呈现文件系统接口。基本上,它就是文件系统进,文件系统出。
就像传统文件系统一样,Linux 实际上提供了许多网络文件系统选项,其中许多都是历史性的或极其小众的。一个常见的例子是Apple 文件协议或AFP(也叫AppleTalk),Linux 也提供这种协议,但今天已经没有任何生产操作系统在使用它。如今,只有 NFS 和 SMB 在任何实际工作中有应用。
NFS
原始的网络文件系统在广泛使用中,字面上也就是这个名称的来源,NFS可以追溯到 1984 年!NFS 不能是 Linux 的原生协议,因为它早于 Linux 出现七年,但自诞生以来,NFS 一直是所有基于 UNIX 或受其启发的操作系统中的默认网络文件系统,并因此代表了一个相当重要的标准。由于今天 Linux 如此突出,大多数人把 NFS 当作是Linux 的协议。
NFS 几乎在所有系统上都有提供。任何 UNIX 系统,甚至 macOS,都提供 NFS,Windows Server 也支持 NFS!NFS 是一种开放标准,几乎是普遍存在的。NFS 通过简单易用、网络稳健且通常表现良好的特点保持了其流行性。NFS 在服务器中仍然被广泛使用,尤其是在需要系统之间直接文件共享的备份系统中。
SMB
Server Message Block(SMB)协议早于 NFS,最初于 1983 年推出。这些确实是非常古老的协议。直到 1990 年代微软开始积极推广 SMB,随着 Windows NT 平台在 1990 年代的崛起,SMB 才开始广泛使用并逐渐流行起来。
SMB 受益于微软大量使用映射驱动器在其服务器与工作站之间进行连接,这使得 SMB 协议在传统用户和技术用户中都非常显眼。
在 Linux 中,SMB 协议的支持由 Samba 包提供(Samba 这个名字其实是对 SMB 的一个玩笑)。Linux 对 SMB 的支持很好,但使用它比起 NFS 更为复杂。
在 Linux 上选择 NFS 或 SMB 进行文件共享,通常取决于具体的使用场景。如果主要使用 UNIX 系统,通常选择 NFS 更为合理。如果主要使用 Windows 系统,则一般选择 SMB。两者都非常强大且稳健,可以满足各种需求。
做出决策时,难度通常非常大,尤其是在可以通过完全不同的方式提供相同需求的情况下。例如,如果需要为虚拟化提供共享存储后端,可能有网络文件系统如 NFS,或者在 SAN 上使用集群文件系统如 GFS2。由于这两种方法涉及的每个方面可能都不同,包括供应商和硬件,因此通常需要在整个技术栈层面进行比较,而不仅仅是在网络技术层面进行比较。
现在,我们已经探索了文件系统技术,了解了 Linux 系统中多种实际的文件系统选择,并且看到文件系统可以是本地的或远程的,可以是单一访问的,也可以是集群的以支持多重访问。在此过程中,我们对如何做出文件系统选择和配置决策有了更好的理解。我们知道何时选择不同的文件系统技术,并且知道在我们可能没有专门探讨的新的或替代的系统中应寻找什么。文件系统不必令人害怕或困惑,它们可以是我们工具箱中的宝贵工具,用来微调我们的系统,提升安全性、可扩展性、访问性或性能。接下来,我们将探讨存储领域中最难理解的部分之一——逻辑卷。
了解逻辑卷管理(LVM)
我不喜欢用新这种词来形容那些在 1980 年代末就已经在使用的技术,但与大多数计算机存储概念相比,逻辑卷管理(LVM)确实相对较新,并且对大多数系统管理员来说,远不如其他标准存储技术那么知名。在 Linux 于 1998 年推出第一个广泛可用的产品之前,LVM 曾经仅限于极高端的服务器系统,微软在 2000 年跟进。如今,LVM 已经无处不在,并且通常在大多数操作系统中是原生且默认提供的。
LVM 是目前使用的主要存储虚拟化技术。LVM 允许我们将任意数量的块设备(通常称为物理卷)合并、分割或以其他方式修改它们,并将它们呈现为任意数量的块设备(通常称为逻辑卷)供系统使用。听起来可能很复杂,但实际上并非如此。通过一个实际的例子,我们会发现它实际上相当简单。
一个例子是,当我们有一个计算机系统并连接了三块硬盘时。它们可以是完全相同的,也可以是不同的。事实上,其中一个可能是传统的旋转硬盘,另一个是现代的固态硬盘,还有一个是外部 USB 硬盘(或者是 RAID 阵列、SAN,随你取名)。我们可以将这三块硬盘作为物理卷添加到我们的 LVM 中。LVM 允许我们将其视为一个单一的存储池,并将其转化为任何我们想要的配置。我们可能会将它们合并成一个逻辑卷,这样我们就能得到这三块硬盘的总存储空间。或者,也许我们会创建十几个逻辑卷,并将每个卷用于不同的目的。我们可以有任意数量的物理卷,也可以创建任意数量的逻辑卷。逻辑卷的大小可以是我们想要的任何大小(在某些情况下甚至可以超过总物理大小!)我们不再受到传统磁盘大小的限制。使用逻辑卷时,我们通常发现创建更多、更小的卷非常有用,这样可以更好地管理和隔离。
使用 LVM 时,我们可以将系统视为一个消费块设备并呈现一个块设备。由于 LVM 使用并提供块设备(也称为磁盘外观),它们是可堆叠的,意味着如果你愿意,你可以在一个块设备上使用 LVM 来创建一个逻辑卷,然后这个逻辑卷又被另一个 LVM 使用,再创建一个新的逻辑卷,以此类推。虽然这种方式并不实际,但它有助于我们理解 LVM 在存储栈中的位置。它总是处于中间,但除了在中间之外,它非常灵活。
LVM 只需要提供基本的块输入,块输出功能,就能成为一个 LVM,但通常还会添加其他功能,使 LVM 更加实用。一些常见的标准功能包括逻辑卷的在线调整大小、热插拔物理设备、快照功能、缓存选项和精简配置。
在 Linux 中,和大多数其他事情一样,我们不仅有一个,而是有多个逻辑卷管理器!随着近年来创建集成文件系统及其独立 LVM 的趋势,这种做法越来越普遍。目前在 Linux 生产环境中,我们有 LVM2、ZFS 和 BtrFS。你当然会认出后两者是我们之前提到过的文件系统。当大多数人在谈论 Linux 上的逻辑卷管理器时,他们指的是 LVM2,通常简称为 LVM。但 ZFS 和 BtrFS 的集成逻辑卷管理器也越来越受欢迎。
由于 LVM 的可堆叠特性,即它能够消费和提供块设备,我们可以选择将 LVM2 与 ZFS 或 BtrFS 一起使用,并且可以禁用它们的集成 LVM 层(因为它们不必要),或者如果它们有我们希望利用的功能,我们也可以继续使用它们!这简直是灵活性极致体现。
分区到底怎么了?
如果你还记得上世纪 90 年代在 IT 领域的工作,我们曾经经常讨论磁盘分区。那是一个常见的话题。如何设置分区,分多少个,基本分区和扩展分区,使用什么分区软件,等等。可以肯定的是,分区仍然存在,只是我们已经很久没有需要它们了(例如自 Windows 2000 或 Linux 2.4 以来)。
分区是一种非常僵硬的磁盘上系统,用于将物理磁盘切割成多个区域,每个区域都可以作为单独的块设备(即驱动器)呈现给系统。这样,分区就像是没有灵活性的超级基础 LVM。分区只能作为单个块设备的一部分存在,哪个区域属于哪个分区的映射信息保存在设备开头的一个简单分区表中。
分区是逻辑卷的前身,至今仍有人使用它们(但只是因为他们不熟悉逻辑卷)。分区缺乏灵活性,缺少诸如精简配置和快照等逻辑卷所能提供的重要选项,而且虽然技术上可以调整分区大小,但这既不灵活,又困难且极其危险。
LVM 提供了分区所提供的所有功能,并且拥有更多功能,而不需要放弃任何东西。多年来,分区(即将块设备分割成多个文件系统)的需求显著减少。在 1990 年代末期,即使是最简单的服务器,甚至是台式机,通常也需要有充分的理由将其划分为多个文件系统。如今,将多个块设备合并为一个文件系统已变得更为常见。这主要是因为文件系统的性能和可靠性发生了彻底的变化,而分区的驱动因素逐渐消失。今天仍然有必要进行文件系统划分的理由,但我们已经不需要那么频繁地这么做了。
目前许多机制,如备份工具,利用 LVM 层的功能执行任务,例如冻结块设备的状态,以便进行完整的备份。由于 LVM 在最终的文件系统层之下运行,因此它具备其他层所不具备的某些能力。LVM 是存储层,它提供的功能相对较少关键,但正是这里发生了许多神奇的事情。LVM 为我们提供了灵活性,使得在初始部署后可以修改存储布局,并且能够在块级别与存储系统进行交互。LVM 是现代二十一世纪操作系统提供使用体验的核心技术组件。
当然,任何新技术层都会有一些限制。LVM 增加了一个额外的复杂层,也给系统管理员带来了更多的理解内容。学习管理 LVM 并不是什么大工程,但比起没有 LVM 时需要学习的内容,它还是要多得多。LVM 还会带来一定的性能开销,因为它需要在物理设备和逻辑设备之间进行转换。通常,这个开销非常小,但依然存在。
总的来说,LVM 的好处远远超过了成本,越来越多的系统开始直接部署 LVM 层,而不询问最终用户是否需要它,因为越来越多的功能已经依赖于 LVM 层,而不允许系统在没有 LVM 的情况下部署,往往会让客户陷入困境,无法理解他们的系统为何无法达到预期,通常这种情况可能在初次部署后几个月或几年才会被发现。
像其他形式的虚拟化一样,存储虚拟化和 LVM 最重要的是 防止未知的风险。如果我们知道一个系统在整个生命周期内的所有使用情况,诸如调整大小、备份、整合等功能就几乎没有意义,但现实世界并非如此。
关于 LVM 的最佳实践通常认为是:除非你能明确提供充分的技术理由,证明 LVM 的开销会产生显著影响,并且这种影响超出了 LVM 提供的保护,否则始终部署 LVM。
逻辑卷管理器为强大的存储解决方案提供了一个关键构建块,在许多方面,它们将现代存储与传统计算系统区分开来。了解逻辑卷如何抽象存储概念,并使我们能够以我们想要的方式操作和构建存储,为我们提供了许多选择,并引导我们进入 RAID 和 RAIN 等附加概念,接下来我们将讨论这些概念如何利用 LVM 构建数据保护、扩展和性能能力。
使用 RAID 和 RAIN
我们已经看过了许多与存储接口的方式。但最令人兴奋的可能是当我们开始处理RAID(廉价磁盘冗余阵列)及其后代RAIN(独立节点冗余阵列)时。在深入讨论之前,必须指出,RAID 是一个庞大的话题,要真正有意义地讨论它需要一本书。理解 RAID 的工作原理以及理解其性能和风险细节所需的所有计算是一个独立的重大课题。我的目标是介绍这个概念,解释它如何融入设计,展示关于它的最佳实践,并为进一步的研究做好准备。
RAID 和 RAIN 是将多个存储设备(块设备)结合起来,利用设备的自然多重性(通常误称为冗余)来提供在单一硬盘中无法实现的性能、可靠性或可扩展性的一些组合。与 LVM 类似,RAID 和 RAIN 是中间层技术,消费块设备接口并提供块设备接口,因此可以叠加在 LVM 之上,LVM 之下,另一个 RAID 之上,或者在各种硬件设备的组合上,等等。非常灵活。
事实上,RAID 和 RAIN 实际上是 LVM 的特殊形式!没有人会这样讨论这些技术,如果你在公司圣诞派对上开始讨论 RAID 作为一种特殊的 LVM,你可能会引来一些奇怪的眼光,但它实际上就是。RAID 和 RAIN 是 LVM 功能的极端子集,关注点非常狭窄。实际上,通用 LVM 通常会内置 RAID 功能,而且集成文件系统的趋势是将 LVM 和 RAID 层都与文件系统集成。
RAID
RAID 是廉价磁盘冗余阵列(Redundant Array of Inexpensive Disks)的缩写,最初作为一套在块设备级别工作的技术被提出,用来将多个设备合并为一个。类似 RAID 的技术可以追溯到 1960 年代,RAID 这个术语和现代定义来自 1988 年,这意味着 RAID 实际上比更通用的 LVM 要早出现。
RAID 本质上是将多个块设备放在一起,并通过许多不同的数据存储机制(称为级别)使它们保持同步。每个 RAID 级别的工作方式不同,并采用不同的机制将底层的物理磁盘合并成一个虚拟磁盘。通过使多个硬盘像一个硬盘一样工作,我们可以根据需要扩展存储的不同方面,但在一个领域的收益通常会带来另一个领域的成本,因此理解 RAID 的工作方式非常重要。
RAID 是一个非常依赖系统管理员深入了解存储子系统内部工作原理的领域。令人惊讶的是,这也是一个极少数系统管理员真正理解其系统工作原理的领域。
虽然 RAID 被定义为一系列级别,但不要被迷惑。级别只是不同类型的存储,它们共享 RAID 的基本原理。RAID 级别并不是相互递进的,较高的级别并不代表某种内在上更优越的产品。
因为 RAID 实际上是一种 LVM,它可以位于存储栈中的任何位置,并且在实际应用中几乎无处不在。一些非常流行的 RAID 级别实际上是堆叠 RAID,利用了其设计的这一固有特性,最著名的就是 RAID 10。
RAID 也有硬件和软件两种变体。硬件 RAID 很像一个直接连接到显示器的显卡,它将工作从主计算机系统中卸载,并直接与硬件通信。硬件 RAID 卡正是执行这一任务,减轻主计算机系统的负载,直接与硬件存储设备接口,并可能提供一些特殊功能(如缓存)。而软件 RAID 则利用通常更强大的系统 CPU 和内存,并具有更灵活的配置。两种方法都是完全可行的。
每种 RAID 级别都有一组独特的属性,并且在不同的时刻使用各自有意义。RAID 是一个复杂的话题,值得单独成册深入探讨。RAID 并不是我们可以草率了解的一个话题,这曾经是存储领域的一个隐患。RAID 的风险因素常常被浓缩成一些毫无意义的陈述,比如一个 RAID X 级别的阵列可以从多少个驱动器故障中恢复? 这并没有任何意义,它的目的只是将一个非常复杂的东西简化为可以轻松记住或者直接放在图表上的内容。RAID 并不是这样的。每种 RAID 级别在性能、可靠性、成本、可扩展性、实际应用等方面都有一个复杂的背景故事。
RAIN
随着系统变得更大、更复杂,RAID 方法的局限性开始显现。RAID 简单且易于实现,但 RAID 缺乏灵活性,对于一些关键特性,如简单的大小调整、自动重平衡和灵活的节点大小,它处理得很差。因此,需要一种新的技术家族。
RAIN 摒弃了 RAID 基于的全块设备阵列方法,改为通过较小的块(通常是块)将存储分割,并在该级别处理复制。为了有效地做到这一点,RAIN 不仅必须理解这些块的概念,还必须理解它们所在的块设备(或磁盘),以及它们存在的节点。这种节点感知赋予了 RAIN 其名字:独立节点冗余阵列。
奇怪的是,在 RAIN 中,实际上并不是节点必须冗余,而是块,实际上你可以在单一物理设备上实现 RAIN,直接与传统 RAID 的最简单形式竞争,但这很少见。
由于 RAIN 处理的是块级复制,因此相对于 RAID,它可以有许多优势。例如,它可以灵活地使用不同大小的设备。不同大小的驱动器可以非常高效地被放入服务器并结合使用。
在 RAID 下,如果一个硬盘驱动器发生故障,我们需要一个能够接替它在阵列中位置的替代硬盘。这通常是个问题,尤其是在旧的阵列中。RAIN 可以通过允许阵列中的任何可用容量来吸收故障硬盘的丢失容量,从而避免这个问题。
RAIN 有多种实现方式,每种实现方式本质上都是独特的,因此我们无法以任何标准化的方式讨论它。今天大多数解决方案都是专有的,虽然一些著名的开源产品已经问世,并成为 Linux 生态系统的标准组件,但它们通常是独立于发行版的,且在我们使用时的行为很像专有产品。
未来,随着这些技术变得更加普及和被理解,我们可能会看到 RAIN 市场内的显著整合,或者至少是标准化。在那之前,我们需要以理解块复制如何工作的方式来接触 RAIN,并知道每种实现可能做出截然不同的设计选择。RAIN 可能内建在内核中,也可能作为更高层次的应用程序运行在堆栈中,在某些情况下,它甚至可能运行在虚拟机中,通过虚拟化在虚拟机监控器上运行!RAIN 如何应对丢失的硬盘、负载均衡、位置亲和性、故障丢失后的再平衡、修复后的重建等问题并没有任何标准来定义。使用 RAIN 时,必须深入研究和学习你将考虑的任何解决方案,并批判性地思考其工件如何随着时间的推移影响你的工作负载。
RAIN 几乎可以确定将是系统存储的未来。随着我们越来越多地朝着集群、超融合、云和类云设计发展,RAIN 显得越来越自然。随着理解的增加,RAIN 的采用将只会增加。尽管这项技术本身并不新颖,但这显然需要时间。
几乎所有我们将设计或支持的生产系统,无论是本地还是远程,都将使用某种形式的 RAID 或 RAIN。到现在为止,我们已经准备好思考选择何种 RAID 级别、配置或 RAIN 实现会如何影响我们的系统。花时间深入理解这些多设备聚合框架中存储因素如何相互作用,是系统管理员在各个领域最有价值的高级知识之一。在下一部分,我们将基于这些技术,看看如何通过外部系统或节点使本地存储实现冗余。
学习复制本地存储
可能是最关键的存储类型,也是最难理解的存储类型之一,就是复制本地存储或RLS。RLS 并不是一个难懂的概念,它其实很简单。但围绕着其他概念(如 SAN)有许多误解,这些误解模糊了 RLS 的功能。例如,许多人开始将共享存储作为外部存储或SAN的代名词。但外部存储并不意味着它是或可以被共享的,本地存储也不意味着它不能或不会被共享。
“复制本地存储”这一术语指的是两个或多个计算机系统,它们之间的本地存储是相互复制的。从每个计算机系统的角度来看,存储是本地附加的,就像正常情况一样。但是有一个过程会将数据从一个系统复制到另一个系统,这样在一个系统上进行的更改就会出现在另一个系统上。
复制本地存储可以通过多种方式实现。最简单且最早的方式是使用网络 RAID,即 RAID 技术通过网络来使用。镜像 RAID(也称为RAID 1)是实现这一目标的最简单技术,也是最好的示例。
有两种方式来处理这种情况,一种是热/冷配对,其中一个节点是热的,可以访问并写入存储,而另一个节点(或多个节点)可以从中读取,并且在原本的热节点失败或放弃控制时,假设其他节点能够接管成为热写节点。这种模型很简单,类似于许多传统的 SAN 共享存储模型。这种方法允许使用常规(非集群)文件系统,如 XFS 或 ZFS。
另一种方法是活/活系统,其中所有复制存储的节点都可以随时读取和写入。这要求与任何共享块存储一样的集群文件系统支持。就像两个节点同时使用 SAN 一样,RLS 集群中的节点将需要通过在集群文件系统的特殊区域存储其活动数据来进行通信。
复制本地存储可以为我们带来许多通常与 SAN 或其他外部存储相关的好处,即多个节点可以同时访问数据的能力。同时,它还具有本地性的好处,包括提高性能和弹性,因为依赖关系较少。当然,复制流量有其自身的开销,这需要考虑。有许多方式可以配置复制,有些开销非常小,有些则开销很大。
常见的误解是认为复制本地存储是新的、创新的或在某种程度上不寻常的。事实恰恰相反。实际上,鲜为人知的是,对于高可靠性的存储系统,RLS 始终被使用。无论是本地使用(即直接连接到计算系统),还是远程使用(意味着远程存储使用 RLS 以提高其可靠性),RLS 都是几乎所有真正高可用存储层的核心。
RLS 有多种形式,主要有网络 RAID 和 RAIN。我们可以在这种情况下称之为网络 RAIN,但我们并不这样做。与几乎总是仅限于本地的 RAID 不同,RAIN 几乎总是在 RLS 环境中使用,因此它的网络特性几乎是默认的,或者至少是网络选项。
Linux 上有许多形式的 RLS,因此我们无法真正讨论所有选项。我们将专注于一些更常见的选项。RLS 是一个领域,既有开源解决方案,也有商业和专有解决方案,性能、可靠性和功能各异,且实施方式常常截然不同。RLS 可能会为任何存储场景增加新的复杂性,因为你必须考虑本地存储通信、复制通信、节点间和远程存储之间的潜在网络通信(即本地存储位于其他节点上)以及算法和协议如何相互作用。
DRBD
Linux 上的第一个也是最简单的 RLS 技术是DRBD,即分布式复制存储系统,它是一个直接集成到 Linux 内核中的网络 RAID 层。维基百科表示 DRBD 不是网络 RAID,但随后又将其描述为完全的网络 RAID。它是否真的是网络 RAID 可能仅仅是语义问题,实际上在使用中,它与网络 RAID 在使用、描述,甚至底层实现上没有区别。像所有 RAID 一样,DRBD 消耗块设备并作为块设备出现,允许它像常规 RAID 和 LVM 一样,堆叠在存储栈的任何位置。
DRBD 基于 RAID 1(镜像 RAID)机制构建,因此支持两个或多个节点,每个节点获取一份数据副本。
DRBD 非常灵活且可靠,由于其简洁性,大多数系统管理员更容易清楚地理解它是如何工作的,以及如何融入存储基础设施。然而,由于 DRBD 限于通过镜像进行完整块设备复制,就像 RAID 1 一样,因此其扩展能力相当有限。单独使用时,DRBD 非常专注于经典的双节点集群或有大量计算节点需要共享少量相同数据的特定用途案例。
使 DRBD 更加灵活
由于 DRBD 本质上只是一个软件 RAID 工具,而且因为你对其有完全的管理权限,并且因为 RAID 作为一个 LVM 技术,具备在堆栈中任意位置灵活部署的能力,你可以将 DRBD 转变为比初看上去更具可扩展性的工具。但目前这个过程完全是手动的,尽管理论上你可以通过脚本或工具自动化这些过程。
我们可以使用的一项强大技术是通过额外的逻辑块设备来错开我们的 RAID 1,从而模拟 RAID 1E,其基本上类似于 RAID 1,但具有可扩展性。该技术的原理是将单个节点上的物理存储空间通过 LVM 技术逻辑性地划分为两部分(或理论上更多)。在标准的网络 RAID 设置中,节点 1 上的整个存储空间会镜像到节点 2 上的整个存储空间。现在由于我们在每个节点上划分了存储空间,我们将节点 1 的第一部分镜像到节点 2 的一部分;节点 2 也会这样做,但是是与节点 3;节点 3 同样与节点 4 进行镜像;这个过程将无限延续,直到终端节点编号的机器与节点 1 完成循环,每台机器的数据都采用 RAID 1,并且数据在两个其他节点之间分割作为镜像对。通过这种方式,我们可以使网络 RAID 1 环扩展到无限大。
这个技术确实非常强大。但它在文档编写和维护方面非常繁琐。如果你有一个静态的集群且不会变化,它可以非常有效。但如果你经常扩展或修改集群,它可能会成为一个相当棘手的问题。
DRBD 和大多数网络 RAID 技术通常具有良好的整体性能,更重要的是,其性能相当可预测。由于 DRBD 本质上提供最终的块设备,它本质上是本地的。为了远程访问 DRBD 资源,必须将 DRBD 作为构建块应用于一个 SAN 设备,然后将其共享到远程。这个过程当然只是语义上的问题。DRBD 始终是本地的,因为对 DRBD 来说,SAN 就是本地计算节点,SAN 接口是堆栈中的另一个更高层次,因此虽然 SAN 是远程的,但 DRBD 仍然是本地的!
Gluster 和 CEPH
Gluster 和 CEPH 完全是两种不同的技术,但它们都是免费的、开源的现代 RAIN 解决方案,专为 Linux 设计,提供高可靠性和高度可扩展性。这两种解决方案至少都提供了将存储设置为与计算节点本地化的选项。这两者都是非常复杂的解决方案,具有多种部署选项。我们不能简单地假设使用这两种技术中的任何一种就意味着存储是本地的还是远程的。就应用来说,本地化是更常见的情况,但两者都提供了构建一个可以远程访问的独立存储层的选项,如果设计成这样,它可以通过网络进行访问。
这些技术过于复杂,选项也太多,因此我们无法在此深入探讨。我们只能从非常高的层次上对其进行处理,尽管这应该足够满足我们的需求。
这种 RAIN 存储是处理大规模服务器池(计算节点)共享存储池的最常见方法。该技术使存储能够本地化,在发生故障时自动重新平衡,但很少能够保证数据本地性。整个组中的存储只是一个池。因此,数据可能有本地化的亲和性,但不像 DRBD 那样严格强制本地化。这给了 DRBD 更多控制,但 Gluster 或 CEPH 提供了更多的灵活性和更好的利用率。
专有和第三方开源解决方案
除了操作系统中自带或可能包含的 Linux 发行版组件外,还有许多第三方组件可以安装。几乎所有这些产品都属于 RAIN 类别,价格、支持和功能各异。一些值得了解的名字包括LizardFS、MooseFS和Lustre。
不可能涵盖所有可能的商业产品,这些产品可能已经存在或未来可能出现。RAIN 存储是一个正在发展的领域,仍然有许多厂商在这个领域生产产品,但并未广泛提供。在某些情况下,你可能会找到商业 RAID 或 RAIN 系统,这些系统只有在与某种类型的设备一起提供或在某些其他项目中包含时才能使用。但所有这些存储系统遵循相同的基本概念,一旦你了解了这些概念以及它们的工作方式,即使你之前没有使用过某个具体的实现,也能做出关于存储系统的正确决策。
存储的虚拟化抽象
在谈论存储时,往往很容易迷失方向,忘记了大多数情况下,存储根本不是我们作为系统管理员需要担心的问题!至少不像我们一直以来处理存储的方式。
存储管理员
在大型组织中,将存储和系统职责分开并不罕见,因为存储本身有许多复杂性和细微之处,成立一个专门团队来理解它们是有意义的。如果你曾在财富 500 强企业工作过,你可能见过这种情况。
这一问题的最大困境之一在于,将深刻理解工作负载的人与一些决定这些工作负载性能和可靠性的重要因素分开。分离往往还意味着核心架构决策需要通过政治手段而非技术手段来做出。如果使用本地存储,就无法在任何实际情况下将存储和系统团队分开。因此,许多组织使用了通常糟糕的技术设计决策,在组织内创建技能孤岛,而没有考虑这种做法会如何影响工作负载。SAN 技术的部署通常就是为了这个目的。
无论这种方法的有效性如何,实际使用时通常意味着存储脱离了系统管理员的控制。这极大地简化了我们的工作,同时在提供最终价值的能力上却使我们受到了很大的制约。我们可以请求某些性能或可靠性水平,并且必须信任我们的需求会得到满足,或者至少不会因存储失败而被追究责任。
同样,系统和平台团队分离也很常见。在这种情况下,我们看到了同样的效果。管理底层虚拟化的虚拟化平台团队将提供存储容量给系统团队,而系统团队则必须简单地使用提供给他们的资源。
在这两种情况下,存储都从系统中抽象出来,并简单地作为盲目块设备提供给我们系统团队。当这种情况发生时,我们仍然需要理解底层组件的工作原理,知道该问哪些问题,最终仍然需要在提供的块设备上管理文件系统。块设备接口依然是存储或平台团队与系统团队之间的通用交接接口。
另一个附带说明:同样的情况通常也会发生在平台团队。它们可能需要从存储团队获取盲目存储,应用到虚拟化层,然后将该块设备划分成更小的块设备,提供给系统团队!
今天在大多数情况下,我们的 Linux 系统会以某种方式被虚拟化。我们必须全面了解整个堆栈的存储,因为 Linux 本身可能是虚拟化管理程序(例如 KVM 的情况),或者被用来控制虚拟化管理程序(例如 Xen 的情况),或者为更高级别的虚拟化管理程序(如 VirtualBox)提供存储,在所有这些情况下,Linux 都有可能管理存储体验的每个方面。Linux 还可能被用来创建 SAN 设备或其他形式的存储层。我们必须全面了解存储的内外,但在大多数情况下,我们的 Linux 系统将从其虚拟化管理程序获取存储,即使我们是该虚拟化管理程序的管理者。
虽然它们可以选择以多种不同的方式行事,但大多数人会设置虚拟化管理程序以充当存储的 LVM 层。它们有点特殊,因为它们将数据从块转换为文件系统,然后再转换为块以传递给虚拟机,但概念上是相同的。一些虚拟化管理程序设置将简单地通过直接块连接到底层存储,无论是本地磁盘、SAN 还是来自 LVM 的逻辑卷。这些都是有效的方法,并且为虚拟机留下更多选择,以决定它将如何与存储交互。但总的来说,预期的虚拟化方式是将存储的块层终止于虚拟化管理程序,将其转换为文件系统,在文件系统之上创建块设备容器,并允许虚拟机像使用常规块设备一样消耗这些设备,许多人实际上将这种虚拟化方法的结果称为虚拟化本身的内在特性,但这并不正确。
您也可以在系统内部使用这种技术。例如,挂载文件系统文件类型如qcow2、vhdx或iso文件!这是我们每天都在做的事情,但很少有人会去思考或意识到我们实际上在做什么。
显然,当从虚拟化管理程序获取存储时,对标准(非复制)本地存储、复制本地存储、标准(非复制)远程存储或复制远程存储的关注都是在系统之外的不同层次进行的,但决策仍然是必须的,并且这些决策完全影响我们的系统最终如何运行。
现在我们已经学习了很多存储抽象方法和范式,比如 LVM、RAID 和 RAIN。现在我们需要开始考虑如何将这些技术结合起来构建我们自己的存储解决方案。
分析存储架构和风险
没有什么比存储给我们的系统带来更大的风险了。这是不言而喻的,但必须要说。存储是我们作为系统管理员能够产生最大影响的地方,也是我们最有可能失败并且失败惨重的地方。
为了应对存储中的风险和机会,我们必须理解整个存储堆栈,以及每一层和每个组件如何相互作用。存储可能让人感到压倒性,那里有太多的活动组件和可选组件。
我们可以通过提供成功的设计模式,并理解在何种情况下应该考虑不同的模式,来缓解一些压倒性的感觉。
一般存储架构
存储架构有两个真正高层次的维度:本地与远程,以及标准与复制。
当然,对于大多数人来说,自然的假设是立刻相信复制和远程是显而易见的起点。实际上,这并不正确。这可能是存储中最不合理的起点,因为它结合了最不可能有用的因素。
简单的本地存储:砖块
不管信不信,对于各类公司的最常见适用存储设计是本地的、非复制存储!请记住,当我们谈论存储架构时,复制并不指没有备份或没有本地复制(如 RAID 镜像),而仅仅指存储是否在实时或近实时的情况下复制到第二个完全独立的系统。
当我们从整个系统设计角度来看,而非单独看存储时,我们会再次讨论这个问题,并且会有些不同。就像生活中的大多数事情一样,保持简单通常是最有意义的。复制听起来很惊人,是必备功能,但复制需要花费大量资金,且通常需要很多成本,而且要做好复制,通常会影响性能,可能影响得非常严重。
复制灾难
存储设计中的一个常见错误是产生一种情感上的感觉,认为复制越多,我们就越能免受灾难的影响。在某种程度上,这是真的,本地复制一些文件并使用 RAID 1 能有效保护我们免受硬盘故障的影响,远程复制则能保护我们免受整个节点失败的影响,但这两者都无法防止更常见的问题,如文件误删除、恶意文件破坏、文件损坏或勒索病毒。
如果我们做一些简单的事情,比如删除一个不该删除的文件,那么瞬间,我们强大的复制机制将确保我们的删除操作会在一两毫秒内传播到整个系统中。它可能不是保护我们,而是成为比我们反应更快地复制我们的错误的机制。过度构建复制机制通常只对抗硬件故障有保护作用,并且可能迅速变成回报递减的局面。
第一级 RAID 可能非常有价值,因为硬盘故障依然是一个非常现实的风险,即使是最微小的硬盘故障也可能导致重大数据丢失。但节点之间的复制仅能防止整个系统的丢失,而这种情况远不如硬盘故障常见。RAID 保护相对便宜,实施成本通常只有几百美元。然而,节点间的复制需要大大更多的硬件,通常需要花费数千或数万美元,提供的保护也只是 RAID 已经提供的一小部分。
像 RAID 这样的机制,尤其是 RAID 1(镜像),也非常容易实现并且非常直接。在镜像 RAID 中,由人为错误引起的数据丢失是相当罕见的。节点之间的复制存储则不同,出错的可能性更大,且人为错误导致数据丢失的几率也高得多。我们并不是通过选择这条昂贵的路来简单地减少风险,而是引入了其他我们也必须减轻的风险。
许多系统管理员认为他们不能使用简单的本地非复制存储,且公司政治问题不可忽视。如果你的公司要 搞政治,并将责任推给你,作为系统管理员,即使错误不在你,并且你的决策对业务来说是最好的,那么你就被迫做出对业务盈利性没有帮助的危险决策。这是系统管理员无法控制的事情。
作为系统管理员,我们可以通过呈现(并做好文档记录)风险和财务决策,来管理这种政治问题,在某些情况下,以此证明即使最终导致数据丢失的决策,仍然是正确的决策。没有任何决策可以消除所有风险,作为 IT 专业人员,尤其是系统管理员,我们始终在做出决定,权衡要减少多少风险,以及我们应该以什么样的财务成本来进行。
风险评估
IT 和尤其是系统管理员领域最具挑战性且最重要的一个方面就是进行风险评估,以便进行适当的规划。风险很少以正式或自然的方式进行教学。这是几乎所有企业都在此领域惨败的地方,而 IT,作为我们所做的所有事情中至关重要的一部分,通常没有培训、没有资源,也没有支持。
教授风险本身就是一项职业,但这里可以简单介绍一些我们应该始终使用的技术。风险的核心是将成本分配到预计的利润上。
我们有两个风险的关键方面。一个是坏事发生的概率,另一个是事件的影响。第一个我们可以表达为每年发生 X 次,如果你觉得这样更方便。第二个可以用金钱来表达,比如它会花费 5000 美元。如果某事每十年发生一次,你可以说它是每年 0.1 次。所以,影响我们 5000 美元的事情,其年度成本将是 500 美元。这个方法极其简单,实际上并不是风险运作的真实方式。但它是一个在向管理层表达风险决策时非常有用的工具,他们希望将数百万个因素提炼成一个最终的数字。
现在我们需要拿出显示风险缓解策略成本的数字。例如,如果我们要实施一个复制技术,年许可费为 300 美元,并且每年需要十小时的系统管理员时间,每小时 120 美元,那么我们可以预计风险缓解成本为 1500 美元/年。
下周需要一个缓解效果。没有什么是百分之百的。但是一个好的复制策略可能有 95%的有效性,典型的策略可能有效性在 65%左右。通过这些数字,我们可以做一些精确的数学计算。
我们知道我们每年面临大约 500 美元的损失风险。如果我们每年花费 1500 美元,就可以有 95%的把握阻止这 500 美元的损失。500 美元 * 0.95 = 475 美元。所以,1500 美元-475 美元 = 1025 美元,这是风险缓解策略每年造成的损失。这些数字你可以带给 CFO。做这道数学题,你应该能展示出节省或保护,而不是损失。如果你展示的是损失,那么你真的,真的需要避免这个计划。这意味着风险保护机制,实际上是通过实施它就代表了一个灾难。
数学,可能听起来有些老生常谈,但平均的系统管理员甚至平均的 CFO 通常会避开使用基本数学来判断一个想法的好坏,而完全凭借情感做决策。使用数学将保护你。它意味着你可以去找 CFO 和 CEO,站稳脚跟。你无法与数学争论。展示给他们看数学,如果他们认为数学是错的,让他们自己计算。如果他们决定忽视数学,那么你就知道你所在的公司是什么样的,你真的应该认真思考,未来在一个不认为利润是驱动力的公司里会有什么样的前景。如果未来出了问题,你被责备了,你可以拿出数学并问,如果这个决定不正确,为什么我们在做决策时没能从数学中看出来?
没有什么比成功地为一个看似疯狂的决策辩护更让人感觉好,这个决策是有数学依据的。证明你正在做最好的工作。不要只是说,不要做没有根据的声明。利用数学并证明你做出决策的理由。将决策从猜测提升到科学的层面。
不是所有工作负载都可以这么简单地处理。但比通常假设的要多得多的工作负载是可以的。除非你有坚实的数学依据来证明相反,否则这应该是你的标准假设。或者你正在处理超出数学范畴的情况,例如生命支持系统,在这种情况下,正常运行时间和可靠性比金钱更为重要。否则,使用数学。
这种所有存储方法中最简单的方法,通常被认为是砖块。它简单、稳定、可靠,容易备份和恢复,易于理解和支持。今天,这种解决方案非常有效,尤其是在现代存储技术和硬件的帮助下,我会说它适用于 85-90%的所有生产工作负载,无论公司大小,至少适用于 99%的小型企业工作负载。
RLS:超高可靠性解决方案
那些不适合上述简单架构的工作负载和情况几乎总是属于这一类别:复制本地存储(RLS)。RLS允许以合理的成本提供高可用的存储,且性能出色。没有任何解决方案能与我们最初提到的直接本地存储在性能和成本上匹敌,但如果你需要比该方案提供的更高的可用性和更好的可靠性,这几乎肯定是适合你的解决方案。
RLS提供了可用的最高可靠性,因为它的移动部件更少。远程高可用性解决方案必然需要处理距离、电缆和网络协议,至少需要这些额外的组件,通常还会额外涉及网络设备(如交换机),这些都比RLS的风险更大。记住,远程存储解决方案如果要实现真正的高可用性,必须通过在本地集群中使用RLS来实现,然后将该存储集群通过网络远程提供,这样你就会遇到所有与RLS相关的复杂性和潜在问题,再加上远程访问技术的开销和风险。
如果直接本地存储没有远程复制,占用了所有工作负载的九成,那么标准的RLS(复制本地存储)将占据剩下的九成(这两者加起来应该占据大约 99%的工作负载)。在进行合理规划时,这两种选项是如此简单、具成本效益且安全,正常情况下它们几乎无法被超越。这些是你的核心选项。
替代存储可靠性
虽然RLS可能感觉像是存储保护的终极解决方案,但它并不是。它在你必须依赖存储层来处理可靠性时非常出色。但从这个角度来看,它更像是一个权宜之计或临时解决方案,而不是终极方案。
在一个理想的世界中,我们有比我们实际存储层更高的存储机制,例如数据库。数据库管理系统能够更好地维护可用性,并协调节点之间的数据复制,而这是一个盲目的块复制机制永远无法做到的。在应用智能所在的地方放置复制是非常合理的选择。
理想情况下,应用程序应该使用它们的数据库作为存储和状态可靠性的层,并让了解数据使用方式的智能系统复制重要数据。数据库是复制的最理想机制之一,因为它们了解它们拥有的数据,并能够做出明智的决策。
因此,许多企业应用程序根本不使用任何形式的存储,甚至没有系统复制。使用不可靠的系统和高度可靠的应用程序是一种稳固的策略,提供了其他方式无法获得的好处。因此,有时我们可以忽略原始存储层的高可用性需求,而只关注性能。
实验室环境:远程共享标准存储
这种架构非常受欢迎,因为它符合销售人员的所有需求:昂贵、有风险和令人困惑。的确,销售人员推动这种设计比其他任何设计更多,因为它为客户提供了许多附加服务的计费方式,同时将所有责任推给客户。
所有架构在生态系统中更多或少都有合法的位置,这种架构也不例外。但在我们列出用例之前,我们应该先说明它的好处所在:非复制的远程存储比本地存储机制更慢、更有风险,而且表面上更昂贵。我们在这样的设计中找到价值的地方在哪里?
主要的好处在于实验室、测试和其他环境中,数据耐久性的价值可以忽略不计,但是我们可以从大型环境中获益,可以审慎地划分存储空间,以实现大规模的最大成本节约。
几乎每个大型环境在其工作负载的某个阶段都需要这种类型的存储。关键是要确定这种需求混合起来是合理的,而不是试图在不合适的地方应用它。因为这种存储在大规模时很便宜(但在小规模时非常昂贵),而且因为经理们经常错误地将远程共享存储误认为是不可能出错的神奇盒子,所以它经常被用在最不适合的地方。没有魔法,对于大多数生产工作负载来说这是一种不良技术,应该极度谨慎地选择使用。
这里的经验法则是:只有在你能够决定性地证明它是有意义的情况下,才应该使用这种类型的存储——即使是标准的可靠性和性能也不再有价值。如果你有任何疑虑,或者组织中有人有疑虑,那么在使用这种架构之前选择其他存储架构,这样可以避免最大风险。性能是软性故障,在事后很容易纠正,而且如果做错了,通常影响也较小。数据丢失是硬性故障,做错了就不是优雅的失败,而是灾难性的失败,事后几乎没有纠正的余地。
优雅失败
我们不能总是避免失败。事实上,很多时候规避失败是我们工作的重要组成部分。为了让这一切有效,我们必须理解如何优雅地失败,而这一点的关键部分就是优雅失败的概念。在存储领域,这个概念比其他领域更为突出。
优雅失败的理念是,如果我们失败了,我们希望它是以一种小的、渐进的方式,而不是悲剧性的全面灾难的方式发生。我们做出的许多存储决策正是基于这个理念。我们知道我们可能会出错。所以,我们要确保尽可能接近正确,同时也要考虑到如果我们出错了怎么办。
通过这种方式,我们通常倾向于在 RAID 中使用 RAID 10,并且在架构中倾向于使用本地存储。如果我们错了,我们希望结果是更加安全,而不是因为我们认为无关紧要而丢失数据。
虽然决定一个完整架构不仅仅依赖于错误的存储决策,但远程非复制存储是许多供应商和经销商常用设计的基础,他们通常称之为3-2-1 架构,而 IT 从业者则称之为倒金字塔毁灭架构。
这种架构传统上被广泛部署,但它无疑是在生产环境中最不适用的架构。它慢、复杂、昂贵,而且风险最大。它主要在实验室环境中有意义,因为在这种环境下,重建存储的数据最多也只是耗时。这种架构真正是围绕通常不在生产环境中的工作负载需求设计的。
巨大的规模:远程复制存储
我们需要考虑的最后一个主要架构是最大的一种:远程复制存储。看起来这可能是每个企业都会采用的存储架构,虽然它并不算稀有,但实际上它的使用频率远低于你想象的。
远程复制存储在小规模部署时实现成本最高,但在大规模时可以变得相对更实惠。它在复杂性上比 RLS 更高(这意味着可靠性较差),性能也低于 RLS 或直接本地存储,因此只有在节省成本至关重要、但仍需一定可靠性时才有意义。这是一种相对小众的选择。
考虑到这两种本地存储架构在工作负载部署中占据了 99%的比例(当然是我亲自做的),因此这个架构承担了剩余的最后那一小部分,至少在生产环境中是这样。
最安全的系统也只能做到这么安全。
我在系统管理员的数十年经历中,最具戏剧性的故事之一,发生在我作为顾问在一所大学图书馆工作的那段时间。我被请来负责处理一些大规模的数据库,该图书馆的系统只有两名管理员。高级管理员正在度假,只有初级管理员在场。这个环境使用了一套高度冗余且高可用性的 SAN 系统,所有的系统都依赖于它。为了保护这个系统,从 UPS 到发电机,再到硬件冗余,投入了巨大的成本。
在我在那里时,初级管理员决定对 SAN 进行一些维护,但由于某种原因,不小心点击了删除 SAN 上所有卷的操作。这当然是一次意外,但却是一个非常粗心的错误,发生在一个假设所有可能的故障场景都已被仔细防范的人身上。然而,所有的高可用性、所有的冗余、所有的特殊技术,都未能解决简单的人为错误问题。
只需她点击一下鼠标,整个图书馆的计算机系统就消失了。应用程序、数据库、用户、日志——所有的一切。所有内容都依赖于一个单一的存储系统,而这个系统几乎不费力就能被有权限的人关闭或删除。所有的鸡蛋都放在了一个篮子里,虽然这个篮子做得非常坚固,但却有一个大开口,轻易就能被颠倒。
更糟糕的是,初级系统管理员并未做好情绪上的准备,因害怕丢掉工作而感到恐惧,以至于必须住院,而所有可能协助的人才都忙着给她叫救护车。由于技术规划不足,再加上人力规划不当,本应仅是一个小规模恢复灾难的轻微事件,变成了一次巨大的故障停机。幸运的是有良好的备份,系统得以较快恢复。但这件事深刻反映出,我们常常投入大量资源去防范机械故障,却忽视了人的脆弱。实际上,人为错误往往比机械故障更可能引发灾难。
存储架构和风险是存储设计中最困难的部分。深入挖掘文件系统的细节通常是有趣的,并且对于我们作为系统管理员来说风险极小。如果我们选择了 EXT4 而 BtrFS 本来更好,惩罚可能是名义性的,以至于我们永远不会预料到任何人会发现我们没有做出完美的决策。但选择错误的存储架构可能导致巨大的成本、长时间的停机或严重的数据丢失。
我们确实需要花时间了解我们业务和工作负载的需求。什么样的风险是可以接受的,我们需要什么样的性能,如何以最优成本满足所有需求。如果我们不知道答案,那么我们就需要找出来。
最佳实践始终是花时间了解所有业务需求,学习所有可用因素并加以应用。但在实践中这很难做到。一些经验法则可以帮助我们很多。
存储最佳实践
试图将存储简化为最佳实践实际上是相当困难的。在最高层次上,存储的基本规则是没有捷径,你需要了解存储基础设施的所有方面,理解工作负载,并应用这些综合知识,同时了解机构风险规避,以确定工作负载的理想情况。
更进一步,最佳实践包括:
-
RAID:如果数据值得存储,那么在 RAID(或 RAID)上拥有数据是值得的。如果你对在服务器上使用 RAID(至少)存储数据的价值产生疑问,那么重新考虑是否存储数据。
-
RAID 物理性:硬件和软件 RAID 实施同样可行。确定哪些因素最适合你的需求。
-
LVM:就像我们将在未来章节中讨论的一般虚拟化一样,存储虚拟化不是提供我们在第一天就需要的具体功能集。它是提供机制来保护未知并且对未来发生的任何事情具有灵活性。除非你能提出非常强有力的论据证明 LVM 是不需要的,否则请使用它。
-
文件系统:不要被炒作或潮流所困扰。研究今天对你重要并有可能在未来保护你的功能,并选择一个可靠、健壮且经过测试的文件系统,让你对自己的文件系统选择感到放心,长期不会受到阻碍。
-
存储架构:除非你能证明你需要或从远程存储中获得显著的财务利益,否则保持你的存储访问本地化。除非你能展示从节点复制中获得明显的好处,否则不要在节点之间复制。简单胜过复杂。
作为系统管理员,你可能很少需要处理存储设计决策。但无论有多不频繁,存储设计决策对我们长期系统的影响是所有决策中最为深远的。花时间认真确定每个工作负载所需的内容。
存储示例
我们应该退后一步,举个例子,看看这些组件如何在现实场景中组合起来。我们不能合理地为每个常见的,甚至是可能的存储场景做出示例,但希望通过这一章的内容,你能对我们讲的内容有个初步的理解。
为了保持事情尽可能简单,我将尽可能采用最常见的小型和中型企业设置,或者至少是应该是它们最常见的设置。
小型企业通常受益于保持其设计相当简单。由于缺乏大规模、经验丰富的员工,并且通常面临较高的员工流动风险,小型企业需要那些需要较少维护并且能够由没有环境内在知识的顾问或员工轻松维护的系统。
对于这些环境,尤其是对于许多更大型的环境,硬件 RAID 和热插拔硬盘非常重要。它们允许硬件维护由专业人员完成,而不需要参与系统管理任务。在处理机房托管或其他远程设施时,这一点尤为重要。在这些情况下,IT 部门的人员可能根本无法亲自参与。
所以,我们从一些通用的假设开始。在物理层面上,我们有八个硬盘。这些硬盘可以是旋转硬盘、SSD、NVMe,任何块设备都可以。其实并不重要,重要的是我们有多个硬盘,但我们希望它们作为一个单一单元来使用。
接下来,我们添加了一个硬件 RAID 控制器。我们用这个 RAID 控制器将所有硬盘连接起来,并将它设置为将它们放入适当的 RAID 级别。这可以是任何一个选项,但在这个示例中,我们假设它们使用的是 RAID 10。
从我们示例的一开始,即使我们还没有安装 Linux 或类似的系统,我们已经利用系统的硬件实现了前两层存储!包括物理设备和第一个抽象层。
我们在这里不会展示实际插入硬盘的过程,因为这纯粹是一个手动过程,而且你的服务器供应商可能已经为你完成了这一步。
至于设置 RAID 本身,每个控制器和供应商可能略有不同,但基本原理是相同的,任务始终非常简单。这正是 RAID 控制器的主要目的之一 - 将 RAID 操作的必要知识和规划最小化,无论是在前期还是在运行阶段。在我们这里的示例中,为了更容易演示,我们假设我们正在处理一个单一数组,而这个数组不是我们操作系统正在运行的数组,这样我们可以更容易地从命令行中展示一些步骤。但这只是一个例子。
请记住,硬件 RAID 对于每个供应商甚至每个供应商的每个产品都是不同的。因此,您始终需要了解您的特定产品的工作方式。
此外,我们应该注意到,对于 RAID 控制器来说,连接到它的每个驱动器都是一个块设备。这是唯一一种情况,其中块设备接口假装是一个物理硬盘,实际上确实是一个硬盘!在随后的每个情况中,我们将使用软件来实现硬盘的接口,但我们代表的驱动器将是逻辑的,而不是物理的:
=>ctrl slot=0 create type=ld drives=2I:1:5,2I:1:6,2I:1:7,2I:1:8 raid=1+0
这是一个真实的世界 RAID 控制器的语法。通常情况下,您将通过 GUI 以图形方式执行此任务。但有时您可能希望使用命令行实用程序。在可能的情况下,我会从命令行工作,这样做更可重复,也更容易进行文档化。
一旦我们完成了初始硬件配置阶段,我们就可以继续进行示例的 Linux 特定部分。
硬件 RAID 控制器通常在/dev 文件系统中创建自己的命名约定。在我们的示例中,控制器使用了cciss语法,并在该系统下创建了设备c0d1。所有这些都会根据您使用的控制器和配置而异。
接下来,我们将在 RAID 层之上创建一个逻辑卷层,以在存储系统中提供更大的灵活性。为此,我们必须首先将新创建的设备添加到 Linux 的 LVM 系统中作为物理设备。我们使用pvcreate命令和我们新设备的路径来完成这一步骤:
# pvcreate /dev/cciss/c0d1
非常快速和简单。现在 LVM 子系统已经意识到我们的新 RAID 数组设备。但当然,所有 LVM 知道并关心的只是它是一个块设备。它是一个特定的 RAID 数组实际上并不是 LVM 可以检测到的,也无关紧要。关键在于它被抽象化处理,无论它是什么,都可以使用相同的方式进行利用。速度、容量和安全特性都封装在 RAID 层中,现在我们可以将其视为一个硬盘在前进过程中。
另一个有趣的地方在于,当使用硬件 RAID 控制器时,这种抽象和虚拟化的硬盘表示只是一个逻辑硬盘,但作为块设备,它实际上是物理的!这真是令人惊讶,不是吗?它确实是硬件,只是不是硬件硬盘。花点时间思考这个。
现在我们的 RAID 阵列已由 LVM 管理,我们可以将这个驱动器添加到一个卷组中。在本示例中,我们将其添加到一个新的卷组中,这个卷组只是为了本示例而创建的。我们将这个新组命名为 vg1。以下是执行此操作的示例命令:
# vgcreate vg1 /dev/cciss/c0d1
好的,现在我们有所进展了。由 RAID 控制器组合的各个物理硬盘的容量,现在在一个容量池或卷组中,我们可以开始切割这个容量的真正有用的子集来在我们的服务器上使用。
卷组创建完成后,剩下的就是制作实际的逻辑卷。请记住,逻辑卷已取代分区,成为将块设备划分为可消耗部分的主要方式。在我们的示例中,我们将做最简单的事情,告诉 LVM 系统只创建一个尽可能大的逻辑卷;也就是说,使用卷组可用容量的 100%(因为这是我们第一次使用它,目前使用率为 0%):
# lvcreate -l 100%FREE -n lv_data vg1
此命令告诉 LVM 创建一个新的逻辑卷,使用可用的所有空闲空间的 100%,在卷组 vg1 中,并命名新的逻辑卷为 lv_data。就是这样。现在我们有一个可以使用的逻辑卷!显然,我们也可以创建一个更小的逻辑卷,比如可用空间的 50%,然后再创建第二个逻辑卷,使用剩余空间的 100%,这样我们就得到了两个大小相等的逻辑卷。
记住,在 Linux 中找到的 LVM 系统会为我们提供灵活性,如果直接将文件系统应用于物理驱动器甚至 RAID 控制器硬件提供的虚拟驱动器上,我们通常会缺乏这种灵活性。LVM 系统允许我们向卷组添加更多物理设备,从而为制作逻辑卷提供更多容量。它还允许我们调整单个逻辑卷的大小,无论是扩展还是收缩。LVM 还允许我们为逻辑卷创建快照,这对于构建备份机制或准备进行风险系统修改以便快速恢复非常有用。LVM 执行非常重要的功能。
现在 lv_data 已创建,我们通常需要使用文件系统对其进行格式化,以使其真正有用。我们将使用 XFS 格式化。在今天的现实世界中,XFS 可能是推荐用于通用需求的文件系统:
# mkfs.xfs /dev/vg1/lv_data
非常简单。几秒钟之内,我们应该有一个完全格式化的逻辑卷。通过应用文件系统格式,我们停止了块设备接口的链条,现在呈现的是文件系统接口,这种变化使应用程序能够以标准方式使用存储,而不是使用存储系统组件所使用的块设备。
当然,还需要最后一步,我们必须将新的文件系统挂载到一个文件夹中以使其可用:
# mkdir /data
# mount /dev/vg1/lv_data /data
就是这样!我们刚刚为其中一个最常见的系统场景实施了一个基于多层抽象的存储系统。我们在多个个别物理硬盘的顶部构建了一个硬件 RAID 控制器上的 LVM 逻辑卷管理上的 XFS 文件系统。
因为每一层都使用块设备接口,我们本可以混合和匹配更多的附加功能。比如使用两个 RAID 控制器,并将它们的容量与卷组合并。或者创建多个卷组。我们本可以创建许多逻辑卷。我们本可以使用软件 RAID(在 Linux 中称为 MD RAID)来使用两个 RAID 控制器的输出创建 RAID!实际上可以做到很多,但实用性让我们脚踏实地。
此时,如果你cd /data,你可以像它一直存在一样使用新的文件系统。它是一个新的文件系统,建立在所有这些抽象层之上,有多个物理设备使所有这些魔术发生在这一点上对你来说是完全隐藏的。它只是工作。
现在,在过去,如果这是 2004 年,我们通常会到此为止,并说我们已经描述了一个如果实施得当的真实世界服务器可能会看起来像什么。但现在已经不是 2004 年了,我们确实需要更多地讨论我们如何可能在最常见的场景中使用我们的存储。因此,今天我们需要考虑我们的虚拟化层如何使用这些存储,因为这里的事情变得更加有趣。
我们将假设我们刚创建的/data 文件系统将用于存储几台虚拟机的驱动器映像。当然,这些驱动器映像只是我们存储在文件系统中的个别文件。非常简单。与在/data 中创建和存储文本文件没有什么不同(除了 VM 驱动器映像往往稍微大一些)。
关于驱动映像的好处(这可以是 QCOW、VHD、ISO 或其他格式)是它们位于文件系统的顶部,但是当它们被能够读取它们的特殊驱动程序打开时,它们再次呈现一个块接口!没错。我们从块到块再到块再到块再到文件系统再到块!在某些独特的情况下,我们甚至可能不使用虚拟化程序,而是在我们的常规服务器中的某个地方使用这个新的块设备文件。Windows 通常使用 VHD 文件在某些情况下传递数据。MacOS 使用它作为创建安装程序包的标准方式。在 Linux 上,这种情况远不常见,但同样可用。
假设我们正在做正常的操作,我们可以假设我们正在运行一个虚拟化管理程序,几乎可以肯定是 KVM,并且在 KVM 上运行的虚拟机将使用我们新创建的文件系统上的磁盘镜像文件存储。在这种情况下,我们在这里做的大部分工作,很可能会在那个虚拟机内部再次发生。
有些部分可能不太适合重新创建。物理硬盘已经由物理 RAID 控制器管理。存储的速度、容量和可靠性已经由该系统确立,不需要在这里重复。标准方法是将单个驱动器镜像文件作为单一块设备呈现给在虚拟机中运行的操作系统。这与我们从硬件 RAID 控制器中获得的块设备没有什么不同。
现在在虚拟机内部,我们通常会进行相同的操作。我们将呈现的块设备添加为 LVM 物理卷。然后我们将该物理卷添加到卷组中。接着我们从该卷组中划分出一个或多个逻辑卷。然后我们使用选择的文件系统对该逻辑卷进行格式化并挂载它。当然,通常这些步骤并不是像我们在这里做的那样手动完成,而是由安装过程自动化处理。
我们可以增加更多步骤,例如使用 MD RAID,或者减少一些步骤,比如完全跳过 LVM。我们也可以仅用一个硬盘而没有 RAID 控制器完成所有相同的步骤。虽然在物理上这会弱一些,但从技术层面上看,所有的示例仍然有效。我们可以在物理机上使用 LVM,但在虚拟机中不使用,或者反过来!灵活性在于根据需求来进行操作。关键在于理解块设备如何层叠,文件系统如何应用于块设备,以及块文件如何将文件系统转回块设备!
抽象和封装是我们 IT 武器库中非常强大的工具,而且它们通常是如此具体可触。
摘要
如果你坚持到本章结束并且还在跟我一起学习,恭喜你,我们做到了!存储在系统管理中至关重要,可能在你管理的其他领域,没有任何地方能为你的组织带来如此大的价值。
我们已经覆盖了存储基础知识,基于块设备接口、抽象技术、文件系统及其接口的概念,并运用这些概念探讨了多设备冗余及其如何用于构建复杂且健壮的数据存储,及如何处理跨设备的存储访问,以满足任何潜在需求。我的目标是为你提供必要的知识,使你能够独立思考在任何给定工作负载下的存储需求,并理解可用性技术以及如何有效地应用这些技术来实现这些目标。
再也不应该将存储视为神秘的黑匣子或一项令人畏惧的任务,你可以将其视为展示机会,展示如何将适当的系统管理最佳实践应用于最大化你的工作负载中最重要的存储因素的机会,而不仅仅是投入资金来解决挑战,或者更糟糕的是,简单地忽视它,希望问题在事情崩溃之前能找到另一份工作。
在我们的下一章中,我们将更深入地探讨系统架构。本章中的许多最有趣的概念将在那里反复出现。系统架构非常依赖存储架构,并且许多冗余和系统保护范式是共享的。看到良好的存储设计元素如何导致真正高性能、高可用性和成本效益的最终解决方案,这实在是令人兴奋的事情。
第四章:设计系统部署架构
我们如何部署系统决定了这些系统今后将表现如何以及它们的弹性将持续多久。了解设计组件和原则对我们理解如何设计将承载我们工作负载的平台至关重要。请记住,归根结底,只有位于堆栈顶端的应用程序才真正重要 - 在应用程序之下的一切,无论是操作系统、虚拟化程序、存储、硬件还是其他工具,都只是用来实现最终应用级工作负载所需功能的工具。很容易感觉到这些其他组件的重要性,但实际上它们并不重要。换句话说,重要的是结果,而不是达到结果的途径。
在本章中,我们将首先查看系统的构建模块(除了我们在上一章中广泛讨论的存储外),然后将所有这些组件作为一个整体来查看它们,以了解它们如何形成我们应用工作负载的强大载体。接下来,我们将进行需求分析。最后,我们将继续将这些组件组装成满足这些需求的架构设计。
通过本章的学习,您应该对此感到自信,尽管 Linux 可能只是我们应用程序堆栈中的一个片段,但您已准备好正确设计整个堆栈,以满足工作负载目标。尽管从技术上讲,这种设计大部分并不严格属于系统管理(或工程),但它通常由系统管理员来处理,因为只有极少数组织拥有来自其他部门高技能和全面知识的员工。系统团队处于所有组件的交汇点,并在两个方向上(向上到应用程序和向下到虚拟化程序、硬件和存储)具有最大的单一角色可见性。系统团队被赋予更大的设计任务是很自然的。
在本章中,我们将学习以下内容:
-
虚拟化
-
容器化
-
云和虚拟专用服务器(VPS)
-
自有、托管和混合托管
-
系统设计架构
-
风险评估和可用性需求
-
可用性策略
虚拟化
二十年前,如果你问一个普通的系统管理员什么是虚拟化,他们可能会一头雾水。自从 IBM 在 1965 年首次在其大型计算机系统中引入虚拟化技术以来,我们就已经在 IT 领域中拥有了这些技术,但对于普通公司来说,这些技术相对较少且难以获得,直到像VMware和Xen这样的供应商在千禧年之交将它们带入了主流市场。企业领域在 20 世纪 90 年代已经使用了许多这些技术,但对它们的了解并没有广泛传播开来。
时代已经变了。自 2005 年以来,虚拟化已经广泛普及并被广泛理解,每个平台和所有价格点都有选择,没有人因为技术或财务上的限制而需要避免实施这项技术。在其核心,虚拟化是创建一个软件中的计算机(在实际硬件的顶部)并呈现标准虚拟硬件集的抽象层。执行虚拟化的软件称为hypervisor
在上一章中,我们反复谈到接口以及某些东西如何消耗或呈现自己作为磁盘驱动器或文件系统,例如。hypervisor 是一种呈现计算机接口的软件,这意味着它不仅仅呈现硬盘驱动器,而是像整个计算机一样运行。如果您从未使用过或思考过虚拟化,这可能看起来非常复杂和令人困惑,但实际上,这是一个通常使计算变得更简单和更可靠的抽象。就像抽象存储的技术(如逻辑卷管理器和RAID系统)一样,在其成熟和理解之后,计算机级虚拟化也被证明是非常有价值的。
在本章中,我们将讨论两种类型的 hypervisor,它们分别被称为 Type 1 和 Type 2 hypervisor。所有的 hypervisor 都呈现同样的东西:一个计算机。但 Type 1 和 Type 2 hypervisor 之间的区别在于它们消耗的内容。
Type 1 hypervisor
有时称为裸金属hypervisor,Type 1 hypervisors 旨在直接在系统硬件上运行,但当然也可以在任何表示自己为能够运行的硬件(如另一个 hypervisor!)上运行。因此,Type 1 Hypervisor 不是应用程序,并且不运行在操作系统之上,因此只需要担心与将安装的物理设备的硬件兼容性。
一般来说,Type 1 hypervisor 被认为是真正适合生产的唯一类型,因为它们直接安装而无需任何不必要的软件层,因此可以更快、更小和更可靠。
Type 1 hypervisor 最初更难工程化,因此最早期的 hypervisor 通常是其他可以将工作传递给操作系统的类型。但事实上,是 Type 1 hypervisor 的引入和足够多的不同产品供应商使市场成熟,鼓励了在 2000 年代极端转向虚拟化。
Type 2 hypervisor
与裸金属 hypervisor 不同,Type 2 hypervisor 是一个安装在操作系统上的应用程序。这意味着 hypervisor 必须等待操作系统提供资源,与其他应用程序竞争资源,并要求操作系统本身稳定,除了 hypervisor 稳定外,还需要使工作负载在其上运行。
当虚拟化技术相对较新时,尤其是在微型计算机领域,由于成本更低且更易于制造,并且几乎不需要硬件支持来完成其工作,因此类型 2 虚拟化监视程序更为常见。类型 2 虚拟化监视程序让裸金属操作系统来处理供给驱动程序和硬件检测、任务调度等繁重工作。所以在 2000 年代的大部分时间里,我们看到类型 2 虚拟化监视程序在推动虚拟化技术采用中扮演了主要角色。它们易于部署,非常容易理解,因为它们只是一种在操作系统之上部署的应用程序,任何人都可以在现有的台式机甚至笔记本电脑上安装一个来尝试虚拟化技术。
到了 2000 年代末,技术发生了相当大的变化,软件得到了先进和成熟的发展,几乎所有计算机都获得了某种程度的虚拟化硬件支持,允许虚拟化监视程序使用更少的代码同时获得更好的性能。类型 1 虚拟化监视程序迅速扩展,到了 2010 年之前,在生产环境中使用类型 2 虚拟化监视程序的想法几乎是不可想象的。类型 1 虚拟化监视程序提供了一个统一的标准操作系统安装目标,将大部分繁重工作从操作系统转移到监视程序,被普遍认为是更佳选择。因为监视程序控制裸金属,能够适当调度系统资源,并从系统中获得最大性能。监视程序预计只占操作系统大小的一小部分。这意味着它几乎只是虚拟化操作系统和物理系统之间的一个垫片(一层极少代码的基本功能层,对于运行在其上的操作系统基本不可见)。这最小化了膨胀和功能,而操作系统通常需要庞大、复杂和功能丰富以在大多数情况下完成其工作。
类型 2 虚拟化监视程序已被证明在实验环境中非常有用,尤其是在需要从个人计算环境(例如台式机或笔记本电脑)进行测试或学习的情况下,或者对于需要完全禁用或甚至在不再需要时可能移除监视程序的特殊临时工作负载也很有用。但对于生产服务器环境来说,只有类型 1 虚拟化监视程序才真正合适。
虚拟化技术通常与两项最佳实践相关联。
-
除非有要求使您无法这样做,否则应虚拟化每个系统。在实际操作中,您几乎永远不会真正看到这条规则的有效例外。
-
服务器始终使用类型 1(裸金属)虚拟化监视程序。
虚拟化监视程序的类型令人困惑。
在现实世界中,要检测什么是 Type 1 虚拟化管理程序可能相当困难。按定义,虚拟化管理程序实际上没有任何自己的最终用户界面。这使得我们必须解释它,但并不是我们真正看到的东西。即使是真正的操作系统也很难指出并说“看,它在这里”,因为我们真正看到和触摸的是作为应用程序在操作系统顶部运行的壳或桌面环境,而不是操作系统本身。对于虚拟化管理程序来说,我们看到的任何界面,无论是什么样的,都必须由运行在操作系统上的东西来呈现,而不是直接在虚拟化管理程序上运行的东西。
当然,虚拟化管理程序需要某种接口来与我们互动。它们处理这个接口的方式差异很大,即使是同类型的虚拟化管理程序,构建方式也不尽相同。在幕后,它们总是在裸金属上运行,但它们可以使用几种不同的架构来处理它们所需的所有功能。每种不同的架构都有不同的机会,展示给最终用户的方式也不同 - 这意味着一个坐到系统前的最终用户可能会体验到完全不同的界面,假装是它们或者可能并不是它们。
在早期的 Type 1 虚拟化管理程序中,运行一个虚拟机(虚拟化管理程序顶部运行的虚拟计算机的名称)通常会赋予它控制虚拟化管理程序的权限。这使得虚拟化管理程序可以尽可能精简,并且可以使用现有工具完成像展示用户交互 shell 这样的大任务,而无需重新发明轮子。采用这种方法意味着早期的虚拟化管理程序工程工作最小化,使得虚拟化本身成为关键关注点。
随着时间的推移,开始出现了替代方法。在虚拟化管理程序顶部运行完整操作系统以充当最终用户接口似乎是资源的浪费。后来的虚拟化管理程序采用创造性方法来解决这个问题,使得虚拟化管理程序本身更重,但总体系统的重量减少。
虚拟化往往令人困惑,供应商很少有理由想要揭示其系统的内部工作原理。因此,误用术语或建议虚拟化管理程序的工作方式与实际不同,无论出于营销原因还是为了试图简化对不太了解的客户的系统。今天有许多虚拟化管理程序,未来可能会有更多。然而,在生产企业环境中,我们预计会定期看到四种,我们将简要分析每种工作方式。没有一种方法是最佳的,这些只是解决同一个问题的不同方式。
VMware ESXi
今天的虚拟化市场领导者。VMware 是最古老的虚拟化产品之一,随着时间的推移,其设计也有所变化。最初,VMware 遵循经典设计,采用了极简的超级监控程序和一个隐藏的虚拟机,其上运行了一个简化版的 Red Hat Enterprise Linux,为用户提供了与平台交互的外壳界面。
如今,VMware ESXi 将一个小型 shell 构建到超级监控程序本身中,仅提供足够的潜在用户交互能力来处理最简单的任务,如检测正在使用的 IP 地址或设置密码。其他所有功能通过从外部工具调用的 API 处理,允许最重要的用户界面部分完全保留在物理客户工作站上,而不是在超级监控程序上。
Microsoft Hyper-V
尽管晚于企业级 Type 1 虚拟化的竞争,微软选择了经典方法,始终运行一个虚拟机,其中包含一个简化版的 Windows,提供了安装 Hyper-V 后用户所见的图形用户界面。这个第一个虚拟机是默认自动安装的,不需要付费许可,不包含 Windows 品牌,相反它被命名为物理机器,这使得它看起来好像根本没有虚拟机,而是在 Windows 安装之上运行的 Type 2 超级监控程序,但实际并非如此。这只是基于复杂的命名和不必要的混乱标准安装过程而看似如此。毋庸置疑,Hyper-V 是一种真正的 Type 1 虚拟化监控程序,以最经典的方式运行。
Xen
与 VMware 同样来自早期时代的 Xen 也采用了经典方法,但与 VMware 不同的是,多年来一直保持这种方式。然而,与 Hyper-V 不同的是,Xen 的安装过程更加手动化,用于提供用户交互的第一个虚拟机完全不被隐藏,事实上是完全暴露的。这意味着在超级监控程序安装过程中,一个虚拟机会被自动创建(因此它总是第一个),并且该虚拟机被特别授予直接操作控制台的特殊权限。因此,一旦启动,您看到的是虚拟机本身的控制台,因为超级监控程序除此之外没有其他控制台。
你甚至可以选择在管理虚拟机中使用不同的操作系统!然而,在实践中,Xen 始终与 Linux 作为其控制环境一同使用。其他操作系统大多是理论上的。这种暴露使得像 Hyper-V 这样的隐藏经典系统变得更加令人困惑,因为在 Xen 中,一切是如此显而易见。
由于 Xen 与 Linux 紧密结合,对于 Linux 系统管理员来说,了解 Xen、通过 Linux 管理 Xen 和 Xen 架构至少有些知识可能很有价值。这种紧密结合并不意味着在使用 Xen 时系统和平台团队会相互交织,但它增加了这种可能性。
KVM
最后,我们来谈谈基于内核的虚拟机(KVM)。KVM 之所以特别,有几个原因。首先,它独特地将虚拟化监视程序(hypervisor)合并到操作系统本身中。其次,它与 Linux 一起工作。与其他虚拟化监视程序不同,其他程序中平台管理者负责管理虚拟化监视程序,系统管理员负责管理操作系统层面。而在这里,这两种角色必须合而为一,因为这两个组件已经合并为一个。在使用 KVM 时,无法分开操作系统和虚拟化监视程序。KVM 将虚拟化监视程序直接嵌入 Linux 内核中。它只是内核的一部分,始终存在。
这种方法具有明显的好处。它简化了整个系统,并提供了几乎每种不同方法的优点,只有相对较少的注意事项。当然,也存在注意事项,例如虚拟化监视程序安装可能导致膨胀,增加潜在攻击面的真实风险。KVM 最大的好处可能是利用 Linux 系统管理员和现有知识的生态系统,因此在管理运行在裸机上的系统的某些更复杂的方面,如文件系统和其他存储架构决策、驱动程序支持和硬件故障排除中,与 Linux 共享,从而获得了一个庞大的基础平台和支持网络。
由于 KVM 的易用性和广为人知的许可(由于其包含在 Linux 中),以及广泛的组件可用性,当供应商希望创建自己的虚拟化监视程序平台时,KVM 已成为远远最受欢迎的选择。许多云端大型供应商、虚拟化监视程序管理或超融合空间已利用 KVM 作为其系统的基础,并在其上进行了定制化。
虚拟化只是为了整合吗?
大多数人问你为什么费心虚拟化,答案总是相同的:因为它允许你在单个物理设备上运行多个不同的工作负载。 毫无疑问,当适用时,整合是巨大的好处,但将其陈述为唯一的甚至关键的好处意味着我们忽略了大局。
虚拟化为了节省成本通过合并的持久神话似乎没有人能够驱散。虚拟化的性质对于普通人,甚至是普通的 IT 专业人士来说都过于复杂,它真正提供的东西仍然被广泛误解。虚拟化的真正价值在于它创建的抽象层,这提供了对未知的避险方式 - 一种使系统部署更灵活、更可靠,同时总体付出更少努力的方法。虚拟化为未来可能发生的未知事件提供了更多选项,这是你无法预计的。
对于虚拟化的一个核心挑战是它提供了太多不一定相互关联的好处。大多数人希望得到一个简单、稳定的答案,不想理解虚拟化的工作原理以及为什么添加额外代码层实际上会使系统更简单、更可靠。这些都有点过于复杂。事实上,虚拟化有很多好处,每一个都通常足以证明始终使用它,并且基本没有任何限制。虚拟化几乎没有成本,基本没有性能开销,不会增加管理复杂性(确实会在某些领域增加,但在其他领域减少,从而总体减少)。
不可避免地,人们会问是否存在虚拟化不适合的特殊工作负载。当然存在特殊情况。但地球上每个 IT 店铺的下一个反应是宣称他们独特且唯一,在他们的服务器需求中虚拟化不合理 - 然后他们可靠地声明一种标准虚拟化的股票和绝对理想工作负载,适用于几乎每个人,并且远离特殊情况或免除最佳实践的例外。相信我,你不是这条规则的例外。每次都虚拟化每个工作负载。没有例外。
大多数人提到他们避免虚拟化的例子通常是虚拟化处理不当的例子。其他非虚拟化相关的错误,如选择不良供应商、错误大小的服务器或选择大幅超支的存储层而需要精简的情况,可能会发生,无论有无虚拟化。无论是系统管理员、平台团队还是硬件采购者,他们仍然必须像没有虚拟化时一样做同样高质量的工作。虚拟化并非万能药,但不能成为消除我们工作需要做好的银弹的借口。这只是错误的逻辑。
现在我们应该对虚拟化有一个清晰的理解,而不仅仅是对其作用的浅显了解,并且知道为什么我们要将其用于所有生产工作负载。无论是在家庭实验室工作,还是在大型生产环境中运行,虚拟化应该很快成为第二天性。让虚拟化成为一个不言而喻的结论,只需要担心一些细节问题,比如存储配置、虚拟机监控程序选择或管理工具的使用。接下来,我们将看看虚拟化的替代方案及其近亲——容器化。
容器化
有些人认为容器是一种虚拟化形式,有时称为 C 类虚拟化或操作系统级虚拟化。近年来,容器已成为一种独立的存在,特定的容器使用场景成为了热门话题,以至于容器这一概念本身几乎被遗忘。然而,容器代表了一种极为有用的(或作为传统虚拟化的替代)形式。
基于容器的虚拟化与传统虚拟化不同,在传统虚拟化中,每个系统硬件的各个方面都由虚拟机监控程序以软件的形式进行复制,并且每个实例或虚拟机(在谈论容器时通常称为虚拟环境(VE))在其上运行时,都是唯一存在的。虚拟机之间没有任何共享的内容,按定义,任何支持虚拟化硬件的操作系统都可以在其上运行,就像它运行在裸机上一样。
基于容器的虚拟化完全不使用虚拟机监控程序,而是由一款软件构建,这款软件在操作系统中进行强烈的资源隔离,允许安装并运行各个虚拟机,就好像它们是完全独立的实例一样,但在后台,所有作为容器运行的虚拟机共享主机的内核实例。由于这个原因,安装任何任意操作系统的能力受到限制,因为只能安装能够共享同一内核的操作系统到单个平台上。
由于没有虚拟机监控程序,且所有系统共享单一内核,大多数容器系统的开销几乎为零,这使其非常适合许多高要求的任务。容器在 Linux 环境中尤其受欢迎,今天有很多容器选项。容器系统几乎完全没有系统开销,曾经是这种方法的一个关键特性,但随着系统从资源紧张到在许多情况下具有丰富的计算能力,挤压硬件每一滴性能的价值开始减弱,相比之下,完整虚拟化所带来的更大灵活性和隔离性变得更加重要。因此,曾被认为是最伟大的虚拟化选项往往被忽视,甚至被遗忘!
容器不需要任何特殊的硬件支持,完全通过软件实现,使得它们能够在更广泛的平台上运行(例如,很容易在老旧的 32 位 Intel 硬件或 Raspberry Pi 上实现),且成本更低。这使得它们在硬件加速广泛可用之前的时代变得非常重要。
在我们关心的 Linux 世界中,多个不同的基于 Linux 的操作系统可以在同一个容器主机上运行,因为只需要共享内核。因此,在单个容器主机上运行 Ubuntu、Debian、Red Hat Enterprise Linux、SUSE Tumbleweed 和 Alpine Linux 等虚拟机毫无问题。
Linux 拥有(也可能是个负担)几乎每个技术领域都具有大量的选项,容器化也不例外。Linux 上存在多个开源和商业容器产品,但今天无可争议的冠军是 LinuX Containers(LXC)。LXC 的独特之处在于它完全集成在 Linux 内核中,因此使用它其实只是简单地启用,不需要额外的软件或内核修改。如果你打算在 Linux 上实现真正的容器,可能性很大就是 LXC。几乎所有基于 Linux 的操作系统都完全支持 LXC。
容器简史
完全虚拟化由 IBM 在 1960 年代引入,但由于其复杂性,直到 1990 年代末期,借助高端硬件支持和大量特定的软件,才使其得以普及并进入主流服务器市场。
容器首次出现在 1979 年的 System 7 UNIX 中,使用的是名为 chroot jails 的机制,按今天的标准看起来相当简陋,但在功能上非常接近现代容器。在 UNIX 世界中,容器(无论是哪种类型)几乎一直都有存在。1999 年,真正的现代容器可以说从 FreeBSD 的 Jails 开始引入,随后其他 UNIX 平台如 Solaris 的 Zones 和 Linux 的 OpenVZ,最终 LXC 开始出现。到了 2000 年代中期,容器已经无处不在,并且在完全虚拟化技术真正起步之前就非常流行。
容器在 2013 年经历了一次复兴,伴随着 Docker 的引入。尽管 Docker 并不完全是一个容器,但“容器”这个术语如今更多地与 Docker 联系在一起,而非与真正的容器。早在 Docker 之前,容器从未被认为是特别吸引人,相反,它们更多是基本的进程隔离工具,承担着为操作系统执行初步安全工作的职责,唯一的例外可能是 Solaris Zones,在 ZFS 发布时曾一度受到大力推广。
如今,因 Docker 的流行及其与容器的紧密关联,大多数人(甚至包括系统管理员!)在提到容器时,会想到 Docker,而不是那些已经存在几十年的真正容器。
我们不能谈论容器而不提到 Docker。今天,Docker 是与容器最相关的名称,且这个称号当之无愧。Docker 最初作为一组构建在 LXC 之上的扩展而出现,为应用程序提供极端的进程隔离以及打包的库环境。尽管 Docker 使用容器,最初是 LXC,现则是其自有的容器库,但 Docker 本身是一个应用隔离环境,提供的服务范围比 LXC 更为有限。使用 LXC,你可以部署一个操作系统(不包括内核),并且几乎将其视作传统的完全虚拟化。而 Docker 则是部署应用或服务,而非操作系统。两者的范围不同,因此 Docker 更适用于第五章,补丁管理策略。由于 Docker 是应用层容器化,它通常会运行在虚拟机上,无论是完全虚拟化还是容器化,以提供其底层操作系统组件。
一般来说,容器代表了一个受信任、成熟且超高性能的虚拟化选项(或替代方案)。尽管在能力上更为有限(例如,一个 Linux 容器主机只能运行 Linux VE,而 FreeBSD VE 是不可能的),但它们更容易维护、更快速、通常也更稳定(因为出错的可能性更小)。容器可以更快地创建、启用或关闭、修补,资源使用上更灵活(它们不需要完全虚拟化所需的严格 CPU 和内存分配),需要的技能较少,运行时开销更小。容器的唯一显著限制是无法混合操作系统工作负载,甚至内核版本。如果你所做的任何事情需要特定的内核版本(且该版本在整个平台中并不统一),或者需要自定义编译内核、GUI、ISO 或类似的完整安装,那么容器显然无法满足你的需求。但如果你正在处理一个纯 Linux 环境,所有工作负载都是 Linux 且能够共享内核,这种情况并不罕见,那么容器将是理想选择。
至少目前为止,容器无法利用操作系统的图形界面,因此它们被限制用于纯文本界面(即 TTY)的服务器工作。因此,容器不是图形终端服务器或 虚拟桌面实例 (VDI) 部署的可选方案。这类工作负载仍然需要完整虚拟化,直到有人为此开发出解决方法。但由于这通常不是一个高度渴望支持的工作负载,因此很少有人会在这个已经容易解决的问题上投入大量精力,只为了能够说他们用容器解决了它。
通过使用容器,你可以让操作系统本身充当虚拟机管理程序,但它仍然是操作系统,并且可以使用所有常规的 Linux 工具和技术进行管理,因为系统仍然是 Linux。你无需学习或维护单独的虚拟机管理程序。这样,利用现有的 Linux 技能和工具的能力非常强大。
必须注意的是,由于 KVM 和容器都以标准的裸机 Linux 安装为基础,并且都直接集成在原生的 Linux 内核中,因此在同一主机上同时运行完整虚拟化和容器化并不罕见,且容器中运行原生的 Linux 工作负载是完全可行的。这确保了较低的开销和更大的灵活性,并且非 Linux(主要是 Windows)或自定义内核的 Linux 系统可以在 KVM 上作为完整虚拟机运行。如果你觉得混合使用更适合你的需求,就没有必要仅选择其中一种方法。容器技术如今已经变得极为流行且重要,但传统意义上对容器的使用已经大大减少。这主要是由于对术语和技术的误解,导致即使在非常合适的情况下,容器也常常被忽视。特别是作为 Linux 系统管理员,考虑在你的环境中使用容器而非传统虚拟化,可能会非常有益。将容器作为你工具箱中的另一个工具,可以让你变得更加灵活和高效。
接下来,我们将结合所学的虚拟化和容器知识,并加上管理方面的内容,来学习云计算。
云与 VPS
任何关于虚拟化的讨论,今天都不可避免地会引导我们进入云计算。云计算已经成为那个热衷了十年的流行词,人人都想要,大多数人都在使用,但却没有人知道它是什么,意味着什么,或者为什么要使用它。没有什么技术比云计算更加被误解,同时又被广泛谈论。因此,我们有很多内容需要讨论,其中大部分是为了澄清误解和滥用术语。
云的奇异困惑
这是一种罕见的组合,既是高度技术化的,又与正常的商业对话不相关,同时几乎在所有层级上都被讨论得像是一个随意的高层非技术性商业决策。考虑到只有极少数 IT 专业人士对云有任何深入的理解,而且更少人能清晰地理解何时选择它,普通的非技术性中层经理人会把这个术语当作讨论邮票价格一样轻松地使用,真是让人难以理解。那些人到底以为自己在讨论什么?没人真正知道。我是说真的,真心的。
问一群经常谈论云的人,把他们分开,避免彼此互相影响。现在,让他们描述云对他们来说意味着什么。你大多数时候会听到一些胡言乱语,显然如此。但当你深入探讨时,你会得到各种各样、彼此完全不同的描述和答案,而听别人讨论云的人通常会说,他们相信那些人说的都是在说同一件事,通常那个一个东西是他们都完全没有意思的,更别提是其中的一个人了。实际上,云对几乎每个人来说意味着不同、随机且毫无意义的东西,没有任何规律可言。
如果云这个术语有一个音乐对应物,那就是阿拉尼斯·莫里塞特(Alanis Morissette)的《Ironic》,这首歌的唯一讽刺之处就是标题。云这个术语也是如此,人人都在用,没人知道它是什么意思。就像“讽刺”一样。
多年来,云通常被用来表示托管。简单地用另一个没有任何理由的新词替代一个已建立的、广为人知的行业术语。当然,云根本不意味着那样。这种可怕的误解导致了没有云,只有别人的计算机的迷因。当然,即使稍微了解一下云的人,听到有人说出这种话时,也会感到羞愧,因为他们完全误解了云的含义。
今天,你更有可能听到“云”用来表示由 HTML 构建,我不是在开玩笑。有时它意味着平台独立,其他时候它表示订阅定价。你可以列出所有可能的含义,而“云”已经被用来指代其中任何一个。你唯一可以确定的是,没人,永远不会,真正意味着云。它可能意味着几乎任何其他东西,但从来不意味着这个术语实际所指的内容。
围绕云定义的广泛狂热唯一的好处是,没有哪个替代定义足够普遍,能够崛起并超越真正的云。然而,问题已经严重到一个程度,你作为 IT 专业人士,除非和一个真正博学且值得信赖的技术同事交流,否则无法和任何人使用云这个术语,因为你知道他们真的知道它是什么意思。
真正令人惊讶的是,云的使用已经取代了像协同这样的术语,成为商业中默认的笑话——也就是说,只有那些真正迷失的人才会使用这个术语。云复杂且被完全误解,已经成为如此常识,以至于你无法用它来传达一个想法。它已经成为一种语言中的标志,用来指代那些仅仅是在说管理术语,却完全不明白自己在说什么的人,而他们没有意识到其他人正默默地嘲笑他们的无能,但你几乎能听到它不断地被重复!无论每个人都知道他们在误用它,云依然具有一种上瘾的特性,并持续不断地被使用。
从这番看似抱怨的话(确实是抱怨)中,你应该记住的最重要的一点是,只有最顶尖的专业人士才能理解“云”这个术语,而只有受过良好教育的 IT 专业人士才能理解云计算。避免使用这个术语,因为无论你认为自己能像别人一样错误地使用它,你都不能。没有任何方式能正确使用云这个词,因为每个人都认为自己知道它是什么意思,尽管他们都认为它是某种独特的东西。
当你必须出于某种原因提到云计算时,使用更完整的术语,比如云计算或云架构,以澄清你实际上是指云,而不是随便抛出一个词让听者自行解读。
从很多方面来看,描述云计算几乎比描述它是什么更容易,尤其是因为每个人都认为它是某种东西。云计算与托管无关,与网页无关,甚至与互联网无关(有时互联网被称为“云”,而不是“一种云”)。我们不能在这里详细解释云计算的每一个可能方面,也没有必要,因为大多数云计算与系统无关,因此也与 Linux 无关。但我们应该在一定程度上讨论它对 Linux 系统管理员的意义,何时适用等问题。
首先,我们必须从NIST(美国国家标准与技术研究院)的云计算抽象定义开始,这一定义基于亚马逊最初的定义。始终牢记,云计算是一个真实的、严格的技术术语,由亚马逊为真实世界的架构所创造,因此它有一个严格、不可替代的定义,任何误用、误解或其他人试图篡改它的使用都不会改变它所指代的极其具体的事物。那些不了解云计算的人常常争辩说它是一个可以按自己理解的方式使用的宽泛术语,但事实并非如此。它不是一个偶然进入词汇表的随机英语单词,它在首次使用前就在行业内被精确地定义过。
NIST 的定义如下:云计算是一种模型,用于启用无处不在、便捷的、按需的网络访问,以共享的可配置计算资源池(例如,网络、服务器、存储、应用程序和服务)为基础,这些资源可以在最小的管理工作或服务提供者交互下迅速配置和释放。这个云模型由五个基本特征、三种服务模型和四种部署模型组成。
对我们作为系统管理员来说,定义中最重要的部分是涉及资源池和快速配置与释放的部分。因此,我们可以快速创建和销毁的共享资源(意味着服务器、CPU、RAM、存储、网络)。虽然云计算的定义远不止这些,但这些是最基本的。如果你立刻想到“这听起来像是虚拟化已经做的事情”,你是对的,确实有很大的重叠,虚拟化是云计算的关键构建模块(包括完全虚拟化和/或容器)。如果你想到“等一下,资源池我可以快速构建和销毁—这些特征对我或我以前工作过的任何环境来说都不太有用”,你也是对的。云计算并不适用于传统工作负载或环境,它是围绕着特定用途的应用架构设计的,这种架构只有少数企业能够在任何规模上加以利用。
使得云的使用更加混淆的是,许多供应商(并且在逻辑上是合理的)自己将云作为其产品的一个组成部分。因此,当你问你的供应商某个产品是否基于云时,他们可能是在回答是否将云作为产品本身提供给你,或者他们可能是在回答是否在工具的构建过程中某个地方使用了云。这两种情况都适用于大多数人提问的方式,而且由于没人真正知道云是什么,没人确切知道你到底在问什么或想要了解什么。让我举一个牵强但合理的例子。
如果我购买一个遗留应用程序,比如一个使用 MS SQL Server 和旧版 Delphi(Objective Pascal)前端的客户端-服务器应用程序,然后使用一个真正的云产品创建虚拟机并部署服务器端组件,这样我们就可以真正说我们是在云上构建了解决方案。然而,最终的产品从任何角度看都不是云计算。仅仅因为架构的某一部分是在云上构建的,并不意味着最终产品就是云。云只是堆栈中的一层。
对我们这些系统管理员来说,我们关心的是一种叫做基础设施即服务(IaaS)的云类型。这是一个高级的说法,实际上指的是基于云的虚拟机。其他类型的云,如平台即服务(PaaS)和软件即服务(SaaS),在云计算领域非常重要,但只有当系统管理员不在时才存在。如果我们是 PaaS 或 SaaS 的系统管理员,那么,对我们而言,云就是工作负载,而不是云。如果我们不是 PaaS 或 SaaS 系统的系统管理员,那么作为系统管理员,我们不需要讨论这些系统,因为它们与我们的角色无关。
从我们系统的角度来看,云几乎就像是一个先进的、灵活的虚拟化层。当然,像虚拟化一样,我们可能会被要求实施云平台。这是完全不同的一回事,值得写一本书(甚至两本)。但从实际角度来看,系统管理员可能会从一个虚拟机监控器、容器引擎或通过云接口编排的任何一个平台中获取资源。对我们来说,这一切都是一样的——它们都是我们部署操作系统的机制。因此,从纯粹的系统管理员角度来看,可以把云计算看作与任何其他虚拟化技术没有区别,因为它们本质上是一样的。唯一的区别是它是如何管理的,以及如何交由我们处理。
从实际操作来看,我们可能需要深度参与有关是否使用云计算与其他虚拟化获取路径的决策。像任何商业决策一样,这归根结底是评估在一个价格点下所提供的性能和特性,并将其与同一价格点下其他选项的性能和特性进行比较。就是这么简单。但是,鉴于我们之前提到的所有原因,在云计算方面,我们往往需要与大量的误解和对“魔法”的信仰作斗争。因此,我们需要稍微谈一谈云计算,尽管我们本不应该这么做,因为这些误解如此普遍且根深蒂固。
首先,有一种观念认为云计算是便宜的。虽然在特殊情况下,云计算可能节省大量资金,但这很少发生。云计算通常是一种极其昂贵的产品,之所以被选择,是因为它提供了很大的灵活性,从而可以减少整体购买量以满足相同的需求。云计算的提供成本非常高,因此供应商被迫收取比其他架构更多的费用以向客户提供(请记住,供应商可能是你们内部的云部门,云计算并不意味着外部供应商)。
水平可扩展的弹性工作负载
尝试描述云计算所应对的工作负载对于那些不熟悉某些类型应用架构的人来说可能是一项挑战。我们需要稍作停顿,深入探讨一些应用概念,才能真正理解我们作为系统团队是如何相关的,并看到为什么不同的方案在这个层次上对我们的平台决策起着如此重要的作用。
在传统的应用设计中,期望是将整个应用程序仅运行在一个或几个操作系统实例上。通常,一个实例会作为数据库服务器,另一个作为应用服务器。可能会有更多的角色,且你可能会有冗余的数据库服务器或类似的配置,但本质上,可用的实例数量是相当有限且静态的。一旦部署,实例的数量就不会再变化。在许多情况下,整个应用程序会存在于一个单一的操作系统实例中。
扩展传统应用程序主要侧重于提高单个操作实例的能力。这可能通过更快的 CPU、更多少量的 CPU、更多的 CPU 核心、更大的内存、更大的存储或更快的存储来实现。或者,正如我们通常所说的,如果你需要服务器做更多事情,你就需要一台更强大的服务器。这种性能提升方式能够产生很大的效果,因为高端服务器非常强大,且很少有公司需要运行超出单个大型服务器性能能力的工作负载。这种扩展方式被称为垂直扩展,意味着我们在框架内提升单线程或单个服务器的性能。这种扩展方式无疑是最容易实现的,并且适用于任何类型的应用程序,无论其设计如何(这就是你提升视频游戏性能或任何桌面工作负载的方式)。
对大多数人来说,专为垂直扩展设计的工作负载是他们唯一了解的工作负载类型。当然,对于在桌面上工作的终端用户而言,一切都是垂直的。即使是系统管理员,也几乎完全需要管理仅为这种扩展方式构建的应用程序。几乎所有内部部署的应用程序都假设这就是你扩展的方式,直到最近,许多开发人员才较为熟悉其他的替代方案,而且仍然有很多(可能大多数)人并不熟悉,尽管那些熟悉的人在媒体上更为突出。
另一种方法是设计能够通过添加额外、独立的操作实例来扩展的应用程序。例如,运行多个数据库服务器实例(可能在一个集群中)不仅仅是为了提高弹性,同时也为了提高性能。运行多个应用程序服务器,可以通过简单地添加更多的操作系统实例来运行应用程序,同时保持每个单独实例的规模较小。在传统的应用程序架构中,我们可能需要一台拥有四个高性能 CPU 和 1TB 内存的应用服务器来处理我们的应用负载。一个水平可扩展的应用程序可能会使用 16 台较小的服务器,每台服务器有 64GB 内存和较小的 CPU 来处理相同的负载。传统上,我们会说我们的系统是向上扩展,但通过添加更多实例,我们说它们是向外扩展。当然,你总是可以同时进行向上和向外扩展,这意味着增加每个单独实例的资源,同时也增加实例的数量。
正如你可以想象的那样,我们在现实世界中作为终端用户或系统管理员使用的少数应用程序设计上并没有考虑或能够有效利用水平扩展(scale out)平台,即使能做到也是有限的。这要求应用程序架构师、分析师和开发人员从一开始就为这种部署方式进行规划。而再多的规划或期望也不能使每个工作负载都能够以这种方式扩展。
一些应用程序,如常见的基于 Web 的业务流程、大多数网站、电子邮件系统等,非常适合这种设计,你可以轻松地找到或制作这些类型的应用程序,以利用这些资源。其他应用程序,如财务处理或库存控制系统,可能会因为设计上的局限性而面临困难,要能够实现这种扩展可能需要更多的工作,甚至有可能根本无法做到。
仅仅因为开发团队设计了一个工作负载,使其具备水平扩展性,并不意味着该工作负载本身就能实现这一点。这可以通过一个简单的例子来说明。你创建了一个帮助人们选择健康早餐的网站,你将其市场定位于美国。从东部时间早上 6 点到下午 2 点(即加州人吃完早餐时),网站非常繁忙,但在这些时间之外,网站运行非常缓慢。另一方面,另一个网站帮助人们选择任何一餐的食物,并且面向全球市场。这个第二个网站的访问量虽然没有第一个网站那么大,但全天保持着相对一致的流量。第一个网站可以利用扩展性,而第二个网站无法做到这一点,因为其所需资源几乎没有变化。
水平可扩展工作负载的关键优势在于它们可以迅速增长。添加一个额外的操作系统实例(或者额外的一百个!)是简单且不具破坏性的。相比之下,向现有服务器添加更多的 CPU 或 RAM 则既困难又缓慢。水平扩展的下一步是让它变得具有弹性。为了具备弹性,系统不仅要能快速扩展,还要能够在容量发生变化时迅速收缩:即在不需要时关闭并销毁不必要的操作系统实例。这正是云计算的独特优势,为弹性、水平可扩展的工作负载提供按需容量,使你可以在需要时使用资源,不需要时停止使用。
垂直扩展资源提供的成本远低于水平扩展资源。你可以通过尝试组装几台规格大致相同的计算机来验证这一点。除非在极少数情况下,构建一台大型服务器的成本是几台小型服务器的一小部分,这在实际经济学中是如此。单一系统只需要一个操作系统和应用实例,而多个系统则需要每个系统都加载相同操作系统和应用程序到内存中,浪费了许多资源。此外,管理一个更快的系统比管理多个较慢的系统要少得多。管理人力也是如此。管理一个高效、快速的员工比管理多个较慢的员工要少得多,后者需要协调完成同样的工作。
因此,要使水平扩展系统成为一个合理的选择,它必须能够利用扩展和收缩两种方式,拥有能够有效利用这一点的工作负载使用场景,并且这一点要足够大,以克服传统设计的低成本、低开销和高度简化。除非你的工作负载满足所有这些要求,否则云计算根本不应成为你的考虑对象。它根本不适用。尽管媒体和趋势驱动的 IT 专业人士常常会误导人们认为云计算无所不在,但实际上,只有少数工作负载能够有效地利用云计算,而且只有少数企业拥有这些稀有的工作负载。
当然,我们谈论的是云计算的 IaaS 方面。在其他云计算领域,只有应用部分暴露给业务,通常是基于云的。但这与我们在这种场景中讨论的内容基本无关,决策过程也完全不同。
第二,存在一种观点认为云计算是可靠的。云计算的定义或设计中完全没有任何东西暗示它具有可靠性。事实上,这与所有标准的云计算思维完全相悖。云计算,由于它是专门为扩展设计而构建的,因此假设任何冗余或可靠性都必须内建于应用程序本身,因为扩展要求——你必须将这一点包含在应用程序内部,以便扩展能够正常工作。因此,在系统或平台层级包含冗余是没有意义且适得其反的。对于云计算的基本理解,应该使我们感到惊讶,如果有人期望在这一层级上提供超出最低要求的冗余。在现实世界中,云计算资源通常比传统的服务器资源更加脆弱,正是因为这个原因。云计算假设可靠性不是非常重要,或者它在技术栈的其他地方得到提供。云计算只是最终系统的一个构建块,绝不是一个完整的解决方案。当然,理论上,可能会出现一个高可用性的云计算服务商,但他们的成本和性能限制将使其很难在几乎完全由价格驱动的市场中竞争。
第三,存在一种观点认为云计算具有广泛的适用性,认为每个公司都应该使用它,并且它正在取代所有其他架构。实际上,这完全不正确。云计算从现在开始已经存在超过十五年(在写作时),并且在那个周期的初期它就迅速渗透了市场。今天,云计算已经成熟并广为人知。那些将要迁移到云端(或为之设计)的大多数公司和工作负载已经完成了迁移,新的工作负载也在以大致稳定的速度在云端创建。云计算的行业饱和率或多或少已经实现。随着旧的工作负载退休或在其他压力下屈服,一些新的工作负载将会迁移到云端。有些工作负载会回流,因为一些过于热衷的云计算爱好者和受流行词驱动的管理者会从云端迁移回来,吸取没有理解或规划的教训。将标准工作负载迁移到云计算而不进行重新设计通常会带来高昂的成本和风险。但总体来说,云计算已经稳定在一个已知的饱和点,计算世界将保持现状,直到另一个激动人心的范式转变发生。基本上,我们今天在高级定制内部软件和大规模多客户软件中看到的东西非常适合云计算范式,而传统的单客户工作负载仍然在传统范式下最为有利。这一切都正如当初云计算首次宣布时所预测的那样。
使用云计算并不需要任何特定的技能或培训,尽管许多行业人士为了销售认证和培训课程,可能希望我们相信这一点。事实上,了解云计算的真正含义通常足以让你有效地使用它。也就是说,个别云供应商平台(例如Amazon的AWS或Microsoft的Azure)如此庞大且复杂,以至于获得供应商认证和培训在了解如何与他们的产品接口交互时确实具有实际价值。但需要明确的是,培训的价值在于学习如何与特定供应商合作,而不是学习云计算本身。
这并不改变这样一个事实:大多数寻求从云计算中获得重大价值的组织,很可能需要通过深度的供应商集成来实现,而这几乎肯定需要对特定供应商的产品知识进行投资。
云计算是一组令人惊叹的技术,服务于一个极其重要的目的。当你的工作负载适合云计算时,其他任何东西都无法与之媲美。无论你是建立自己的私有云还是使用公共共享云,无论你是将云托管在内部还是让托管公司处理数据中心组件,云计算可能是某些工作负载的正确技术。通过你在这里的理解,你应该能够评估自己的需求,判断云计算是否可能发挥任何合理作用,并能够查看实际供应商和成本,进行与其他选项的比较,并做出基于数学的合理评估。
现在我们了解了云计算,我们可以回顾一下虚拟专用服务器的旧概念,并探讨它们为何与今天的云计算紧密相关,但实际上并不相同。
虚拟专用服务器(VPS)
与 IaaS 云计算类似,甚至在事物的维恩图中几乎重叠的现代概念是虚拟专用服务器(VPS)。VPS 实际上早于云计算,源于更简单的虚拟化(或容器化)技术,允许供应商(当然也可以是内部部门)从更大的共享环境中为客户划分单独的虚拟机。客户无需提供完整的服务器,而只需购买供应商服务器的一个小片段或几个片段来满足他们的需求。
正如我提到的,这听起来与我们刚才描述的 IaaS 云非常相似,实际上它确实是如此。实际上,许多人使用 IaaS 云时,实际上是在不自知的情况下使用其 VPS 方面。VPS 背后的理念是允许公司以通常所需的物理服务器规模的很小一部分来购买服务器级别的资源。如果你回想一下我们讨论虚拟化时提到的,如何通过使用虚拟机监控程序(hypervisor),我们可能将一台物理服务器转换成一百台虚拟机,每台虚拟机运行自己独立的操作系统,那么我们可以将这些资源卖给一百个不同的客户,每个客户都能在自己的安全空间内运行一台小型服务器。这使得小公司或有小需求的公司能够以任何现实的预算购买企业级数据中心和服务器硬件的容量与价格。
在继续之前,我们需要快速进行一次 VPS 与 IaaS 云的对比分析,以了解为什么 VPS 与云计算如此常被混淆,并且它们为何经常相互竞争:
-
首先,目标:IaaS 云的目标是通过自动化提供按需快速创建和销毁资源的能力——主要供最大型的组织或工作负载使用。VPS 背后的目标是将传统服务器资源划分,以便小型组织和/或工作负载能够负担得起。一个追求的是最大的规模和最复杂的系统,另一个追求的是最小的规模和最少的复杂性。一个预计应用程序和基础设施团队双方都需要进行定制化工程工作,而另一个则期望传统应用程序,并且任何团队无需特殊知识或额外配合。
-
其次,接口:在云计算中,期望和目标是系统能够自我配置(并且自我销毁)。云并不是为了让人类手动交互来请求资源,也不是为了配置它们,也不是为了决定何时需要更多(或更少)的资源,也不是为了在完成后销毁它们。因此,云的重点是提供 API,使软件能够处理资源配置。VPS 的设计目标是像任何正常的虚拟机一样工作,由人工启动构建,安装操作系统,可能进行操作系统配置,并关闭虚拟机,最后在不再需要时删除它。云产品通常不提供与虚拟化硬件的任何直接交互,例如访问控制台,因此需要控制台级别交互(如图形用户界面)的一些系统是无法实现的。要成为 VPS,必须提供控制台和图形用户界面访问,才能以标准方式完全模拟硬件设备。如果你能使用普通服务器,那么你就能使用 VPS。
-
第三,资源配置:云服务假设需要快速配置。当然,“快速”是一个相对的概念。但在云生态系统中,系统必须能够在几分钟甚至几秒钟内从首次请求到完全功能的状态,这几乎是理所当然的。在 VPS 的世界里,虽然我们总是希望一切能尽快准备好,但在开始手动安装操作系统之前,等待几分钟的时间是很常见的,甚至可能需要几十分钟。我们假设云实例是通过软件创建的,而 VPS 实例则是由人工手动创建的。
-
第四,计费:由于云计算的价值假设来源于其能够快速创建和销毁的特性,从而保持成本的可控性,因此计费必须是细化的才能实现这一点。为此,计费通常按分钟或可能是小时的增量来处理,或者以其他极短的单位如处理器周期来计算。VPS 有时也会按这些短的时间增量收费,但也可以轻松使用较长的时间间隔,如按天或按月收费,因为它不是一个快速创建和销毁的服务。(我们可以说,云服务倾向于无状态,而 VPS 则倾向于有状态。)
使 VPS 和 IaaS 云服务更难区分的一个原因是,今天几乎所有的 VPS 提供商都使用 IaaS 云服务作为其 VPS 配置的底层机制,而大多数 IaaS 云服务提供商也选择额外提供 VPS。这种情况注定会发生,原因有两个。首先,VPS 提供商使用云服务,因为这是一种非常合理的方式来构建 VPS(如果你考虑一下 VPS供应商的需求,它们听起来与云服务的目标非常相似),并且由于 VPS 是建立在云计算之上的,你可以将它作为云的一部分来宣传,并成为一种简化的云资源接口。对于云服务提供商来说,提供 VPS 也是有道理的,因为大多数寻找云服务的客户根本不知道它是什么,只是出于政治而非商业或技术原因使用它,因此提供一个简单的服务让他们可以从你这里购买并使用你的资源(因为云服务非常复杂难懂)能够帮助你捕获大多数的收入。
像 Amazon 这样的供应商曾经没有提供 VPS 服务,如果你并非真正需要云服务,使用他们的资源是非常困难的。为了解决这个问题,Amazon 将 LightSail 作为 VPS 产品加入到他们的云产品之上。
其他云服务提供商,如Digital Ocean、Linode和Vultr,将 VPS 作为其主要产品,并几乎完全专注于它,同时将其云界面静静地放在一旁,让真正需要云服务的客户能够找到它,而那些原本打算使用 VPS 的人则能立即获得所需的服务。
VPS 是现实世界中企业运行工作负载的最受欢迎且最有效的方式之一,尤其是对小型公司而言,但任何规模的公司都可以利用它们。云计算是有效的,但主要适用于特殊情况的工作负载。大多数宣称正在利用云计算的公司实际上正在使用 VPS,并且甚至没有意识到他们完全忽视了云计算。
值得注意的是,当我们谈论云采用率时,我们面临一个根本性的问题:没有人知道云计算是什么,包括那些认为自己当前在使用或没有在使用云计算的人!像亚马逊这样的供应商可以告诉你他们有多少客户,但他们不能告诉你这些客户是在将他们的产品作为云使用,还是以其他方式使用云计算。在关于云采用的调查中,几乎没有合理的机会,能够确保被询问的人、问卷调查的人以及阅读采纳率报告的人,三者对云计算的理解足够深入,能够有意义地回答或提问,实际上,通常他们都根本不知道被问到的问题是什么。所以,关于云采用率的任何信息都接近完全没有意义。没有任何真实的机制可以让任何个人或组织真正了解云计算生态系统的真实面貌。如果一群松鼠对一堆仓鼠进行天体物理学调查,然后把结果交给一群超级活跃的小狗来解读,你会得到同样有意义的数据。人们喜欢报告和数据,很少关心调查本身是否有任何实际意义。
在这一点上,你可能会对 IT 和业务领域中对云计算的理解状况感到既不知所措又沮丧,但作为 Linux 系统管理员的你,现在应该准备好去解释它,评估它,了解它所构建的基础,并知道何时以及如何选择将其用于自己的工作负载,何时则应考虑选择 VPS。
本地部署、托管和混合托管
既然我们已经讨论了这么多构成我们平台的底层组件,用以部署操作系统的基础,接下来我们终于可以讨论这些系统应该存在在哪里!
至少,这些是我们讨论的最简单的主题。物理位置容易解释,尽管许多企业在实践中对此感到困惑。从概念上讲,我们通常只考虑两种工作负载位置,即本地部署和非本地部署。尽管如此,这可能有点复杂,因为公司拥有多个地点,所以对某一个地点来说是非本地的,在另一个地点可能就被视为本地的。然而,我们通常认为本地部署是指公司所有的站点,而非本地部署则指由第三方运营的任何站点。因此,我们通常将非本地物理性称为托管,因为物理系统是由我们委托托管的。然而,也有一些原因,这种说法可能会误导人。
大多数人认为,当系统托管在本地时,这也意味着它将由内部团队操作。这通常是对的,但由第三方团队管理本地系统并不鲜见,尤其是在高性能或高安全性环境中。例如,如果你需要亚马逊特定范围的云计算产品,但又无法允许任何外部托管,你可以让亚马逊在你的本地运行 AWS 云实例。这远非低成本或简单,至少需要一个小型的自包含数据中心及其所有相关人员!
托管在实践中变得更加复杂,但核心问题始终如一:划分点。当我们决定将系统托管到外部时,问题迅速变成了定义哪些部分由托管服务提供商提供,哪些由我们自己提供。
在最极端(也是不切实际)的情况下,你可以租一座房子、办公室或储藏室,并根据需要提供自己的机架、服务器、互联网、冷却、供电等,但如果我们这样做,可以说我们实际上已经将这个地方变成了我们的本地场所。说得好。
传统上,人们认为几乎所有工作负载都应该在本地运行。这是因为一个非常简单的原因:早期的商业网络没有互联网连接,因此将其托管到其他地方几乎是不可能的,或者至少不实际。再加上在互联网初期,广域网连接速度慢且不稳定,使得远程服务器几乎无法使用。而且,软件是围绕局域网网络特性构建的,与今天不同的是,今天任何优质的企业软件都假定它需要在长距离连接上(最有可能是互联网)有效地运行。
由于这些旧的假设,服务器需要位于员工工作的办公室这一“部落知识”被代代相传,很多人未曾对此进行评估。随着 2000 年代初期的到来,这一信息从普遍正确转变为几乎不再正确。
今天,大多数工作负载通过互联网有效运行,因此可以几乎位于任何地方。使用某种形式的外部托管或不基于任何特定公司位置的集中式托管如今已成为常态,而不是例外。
在所有本地和外部托管的评估中,我们有一些普遍的因素:谁会访问数据,以及从哪里访问,延迟和带宽如何影响应用性能,哪些访问数据的人具有优先权,以及在不同位置的性能问题成本如何。
没有固定的规则,我们只是需要尽可能仔细地考虑尽可能多的因素。场内和场外解决方案仅仅是位置,应当视作如此。使用企业级场外数据中心可能非常重要,特别是如果我们在场内没有真正的服务器机房。而且灾难恢复在场外位置可能会更好。但如果服务器离得很远,用户体验是否足够好呢?这些问题都是情境性的问题,需要从当前的业务基础设施状况以及未来短期的角度来回答。
合租机房
当一个站点提供了房地产、冷却、电力、互联网、机架、网络等服务,而我们提供自己的物理服务器时,这被称为合租机房。合租机房是我们作为系统管理员,在保留使用任何对我们的组织和工作负载有意义的硬件灵活性的同时,获得企业级数据中心服务的最流行和有效的方式之一。合租机房对从非常小的企业到绝对巨大的企业都有效。没有任何公司会超越合租机房可能带来的价值,政府也一样。这是一种没有上限的策略。
合租机房是将 IT 设备移出场地的最有用和有效的形式之一,因为它允许 IT 部门保留对硬件采购和配置的完全控制,不仅仅是对系统,还有网络和设备的控制。只有支持技术硬件的非 IT 职能是由合租机房提供的。这使得合租机房能够专注于强大的设施管理技能,而 IT 部门则保留所有 IT 职能和灵活性:基本上,你可以通过第三方远程完成原本希望自己内部团队做的事情,假设你有足够的业务量来这么做。预计合租机房提供商也会有远程操作人员,在必要时帮助完成一些基础工作任务,比如更换或验证电缆、重启设备等。
灵活性是合租机房的关键。不论是因为你希望定制自己的硬件、维护遗留系统、使用特殊硬件(例如 IBM Power 硬件),还是希望将现有的整个环境从场内迁移到合租机房,合租机房都能提供这种自由。大多数合租机房设施也允许不同规模的部署,从为你托管一台 1U 服务器,到为你提供部分机架(通常有十分之一、四分之一、半个、全机架等规格),甚至提供能够容纳多个机架的笼子,甚至出租整个数据中心楼层!
合作托管面临的最大挑战是没有有效的方法去实现极小规模,因为你可以合理托管的最小规模是单个服务器。如果你的需求小于这个规模,那么合作托管通常难以为你提供具有成本效益的解决方案。但不要仅仅因为认为它昂贵就拒绝合作托管。我经常为那些认为合作托管太昂贵的公司做这些计算,结果发现合作托管的成本不到他们其他提案成本的一半,同时还能提供更多的增长灵活性,而无需额外支出。大多数人认为服务器比实际更贵,合作托管的费用比实际更高。合作托管的费用常常不恰当地与传统系统挂钩,好像只有二十年的旧设备才能进入数据中心,而人们往往设想的是几十年前的成本模型。二十年前,服务器比现在贵得多,使用寿命也明显更短,数据中心空间的成本也比今天高。就像 IT 中的一切一样,成本随着时间的推移已经下降,对于任何规模的工作负载,合作托管通常比大多数替代方案便宜得多。
合作托管只是将系统托管到远程的其中一种方法。其他方法如公共云、托管云和基于云的 VPS 系统是标准的替代方案。
关于本地性的最大挑战,实际上都是与理解当前市场上不同方法的定价相关,并能够评估在本地或远程托管设备的好处和注意事项,以及这些设备应该是专用的还是共享的。现在你应该准备好做出评估,并根据你的部署情况做出适当的选择。接下来,我们将深入探讨平台级系统设计架构这一更复杂的话题。
系统设计架构
系统管理中最具挑战性的一部分就是处理系统架构这个广泛的概念。在某些情况下,我们的预算非常低,或者我们的需求非常简单,以至于我们根本不需要考虑除了最基本的选项之外的任何事情。但对于许多系统来说,我们有更广泛的需求,且需要考虑的因素非常多,使得系统架构在许多方面都可能变得具有挑战性。
我们现在理解了平台概念、本地性以及通常与提供一个可以安装操作系统的环境相关联的服务范围。接下来,我们需要开始描述如何将这些概念结合到现实世界中,形成可用的设计。大多数系统设计其实就是常识和实用性。记住,任何事情都不应像魔法或黑匣子一样神秘,如果我们从供应商那里获得服务,他们使用的技术和选项范围与我们是一样的。
我们将在下一部分讨论风险和可用性,但在此之前,我们应该提到这一点,以便更清晰地说明为什么系统设计依赖这些数据:我们为整体系统增加的任何冗余(无论是为了性能还是风险降低)都可以在不同层次上进行。主要是在系统层(我们当前讨论的层面),或者在应用层(我们无法控制的层面)。因此,即使在需求最苛刻的高可用性工作负载情况下,我们也可能不需要一个强大的底层系统设计,在思考设计选项时必须考虑这一点。
我将分析常见的设计方法,以便我们理解它们如何最好地应用于不同的场景。这些是包括存储和计算的物理系统架构。假设在每种情况下都使用某种抽象技术,即虚拟化和/或容器化,因此在每个案例中不会逐一提及。
独立服务器,也叫“雪花服务器”
这个设计可以说是最基础不过的了。简单的服务器,作为所有其他设计的基准。自包含的“一体化”服务器,将存储和计算都集成在一个机箱内。没有外部依赖,没有集群,也没有冗余(单一机箱外部的冗余)。当然,我们假设遵循了标准硬件实践,比如最基本的 RAID 和双热插拔电源供应等。
如今,许多 IT 人员会对尝试使用独立服务器表示反对,但他们不应该这么做。经典的单一服务器是一种强大、有效的设计,适合大多数工作负载。这应该是首选设计,默认的起点,除非你有特殊需求做其他事情。
由于其简单性,单服务器设计具有最好的成本比,较其他因素相比,它们比看起来更强大,且性能优秀。许多人认为服务器是一种脆弱的设备,而多年前它们确实是这样;但这种印象源自 1980 年代和 1990 年代初的服务器。到了 1990 年代末,服务器技术逐渐成熟且可靠,今天在良好维护的服务器上,故障率极低。认为单一服务器风险很高的观点已经过时了,但像我们行业中的许多事情一样,过时的观念常常残留下来,并在导师与学员之间传递,而没有重新评估这些因素是否仍然成立(而且在许多情况下甚至没有最初的评估,根本不知道这些观点是否曾经成立)。
与任何其他方法相比,单个服务器受益于拥有更少的组件和更低的复杂性,并且由于部件失败较少且配置错误较少,使其更加容易实现真正的可靠性:这就是为什么我们有时将其称为砖块方法。砖块简单而有效,虽然它们可能失败,但很少失败。情感上常常将复杂性与健壮性联系在一起,但实际上简单性更加可取。复杂性本身就是其敌人,不必要的复杂系统会带来不必要的风险(和成本)。
尽管由于许多原因难以衡量,我们通常假设一个良好维护和支持的独立服务器可以提供接近五个九的平均可用性(即每年约一小时的停机时间)。在任何业务中,很少有工作负载不能很好地应对这种停机时间。独立服务器面临的困难是这只是一个平均值(当然),我们将有孤立系统经历更高的停机时间,而其他系统则完全没有停机时间。
简单性还带来了性能。通过路径中减少组件,单个服务器具有出色的性能。试图获得超过单个服务器所能实现的总体性能是困难的。单个服务器为我们提供了几乎任何方法中最低的延迟和几乎最佳的吞吐量。
当涉及到单个服务器系统时,使用数学和逻辑来解释它是否合理是很重要的。许多人在系统架构方面依赖情感,这是不应该发生的。我们对系统设计的关注点是性能和可用性,这些纯粹是数学组成部分。情感在这里没有任何作用,事实上,它们是我们的敌人(就像它们是任何业务流程的敌人一样)。
单个服务器的扩展能力远远超出大多数人的想象。我经常听到的论点是,他们无法考虑单个服务器,因为他们的需求如此巨大,但随后部署的系统仅仅是标准规模的一小部分,更不用说单个服务器可以达到的最大规模了。请记住,与横向扩展相比,纵向扩展效果显著,并且通常也具有成本效益。最大的单个服务器系统可以支持数百个最强大的 CPU 和许多 TB(甚至更多)的 RAM。挑战不在于找到一个足够大的单个服务器来完成任务,而是找到任何能够有效利用如此强大能力的工作负载的任务位置!
独立服务器的一个重要优势是,每台物理设备可以根据其工作负载的需求进行扩展和定制设计。因此,不同的服务器可以使用不同的 CPU 到 RAM 到存储比例,不同的服务器可以使用不同的 CPU 代数或架构,一个系统可能使用大容量硬盘,而另一个则使用小巧但速度极快的固态存储。调整非常简单。
简单并不一定意味着简单
拥有独立的服务器并不意味着我们放弃所有我们可能认为需要从更复杂设计中得到的选择和灵活性。这只是意味着我们必须以不同的方式考虑它们。关于独立服务器的许多关切很可能源于一个虚拟化技术尚未普及,网络相对较慢的时代。今天我们拥有虚拟化、快速存储和快速网络,这些可以在一定程度上改变游戏规则。
我们将服务器称为独立的,是指它们的架构,一切都是自包含在一块硬件中的。这并不意味着我们没有(或不能有)多个服务器。相反,像世界五百强公司经常会拥有数千台独立的服务器。使它们独立的是它们彼此之间没有依赖。其中一台的完全失效(或被盗)不会对另一台产生负面影响。
一个小型组织可能会选择依赖单个独立服务器来支持他们的整个业务,并完全依赖备份和恢复到替换硬件的能力,如果灾难发生。这是一种完全有效且相当常见的方法。
如果您的组织规模较大,或者工作负载需要更快的可用性保护,那么运行多个标准服务器是标准做法。这会在物理硬件设备之间分担负载,并且由于虚拟化,提供了通过快速在其他硬件上重建丢失工作负载来缓解硬件故障的自然方式。如果部署密度过高,备用硬件也是一种选择。借助现代存储、网络、系统管理和备份技术,恢复许多工作负载可能只需几分钟,即使完全硬件故障也通常只会带来微不足道的系统影响。事实上,将备份存储在其他独立节点上可以实现丢失系统的几乎即时恢复,同时保持强大的解耦。
独立的服务器也并不意味着没有统一的管理形式。像 ProxMox 或 VMware vSphere 这样的工具允许管理的集中化,同时保持系统硬件的独立性。现代工具使得管理庞大的独立服务器群变得非常简单。
独立服务器的几乎每个方面都可以通过增加更多内容和使其更复杂来改进,它始终引领的两件事是成本和简单性。在商业上,没有其他方法能够可靠地保持我们的成本或我们的简单性如此之低,这通常是最重要的因素。
许多对多服务器和存储
随着公司成长,可能会有机会整合架构中的不同方面以节省成本。分离网络和存储是最常见的做法。创建一个计算节点层和一个存储节点层可以带来很大的灵活性。其主要好处是能够轻松移动资源,并更好地利用系统。
例如,一个组织可能需要十五个物理计算节点(传统服务器),但只需要六个存储节点(SAN 或 NAS)来支持它们。每个独立系统可以轻松定制扩展,并且不需要与池中的其他系统匹配。通过这种方式,这种方法与独立服务器方法并没有太大区别。
应当注意的是,存储层相较于计算层,在做这件事时存在更大的风险,原因有两个。首先,存储是有状态的,而计算是无状态的,这意味着我们不仅需要保护系统的可用性(正常运行时间),还需要保护数据的存储,因此存在数据丢失的风险——这里有更多的东西需要保护。其次,存储比计算更复杂,两个层级上的硬件和软件相同意味着存储层更容易因复杂性而发生故障。这些风险在独立服务器中也存在,但当它们被组合成一个单一机箱时,可能更难理解风险发生的位置,即使我们知道整体的风险结果是什么。
在最简单的实现方式中,我们会有一个计算服务器节点和一个存储节点(通常是 SAN 阵列),并通过一根直连电缆(如以太网、eSATA、FC 等)直接连接它们。这实际上是一个假设场景,因为它显然是膨胀且不合逻辑的,缺乏规模化,但我们可以从这个例子中学习,看看如何将单一独立服务器设计,在没有任何规模效益的情况下,简单地将机箱数量翻倍,从而管理并增加系统设计的物理复杂性和逻辑复杂性。
通常,这种设计的最大优势是能够大规模整合存储,将尽可能多的存储推入单个节点,同时拥有许多小型到中型(一个或两个 CPU)的服务器,允许工作负载在这些服务器之间流动,以便最佳地平衡工作负载。这种方法具有灵活性,通常具有成本效益,并且使大规模扩展变得相对简单。
超越独立服务器的设计意味着我们开始引入需要讨论的依赖关系。至少,当我们转向一个多节点系统时,就会有节点间连接的复杂性(这些连接可能只是简单的电缆,也可能更复杂,比如通过某种交换网络),以及配置节点之间的通信所带来的复杂性,还有额外组件故障的风险。
这种设计实际上并没有解决风险问题,反而比标准的独立服务器更具风险。这就是为什么将独立服务器作为基准,并从这个基准点出发发现风险变化是很重要的。在一个网络系统设计中,没有冗余,因此每个工作负载完全依赖于它所关联的计算节点和存储节点。这个风险可能在计算节点之间是均匀的,或者每个工作负载所在的节点可能有独特的存储配置,从而导致同一服务器上不同工作负载的风险差异很大。在这里,风险变得更加复杂,因为我们必须处理计算节点、存储节点、两者之间的连接以及配置的累计风险!每个单独的部分都非常难以单独衡量——将它们放在一起时,我们大多数情况下只能从相对的角度来看,并理解它比独立服务器更具风险。
将世界视为工作负载
系统架构是按工作负载来设计的,没有必要让组织中的所有工作负载,甚至单一计算节点上运行的所有工作负载,都共享相同的架构。混合搭配完全可行,而且在某些情况下是常见的。每个工作负载应根据其自身需求进行评估,然后评估整体架构。
经常被忽视的是,可以为不太重要的工作负载使用复杂且不太可靠(但在大规模情况下可能更便宜)的网络设计选项,同时在相同的计算节点上为更关键的工作负载提供极其快速和/或可靠的本地存储。在需要存储合并的一个大环境中,混合搭配可以是一种强有力的策略,这样做不会危及少数高度关键的服务。
同理,每个工作负载都可以有自己的备份、复制、故障转移和其他灾难应对的风险缓解策略。共享一个计算节点通常不会对工作负载间如何处理可靠性和可用性提出过多要求。当然,通常所有工作负载都会以相同的方式处理,要么是出于标准化和简化的愿望,也常常是因为误解了每个工作负载可用的定制化范围。人们常常认为选择一个系统设计是一个非此即彼的决定,但事实并非如此。
网络系统设计的主要挑战在于,任何获得的效率提升都必须抵消由需要更多节点(分离计算和存储意味着同样的任务需要额外的硬件机箱和操作系统)所带来的额外成本,并且在任何规模下,都会需要更多的网络设备来处理互联连接。网络设备可以是一个简单的以太网交换机,也可以是复杂的光纤通道或 Infiniband 交换机集群。交换机不仅代表了额外的购买成本,还增加了硬件故障的风险,并且在较小程度上也增加了配置的复杂性。通常会购买冗余交换机来降低硬件风险,但这会增加成本和配置复杂度。即便是在极其庞大的环境中,这也意味着额外的成本和风险,这些往往是难以克服的。
末日倒金字塔:集群化计算与高风险存储,亦称 3-2-1
遗憾的是,倒金字塔(又称 3-2-1 或 IPOD)传统上在 2000 年代和 2010 年代的大多数时间里,一直是中小企业中最常部署的架构,同时也是普通工作负载需求的最糟糕设计决策的典型例子。它也是供应商和转售商最大化利润的设计,因此这是每个人都希望你购买的方案。
IPOD 设计与上述的网络系统设计的区别在于,计算层是集群化的,以实现高可用性,而存储层则不是。如我们在上次的设计中讨论的那样,存储既需要更好地保护,又更容易发生故障。通常,网络层(即提供计算与存储之间连接的层)也会进行集群化以实现高可用性。每一层的节点数量决定了所使用的命名约定:3-2-1 指的是设计中有三个(或更多)计算节点,连接到两个冗余交换机,所有这些都依赖于一个单一的存储设备,通常是一个 SAN。
从架构图来看,IPOD 是一个金字塔,宽的部分在上面,一切都平衡在顶点上。因此有了“倒金字塔”这一术语,这种设计的目的就是尽可能地增加成本和风险,因此才有了“末日”的绰号。
自上而下的冗余
为什么像 IPOD 这样明显不切实际的设计在传统上如此流行?答案需要我们理解几个因素。首先,冗余、风险和系统设计是大多数企业,甚至企业内部的大多数 IT 部门,缺乏培训且普遍没有意识的领域,因此容易成为供应商进行操控的目标。
真正的技巧来自于两点:语言学和自上而下视角带来的简化。语言学的技巧发生在冗余这个词的含义上,因为这个词并不像大多数人理解的那样,其系统确实有冗余,但几乎是无意义的。所以,当客户说“我需要冗余”时,他们实际上是指“我需要高可用性”,而这使得供应商可以声称有冗余,忽略实际需求。语义在所有商业领域都非常重要,IT 领域尤其如此。
系统的自上而下的视角来源于我们如何看待架构。作为 IT 专业人员,我们知道我们应该从侧面看待我们的架构,也就是说,层层分明地看待其可靠性,知道计算建立在网络之上,网络建立在存储之上。但如果供应商想要引导客户相信系统有强大的冗余性,他们会展示一个自上而下的视角,只显示有冗余的计算层。其他层次则过于复杂,常常被各方忽视,认为它们是黑箱,做着魔法般的工作。忽略困难的部分,仅专注于冗余性不太重要的简单部分,这使得误导客户变得非常容易。
当然,如果我们真的停下来思考一下,真正重要的是整个系统的总体可靠性。被任何单一层次的事情分散注意力只会让我们误入歧途。我们需要了解所有的层次,以及它们如何相互作用,才能确定整体的可靠性。但人们有强烈的情感驱动,常常认为某一层是极其可靠的(比如这里的计算层通常是),然后觉得整个系统因此也必须是极其可靠的。但事实恰恰相反。系统的整体可靠性主要由最脆弱的层决定,而不是最可靠的层。如你之前所记,系统的风险是累积的。你将所有的风险合并,因为每一层都百分之百依赖于其他所有层,一旦任何一层失败,整个系统都会失败。你可以通过一个思维实验轻松证明这一点……如果某一层的失败概率是 100%,而所有其他层的失败概率是 0%,那么系统依然会 100%失败。那些几乎可靠的层对抵消不可靠层的作用几乎为零。
冗余本身是一个危险的词。在一般的英语用法中,冗余意味着你拥有某个事物的多个副本,而实际上只需要更少的副本。这可能意味着当某个副本失败时,另一个副本可以作为替代或备份,但这并不是必然的,且这个词常常被用来表达其他意思。例如,在 RAID 中,RAID 0 有多个磁盘(冗余),但冗余越多,风险反而越高,而不是越低。RAID 1 则恰恰相反。在那里,冗余是它的对立面,甚至在同一个上下文中也是如此。这真正体现了 IT 中语义学的重要性(实际上在商业中,甚至是生活中也是如此)。人们常常把冗余作为可靠性的替代词,但两者的含义是截然不同的。使用你真正想表达的术语,你将获得更准确的信息。
IPOD 设计中最大的问题是其实用性。如果我们从可靠性的角度来看,它比网络系统设计更安全,因为至少有一些层包含了高可用性措施,即使并非所有层都有。但这确实是正确的,但也容易让人产生误导。网络系统设计的目的是通过牺牲高风险来节省成本,相对于简单的独立服务器设计,使用“比某个根本不打算设计为安全的系统更安全”这一说法,并不完全错,但在这种语境下讲述时,常常会激发一种情感反应——让人觉得 IPOD 更安全,但这并不等同于更安全。如果我们将 IPOD 的可靠性与独立服务器进行比较,它的安全性会显得非常差。请记住,我们一开始就指出,低成本、简单的独立服务器是我们比较的基准。IPOD 的问题在于,它的风险极高,接近网络系统设计的风险,而它的成本又远高于网络系统设计,通常也比独立服务器设计要高,而且给 IT 团队带来了更多的复杂性和工作量。正是这种高风险和高成本的持续结合,使得 IPOD 成为一个有问题的设计,并且通常被认为是现实世界中最糟糕的设计。
在生产环境以外,IPOD 通常非常适合大规模实验室环境,其中容量最为重要,而可靠性则不那么关键。通过灵活扩展计算能力,使用一个统一的、低成本、可靠性较低的存储层,可以使大规模实验室变得更加实惠。
分层高可用性
从我们已经看到的内容派生出的逻辑系统设计,是将网络系统设计的各个独立层以及“毁灭金字塔”计算层中的高可用性集群应用到所有层,从而得到高可用性的存储层、高可用性的网络层和高可用性的计算层。通过这种方式,我们可以拥有大规模的计算、存储和网络,而不会对任何单独的层次产生高度关注。
每一层仍然依赖于其他每一层,因此这三层高度可用的层仍然必须被评估,并且每一层的风险需要加在一起。所以,尽管我们几乎可以肯定地让任何单独的一层比单一的独立服务器更可靠,或者甚至远远更可靠,但当我们将每一层的风险累积起来,再加上将这些层结合在一起所带来的额外复杂性风险时,它可能不再比独立服务器更可靠。
可靠性是相对的
在讨论可靠性和这些不同的架构时,我们必须记住要进行同类比较,而不是苹果和橙子的比较。当我们说一个单独的服务器具有一定的可靠性,而使用标准高可用性技术集群的服务器具有相对较高的可靠性时,我们假设这些服务器在个体可靠性上大致相同。在大多数情况下,这种假设是正确的。无论是计算节点、网络硬件,还是存储节点,在大致相同的价格范围内,我们获得的硬件和软件质量相似,并且故障特性也大致相同。因此,这些质量相同的不同设备的可靠性大致相同,网络硬件是最可靠的(最简单的),而存储节点则是最不可靠的(因为它们最复杂)。
然而,我们可以大幅度地操控这一点。一台五千美元的服务器通常会比一台五十万美元的服务器不那么可靠(和性能差)。然而,每一台都是独立的单体服务器。所以,显然,我们必须同时考虑架构可靠性(我们所设计的系统的可靠性)和个体组件的可靠性。
这里常见的一个问题是,你得到的就是你付出的 这一原则完全不适用,你很容易找到一些极为昂贵的单机系统,不论是计算节点还是存储节点,它们的可用性都不高,甚至可能比普通设备还不可靠!由于可靠性很难衡量,甚至更难证明,供应商几乎没有动力告诉我们真相。供应商有很强的动力告诉我们任何能够让我们花更多钱的事情,无论是让我们觉得传统服务器比实际更脆弱,还是对那些本质上是由稻草(以及猪)构建的设备作出狂野的高可用性声明。
所以我们必须小心,考虑所有的因素。我们必须理解,保护单一机箱(垂直可靠性)与保护多个机箱(水平可靠性)是不同的。单一机箱的可靠性对于某些组件(如冗余电源、高质量组件和镜像 RAID 存储)通常非常强大,但对于其他组件(如 CPU、内存、主板)则往往比较复杂和问题多发。而单一机箱系统虽然操作更简单,但无法像多个机箱那样处理一些关键问题,比如物理损坏(水、火、叉车等)。
我们还必须敏锐地意识到,市场营销人员和销售人员常常利用对可靠性的混淆作为销售策略,并推销像双控制器系统这样的概念,声称它几乎不可能出现故障,但却没有科学或数学依据来支持这一说法。双控制器系统实际上只是将系统水平扩展到单一机箱内部,具有前者的所有复杂性,并且缺乏后者的物理保护。任何基于误导性信息进行销售的产品,都更有可能做得很差,因为这意味着供应商不太可能对质量设计承担责任。
尤其是在 2010 年代初期,服务器供应商常常推出那些标榜为高可用或无法失败的产品,这些产品甚至连传统服务器的基础可靠性都无法接近。由于客户无法自行验证这一点,他们通常只能相信供应商的说法,如果企业因此亏损,指责和推诿是常见的后果。
这种方法必然是我们能够合理组建的最昂贵的设计,因为我们需要在每一层都拥有多个设备,并且还需要技术来创建每一层的集群。这最适合非常大的系统,其中每一层的规模足够大,可以在各个层面实现规模效益。
值得注意的是,几乎所有基于云的系统都运行在这种架构上,这是由于它们的巨大规模。当然,并非所有的云都使用这种架构,因为云可以使用任何架构,但这无疑是大型公共云实施中最常用的架构,并且通常也会出现在中等规模的私有云实施中。然而,许多云确实在独立服务器上运行,即使在巨大的规模下也是如此。
超融合
我们将要看的是最后一种架构类型——超融合架构,它将复杂设计的趋势推向了一个极简的方向。超融合作为一种架构并不新颖,但在过去几十年里几乎被完全忽视,直到 2010 年代中期才经历了某种复兴,现在,它与独立服务器一起,成为了系统架构设计的基石。
超融合(Hyperconvergence),也叫 HC 或 HCI,将其他更复杂架构中的计算和存储节点重新组合成单一服务器(或者你也可以把它理解为将独立的服务器通过工程冗余添加高可用性,而不增加不必要的复杂性)。超融合为我们提供了两全其美的解决方案,既有独立服务器的简洁性,又有类似分层高可用性的高可用性选项。
超融合既简单又高效,这让它变得很难解释。关键策略是利用独立方法现有的性能和成本节约,同时尽可能少地做事,仍能增加高可用性集群。通过将多个独立节点进行集群(那它们还算独立吗?)我们使所有组件都具备高可用性,同时减少了所需的总组件数。
当正确实施时,数据也可以保证保留在计算节点本地,即使存储在节点间复制以实现存储高可用性,这不仅意味着我们能够像独立服务器一样获得存储的高性能,还意味着我们可以避免跨节点的依赖,让任何节点即使在所有其他节点和/或连接它们的网络发生故障时,依然能够继续工作!这意味着,与所有其他系统设计不同,我们仅在独立服务器设计的基础上增加了更多的弹性!这非常重要。所有其他设计都必须投入大量精力来克服它们自己引入的脆弱性,且有可能未能充分克服这些问题,导致其风险可能比我们什么都不做时还要高。
因此,超融合作为独立设计的逻辑延伸,可能是任何大规模系统设计中最适用的方案。虽然超融合常被认为仅限于小型系统,但它可以扩展到集群技术的极限——这一点适用于所有设计选项。所以所有标准设计的规模大致相同,而这个规模通常远大于实际应用中单一系统的需求。
高可用性与基础集群
在本节中,我们假设集群(无论是计算、存储还是网络)是为了使系统在至少这一层面上具有高可用性而进行的。然而,高可用性集群并不是唯一的集群形式。在所有这些设计中,包括独立设计,我们都可以将通用集群作为管理层来管理多个系统。这可能会让人困惑,因为“集群”这个术语可以有多种含义。
系统设计架构中的最佳实践
系统设计的最佳实践是尽可能将架构保持简单,以满足需求,但又不能更简单。记住,简单是一种优势,而非限制。复杂性应尽量避免,因为复杂性会带来成本和风险。
在任何评估中,从砖块开始。就一个,单独的独立服务器。简单而有效。现在评估一下,这是否满足你的需求?如何通过多花钱更好地满足你的需求?
如果需要高可用性,请评估超融合架构。从架构角度来说,没人能比它更可靠了。
如果你有特殊情况需要在大规模下进行成本节约,其他设计可能会适用。但请记住,无论情感上感觉多么可靠,或销售人员如何推销该解决方案,超融合架构在设计上从根本上是无法被超越的可靠性。确保任何不是这两种起点之一的设计,都要在全面了解所有风险和成本的基础上使用。
我们覆盖了大量的材料,也颠覆了很多传统思维。令人遗憾的是,传统思维在这里等同于盲目忽视需求和风险逻辑,但事实就是如此。这是一个非常困难的话题,因为它对大多数人来说既陌生,又是一个非常专业的技能。而且在许多情况下,你会遇到很多来自他人的反对,他们难以评估或沟通风险,也无法将风险信息转化为可执行的商业决策。
此时你已经拥有了物理设计系统所需的工具和知识。这是一个庞大的话题,可能值得时不时地重新审视。这是非常基础的知识,为我们提供了在“象征性堆栈”上构建可靠系统的起点。现在,我们知道如何根据不同的需求设计不同的系统架构,接下来我们将探讨风险本身,学会询问什么样的风险缓解措施最适合我们。
风险评估和可用性需求
在我们设计系统架构的核心任务中,就是将业务需求(关于性能和可用性)与我们对风险的理解结合,并且像所有商业(因此也是 IT)中的事情一样,评估成本。在上一部分中,我们已经讨论了很多关于风险的内容。我们必须这样做——风险和性能几乎定义了我们在设计阶段的所有内容(除了严格的能力和功能)。
如果我们询问企业关于风险的看法,我们几乎总是会收到两种标准回答之一:我们不愿意花费任何成本来缓解风险,或者我们不能承受停机,必须百分之百的时间保持在线。这两种回答显然是疯狂的,任何商业人士或 IT 专业人士都不应该说出这样的答案,然而,这几乎是你得到的唯一答案,完全没有任何指导意义。它们代表着管理层完全忽视 IT,将所有决策风险都留给 IT,而管理层却没有提供任何指导。
我们有一些基本的指导原则,几乎总是可以应用的。在范围的低端,经验法则是,如果数据足够有价值,值得一开始就存储,那么至少它是值得备份的。这是数据和可用性保护中最简单的方面,如果你的公司认为他们存储的数据甚至不值得备份,你应该问问自己,你为什么在这里工作。确实有一些极特殊的情况,存储的数据确实是暂时的,不需要备份,但这种情况是如此独特和罕见,以至于可以安全地忽略不计。
在范围的另一端,没有任何一个系统,无论在哪里,都重要到不值得任何形式的停机。首先,完全避免停机是不可能的。没有人能够在任何资源的情况下做到这一点。我们可以使一个系统变得极其可靠,并能够从几乎无尽的潜在场景中轻松恢复,但无论是政府、军队、秘密集团、外星物种、投资银行,还是其他任何机构,都不可能满足小型企业经常要求的那些没有任何讨论的要求。为了使系统可靠所能投入的理论最大值,就是相关公司的全部价值,即使最大的公司将每一分钱都投入到提高可靠性而不做任何其他投资,风险仍然存在,无论多么微小。
风险与收益递减
尝试投资于风险缓解技术是一件非常困难的事情,因为随着系统变得越来越可靠,将“针”向更高可靠性移动的成本变得越来越昂贵。例如,获取一台构建良好的独立服务器,可能为我们提供高达五个 9 的可用性,而无需任何特殊的高可用性特性。
我们可能发现我们需要更高的可用性,也许是六个或七个 9。为了获得这种数量级的可靠性提升,几乎肯定需要至少双倍于独立服务器的硬件投资。这可能完全符合我们的需求,但每单位工作负载的成本大幅上升。
如果我们想要再进一步,提升一个数量级,价格又会再一次跳升。我们投入更多的钱,得到的保护却越来越少。
因此,由于我们的企业很少愿意或能够清楚地定义我们的风险规避水平,通常需要由 IT 部门,具体来说是由系统管理团队,代表管理层执行这一极其重要的任务。这通常需要一些数学计算、大量与公司各个部门的访谈、一些常识,当然,还有一些猜测。与风险打交道时,需要保持一种逻辑性的视角,尽管情绪化的反应是非常诱人的,这也是商业中常犯的错误。企业主或经理往往会情绪化地反应,要么认为用于保护的资金没有直接产生收入,因此不值得投入;要么认为他们的业务不值得保护,从而过度支出,试图通过展示公司具有价值来给人留下深刻印象,因为停机对公司来说将是极其可怕的事情。
当然,良好的管理总是会在风险评估任务中发挥重要作用。这不应当由 IT 部门承担。虽然 IT 部门具有深刻的洞察力,并且在任何风险讨论中是一个宝贵的贡献者,但真正拥有完整风险图景的,是核心管理、运营和财务部门,他们才是制定公司基础设施风险策略所必需的部门。
在评估工作负载时,我们必须尝试评估停机会给我们的企业带来什么真正的成本。这在几乎任何情况下都不是一件简单的事情,但这是我们需要理解的内容,以便有任何合理的方式来讨论风险。大多数企业希望将停机成本简化为最简单的术语。因此,每分钟或每小时的美元损失通常是讨论停机时间的方式。例如,失去公司的主要业务应用程序将使企业每小时损失一千美元。
尽管简单,几乎没有现实中的工作负载会在每小时内均匀地损失收入。在现实中,通常会看到一条复杂的曲线。例如,在最初的几分钟,甚至可能是几个小时,我们可能几乎看不到任何收入损失。但随后,我们通常会看到一个峰值,因为停机时间足够长,首先会被客户察觉,接着引起客户的关注。缺乏信心和缺乏操作的峰值往往会相对迅速地达到顶峰。接着,长期的收入损失通常会在几天或几周后开始显现,因为客户流失。但这个曲线对每个企业来说都是不同的。当然,绘制出所有停机场景的完整曲线图是困难的,可能也不实际,但企业应该能够预测沿时间线的关键转折点,这些点代表了影响行为的重大变化。
我们常常容易将故障看作是全有或全无的情况。基本上,忽视工作负载,将整个公司视为完全瘫痪,就像僵尸末日发生了,所有员工都被感染了一样。能够如此影响企业的工作负载是非常罕见的。例如,如果公司失去了电子邮件工作负载,可能会带来影响,但由于电子邮件不是实时的,可能需要几个小时甚至几天才会实际造成收入损失(但如果电子邮件用于实时竞标,失去几分钟可能会产生非常大的影响——这完全取决于具体情况)。但假设电子邮件无法在几个小时或几天内恢复,正常的企业将立即通过其他渠道开始缓解电子邮件工作负载的损失。也许员工们会面对面交谈,或者使用公司即时通讯工具。也许销售团队开始通过电话联系客户,而不是发送电子邮件。在失去工作负载的情况下找到解决办法,往往比人们想象的要容易和有效,直到通过分诊过程来查看实际的恢复可能是什么样的。
工作负载相互作用
另一个我们需要理解的内容是工作负载之间是如何相互作用的。作为系统管理员,我们可能对技术依赖关系有深入的了解,比如一个关键的 ERP 或 CRM 系统依赖于另一个应用程序(如电子邮件或财务系统)才能正常运行,如果其中一个系统出现故障,另一个也会受到影响。这是工作负载依赖关系的一个重要方面,但只需提到它,大家通常就能理解。更难理解的是系统的人类工作流程相互依赖性。
有些工作负载可能是完全独立的。有些可能会显著依赖于其他工作负载。其他的工作负载可能会重叠并提供非正式的风险缓解。
我们先来看第三种情况。如今许多组织可能拥有传统电话、电子邮件、几种类型的视频会议解决方案,以及一些即时通讯工具。即使在一个小型组织中,也很容易因为许多工具捆绑了大量功能而随意地拥有多个重叠的解决方案。在这种情况下,失去电子邮件可能在很长一段时间内影响不大,因为内部通讯可能会转移到即时通讯工具上,客户通讯可能会通过电话或视频会议进行。大多数组织都有能力通过使用其他可用工具来应对某个系统的故障。
但反过来也是成立的。两个技术上没有关联的系统,比如 CRM 和电子邮件,可能无法直接连接,但人类的工作流程可能需要同时使用它们,而失去其中任何一个可能在功能上等同于失去两者。因此,我们必须考虑所有的使用案例以及所有的应对措施。
这种相互作用的知识将帮助我们决定如何合理地部署某些工作负载。例如,如果电子邮件和即时消息在危机期间会相互重叠,那么尽量解耦它们可能更为合适,以便在其中一个的硬件或软件发生故障时,不会波及到另一个系统。
如果我们有一些系统,例如电子邮件和客户关系管理(CRM)系统,两个系统互为依赖,那么将这两种工作负载组合在一起共享失败域可能是完全合理的。举个例子,如果我们有两台独立的服务器,一台运行 CRM,另一台运行电子邮件,那么每台服务器都会有自己的故障风险,并且几乎可以肯定,这些故障不会在重叠的时间发生。每个工作负载都有相同的预期年停机时间 X。两个工作负载的总停机时间是 2X。这个数学很简单。将这两个工作负载合并到同一台服务器上,因为每个工作负载仍然保持相等的年停机风险,即 X,那么合并后的总停机时间仍然是 2X。但第一个例子的有效停机时间是 2X(或者 1.99999X,因为停机重叠的几率非常小),而第二个例子的有效停机时间仅为 1X。我们是怎么做到的?不是通过减少单一风险,而是通过降低有效风险——即影响到业务最终结果的风险。在背后,我们确实降低了风险,因为一台服务器的停机风险只有两台相等服务器的一半,原因就是故障的设备数减少了一半。
即使是公司完全停运,也不一定意味着完全的损失。让员工回家享受一个突如其来的假期,可能会降低保险费用并提升士气。给员工一两天的时间待在家里,可能会重新激发他们的活力,他们可能会在系统恢复后高兴地回到工作岗位,更高效地工作,或者为弥补失去的业务投入一些额外时间。我们在评估失败工作负载所带来的损失时,必须考虑缓解策略。一些企业可能只是效率下降,而其他企业则可能会失去客户。
当然,我们也必须考虑相反的可能性。如果你是一家严重依赖客户对高可用性认知的企业,即使是一个小小的停机也可能产生广泛的影响呢?也许你的整个业务每小时仅生成一千美元的收入,但即便是两个小时的停机(在这种情况下,我们假设停机最多只会损失两千美元)也可能导致客户信心的丧失,从而引发客户流失,造成几十万甚至几百万美元的损失!
所有这些损失都只是估算。即使停机事件真的发生了,也没有可靠的方式来知道如果没有发生停机,收入会是多少。所以如果我们在事件发生后无法确定这个数字,那么显然,在事件只可能发生、尚未发生之前,我们也无法确定这一数字。结论是……估算风险是非常困难的。
在一个大型组织中,可以考虑在周末与来自不同部门的员工进行 假设 游戏。模拟一些 X 或 Y 失败了 的场景,并尝试在小范围内进行几乎真实世界的模拟来减轻问题。你能用某个工具继续工作吗?哪些部门会变得功能失效,哪些仍能正常运行,你的客户如何看待这种情况?这种类型的 游戏 最适合由强大的规划者与感知者(例如:急救专家)结合进行。规划者思考风险策略并编写程序,而感知者则不做计划,而是在现场进行战术工作,找出如何利用现有工具继续工作。
定义高可用性
我在 IT 领域最喜欢的一句名言来自约翰·尼科尔森,他说过 高可用性不是你能购买的东西,而是你需要做的事情。我们常常会把高可用性看作是 IT 中的一个内在需求,认为它复杂到无法理解,因此会被那些将未经验证的 高可用性 标签贴在产品上的厂商所欺骗,甚至仅仅把它作为产品名称的一部分,假装购买某个产品就能实现高可用性,然而从逻辑上讲,这几乎是不可能的。比如,想象一下购买一架高可用性的飞机。虽然你可以使一架飞机比另一架飞机更可靠,但你整体的可靠性和安全性主要来自飞行员,而非飞机本身。在 IT 领域也是如此。即便是做工最好的产品,如果操作不当,其效果也微乎其微。一个没有备份的百万美元集群,可能比一个备份完善的台式机还不安全!
所以,首先我们需要建立一个衡量的基准。在上一节中,我们提到独立服务器基础设施作为我们的基准。这一基准必须代表我们所说的 标准可用性。我们现在有两种方法来衡量这种可用性。一种是通过给出一个 九 数字,来以绝对的方式表示可用性,通过行业证据,维护良好、做工精良的独立服务器可以达到五个九的可用性,这大致意味着每年有六分钟或更少的计划外停机时间(计划内的维护停机时间可能是潜在问题,但并不包括在这样的可靠性数字中)。
现在请记住,当我们谈论服务器或系统设计架构时,我们并不包括最终的工作负载,只是指提供底层系统的平台,平台上将安装虚拟机监控程序。所以,基本上是指硬件可用性。在其上运行的任何软件可能有自己的可靠性问题,平台的稳定性无法解决来自最终工作负载中糟糕代码带来的不稳定问题。
另外一种,通常也更有用的方式来看待系统架构的可靠性,不是以无法衡量的绝对标准,而是通过相对方式将不同设计进行比较。没有人真正知道系统的可靠性是什么。服务器供应商并没有在对我们保密,他们只是不了解。每一个小小的系统配置差异都会产生非常不同的可靠性数据,就像我们对飞机的说法一样,操作系统的用户对可靠性产生了最大的影响。一个拥有完美数据中心、持续现场支持、能及时响应警报并且有备件随时待命的公司,可能会从同一台困在没有空调、充满灰尘并且通常被忽视的机房里的服务器中挤出完全不同的可靠性数据。影响因素实在是太多了。即使我们能够 somehow 考虑所有潜在的变化,为了获得关于如此复杂且故障率如此低的系统的有意义统计数据,我们也需要运营数千台甚至数万台服务器超过十年,才能收集到有用的数据,而这些数据过十年后都会过时。所以,实际上,这些都无法被衡量。
所以,我们最重要的工具不是以九个为单位谈论,这是一个伟大的营销工具,也是一些深陷于复杂流程(如六西格玛)的管理者喜欢重复的内容,但在这个语境下并没有实际意义。相反,我们应该着眼于系统与基准的偏差数量级。比基准可用性高得多的系统可以被归类为高可用性,而比基准可用性低得多的系统可以被归类为低可用性,任何与基准大致相同的系统则保持标准可用性。超出这些一般术语之后,讨论几乎变得不可能。
类似超融合的系统设计通常被归类为高可用性,因为它是最可靠的设计方法。而 IPOD 通常被归类为低可用性,因为它更接近于最不可靠的设计方法——网络系统设计。分层集群通常被认为是高可用性,但不如超融合那样高。当然,在这种情况下,我们仅仅考虑系统设计的可用性,而忽略单个组件。如果我们在 IPOD 的每一层都使用极高可用性的单个组件,理论上可以将其恢复到标准可用性,但可能需要付出极大的成本。
从相对角度考虑可靠性要比从绝对角度考虑更有价值。单纯通过常识和风险的定位、风险缓解、风险积累等设计要素,几乎可以轻松看出一个独立服务器、一个 IPOD 以及超融合系统在可用性上的明显高、中、低差异。这不需要特别的培训或数学能力,就能明了每个系统之间的区别以及如何提升组件的整体质量会移动绝对可靠性数值,而相对可靠性却不变。最终,我们所能知道的就是这些。
通过了解停机对我们业务的财务影响,即使只是一个非常粗略的估算,我们在决定如何投资风险缓解时就有了参考依据。我们永远不应在风险缓解上投入超过计算风险所显示的潜在损失。这听起来很明显,但在许多公司中这是一个常见的评估难点。例如,如果一次可能的停机会导致我们损失一千美元,而有效地保护这一停机的费用是两千美元,我们就绝不应考虑花钱来缓解这个风险。
我们应该把风险缓解看作是一种停机本身,从数学角度来看,这是为了让计算变得更容易理解。通过良好的风险缓解,我们现在会承受最低的财务损失(例如花费一千美元)来防止一次可能导致十万美元损失的大规模停机。前期成本是确定的,而未来风险仅仅是一个可能性。因此,任何风险缓解的投入都应该远低于其所要保护的潜在损害。
我用来形容为了缓解风险而支付的费用超出了潜在损害的类比已经用了多年:这就像今天为了避免明年可能会得头痛而朝自己脸上开枪。
在比较标准可用性系统和高可用性系统时,我们可能只是在讨论每年平均几分钟的停机时间差异。因此,高可用性必须迅速证明其成本和复杂性的合理性。对于一个巨大的公共网站,如果仅仅一两分钟的不可用就可能导致数百万的购买损失,或者更糟糕的是,损害客户信任,那么即使节省的时间看起来微不足道,仍然可以轻松证明在高可用性系统上的大量支出是合理的。但对于一个服务员工的内部系统而言,客户信任并非关键因素,且停机不会导致用户转向竞争对手(例如:电子邮件系统、财务系统、CRM 系统等),即便是每天失去几分钟,甚至一年,也可能对财务没有实际影响,重金投入来保护这些系统反而是浪费。
那么,我们如何将这一切应用到最佳实践中呢?困难的答案是,风险评估和随之而来的系统设计是非常艰难的工作。确定风险是一个漫长的过程,涉及大量的数学、逻辑,并在某种程度上需要猜测。这要求我们深入了解我们的业务和技术栈。它要求我们在各个层面和各部门与业务进行互动,整合通常是孤立的信息。它迫使我们将其他风险评估与逻辑和预期的情感反应进行对比。
经验法则告诉我们,我们部署的大多数系统应该是独立服务器,几乎所有剩下的系统应该是超融合的。这两种标准模式代表了现实世界中正确设计的近乎全部内容。所有其他设计实际上都被归类为极为小众的用例,其中 IPOD 是最典型的反模式,除了极端特殊情况外,绝对不要去做。
本章我们覆盖了很多内容。但现在我们已经知道如何做出风险判断,如何基于这种评估设计架构。我们理解了如何以及为何使用不同种类的虚拟化,为什么我们总是进行虚拟化。而且我们知道如何评估云和局部性在部署中的使用。现在,将这一切结合起来!我们在决定每个工作负载的部署时都会使用这些工具!有这么多选择,但这正是让我们的职业充满挑战和成就感(也是让我们值回薪水的原因)。
总结
总结来说,系统架构是复杂的,要求我们真正深入了解业务需求、运营方式,与组织中的关键角色沟通并获取意见,并广泛地考虑技术构建块,构建能够以最低成本提供所需性能和可靠性的解决方案。
我们研究了虚拟机和容器的基本组件,现在应该能够为它们的使用辩护,并在它们之间做出正确选择,还能使用传统容器而不被较新的应用容器搞混。而且我们学到了局部性。你应该能够穿越复杂的语言迷宫,理解经理们讨论服务器资源的部署和所有权时的难点,分析成本和风险,并为组织找到合适的选择。共址、云、传统虚拟化、本地部署,所有这些选择你都能理解。
最后,我们来谈谈系统设计和架构。将我们系统的物理和逻辑组件整合,构建一个完整的功能平台,能够提升我们的工作负载,而不是削弱它们。这是一个很长的章节,涉及了许多非常少被单独教授的话题,更不用说将它们结合起来了。这些都是非常难的话题,可能在继续之前值得再次深入探讨这些内容。
对于许多从事系统管理的我们来说,可能几乎永远不会使用本章节中的内容。而对于其他人来说,这可能是几乎每天都需要的技能。这些话题通常能让你通过展示能够将看似平凡的技术细节与系统设计决策结合,解决关键的组织需求,彻底提升你的职业生涯。在本书的所有话题中,这个话题可能是最能让你脱颖而出,跨越组织边界的一个。
我希望通过这里提供的信息,您能够过滤掉销售和市场营销的虚假信息,运用严密的逻辑和推理,并在永恒的概念上进行构建。花时间真正理解故障域、附加风险、虚假冗余等,将使你在信息技术旅程的几乎每个方面变得更加出色,无论你的目标是纯粹的技术性,还是梦想着坐上董事会的椅子。
在我们的下一个章节中,我们将回到看似更为平凡的话题——系统补丁管理,并从高层次的系统策略转向实际操作中的安全性和稳定性战争。
第九章:备份与灾难恢复方法
我在本书中已经说过,并且无论多少次,都要重申:作为系统管理员,保持良好的备份是我们工作中最重要的事情。它是我们的首要任务。重要到许多组织都会维护一个独立的系统管理团队,专门负责备份工作,以确保能够持续关注这一任务。
备份并不吸引眼球,也很少让人兴奋。这不仅仅是因为它们对我们技术人员来说是一个挑战,当我们本可以花时间实施新的自动化或者做其他更令人兴奋的事情时,我们却要花时间思考备份问题,还因为这意味着管理层往往不会优先考虑预算或将备份作为优先事项。这为系统管理员带来了潜在的风险,如果我们过于关注像备份这样的关键功能,而不是做那些炫目、高调的项目以维持管理层的兴趣,往往会面临被惩罚的高风险——如果那些他们未曾优先考虑的备份在需要时无法完美运行。
然而,备份越来越多地出现在我们的意识前沿,因为它们已经不再仅仅是保护免受灾难性硬件故障的手段,而是处于安全问题的前沿。近年来,备份发生了演变,现如今它们不仅提供了在我们组织中政治上发光发热的机会,也为技术上的新兴趣带来了重新点燃的机会。上世纪 90 年代和 2000 年代那个枯燥的备份与恢复的局面,简直可以说已经成为过去式。今天,我们有了那么多的备份方法、选项和产品,以至于我们必须把备份视为一个比以往更广泛的问题来处理。
在这一章中,我们将涵盖备份的许多不同方面。我们将从备份的广泛概述以及备份系统中存在的组件开始。接着,我们将讨论一些常与备份一起使用、但有时可能会与备份混淆的相似技术。然后,我们将深入探讨本书中提到的概念——现代以 DevOps 为中心的备份方法,并对这一方法进行详尽的讨论。接着,我们将探讨代理以及备份中数据崩溃一致性的问题。最后,我们将讨论分类以及灾难发生后如何改进恢复。
言归正传,让我们开始本书中无疑是最重要的一章。我想,任何一本书都是如此。
在这一章中,我们将学习以下内容:
-
代理和崩溃一致性
-
备份策略与机制
-
快照、档案、备份与灾难恢复
-
DevOps 世界中的备份
-
分类概念
代理和崩溃一致性
在下一部分,我们将探讨备份机制。在此之前,我想先讨论为什么备份本身这么难做好。为了做到这一点,我将通过两个示例来解释。一个是我们使用最爱的文本编辑器创建的文本文件。我假设你是个普通人,和我一样热爱使用 vi 编辑器。另一个则是企业数据库系统中的数据文件。
当我们谈论备份时,我们是在谈论将存储在物理介质上的数据复制到一个与原始系统分开的地方,以便在许多情况下原始系统失败时,备份仍然能够存活下来。这是备份目标的一个高层次概述,它满足我们的需求。因此,为了执行备份,我们必须能够获取系统中的数据,读取它,移动它并将其写入。
在这些步骤中,看起来将数据移动到另一个位置或将数据写入某个地方可能是最大的挑战。这个想法是错误的。能够读取数据实际上才是问题的根源。主要是因为我们需要读取的数据并不总是明确的。
计算机是如何在磁盘上存储数据的呢?并不是每个计算机系统的工作方式都相同,但存在一些我们知道没有替代方法的基本原理。在处理数据时,计算机会将数据保存在随机存取内存中。在内存中,它是完全易失的,但速度非常快。当计算机处理完一个文件时,它会将内存中的数据写入存储设备,假设是硬盘或 SSD。
如果我们尝试在数据仍保存在计算机内存中并尚未写入磁盘时进行备份,我们的备份将不包含任何相关数据。听起来可能有些荒谬,但这是必须记住的。无论是技术人员还是管理人员,都常常假设数据总是被存储在某个地方,即使它只是进入了内存,还没有时间被存储到任何地方。
一旦数据被写入磁盘并进行备份,磁盘上的数据应当被复制到备份位置。世界一切正常。
这一切听起来不错,但计算机处理的情况要比仅仅接收文件并保存到磁盘复杂得多。在现实世界中,计算机几乎总是在从存储机制中读取现有文件,将其保存在内存中并进行数据操作,然后将修改后的数据保存回磁盘。这就是事情开始变得棘手的地方。
现在我们应该开始使用我们的示例。首先是vi中编辑文本文件的情况(如果你坚持的话,你也可以使用 Atom 或其他编辑器。)我们还假设我们不是创建一个新文件,而是在编辑已经存在于磁盘上的配置文件。一个很好的例子是hosts文件(位于/etc/hosts)。
如果我们在文件编辑过程中进行备份,我们将获得编辑前的旧数据副本,因为任何正在进行的编辑仅存在于内存中,而不是磁盘上。文件在打开时并不意味着数据正在写入磁盘。旧数据仍然保存在磁盘上,而新数据则存在于内存中。
当文件被保存时,数据会被写入磁盘。写入完成后,我们可以进行复制。当然,在数据写入过程中,可能会有一个短暂的时刻,磁盘上的内容既不是原始版本,也不是新版本,而是处于两者之间的某个状态,因为数据尚未完全写入。
我们可以尝试锁定文件,但即使文件被锁定,情况依然复杂。无论备份机制是什么,它必须决定是跳过锁定的文件、等待锁释放,还是忽略锁定直接进行备份。没有一种情况是理想的。我们要么无法在任何特定的备份过程中备份所有文件,要么面临长时间等待某个可能永远不会发生的事件,或者我们面临备份过时文件,甚至更糟,备份损坏的文件。没有完全简单的解决方案。
Linux 中的锁机制
当进程在 Linux 上使用文件时,实际上在任何操作系统上,我们通常会看到三种基本策略。第一种,也是最明显的,就是不做任何操作。是的,没错。在许多情况下,根本没有执行任何锁定操作。文件内容被读取,而文件本身并未被标记为已打开。它只是被读取。这种方法的优点是任何其他进程都可以以任意方式继续使用该文件,但它也无法提供任何关于文件是否即将以某种方式更新的信息。
Linux 上的主要替代机制称为建议锁(advisory lock)。通过建议锁,操作系统会标记一个文件是否已被进程打开。这些锁被称为建议锁,因为操作系统通知其他进程该文件正在使用。其他进程可以选择忽略该锁,继续读取,甚至覆盖被锁定的文件。这种方式的好处是我们可以锁定文件而不必担心完全阻止其他人访问它。风险在于我们的锁可能不会被遵守,导致竞态条件发生,数据可能被更改顺序错误,或者本以为已保存的数据被覆盖。忽略建议锁以查看文件并检查一些旧数据是相对安全的。忽略建议锁以在没有原进程知情的情况下覆盖文件并进行更改则是危险的。完全支持并遵守建议锁的进程称为合作进程(cooperative processes)。
第三个选项是强制锁(mandatory lock)。顾名思义,进程别无选择,必须遵守强制锁。强制锁由 Linux 内核管理,只有在文件系统特意以这种锁定方式挂载时才会存在。然而,Linux 上的强制锁存在实现问题,使得它们不可靠,并且容易受到一些罕见的竞态条件的影响,这些竞态条件实际上使得锁的目的无法实现。因此,强制锁在 Linux 系统中几乎总是被忽视。
锁定在概念上是困难的。它带来了风险和系统开销。对被锁定文件的最佳响应方式并不总是显而易见,并且可能因操作系统无法预见的各种不同用例而有所不同。由于操作系统并不知晓文件最初为何被访问,它几乎没有有效的手段来强制执行二次访问的限制。几乎总是有理由我们可能想要读取一个被锁定的文件,甚至有时有充分理由对一个被锁定的文件进行写操作。信任我们只会运行那些在我们使用场景下能够按需执行的进程,是我们在几乎所有情况下的最佳行动方案。当需要更复杂的访问时,比如大多数数据库文件的情况,就需要转向单一进程访问,由该进程处理来自应用程序栈上层的额外数据访问,因为那里的进程对文件的预期用途有更多的了解。
除了锁定,另一个我们必须理解的重要概念是静默(quiescence)。静默简单来说是指存储达到一种休眠状态,即没有波动。当我们说存储已经达到静默状态时,我们的意思是所有当前正在传输的数据,无论是正在被应用程序使用,还是仅仅被存储在多个缓存层中的某一层,已经被写入磁盘。从某种程度上讲,我们可以将锁定视为一种机制,用来警告我们(或一个进程)系统目前未处于静默状态。
不幸的是,Linux 上没有通用机制来强制执行或甚至确保系统的静默状态,Windows 上也没有,尽管许多关于 VSS(卷影副本服务)能做到这一点的说法是错误的。VSS 是 Windows 上的标准逻辑卷管理器(LVM),因此常用于许多存储操作。常有人说 VSS 保证所有文件都处于静默状态,但这不准确。VSS 与许多常见的应用程序(主要是 Microsoft 的应用)有特殊的挂钩,例如 SQL Server、Exchange 和 Active Directory,以便它们能够有效地与存储层通信,了解自身静默状态。这是一个令人惊叹的功能,并且自动与操作系统集成非常方便。然而,它并未解决第三方应用程序的问题,这些应用程序很少有 VSS 集成,导致它们处于危险的非静默状态,而许多 Windows 管理员认为 VSS 神奇地管理了所有应用层的数据刷新,但事实并非如此,它无法做到这一点。
在操作系统层面,我们作为系统管理员通常需要使用的静默工具是来自逻辑卷管理器的快照(例如 LVM 或 ZFS 提供的快照),或者冻结文件系统本身,如 XFS 所能实现的那样。我们越接近栈的上层(“上层”意味着更靠近应用程序本身),我们冻结系统的范围就越大,系统中仍在传输并未写入磁盘的数据的可能性就越小。然而,最终,无论操作系统如何,除非应用程序本身保证它已经将所有数据刷新到磁盘并且没有留下任何缓存或正在处理的数据,否则我们所能希望的最多也就是尽力而为。这是一个普遍存在的挑战。计算机本身就是非常复杂的东西。
在大多数情况下,事实上几乎所有情况下,一种或多种静默方法都能很好地将数据安全地写入磁盘。实际上,大多数备份和企业通常很少依赖如此多的保护,通常依赖尽力而为的文件锁和多重备份来提供系统中足够数量文件的有效副本。大多数工作负载写入磁盘的频率较低,使得很少发生高风险场景。但我们不能忽视的是,这些方法中的任何一种都无法真正确保系统完全静默,并且我们始终面临某些程度的风险,关键数据可能以某种形式仍在传输中。如果我们讨论的是仅提供静态网站的 Web 服务器,风险可能低到可以忽略不计。如果我们讨论的是用于财务和会计数据的关键企业数据库,风险可能极大,这是无论如何都不能承担的风险。因此,如果我们想要在系统层面进行备份,我们需要考虑我们的工作负载、它们的静默状态以及由此带来的风险。
当我们使用其中一种不与应用工作负载端到端协调以确保物理媒体上的数据完整和静默的机制进行备份时,我们称我们的备份为崩溃一致。这是一个重要的术语,经常使用。崩溃一致性并不意味着系统实际上已经崩溃,而是指计算机系统突然崩溃或断电后存储的状态。
崩溃一致性是一个非常关键的概念,我们需要真正理解我们所说的意思。对于一些人来说,它被说成是一个即将到来的灾难的可怕警告。其他人则用它来暗示一个可靠的系统状态。那么,它真正意味着什么呢?
当任何计算机完全崩溃时,意味着在事件发生后没有恢复或保护能力,例如当硬件发生灾难性故障或电源突然无法提供给系统时,绝对没有机制可以确保磁盘上的数据准确或完整。正如任何计算机用户所知,计算机突然断电通常不是问题,除非文件的任何未保存更改或我们在视频游戏中的最新进展等都将丢失。这似乎是显而易见的,我们通常不会认为这是系统设计的一个重大问题。偶尔,我们会发现一个程序或数据集已经损坏。当系统从崩溃中恢复时,我们都害怕这种情况,但实际上很少是一个问题 - 至少对于最终用户而言。
实际崩溃后系统的状态与没有任何静默期备份的系统状态基本相同。任何当前正在修改的数据都将丢失。偶尔会发生我们认为已保存到磁盘的数据损坏的情况。总体而言,一切都在那里。这就是为什么我们称这种状态下的备份或任何拷贝为崩溃一致,即与物理机器上的灾难性崩溃一致性相同。
当谈论到桌面时,更容易说明这一点。服务器上存在相同的风险,但程度严重得多。在桌面上,我们往往只有一个用户,对当前可能正在传输的所有数据有很好的了解,并且存储比较直接。在服务器环境中,不仅可能存在大量的存储复杂性,每一个转折点都可能存在不同的可能且可能有风险的机制,而且我们很可能在整个堆栈中有更大更多的缓存情况,并且一个或多个多用户工作负载会在崩溃时很少与用户有意义地交互。
考虑一个典型的 Web 服务器示例,数据存储在数据库中。用户与网页进行一些交互,可能是输入销售信息、上传表单、处理银行交易或下订单。用户认为交易已完成,因为他们收到了反馈,显示提交已完成。用户很可能不会刷新页面或返回,因为对他们来说,交易已经完全完成。但真的是这样吗?
Web 服务器可能将交易排队在内存中,稍后几秒钟再处理,或者将部分数据保存在缓存中。或者,它可能已将交易写入数据库,而该数据库可能仍然将数据保留在缓存中。也许数据库已将数据写入文件,但文件系统仍然将数据保存在缓存中。也许文件系统已提交数据,但逻辑卷管理器还在缓存中持有数据。如果你有硬件 RAID,那里可能会有缓存,在数据写入物理磁盘之前,它会停留在那个缓存中。物理磁盘本身也可能有缓存,虽然在这种情况下应该禁用它,但它可能没有被禁用,并且可能是另一个数据在驱动头将数据实际写入磁盘之前可能被缓存的地方。
当然,可能存在许多机制来防止这些故障。磁盘缓存应该禁用,RAID 缓存通常通过使用非易失性内存或电池保护,以便即使系统发生断电,它们也能将数据刷新到物理磁盘,数据库通常会在进行最终写入之前记录事务,因此如果无法向前滚动,它们就有能力回滚,应用程序通常不会在至少确保某种程度的事务已记录的情况下向最终用户报告一切正常。我们希望这些情况都能存在,但没有什么能够保证它们,除非在端到端的应用程序和系统设计的结合下。即使是设计最好的应用程序,也可能会被虚拟机监控程序欺骗,它将易失性内存表现得像硬盘一样,并报告系统已空闲,但实际上没有写入任何存储数据。因此,需要信任。
数据在传输过程中丢失只是一个问题,另一个问题是数据损坏。沿途的许多层可能会因写入操作不完整而发生损坏。单个文件通常是我们看到损坏发生的地方,这是最常见的地方。二十五年前,我们也经常看到文件系统损坏。今天这不再是一个常见问题,但它仍然存在风险。不同的文件系统在这种情况下的风险程度不同。理论上,逻辑卷管理层可能会存在某些损坏风险。显然,RAID 或 RAIN 存储层可能会发生损坏,并且有时,如奇偶校验 RAID,在损坏事件发生时有可能导致数据完全丢失。
所有这些步骤都不太可能发生,但都有可能发生。正常崩溃时通常不会发生丢失或损坏数据。灾难发生的可能性取决于许多因素。我们不应该把崩溃一致性级别的解决方案看作毫无用处或等待发生的完全损失,但我们也不应假装它们没有忽略没有任何系统确保一致性的基本风险。在所有情况下,我们只是在掷骰子并希望得到最好的结果。我见过许多小企业丢失了他们认为完全可靠的备份数据,因为他们依赖于崩溃一致性,而供应商却假装数据损坏不是一个问题。由于崩溃一致性机制便宜且简单,因此它们受到供应商的广泛关注。
替代方法称为应用一致性。我们之所以这么称呼,是因为它指的是当工作负载应用程序能够确认已将所有数据刷新到磁盘,并且当前没有数据在传输中时,系统可能的状态。应用程序可以通过确认它们当前处于静默状态来简单实现这一点,或者它们可能有机制强制发生这种状态。无论哪种方式,它们通过从应用程序堆栈的最上层应用智能来避免崩溃一致性的问题,并验证数据已经准备好进行备份。
这种方法要求应用程序支持提供这种静默状态,如果我们想将此操作与任何类型的备份机制协调,我们必须有一种方式让备份机制调用应用程序请求静默,或者让应用程序调用备份机制。在 Windows 环境中,正如我们之前讨论的,VSS 提供了一个标准接口,任何应用程序都可以选择支持。如果它们愿意的话。当前 Linux 没有类似的标准。
因为所有这些机制都复杂且非标准化,所以在处理任何超出有限范围的流行服务时,都会遇到重大挑战,这些服务通常是广为人知且得到支持的。实际上,Windows 也同样有限,但在那里使用一小部分非常标准的服务更为常见。
许多应用程序选择通过集成自己的备份服务来解决这个问题,而不是尝试依赖其他机制。有些可能会构建一个非常强大的备份机制,直接支持多种不同的选项,例如内置的调度、多级备份以及直接存储到多种不同类型的介质。这种情况并不常见,但确实存在。
从最简单的应用程序到企业数据库,最常用的选项就是直接从应用程序写一个备份文件到本地文件系统。这是非常常见且有效的方法。它会生成一个简单的文件或一组文件,可以指定为备份,并防止它们被用于除另一个备份机制之外的其他用途,后者会使用这些文件来复制或发送到其他位置。
这个非常常见的例子是 MySQL 和 MariaDB 数据库。数据库是我们最难以安全备份的应用程序类型,因此几乎所有的数据库系统都会采用某种方式来安全地保护数据,而不必采取如关闭数据库、复制文件并在完成后重新启动等极端的暴力步骤。
使用 mysqldump 工具的 MySQL 示例
几乎可以肯定,Linux 生态系统中最著名的应用级备份工具是随 MySQL 和 MariaDB 提供的mysqldump。这个简单的命令行工具连接到一个正在运行的 MySQL 或 MariaDB 数据库服务器,锁定它并将所有数据静默到内存中(它不需要刷新到磁盘),然后将这份数据的副本保存到磁盘。它是任何工具中最简单易用的,同时也是极其强大的。它对正在运行的系统几乎没有影响,而且由于它不需要在将应用程序一致性的副本保存到磁盘之前进行任何复杂的刷新操作,所以不需要停止数据库的读取操作,只需要短暂暂停写操作。
在这里,我将展示一个简单的单一命令,用于轻松备份由单个 MySQL 或 MariaDB 实例管理的所有数据库:
mysqldump --all-databases > mysqlbackup-`date +%H%M`.sql
这个例子几乎是最基础的,你几乎无法简化得更多了,但它非常有效。你可以随时运行它,并且因为它在过程中记录当前时间,所以它不会覆盖任何其他备份文件,即使是比它早一分钟创建的文件。你可以将备份写入磁盘上的任何位置。你可以在备份文件写入时或稍后使用标准工具轻松地压缩生成的备份文件。请记住,这只是一个备份文件,是用来进行备份的文件,但到此时它还不是一个实际的备份。
一旦这个文件存储到磁盘,它就变得安全,任何备份工具现在都可以在不担心应用程序正在使用或修改它的情况下获取这个文件,并将其放置在任何合理的位置。完全灵活,且应用程序的一致性简单易懂。
目前,我认为我们理解了一致性、锁定和静止状态的作用,以及在尝试备份甚至单个文件或应用程序时可能面临的所有问题(请记住,并非所有备份都涉及存储在任何地方的文件格式数据),更不用说尝试备份整个文件系统或系统了。理解这一挑战是关键,因此我们关心不同类型的备份工具的不同方面,下面我们将一起进行探讨。
备份策略与机制
实际上,备份比大多数人想象的要复杂得多。在处理备份时,我们经常只是被告知“进行备份”,好像这是一个简单的活动,几乎没有变数。然而,在现实世界中,我们确实有一些常规方法,可以满足大多数需求,即使只是最低限度地满足。然而,在某些情况下,要有效地进行备份需要更多的思考,并且需要深入理解我们的工作负载和基础设施,以便能够正确地进行操作。
在过去的好日子里,就像上世纪 80 年代和 90 年代那样,备份几乎总是相同的。它们涉及某种简单的代理程序,例如标准的 Linux tar命令,该命令会按计划运行(我们可能需要手动设置类似于cron的计划任务),它会将一个目录中的所有文件,或更可能是整个系统,打包成一个单一文件,并将该单个大文件放置在磁带设备上。然后需要人为移除磁带并将其运输到安全地点。
多年来,新技术不断涌现,备份逐渐变得更加强大和复杂。磁带逐渐不受欢迎,而其他备份目标,从可交换的硬盘到始终在线的存储,也应运而生。随着备份介质的发展,备份机制有机会从离散的“每次备份一磁带”的计划转变为更灵活或更复杂的设计。伴随而来的是复杂的备份应用程序,备份领域由简单和基础的状态转变为相当复杂的情况。
由于今天涉及的变量如此之多,简单地进行备份已不再是一个简单的概念。每个人对备份的理解和需求各不相同,基于他们的期望和经验。这种多样性甚至可能导致我们产生视角狭窄的危险,认为所有人都以类似的方式看待备份,而实际上,现实世界中处理备份需求的方式有很多种。
备份类型
首先,我们将讨论可能使用的实际备份机制。这些通常分为两类:基于代理的和无代理的(我真的讨厌这两个术语),但人们通常会将其视为三类,其中第三类是临时脚本。关于它们身份的所有这些想法当然都是完全错误的,正如许多人常说的那样。这些术语已经得到了广泛使用,尽管它们不准确,你仍然需要使用它们。
系统级备份
系统级备份就是所谓的基于代理的备份。这些备份之所以得名,是因为通常会在操作系统上安装一个运行的软件代理,并且该代理是可见的。你可以在系统上的某个地方看到它出现在已安装的软件列表中。然后,代理会运行并从操作系统上下文的内部抓取文件,并将其发送到其他地方进行存储。通常会有额外的处理步骤,如打包、压缩、去重和加密,但这些技术上都是可选的。
一切都是代理
当我们说有一个基于代理的备份解决方案时,脑海中会浮现出必须购买、下载并安装到我们计算机上的软件。毫无疑问,这是人们常做的事情。
然而,代理的概念要广泛得多。备份代理可能是操作系统中内置的复杂备份工具,而不是单独获得的。在 Linux 世界中,这种情况几乎是常见的,因为许多强大的备份选项已经包含在典型企业级发行版的仓库生态系统中。
代理的范围甚至更广。像tar和rsync这样的经典工具,就是,或者至少可以成为,备份代理。它们是已安装的软件组件,可以用于在操作系统内部执行备份。
我们可以继续下去。如果你编写自己的脚本来移动块或文件,那也是一个代理。代理的概念非常广泛,从逻辑上讲,总是需要某个组件来执行备份任务,而这个组件永远是代理。
通过在操作系统内部工作,位于此处的代理可以利用明显的访问方法来访问我们想要备份的数据。它可以通过使用像dd这样的工具在块级别与存储设备进行通信,或者使用像 LVM 这样的稍高层次的逻辑卷工具来提供强大的块级处理;或者它可以使用文件系统层逐一请求文件;或者它可以使用 API 与正在运行的应用程序进行交互,从而提供某种类型的高级数据访问。通过这些方式中的一种或多种,代理可以访问备份所需的数据。
所有这一切都意味着,代理程序的任务是与操作系统进行交互,尝试从存储子系统中触发某种程度的静默,以增加获得一致性备份的机会。有些代理程序会与许多应用程序进行广泛的交互,而有些则根本不与任何应用程序交互。
代理程序完成所有工作,并提供多种方式与我们的数据进行交互。但它们有一个局限性,那就是它们只能访问操作系统能够访问的内容,并且只有在操作系统启动并运行时才能使用。最后这一点意味着,操作系统本身正在使用的任何资源,在代理程序需要访问它们时也会处于使用状态。这就给系统范围内的一致性带来了真正的挑战。然而,我们很少真正关心整个系统范围内的一致性。当然,我们会更喜欢一致性,但大多数系统文件的影响较小,如果丢失或损坏,也能轻松恢复。通常,只有关键的应用程序数据或安装的应用程序本身才是主要关注点,其他的文件只是为了在需要快速恢复时提供帮助。
通常,但不是普遍的,对于系统级备份,进行恢复操作时,必须先安装一个空的操作系统,然后安装恢复代理,并允许代理对存储的备份进行操作,将文件恢复到操作系统中。这通常意味着系统级备份在备份单个文件并能够恢复单个文件方面表现优秀,但在恢复整个丢失的系统时却更加困难。
曾经一度,几乎所有备份都是这么做的,普遍的假设是,几乎所有恢复操作都是为了检索单个丢失的文件,而不是为了恢复整个失败的系统。
人们已经不再像以前那样丢失文件了。
在写这章时,我被过去三十年中计算体验的巨大根本变化所打动。在我年轻时的整个行业生涯中,甚至在我只是一个计算机用户之前,我们最大的担忧一直是丢失、删除或使某个文件以某种方式损坏。我们所有人都把备份的概念看作是将许多单独的文件复制到某个地方,我们设想任何恢复过程就是把那些文件复制回来,一旦有了存放它们的地方,而往往这种恢复操作的发生是没有任何故障的情况下进行的。
最后这一点是我最感兴趣的。几十年来,人们一直认为他们会经常意外覆盖或删除自己需要的关键文件,而这确实发生过。需要追踪并恢复一个终端用户删除的单个文件是一个完全常见的任务,这项工作如此频繁,以至于大多数大公司都有专门的团队来专职处理这类事务。
计算已经发生了改变,今天这种情况很少见,重要文件自行丢失的想法似乎不可能,但肯定是不太可能的。我假设用户在文件管理方面变得更加有教养和更加勤奋,当然,过去作为个别文件完成的大部分工作已经转移到某种数据库或者数据存储在应用程序前端背后的地方,这保护了最终用户免受自己的伤害(这可能从 Google Docs 到 Flickr,但即使是最终用户自己管理文件的工作也显著减少)。大多数操作系统,甚至一些应用程序本身,现在都实施了回收站功能,这些功能将删除的文件保留,直到它们被明确处理,以便最终用户有足够的时间改变主意或找回意外删除的内容。最后,像操作系统自带的自助文件恢复功能或者简单的附加应用程序都可以让文件从其他媒体恢复回来,而无需引入传统的备份或者备份团队,因为数据仍然本地存储(更不用说可以被最终用户使用的在线备份系统了)。
简单来说,值得注意的是,曾经成为一个常见问题,甚至推动整个行业发展的问题,如今在今天已经基本消失了。计算机被视为文件管理和操作设备的时代已经过去,现在已经变成了在线数据消费设备,大多数用户甚至不再关注文件。今天的许多年轻用户甚至可能对文件和存储管理的概念感到困惑。
平台级备份
另一种方法是从平台级别进行备份,即从操作系统下层进行备份。在实际操作中,这意味着虚拟化层,通常是指虚拟化监控程序,但在某些情况下可能仅限于操作系统外部的存储虚拟化,例如,如果使用 SAN 设备,这种情况尤其常见。
随着虚拟化的到来,这种方法迅速流行起来。新的备份厂商推出了新技术,旨在使操作系统外的备份更简单、更快速。此层级的备份当然无法访问文件系统或应用程序 API,无法与这些组件进行通信或了解数据布局。因此,进行此层级的备份必须直接与块设备或虚拟化层的存储抽象层进行交互,而这些抽象层本质上是块设备本身,这让我们通常无法知晓正在备份的数据到底是什么。在这个层级,我们可能知道,或者说可能知道,操作系统呈现给我们的物理设备分离。但我们无法看见文件系统或更深层次的内容。因此,我们在进行系统级备份时所关心的一切一致性问题,可能会在此层级被放大多倍。我们不仅无法知道一个特定的应用工作负载是否已经静默,而且我们甚至无法告诉系统管理的文件系统、文件锁或逻辑卷管理器,我们正在尝试读取块设备。所以,如果我们仅在这个层级进行备份,我们实际上是完全盲目的,仅仅从虚拟磁盘中读取块数据,而没有理由相信这些数据处于一致状态,而且没有任何信息告诉操作系统有任何事情发生。如果我们仅仅这样做,操作系统根本无法知道事情正在发生。
不需要多想就能意识到,没有代理的平台级备份几乎是不可能实现的。我们当然可以关闭虚拟机,并在其关闭时对存储层进行备份。操作系统的完全关闭过程实际上是确保完整静止和一致性的最佳方式。我们如何在不直接拔掉虚拟插头并让自己进入崩溃一致性状态的情况下,从平台级别关闭虚拟机呢?出奇的是,使用了代理。
这就是平台级(即无代理)备份的最大秘密:它们使用了代理!必须使用代理。在现实世界中,直接从任何低层服务进行备份是完全不可靠的。但我听到你在低声说我做过这种事,每个人都做过,而且我们不安装任何代理。
在虚拟化环境中,使备份代理难以识别的原因是因为我们自动和普遍地安装它们,以至于我们不会去思考它。在某些情况下,这些代理程序直接构建到操作系统中。根据您使用的平台不同,它们有不同的名称。最著名的是 VMware Tools,因为 VMware 使用它,并且安装过程众所周知。KVM,Linux 世界中的主要虚拟化管理程序,不仅将客户机代理内置到大多数基于 Linux 的操作系统中,而且实际上直接内置到 Linux 内核中!因此,您实际上永远不需要看到代理,尽管它几乎总是存在的。许多 Linux 发行版也采用了 Hyper-V 的等效代理称为 Linux 集成服务,虽然它们没有内置到内核中,但通常会自动包含在操作系统中。
在这些情况下,我用作示例的虚拟化管理程序供应商的代理程序并不严格是备份代理程序,它们是用于协调虚拟化管理程序和操作系统之间活动的通用代理程序,但实际上,这只是一个更高级的代理功能,没有其他更多内容。从各种可能意义上来看,它们都是代理软件,必须安装到操作系统中才能工作,就像更传统的备份代理程序一样,有时它们包含在操作系统中,有时是第三方附加包。
这些代理通常是一组高性能驱动程序的一部分,用于使完整虚拟机高效运行,因此很少被忽略。它们提供了一个关键通道,允许底层平台层与操作系统层甚至更高层通信。这种通信通道用于向虚拟机发出优雅关闭命令,以及通知其需要使文件系统静默或对卷进行快照。理论上,这种代理甚至可以钩入特定应用程序,尽管在 Linux 世界中这主要是理论性的。
进行平台级备份有重要的优势。如果我们考虑这些备份系统的工作原理,我们很容易看到预期将是对整个文件系统容器或块设备进行块级镜像拍摄。这样做的真正优势在于其完整性。如果我们进行镜像级备份,而不是文件备份,我们有机会获得整个设备,而不仅仅是其部分内容,这将使我们能够完全恢复系统,而不必部分重建然后再恢复。
磁盘镜像
当我们谈论文件级备份的基本机制时,最终讨论的是某种形式的文件复制。文件 X 存在于我们想要保护的文件系统中,为了保护该文件中的数据,我们将该文件复制到另一个位置,以便数据可以同时存在于多个地方。简单明了。
在平台级别进行完整块设备复制时,我们称结果复制为镜像或磁盘镜像。理论上,我们可以从一个物理块设备复制到另一个物理块设备,或者至少从一个虚拟块设备复制到物理块设备。在几乎所有实际情况下,特别是涉及备份的情况,我们实际上是将块设备复制到一个文件中。该文件称为磁盘镜像,有时奇怪地被称为 ISO 文件。
我们之所以称之为镜像,是因为它本质上是任何给定时刻整个磁盘的图像。我们还使用“快照”一词来指代同一操作。在常规英语中,快照就是镜像。这些术语几乎可以互换使用。在计算中也是如此。有时一个术语被用来暗示与另一个不同的含义,但没有被接受的定义使它们不完全重叠。
在日常使用中,“镜像”通常指存储为常规文件的镜像,例如 ISO 文件,并包含原始文件系统的完整副本。而“快照”通常指几乎相同的情景,但逻辑卷管理器创建的部分镜像文件与原始文件以某种方式连接,并且可能仅包含两者之间的差异。但该文件通常用于创建一个独立的镜像文件,否则与镜像文件无异,但仍被称为快照。这导致了一个不恰当的情况,即两个相同的文件可能基于不可追踪和不可知的历史有不同的命名。显然,关于这些文件的常见误解导致了对相同事物不同名称的使用。尽管如此,镜像和快照是重叠的概念。
因为磁盘镜像包含块设备的全部内容,所以可以直接用于恢复整个块设备,甚至在没有任何了解该块设备应包含什么的硬件上也可以。如果备份了 Linux 服务器并进行了恢复,整个系统都将恢复,即使它被加密。镜像不会绕过加密,但加密也不会改变镜像过程。
大多数虚拟化平台,即使使用外部存储设备如 SAN 设备,也会将属于虚拟机的磁盘存储为一个或多个磁盘镜像文件(通常不是原始 ISO 文件而是一种高级格式)。这表明镜像文件是一个完整的块设备(虚拟),因此可以在任何其他块设备使用的地方使用。这在我们想要谈论恢复数据时非常重要。如果我们有一个完整的镜像文件,在我们能够访问的地方就不需要恢复。我们可以根据需要直接挂载它。
镜像备份在性能方面可以更接近硬件,因此具有一些重要优势。但也存在一些显著的劣势,所以并非一切都很完美。
允许系统在仍然处于活动使用状态时冻结某一时刻并与之一起工作的先进快照技术对于允许主要备份活动系统具有重大意义。获取完整系统镜像是处理备份的最简单过程,因为我们不必考虑备份的内容,只需获取所有内容。我们不仅可以获取整个操作系统,还可以获取单个虚拟化层上存在的每个操作系统的所有内容。我们甚至可以对关闭电源的虚拟机以及正在运行的虚拟机进行备份。系统级别的备份必须针对每个系统进行,只能在系统运行时完成,并且只有在非常有限的情况下才能有效地进行完整备份,甚至更少的情况下才能找到一种方法以提供可以在相同方式中恢复的完整块级重新创建系统。
平台级别的备份现在已经流行了十多年,原因充分。它们高效,可以防止选择正确要备份的数据失败,如果必要,可以由不同的团队处理,而不是标准的系统管理员,而且可以在大规模上实施,基本上不需要进行其他工作(除了需要的代理部署和备份软件部署到虚拟化层)。平台级别的备份完全符合大多数组织希望工作的方式,并且对支持供应商来说,作为服务提供是非常容易的,无需进行任何尽职调查。
平台级别的备份也有很多注意事项,因此我们需要意识到为什么大部分时间我们可能不希望专注于它们。由于其盲目性,通常需要最大的存储容量来存储备份,因为它们往往包含许多不必要的数据,比如系统文件。这种膨胀还意味着,不论是出于存档目的还是为了将文件移到恢复所需的位置,移动生成的镜像都可能比通常所需的时间长。仍然需要部署代理。系统几乎普遍被误解,因此很容易犯错,就像许多对于普通用户来说过于复杂而被视为万灵药而不是考虑的另一种工具。
平台级别备份对于平静状态确实是一个真正的挑战。即使所有代理都正确放置,这些代理的性质是它们暴露的选项较少,并且在应用层面的钩子较少,这意味着从该层面获取的备份有较高的风险,可能只是崩溃一致的。操作系统文件将受到保护,因为几乎总是通过代理与操作系统本身进行适当的通信,但几乎没有应用工作负载会受到保护。
平台级备份很引人注目且酷炫。它是供应商通过做最少的工作来利用备份恐惧的简单方式;它是一条容易获得大幅利润的捷径,而任何实际的风险都被推给了那些很少做功课的客户。它让客户感觉安全,因为这些风险太复杂,甚至更多的 IT 从业人员都无法理解,它让他们可以告诉自己,他们得到了保护。无知让人晚上睡得安稳。
平台级备份是一项强大的工具,是现代的奇迹,但它仍然只是一个机制,一种方法,当然也不是每次都适用的。
这只是关于两种非常简单的备份机制的许多信息。我们需要有这个扎实的理解,以便能够继续讨论备份和恢复领域中许多存在的概念。
快照、归档、备份和灾难恢复
有许多技术要么被误解为备份,要么可能是备份的组成部分。在这一部分中,我想拆解这些基础知识,确保我们理解它们是什么、为什么重要、如何使用它们,以及何时我们自己应该利用它们。
快照
在上一部分中,我们讨论了如何拍摄块设备镜像,镜像和快照实际上是一样的,使用快照这个术语时人们通常意味着什么,而不是使用镜像这个术语。现在,我们将真正深入探讨快照。
快照,正如人们通常使用的术语,是在存储中做一些非凡事情的惊人工具。快照通常用于抓取块存储设备状态的瞬时镜像。在这种情况下,术语“快照”非常形象。
对于大多数快照系统来说,正如大多数使用该术语的人所理解的那样,拍摄的快照会与原始数据一起保存在本地存储中,并且两者是内在联系的。假设是快照只包含与原始数据之间的变化或差异。实现这一点的方法有多种,但本质上,最终结果是相同的:一个比原始数据小得多、创建速度快、但能够完美地重现拍摄快照时块设备状态的文件,或者说是快照。
这种过程的显而易见风险是,快照假定仅仅包含了拍摄时与原始数据之间的差异。因此,这里并没有对系统故障提供保护。如果原始文件损坏或丢失,快照将无效。快照可能是一个有效的保护机制,可以防止误删文件、恶意软件或勒索软件,因为它允许系统轻松、快速地恢复到未受损害的状态。这是一个重要的价值,早期的快照机制通常专门用于防止文件删除和覆盖错误。但由于它们与原始数据紧密耦合,真正的备份所能提供的最重要的保护在这里完全缺失。
这种风险导致了“快照不是备份!”的口号。你到处都会听到这个。确实,它们单独并不是备份。不过,快照是备份的重要组成部分。过度强调这一口号导致许多人错误地认为,使用快照作为来源创建的备份不是真正的备份。
快照类型
快照是一个通用的概念,可以通过多种方式实现。写时复制和重定向写入是两种常见的快照机制。几乎你遇到的任何生产系统都会利用这两种机制之一。理解这两者有助于深入了解快照的思维方式和设计,并解释它们为何如此强大。
首先,写时复制(有时称为 COW 快照)。当启动写时复制快照时,一个块设备本质上被冻结在某个时间点。通常这是理论上的,因为实际上什么也不会发生,直到尝试对存储进行更改时,才会有任何操作发生。
当有人尝试向块设备写入新数据时,存储系统会将即将写入的任何块复制到新位置,然后用新数据覆盖原始块。当然,在所有这些复制操作进行时会有性能损耗,并且随着更改的积累,复制数据的大小将不断增加。因此,虽然我们第一次启动快照时它的大小为零,但只要我们继续写入块设备,它将不断增长。
写时复制快照很受欢迎,因为它们被销毁时几乎没有任何代价。删除快照所需做的只是删除额外的数据。在这个过程中,工作块存储不受影响。即使有一个进程在监控原始块设备,它也永远不会知道在某个地方存在快照,因为与快照相关的所有内容都与原始块设备外部有关。所以,当快照不再需要时,清理它基本上没有任何代价。
另一种替代方法——重定向写入——通过操作指针来实现,稍微有些不同。这些指针指向存储设备的所有数据块位置。当数据块通过写入新数据进行修改时,系统不会修改原始数据块,而是将新数据写入新位置,并仅仅将该数据块的指针指向新位置。这样,写操作对数据块的任何影响基本上可以忽略不计。影响不是零,但极低,尤其是相比于写时复制,后者在正常操作中需要移动和重写现有数据。
使用重定向写入,我们可以获得一些非常有用的功能,比如能够维护存储设备几乎无限的版本。事实上,有些存储设备会将所有操作都视作重定向写入,并不将变化视为快照,而是将整个存储系统看作一个永恒的快照机制,以便存储的任何部分都可以回滚到任意时间点。
重定向写入(Redirect on write)看起来一开始非常完美,但它的警告是,你会随着时间的推移积累越来越多的数据,如果你保存数据的中间版本,而不是仅仅保存一个时间点的版本,数据的增长可能会变得非常惊人。如果你需要清理这些数据,清理指针系统的过程可能会变得相当复杂,并且会带来性能损失。
写时复制(Copy on write)通常是处理短期快照时的最佳选择,例如在执行重大系统更新之前创建快照,并且需要在更新之前的时刻进行回滚,或者在备份操作中为了将数据发送到外部而创建快照。在这些任务完成时,快照将被销毁并忘记。写时复制的核心在于快速创建和销毁整个快照,而不是保留它,因为写时复制的代价只会存在很短时间,而且销毁过程没有痛苦。
当我们打算长时间保留快照并希望多个快照相互叠加时,重定向写入非常强大。因为在使用过程中几乎没有代价,只有在销毁快照时才会产生真正的代价,它的作用恰好与写时复制相反。
所以:重定向写入可能是将快照用作持续数据保护的最佳选择,而写时复制通常用于像备份软件这样的系统中,用来生成数据集。
即使我们没有任何特殊的备份软件,我们也可以使用存储系统拍摄的快照,并将其作为有意义的手动备份的构建块。这比听起来要简单得多。在最简单的示例中,假设我们有类似于挂载的磁带驱动器可以在同一系统上写入数据,我们只需利用存储系统将快照挂载为不可变版本的块设备,然后将其复制到磁带上。
当我们这么做时,源快照文件可能非常小,理论上甚至为零字节,但发送到磁带(或任何其他存储介质)的却是整个块存储设备的完整副本,且其状态与拍摄快照时的状态一致。这就是快照技术的奇迹。在使用极少的、通常是微不足道的额外存储空间的情况下,自动且通常完全透明地重新创建或恢复原始块设备的状态。
当我们这么做时,我们面临着一个语义上的挑战:我们该如何称呼那个不再位于原始媒体上的副本?当然,它是一个镜像,但通常我们仍然称之为快照,因为它在各方面都与快照相同,并且代表着在某个时间点的块设备快照。所以,当我们这么做时,“快照不是备份”这一说法就变得不成立了,因为我们可以拥有一个既是真正的备份又是快照的副本。正确的说法应该是快照通常不是备份。然而,快照确实经常作为备份使用,甚至更常作为备份的基础。
由于快照提供了在某个时刻(或多个时刻)冻结块设备的能力,并且提供了一种利用该冻结时刻的方法,而无需中断块设备进行未来操作,因此它非常适合作为创建备份源的手段,同时允许正在运行的系统继续运行。然而,必须注意的是,传统的快照操作都是基于同一个底层物理块设备进行的。因此,虽然我们不需要停止存储设备来执行快照操作,但我们确实会使用原始设备的 IOPS(每秒输入/输出操作次数)。我们的操作并不是零开销的神奇过程,但它们的开销远低于其他备份机制。
由于这一切,快照成为了一个流行的工具,被广泛用于幕后和底层,使得许多现代备份成为可能。实际上,每个虚拟机监控器或存储设备级别的备份(平台备份)都是由快照提供支持的。在许多情况下,即使是系统级备份(即操作系统内的代理式备份)今天也使用快照,无论是 Linux 系统还是其他操作系统。
存档
与备份密切相关,但又有重要区别的是档案。这两个概念经常被混淆,甚至在企业圈子中也不例外。理论上,只要提到这两个名称,问别人,任何人,描述他们对备份和档案的看法,就足以让他们自己认识到这两者并不相同。但将我能定义它转化为我能清晰地表达并内化这两者的不同并不是自动的。
备份,稍后我们将进一步定义,至少是一个副本。这一点应该很清楚。我们在英语中使用这个术语就是指这一点。我们称之为我们的备份副本。如果你表达得清楚,大家都会同意,如果它不是副本,那么它就不是备份。
档案是不同的。归档某个东西并不意味着没有副本,我们有时甚至会说档案副本,但在档案的定义中并未暗示需要有副本。档案指的是长期存储,通常假定其成本较低,访问更困难,或其他方式归档。长期存储,但不一定是随时可以获取的。
档案存储可以简单地理解为一个第二硬盘,数据不会发生变化。也许它是离线磁带,也许是冷存储云。档案存储并不一定意味着存储的性能或可访问性比常规存储差,但通常情况下,它们的性能确实会更低。
大多数组织使用档案存储作为一种低成本手段,以维持对那些不再需要经常访问的数据的紧急或偶尔访问。这种情况很容易举例说明。旧数据可能是去年的财务记录、旧收据的副本、已经处理过的材料的视频片段、旧发票、旧会议记录、已完成项目的蓝图、旧项目文物,你可以想象到。这些企业会产生大量的数据,虽然他们从未预料到需要再次使用这些数据,但也不能完全删除。
假设是,如果档案中包含任何重要数据,它也需要像任何其他存储一样进行备份。经验法则是,任何值得存储的东西都值得备份。如果你觉得备份的成本或努力太大,那么你应该仔细重新评估是否继续存储这些数据。为什么还要为它的存储付费呢?
在正确规划的存储基础设施中,这正是发生的事情,而存档与备份结合起来时,存档是数据保留和保护的强大机制。由于存档一词意味着数据不会更改,这意味着数据不应该被锁定,并且备份可以尽可能简单。处理存档时不存在备份过程面临的复杂性。通常也不需要定期进行备份;如果存档是静态的,可能只需要一个备份就足够了。或者如果存档很少更改,也许每月或每年进行一次备份可能就足够了。
将备份转换为存档
一个常见的情况是备份变成存档。这种情况比你想象的要频繁得多,发生的原因大多数人都能理解。我曾经看到最大的组织中发生过这种情况,而且没有政策来避免这种情况。
在正常情况下,所有想要存储的数据都是实时的,并位于其适当位置以供使用和正常使用。对这些数据进行备份,以防发生灾难,系统可以恢复。在发生灾难之前,所有数据都存在于原始位置以及一个(或多个)备份位置中。这种位置的冗余性是使副本成为备份的原因。从技术上讲,如果原始存储位置失败,主要备份(可能是唯一的备份)将停止成为备份,并且暂时成为数据的主要来源位置。我们从不这样说,因为我们都知道“从备份中恢复”的含义,但是在原始存储消失的那段时间内,第一个备份现在是该数据的主数据,而不再是备份。它可能有自己的备份,通常我们会这样做,但是只有当有非备份数据时,备份才能成为备份的备份!很难解释,但这是一个关键的概念。
这很重要的原因是一旦对数据进行了备份,就很容易感觉我们的备份可以保护我们,因此我们可以删除原始数据。因为已经有了备份,我们觉得我们可以这样做。这里的问题是,如果我们删除了原始数据,备份(或至少是第一个备份)就不再是备份,而是存档!在大多数情况下,如果假定的主源位置不再存在,可能没有机制来进一步备份这些存档数据。甚至可能没有任何手段来定位它。
我亲眼见过这种情况发生在现实世界中。每天的备份任务都会运行,而终端用户却默认认为他们不需要存储任何他们需要的数据,即使法律要求保留并备份数据在主系统上,因此他们会在创建后立即删除数据,假设他们的数据受到备份系统的保护。然而,这种计划存在一些关键缺陷。
首先,通过删除原始数据,任何现有的备份都会成为源位置而不是备份,并且仅仅是基于磁带的归档。考虑到数据有法律要求需要保留和备份,这违反了法律的保留要求。
第二,备份机制是分阶段的,有些备份保留数年,有些保留数月,有些保留数周。因此,如果数据碰巧存在于保留数年的运行中,那么包含相关文件的那一盘磁带很可能可以读取以检索数据,但如果数据仅存在于每周作业的备份运行中,即使是归档版本也会在几周后磁带被覆盖时被删除。
第三点,与档案情况无关,经常是数据在每日备份作业运行之前就已删除,这意味着数据在没有任何备份或档案的情况下立即丢失了。结果是从未存在过备份,偶尔某些文件可能会幸运地保留几年,但大多数文件要么根本没有被归档,要么只是短暂地被归档,并在几周后的磁带重用时被删除。
考虑到需要保留七年的要求,再加上对该保留的备份,很容易看出流程有多大偏差,因为最终用户认为他们可以有意删除原始文件,因为他们认为魔术备份过程某种方式在保护他们。备份团队认为所有数据都会保持七年,并且如果有任何文件丢失或损坏,最终用户会立即通知备份团队进行恢复。他们从未考虑到最终用户会自行销毁数据并且从未通知备份团队数据已被销毁,因为为什么会这样呢?
很容易看出我们可以通过许多情况下最终用户的行为,无意中将我们的备份位置转换为档案位置,并且由于我们不理解备份过程的复杂性,可能会丢失数据。如果数据不会在主要位置永久保留,那么通常需要非常复杂的过程来确保删除的安全工作流程。
档案是降低成本并保持我们主线存储瘦身的强大机制。也许我们仅使用档案来降低成本。在许多情况下,通过将多余的数据远离我们顶级存储层,可以让我们投资于更快速但更小型的系统,用于我们日常使用的数据。
档案也可以应用于文件的部分。当然,有时甚至数据库也使用混合存储位置,以便能够将经常访问的表或表的部分存储在最快的存储上,而很少接触的表或表的部分可以存储在成本更低的较慢存储上。这可能在数据库引擎内部自动进行,或者应用程序可能使用多个数据库系统,并在应用程序层面在它们之间移动数据,例如。
档案是一个有用的工具,但绝不能替代备份。
备份
很难相信在没有实际深入探讨我们说“备份”时确切含义的情况下,我们已经走了这么远。与许多事物一样,有时候直接进入定义是很困难的,因为我们需要考虑的事情实在是太多了。
在最基本的层面上,备份是原始数据集的副本。我们在上面已经讨论过这一点。如果数据没有变得冗余,那么它就不能算是备份。这是难题中最明显的部分。
接下来,数据必须存储两次。这意味着硬件必须存在不止一次。
在许多情况下,我们可以将其与纸张或其他物理形式的数据存储进行比较。如果我们有一张重要代码的纸张,我们会感到有必要将这些数据复制到其他地方 - 进行备份。我们知道纸张容易被弄脏、烧毁、丢失或者洗涤机洗过。
或许备份要求中最令人困惑的部分是它必须与原始材料强烈解耦。强烈解耦是一个涉及一些观点的术语,这使得确定适当的解耦水平有些困难。对于一个组织来说足够解耦的程度,对另一个组织来说可能还不够。
当我们使用术语紧密耦合时,我们指的是原始数据和数据副本之间存在连接的情况。在最紧密耦合的情况下,类似快照的概念,任何发生在原始文件上的事情也会影响到快照。这是完全耦合的情况。稍微松散耦合的情况可能是将副本存储在同一物理设备上。副本与原始数据之间的距离越远,它们的耦合性就越低。
耦合可以涉及到更多的内容。它还可以包括诸如存储在共享凭据(如用户名和密码)系统上的概念。耦合可以很复杂,并且没有单一、明确的描述方法。但是,当我们谈论保持备份高度解耦时,通常意味着一些事情,例如:完全不同的硬件和媒体、物理上分离的位置以及断开的身份验证。
每增加一步解耦的背后想法,是让任何可能发生在原始数据上的事件,几乎没有可能同时发生在备份数据上。这可能是文件意外删除、存储设备故障、勒索病毒攻击、洪水或火灾。丢失原始数据或无法访问它的方式有很多种。我们必须尽可能广泛地考虑这些可能性,并评估多少解耦,以及什么类型的解耦是合理的。没有任何两个系统能做到完全解耦,但我们可以很容易地将解耦做到一个实际的水平。
第一步很简单,很少有组织犯错误尝试将备份文件放在与原始数据相同的媒体上。然而,这种情况确实发生过。使用同一硬盘的情况非常罕见,但尝试在同一设备内使用第二个硬盘却悲哀地相对常见。当然,正如你所想象的那样,许多会导致计算机中一块硬盘丢失数据的事件,可能也会导致另一块硬盘上的数据丢失。机箱内的火灾、极端震动、洪水、断电、盗窃、由于各种事件导致的数据损坏或恶意攻击,都很可能同时摧毁备份数据与原始数据。这几乎完全否定了备份的意义。
如果用物理世界来做类比,我们可以比作纸张。你有一张存储关键数据的纸。你把这张纸放在文件柜里。你担心保护这张纸免受不好的事情的发生。你可以使用一张纸,将信息写两遍。你可以在同一个文件夹内同一个文件柜里放第二张包含数据的纸。你也可以把副本放在第二个文件柜里的独立纸张上,文件柜与第一个文件柜相邻。或者,你可以把纸张的副本放在另一个建筑物的独立文件柜里。
在这些例子中,很容易看出从紧密耦合到高度解耦的演变。当共享一张纸或两张放在同一个文件柜里的纸时,风险是显而易见的。几乎任何损坏第一份副本的情况都会同时影响第二份副本。将纸放在第二个文件柜中,至少提供了一定的保护,因为两个柜子可能有不同的钥匙,一个柜子掉入水中可能不会影响另一个柜子,一个文件损坏可能不会影响另一个文件,等等,但很容易看出它们的风险仍然是耦合的,只是没有那么紧密。
通过将文件柜放置在完全不同的建筑物中,可能是在不同的楼层,甚至是不同的城市,那么发生洪水、火灾或盗窃,能够同时摧毁原始数据和备份的可能性极低。也有可能发生火山事件、核战争或陨石撞击,即便备份和原数据分别存放在几英里之外,它们仍然可能被摧毁。这就是为什么我们说强解耦,但绝不完全解耦。
在备份中,我们必须考虑我们的数据解耦的程度,以及进一步解耦所需的成本。我们还必须考虑解耦的有效性以及它对我们业务的影响。这是一个复杂的问题。然而,对于大多数企业来说,我们希望备份具有物理距离、各种介质、身份验证的分离和多个副本。备份包含的内容以及它们如何使用在这一过程中起着重要作用。
这里没有简单的最佳实践,甚至常见的经验法则在基本的极限之外也很少适用。最佳实践要求:
最佳实践:如果数据值得存储,它就值得备份。
最佳实践:备份需要与原始数据高度解耦。
备份的可能性范围如此广泛,以至于我们必须全面评估每个企业的需求,在许多情况下,还需要考虑个人工作负载。在某些情况下,像整个操作系统的备份,我们的主要关注点可能是硬件故障时的快速恢复,而备份的实际内容可能并不重要。在另一些情况下,备份可能包含大量高度专有的数据,确保这些备份的安全性,确保它们不会落入错误的手中,成为优先考虑的事项。
为什么磁带仍然重要
在谈到备份时,磁带介质的问题不可避免地浮现出来。通常你会听到两种回应:磁带太棒了,我总是使用它;或者磁带已经死了。意见极为分歧。
曾几何时,磁带几乎是唯一的备份介质选择。固态硬盘还不存在,而硬盘的每兆字节价格极为昂贵,且其使用寿命和抗震能力都非常差。磁带是唯一既实惠又耐用的介质选择,尽管当时它也并不好。
在过去的几十年里,一切都发生了变化,正如它经常发生的那样。硬盘、固态硬盘以及为你托管这些服务的公司都已经变得非常标准化。驱使我们使用磁带的主要因素已经消失,我们有很多可行的选择。这使得许多人专注于这些新选择,而没有跟上磁带技术的进步,但和其他所有技术一样,磁带技术也已经取得了相当显著的进展。
磁带几乎是专为备份而设计的介质。它可以以极高的速率移动线性数据,存储每兆字节的成本非常低,并且具有出色的保管耐久性和抗震能力。磁带自然地,除非你将磁带留在驱动器中,否则只需从驱动器中弹出磁带,它就会与原始系统解耦。你甚至可以拥有一个远程磁带系统,通过自动磁带弹出使技术和物理解耦完全自动化!
磁带的优势在于允许每个磁带至少部分地与其他磁带解耦。磁带可以存储在不同的位置,并且可以使用多个磁带来存储数据的多个副本。在某些情况下,磁带组可能会存放在一个盒子里,实际上重新耦合了磁带。如果磁带分开存储,则不仅源数据与备份之间可能实现显著的解耦,备份内部的数据之间也能实现解耦!
磁带并不完美。它需要物理装载磁带才能恢复,并且在查找备份中深埋的单个文件时表现很差。磁带在备份或恢复大量连续数据时表现出色,但一旦开始搜索特定数据,性能就会迅速下降。一些公司通过使用机器人和磁带库来解决磁带管理中的人工问题,但这实际上将磁带重新“上线”,并可能将其与原始数据重新耦合,至少部分耦合,削弱了其保护层。没有机器人或磁带库的直磁带有一个好处,那就是需要“黑客”攻击一个人,除非攻击计算机,才能同时摧毁原始数据和备份。
磁带足够有用,甚至一些在线云备份提供商也将磁带作为其存储解决方案的一个组成部分。磁带在现代世界中占有重要地位,在可预见的未来也将如此。
当然,备份可能不是针对某一工作负载的单一解决方案。一个工作负载或系统可能需要多个备份。一个可以本地存储、耦合适度的备份,用于发生意外或硬盘故障时快速恢复。远程备份到磁带或不可变云存储,用于长期、高度解耦的数据保留,以应对勒索软件攻击或整个站点丧失的情况。
解耦对备份的功能性或有用性至关重要,以至于我们必须将其纳入备份定义中,即使我们不能完全清楚地定义什么构成足够重要的解耦。这是因为对一个组织或情况来说足够的标准,可能对另一个组织或情况来说并不适用。对我来说,这意味着我们的解耦定义必须是主观的。利益相关者需要定义备份应防护的内容,并根据此定义必要的解耦程度。
不能忽视的是,现代勒索软件已经成为推动组织开始分析传统备份耦合水平的一个驱动力,因为突然之间,备份具有任何实际耦合级别的影响和威胁变得非常剧烈。到目前为止,勒索软件技术积极采用策略,尽可能勒索备份本身,并使用隐藏其活动的技术,阻止备份在系统加密时提供保护。备份仍然是防御此类威胁的最佳手段,但确保极高的解耦级别通常需要像不可变存储和将备份物理断开连接等技术,以便没有计算机能够在没有人工干预的情况下访问它们。
如果你无法恢复,那就不是备份。
我听过很多次这句话,我仍然很喜欢。简单来说,如果在灾难发生时你的备份无法恢复,那它真的算是备份吗?在某种程度上,这种说法有些夸张。备份可以失败,这种失败可能与原始工作负载的失败时刻重合。但这种情况应该在统计上非常不可能,如果发生了这种情况,应该有一个极为明显的巧合。
许多人想表达的是备份测试的必要性。备份非常复杂,了解使用可用机制的速度、过程和效果是任何备份过程中的一个非常关键的环节。如果你从未测试过你的系统,你必须假设它们不会起作用。即使你已经测试过它们,最好还是最近进行过测试。有些备份系统甚至会每次自动进行恢复测试,以展示备份的有效性。
备份测试可能会产生误导。像许多其他数据保护机制一样,如 RAID、冗余电源供应或故障切换 SAN 控制器,我们通常在一个可预测、完美的环境中测试备份,但这种测试通常并不能反映在紧急情况下恢复所需的真实情境。备份测试通常是在系统空闲或比平时慢的情况下进行的,且通常会反映出最佳的情况,从而导致几乎总是通过测试,即使是在现实世界中几乎总会失败的系统上。考虑一下不利的条件,比如正在故障的系统(而不是完全失败的系统)、高负荷操作或不一致的数据状态(崩溃一致性),这些情况在测试场景中是无法反映的。
备份可能看起来是一件简单的事情,每个备份供应商都会将他们的产品呈现为消除了你对数据理解的需求。供应商希望你对他们的盲目信任,认为他们能够做不可能的事,并让你打开钱包、单纯地期待一切顺利。作为系统管理员,我们的任务是理解我们的数据,了解我们的备份机制如何工作,确定我们组织和工作负载的一致性与耦合需求,并组建一个符合或超越这些需求的备份解决方案。
灾难恢复
最终,任何备份机制的目的都是为了实现灾难恢复。灾难恢复是我们都希望永远不必面对的事情,但它却是我们职业生涯中最为重要的时刻。灾难情境是我们比任何时候都更能展现价值的时刻。在灾难来临时,你能够冷静从容地应对,掌握如何将工作负载恢复上线的知识,并能够适应任何变化或突发的挑战,这一点至关重要。灾难中的表现可能意味着数百个百分点的薪资差异。
随着我们深入了解了各种备份类型和方法,现在自然地出现了许多恢复方式。在灾难恢复的规划过程中,我们必须将所有这些因素考虑在内,因为我们的规划过程会因此发生巨大的变化。
如果我们使用基于镜像的备份方法,那么假设是我们将通过一次性恢复整个块设备镜像(或多个镜像)来进行恢复。这在灾难恢复中有一些显著的优势,因为我们只有一个步骤:恢复整个系统。在某些情况下,我们的恢复机制将会一次性自动恢复所有系统,而不仅仅是单个系统!这是一个非常诱人的前景。这个方法的警告是恢复通常较慢,并且一般只是在崩溃一致性方面达到要求。以最快的速度恢复并确保可靠性是此方法面临的最大挑战。
使用基于文件的备份时,我们几乎总是需要首先恢复一个空白的操作系统,通常是模板或原始构建,然后再将单个文件恢复到最初的位置。理论上,这种方法比镜像基础的完整恢复更快,但在实践中很少如此,因为从传统方法构建基础操作系统所需的时间。虽然从现代方法理论上可以构建基础系统,但这通常并不会发生,因为如果这样做,你就自然会转向 DevOps 风格的备份。然而,这两者在概念上开始重叠,你可以将基于文件的备份机制与传统的文件恢复相结合。当然,变化在于,文件备份将专注于有意义的系统数据,而不是盲目地备份任何东西。
最后是完整的 DevOps 风格恢复。这更为复杂,因为没有明确的单一定义。这里的假设是,由于任何数量的自动化构建机制,基础操作系统的重建几乎是瞬时完成的。而且数据恢复将被大幅度最小化,以便也能以极快的速度进行恢复。
当然,所有这些操作将与我们稍后讨论的优先处理操作同时进行。规划和时间安排这些操作,使其广为人知,流程经过测试,并且在不同场景下恢复时间可预测,为灾难情景中的决策提供了宝贵的信息。
灾难恢复规划不应仅仅是对单个工作负载的孤立测试,也不应仅仅测试数据丢失。不同的组织面临不同的风险,测试多种类型的场景非常重要。我们在考虑灾难恢复时,通常会想到数据恢复,但这可能并不是我们面临的挑战。如果我们的工作负载分布在多个位置,我们可能需要考虑如何在较慢的连接或不理想的数据中心位置下工作。灾难恢复测试可能涉及测试在备份系统上启动工作负载、故障切换集群,或从备用数据中心运行的能力。
灾难恢复的最佳实践是始终测试你的场景,并定期进行测试。永远不要盲目相信我们的备份、规划、网络或数据中心会正常工作。我们不仅需要测试计划背后的技术,还需要测试这些计划的操作流程。
现在我们已经讨论了备份相关的机制和术语,是时候真正探讨现代的 DevOps 世界如何重新定义我们的备份操作了。
DevOps 世界中的备份
在本书的早期部分,我们讨论了像 DevOps 和基础设施即代码等现代概念对系统管理领域的影响。你可能会想,这些现代概念是否对备份和灾难恢复领域有潜在影响。好问题!如果章节标题没有透露答案,我现在来给你提示:是的,它们确实有影响!
传统上,我们认为恢复数据要么是非常老式的方式——只恢复单个文件,要么是较现代的方式(过去二十年内的做法)——恢复整个系统,包括操作系统及所有相关文件。我们已经习惯了这种方式,以至于常常很难从其他角度来思考恢复系统的问题。
在超现代的 DevOps 风格世界中,系统通过自动化构建,并在代码或配置文件中定义,我们必须开始以全新的视角看待几乎所有事物。当系统可以通过标准的非灾难性流程自动、轻松且快速地构建时,恢复这些系统的需求就完全消失了。试想,如果你可以用更少的钱、更少的时间、更可靠地将一辆全新的、完全相同的汽车送到你的门前,而不是在事故后修理旧车——你就永远不会浪费时间去恢复一个损坏的东西,而是直接选择拥有一个全新的完美副本。
版本控制系统
在谈论备份时,特别是与 DevOps 相关时,我们还应该谈论版本(或修订)控制系统。版本控制系统,如 GIT、Mercurial 或 Subversion,虽然本身不是备份系统,但它们作为一种机制,用于将系统上一些最重要的数据同步到另一个位置,备份通常会发生在这个位置。
在备份的上下文中谈论版本控制时,可能会有些困惑,因为在某些情况下,我们可能把操作系统视为主位置,而版本控制系统可以用于将配置文件复制到另一个位置,从那里它们可以通过任何常见的备份机制轻松地进行备份。
因为版本控制系统不仅存储当前数据,还存储文件的历史版本和变更,它们实际上变得不可变,因此在备份样式的情境中非常有用,因为备份机制不需要处理随着时间推移的版本问题。版本控制系统保存了文件历史中的所有版本和更改。因此,对整个版本控制系统的备份自动包含了所有文件的更改。因为这一点,终端用户意外删除文件、文件的错误更改、对数据的勒索攻击等问题变得无关紧要,因为能够恢复到坏更改发生之前的状态是内建的功能。
版本控制系统通常不仅可以用于在一个端点和版本控制服务器之间复制文件(及其版本历史),还可以复制到多个额外的端点。例如,一个系统管理工作站或跳板机(我们将在下一章中描述)可能包含公司中每个 Linux 系统的配置文件的完整副本,且该副本与任何服务器或备份系统分开。即使由于巨大的灾难丧失了所有官方数据副本,单个工作站也可能能够重建整个文档集。
这些类型的系统已经在非备份相关的场景中广泛使用,并且在 DevOps 领域被视为必备工具。我们可能已经在一些系统管理任务中使用它们。即便是在没有 DevOps 流程的系统中,考虑到数据保护的需求,这些工具也可能被用作版本控制。
即使是最传统的(意味着尽可能远离 DevOps)Linux 系统,也能从其配置文件使用版本控制中受益。如果组织认为不必要,甚至无需为版本控制建立自己的基础设施。像 Gitlab 和微软通过 GitHub 提供的企业托管版本控制系统,具有丰富的功能和访问控制系统,且免费提供。
一家拥有传统遗留系统的小公司,想要引入版本控制保护的话,在一个假设的例子中,简单地进入 /etc 文件系统并将其添加到远程 GIT 仓库,然后进行推送。瞧,所有的数据都得到了保护,快速而轻松。设置一个 cron 作业,每隔几个小时推送任何额外的更改,您就能自动化一个强大的备份系统,几乎不需要任何努力,且肯定是零成本。
版本控制系统是开发世界中那些不为人知的秘密之一,它们已渗透并被许多其他行业所接受。任何大量使用文本文件的系统,都应该尽快加入版本控制的行列。版本控制是提升数据保护水平的最简单方式之一。尽管这个简单的例子可能没能体现出其所有优势,但恢复一个系统也存在一定的风险,可能会恢复到已损坏的系统,甚至更糟的是,恢复了感染或 rootkit。干净的重启可以消除这些风险,确保您从头开始时拥有安心。很可能是最快的路径,能够以最可重复和可预测的方式进行操作,并且风险最小。此方法也是最容易测试的。每次构建新服务器时,无论是生产、测试、预发布等环境,您都会自然地测试至少部分内容。
当我们构建基础操作系统、安装应用程序,并通过 DevOps 风格的自动化部署配置时,我们只需恢复来自备份系统的系统特定数据,而且这种恢复通常仅在部分情况下需要。如果你考虑一个典型的多层应用程序,唯一的、不能从初始构建过程中获取的数据通常仅限于数据库文件或有限的文件存储。在一个运行于多个操作系统实例上的应用程序中,我们通常期望这些数据只存在于那些节点的某一层,通常是数据库。如果该节点是复制的,我们通常只需要从集群中的单个节点备份数据(因为我们通常会在所有节点之间复制所有数据)。通过这个过程,我们减少了备份的多个节点、减少了备份类型,并仅识别出可能存在风险的实际数据。
每个环境都不同,在某些环境中,我们可能发现需要特别保护的数据仅占所有数据的百分之一,而在另一些环境中,可能占到百分之九十九。我们无法确定现实世界中你将会面临什么,因为每个组织和工作负载的情况差异很大。普遍来说,能够限制备份的规模,进而限制恢复的规模,是有优势的。备份越小,备份过程越快速且对系统的影响越小。备份越小,存储它的成本也越低。较小的备份意味着验证数据是否损坏的工作量更少。减少备份时间的同样较小的大小,也同样能够减少恢复时间。
在我们这个多层的例子中,我们可能需要重建三个节点才能使应用程序重新启动。顶层的负载均衡和代理层假定没有独特数据,可以通过已经测试过的构建过程恢复,这个过程最初就是用来构建它的。应用层同样不应该有独特数据,并能够使用已经测试过的构建过程自动恢复。
我们最后一层标准层,数据库,应该同样通过完整的构建过程来部署所有配置和应用程序。此时,应用程序的所有层级和配置都已经恢复,备份和恢复机制甚至还没有发挥作用。此时唯一缺失的部分是数据库中最新数据的恢复。数据库已就位,但其中的数据尚未恢复。此时,我们的恢复过程启动,将数据恢复到正确的位置。这可能只是一个简单的文件从远程位置复制到数据库位置,并在文件到位后重启数据库。或者可能需要对数据执行特定于数据库的恢复操作以重新加载数据。无论如何,恢复的数据量非常小,类型也非常有限。
这种方法改变了我们传统上对备份的所有认知。它改变了备份操作的速度和影响力,改变了我们需要使用的工具,并可能将它们完全淘汰,它使得恢复变得更快,甚至可能实现完全自动化!
如果我们回到之前的示例,假设我们使用的是流行的 MySQL 应用程序作为我们的数据库平台,且所有必要的数据都存储在这个位置——对于许多常见的工作负载设计来说,这是一个合理的假设,那么我们可能不再需要使用特别的备份工具。我们也不需要依赖像快照这样的复杂或风险较高的机制。我们可以使用数据库平台的内置工具,可靠地从工作负载层(我们不愿意称之为应用层,因为那是一个软件工程术语,和系统层面的术语有所不同)获取完整的数据集,且我们知道,工作负载在备份操作期间,凭借其所有必要的智能,能够稳定并锁定数据,从而确保我们的备份是安全的应用 一致性。
当我们退后一步,开始忽略常规,停止单纯地购买解决方案,而是戴上 IT 的帽子,确定如何最好地保护我们的环境时,我们常常能找到既能保护我们的组织又能节省开支的方法。
IT 提供解决方案,供应商销售组件
超越备份,甚至超越系统管理,了解解决方案的来源是我们在 IT 领域做得好的一项基本任务。核心是,生产解决方案的责任属于 IT,而不是其他人。在很多情况下,我们需要依赖供应商提供某一或多个解决方案的组件。IT 不可能自己制造 CPU、组装服务器部件,或者编写操作系统,因此供应商(在这个上下文中,供应商包括那些不收费但提供像开源软件(例如 Linux 操作系统)这样的东西的供应商)是解决方案过程中的必要部分。
供应商不是解决方案提供者(尽管很多供应商会以此作为营销名号,自称为解决方案提供者,当然),他们更像是销售组织。他们的角色是提供工具的访问权限,希望这些工具能在我们追求解决方案的过程中带来帮助。真正决定使用哪些工具的,是 IT 部门,IT 部门负责选择合适的工具,并用它们来组装最终的解决方案,以满足业务需求。IT 是提供解决方案的部门,这不仅仅是我们购买的东西,而是我们所做的事。我们不能仅仅依赖供应商来卖给我们一个能保护我们的产品;事情并非如此简单。我们需要理解业务需求、工作负载、备份产品、方法,并将所有这些信息整合起来,做出一个适合我们的统一解决方案。每个企业都是独特的,每个解决方案也应该是独特的。
没有任何供应商提供的工具能够考虑到我们今天所有独特的备份需求,更不用说能够适应未来可能的变化了。如果你能想象的话,许多公司对供应商购买流程上瘾,以至于他们试图将自己的工作负载和内部流程(以及需求)调整到适应供应商想要销售的产品需求!这就像是为了让你的船销售员解释他推销给你的船,而不是能让你轻松上下班的车,你非得搬到一个不理想的房子里。
DevOps 和类似的基础设施确实揭示了传统的只是购买销售员想让你购买的东西流程,如何迫使企业适应采购,而不是选择对企业更有意义的产品。在以前的技术时代,选项要少得多,差异也要小得多,所以很容易忽视或忽略这些低效之处。今天,已经不可能再这样做了。
增强的备份和恢复流程实际上是考虑投资 DevOps 和基础设施即代码工程的最佳理由之一。通常情况下,我们可以找到许多理由让 DevOps 更具吸引力,但更好的备份显然是最有价值的好处。
现在我们已经了解了如何在真正现代化的基础设施上进行备份,接下来我们要讨论的最后一个话题是:分类。是时候从备份的操作转向如何使用备份了!
分类概念
规划很重要,它帮助你为许多可能的情况做好准备。然而,当灾难真正来临时,大部分的规划都会被抛到窗外。你对备份可靠性的所有信心并不会让你放松,最终用户会陷入恐慌,管理层会忘记你需要解决问题,反而会把你拉进会议,压力巨大,所有情况都和你原本的规划完全不同。
分类之所以困难,是因为每个工作负载、每个时间点、每个当前情形都包含了许多动态的因素。我们必须准备好随时做出调整,并尽可能快速地让我们的系统恢复正常。
灾难发生的瞬间,才是最关键的时候,这也是系统管理员真正展现能力的时刻。准备好应对灾难相对简单,但保持冷静、理性,实时评估局势,并管理周围的人,都会变成不可预测且非常情绪化的挑战。
没有简单的分类指南,并非每个人都擅长这一点。我们越是事先做好准备,越是了解整个环境,越是了解我们所处的商业环境,我们就越能适应变化。
分类是一项最适合由 Myers-Briggs 性格类型中的知觉型(Perceiver)来处理的技能。因此,在这里,管理工作,相对于工程设计,确实能展现出其最极端的优势。
分析停机时,我们的第一步是评估情况并确定灾难的范围。是只有某些服务不可用吗?还是所有服务都中断了?是否有数据丢失?停机的当前、正在发生和未来可能带来的影响是什么?如果我们手头没有这些数据,应该让人员忙于为我们收集这些信息。
紧急处理尤其需要帮助业务了解在停机期间能做些什么。许多企业会陷入恐慌,或者根本没有计划(即使有计划,也无法正确执行)。但业务行为需要与技术恢复工作协调一致。在我们开始恢复的过程中,我们还需要努力帮助业务尽可能地继续运作。当然,我们希望公司管理层根据 IT 对影响的评估以及恢复可能的样貌,来指导运营,以提高效率。IT 往往也需要准备好提供指导。
在任何紧急操作中,我们都必须确定工作负载的关键性及恢复的可能性。最关键的工作负载,如果恢复需要几周时间,而许多基本服务能在短时间内恢复运行,那么它也将排在后面。在决定如何进行灾难恢复时,我们需要考虑生产力损失、客户信任丧失、合同无法履行以及类似的顾虑。
恢复计划,即使是在紧急时刻,也需要与业务部门协调。业务部门可以做些什么来帮助恢复,技术方面又能做些什么来实现这一目标?通过良好的合作,不同的业务可能会发现多种途径来最大限度地减少停机带来的损失。
企业可以采取一些简单的措施,比如让员工回家休息,避开工作现场,这样 IT 部门可以有更多的自由进行恢复。一个享受了突然假期的员工,回到办公室时可能会精神焕发,甚至尝试弥补部分失去的工作时间。与其让团队因无法工作而感到沮丧,为什么不奖励他们的辛勤工作呢?
将通信转移到未停机的系统上同样非常重要。如果电子邮件停了,员工能否转而使用电话?如果电话停了,能否用电子邮件?即时通讯呢?或者通过其他平台进行语音聊天?也许这时候是去拜访客户的好时机!
没有办法列举出企业利用停机的无数方法。我们需要的是创造力和与业务合作的自由,帮助他们看到如何尽最大努力继续工作,并引导我们以最适合他们的方式进行恢复。
思考分类操作凸显了我们已经讨论过的概念的重要性,如自恢复系统、最小化的恢复大小和周密的规划。它还强调了让运营和其他部门参与进来、了解可用计划并准备好协助和协调在问题发生时的重要性。良好的规划能让分类操作更有效,但你无法为你的分类操作做出完全的规划。变量太多,无法真正预见所有的突发情况。
我希望分类处理和灾难恢复监督是我们可以具体教授的内容。那是一个令人恐惧的情况,我们所能做的就是确保具备分类处理和洞察力思维的正确人员在关键时刻能够及时行动,拥有良好的备份、良好的恢复流程,并尽可能做好规划,同时确保整个组织能够作为一个协同团队共同努力以尽量减少影响。
总结
没有什么比备份更重要。我觉得这至少是我在本书中写下的第五次,显然这还不够。如今,备份比以往任何时候都重要。我们面临的灾难场景和更为复杂的数据丢失情况比我们行业以往的任何时候都要多。备份一直是且可能永远是我们防止完全失败的最强防线。
近年来,备份发生了很大的变化。即使是十年前我们备份的假设,今天也不再适用了,然而许多组织仍在使用传统应用程序、传统设计,仍然需要使用传统的备份。所以,我们的工作是复杂的,我们对现代备份的需求可能推动我们朝着更加现代化的应用设计发展,从而使我们能够以更好的方式保护它们。
但现在我们已经理解了不同备份方法背后的机制,为什么我们要考虑以不同的方式进行备份,以及如何将我们的备份实践推进到未来。备份可能是你与众不同的最佳机会;没有什么比备份更重要的了,而且很少有什么像备份那样被忽视。
在下一章,我们将探讨用户在 Linux 系统中的存在与互动,以及我们如何处理身份验证、远程访问和安全性问题。
第五章:补丁管理策略
在 Linux 系统的日常操作中,平均系统管理员最常见的任务大概是补丁管理(即补丁更新)。与 Windows 和 macOS 世界不同,系统管理员通常负责处理各种操作系统和应用程序的补丁更新任务,涵盖了主系统和第三方生态系统。同时,系统中通常内置或通过第三方提供应用程序管理工具,以协助完成这项可能令人生畏的工作。
补丁管理,当然还有系统更新,是我们工作中的重要部分,虽然它可能感觉平凡,但确保它做得正确非常重要。而今天的生产 Linux 系统比十年前更加复杂和多样化。补丁管理也变得比以往任何时候都更为重要,我们预计这一趋势随着时间的推移只会越来越明显。
我们将首先了解补丁和更新是如何提供的,以及我们所说的不同安装方法的含义。
在本章中,我们将学习以下内容:
-
二进制、源代码和脚本软件部署
-
补丁理论与策略
-
管理员的编译工作
-
Linux 安装与重新部署策略
-
重启服务器
二进制、源代码和脚本软件部署
软件有各种形态和大小。因此,软件部署并不是一刀切的事。软件的标准部署方式有三种:直接作为二进制包、通过需要编译成二进制包的源代码,或者作为脚本。我们将深入探讨这些方式,因为理解每种方式的含义及其适用场景非常重要。
编译型和解释型软件
许多系统管理员从未作为开发人员工作过,通常也不了解软件的存在形式。编程语言主要有两种基本类型:编译型和解释型。
编译语言是用一种语言(源代码)编写的,通过编译器生成二进制可执行代码,这些代码可以直接在操作系统上运行。这可能是一个过于简化的说法,但我们不是开发人员,仅需要关注原始代码被编译成二进制格式即可。对于 Linux,这种格式被称为ELF,即可执行与可链接格式。编译后的二进制文件在操作系统上运行。
解释型语言有所不同。它们不像编译成二进制那样,而是保持原样,并由一个叫做解释器的程序实时处理,解释器本身是一个二进制可执行文件,它将代码作为输入文件来处理。因此,解释型软件要求操作系统上安装适当的解释器,以便该软件能正常工作。例如,如果你有一个 Python 程序,并希望在某个系统上运行,那么你需要确保该系统上安装了 Python 解释器来处理这个文件。
这两种软件方法完全正常且有效。作为系统管理员,我们将始终与这两种方法打交道。现代计算机(和解释器)速度非常快,因此两者之间的性能差异几乎没有什么关切,其他因素(主要是开发人员的考虑)通常在决定软件如何编写时更为重要。
软件并不完全如此简单,存在一些奇怪的概念,比如看似解释型的代码,实际上却在最后一刻被编译并像二进制文件一样运行。一些像基于.NET 和 Java 的语言,虽然是编译的,但并不是编译成二进制文件,因此本质上是结合了两种方法的一种混合体,兼具两者的优点。
然而,通常我们将所有软件视为二进制可执行文件(直接在操作系统上运行,无需帮助)或解释型软件(需要操作系统上的编程语言环境或平台来运行)。为了理解代码部署的目的,像.NET 和 Java 这样的语言,以及JIT(即时编译)的语言,如 Perl,由于其行为,通常被归类为解释型语言。
常见的预编译语言包括 C、C++、Rust 和 Go。常见的解释型语言,或者看起来像是解释型语言的,包括 Python、PHP、Perl 和 Ruby。更让人困惑的是,任何解释型语言都可以被编译。标准编译语言甚至可以被解释!更重要的不是语言本身做了什么,而是在特定情况下它是怎么做的?本质上,任何语言都可以根据我们在实践中的处理方式来选择编译或解释。然而,在现实世界中,没有人会解释 C++,也没有人会编译 Python。但如果你愿意,还是有可能的。
作为系统管理员,我们实际上对软件的构建没有发言权,我们只需要按给定的方式部署软件。我们最需要理解的是,我们可能对整个平台的控制和影响力有多少。如果我们运行一个二进制应用程序,那么我们的实际选项可能仅限于我们所运行的内核版本。但如果我们要安装一个 PHP 脚本,我们可能还需要决定如何安装 PHP,选择哪个版本,选择哪个 PHP 提供者,等等。在某些情况下,这可能变得相当复杂。
在几乎所有商业场景中,我们部署的大多数软件将是二进制格式。通常,我们甚至可能不知道(或不关心)特定的软件,因为整个过程通常会由其他人处理。盲目安装软件的情况非常常见。
系统管理员安装由脚本构成的软件的情况越来越常见,这些脚本是可以直接读取的代码。这些文件只是由解释器处理。因此,软件从未以二进制形式存在于磁盘上。由于现代计算机系统如此强大,尽管这一过程在效率上似乎存在问题,但通常并不成问题。现在,许多流行的软件包都是以这种方式编写和交付的,因此大多数系统管理员通常会与脚本安装打交道。
在许多情况下,脚本的安装与二进制软件包使用相同的自动化方法,这使得整个过程通常对管理员透明。作为系统管理员,你可能并不总是知道自己正在部署的是什么类型的软件包,除非你深入其底层组件。这种情况在非关键软件包中尤为明显,尤其是使用依赖解决系统部署的软件包(例如 PHP 或 Python),它们为你处理了平台的集成,或者这些依赖项已经为其他组件提前安装好了。
今天,我们预期脚本的安装将成为一项常见的任务,这可能不会代表部署到系统上的大多数软件包,但它很容易构成系统上主要的工作负载代码。我的意思是,操作系统、支持工具和大型系统库通常是二进制软件包。但最终的工作负载,系统之所以存在,往往有很大可能是脚本,而非编译后的二进制文件。
最后,最后一种类型是不能直接运行的源代码,必须先编译成二进制软件包才能运行。我们将在接下来的两个部分中深入讨论这个主题,因此这里只会简单提及。你可以争辩说,这种方法仍然是二进制安装,因为最终部署的软件包是二进制的,这完全正确。然而,为了获取和部署这个二进制文件,必须遵循的工作流程截然不同,因此这成为了一种有效的三级部署选项。一些系统会自动执行编译步骤,因此有可能出现一个部署包,它在编译并安装二进制文件的同时,系统管理员甚至都没有察觉。
误导性的源代码安装使用
由于我们稍后将在本章深入讨论的原因,从源代码安装软件通常会有不好的声誉。在某些方面,这是应得的,而在某些方面,又并非如此。
因为源代码安装在实际上是自由和开源软件世界的独特存在,它在 1990 年代和 2000 年代时遭到厂商和 IT 从业人员的猛烈攻击,目的是为了抹黑它,因为它严重影响了传统的闭源产品(以及那些只支持闭源软件的人的工作)。这当然是完全虚构的,但由于源代码授权复杂难懂,很容易让那些没有掌握该话题细微差别的人产生恐惧和怀疑。
然而,更重要的是,源代码安装被贴上了不专业且不必要的标签,原因是它被认为是由一些更像爱好者的系统管理员推动的,他们在没有真正考虑业务需求的情况下以这种方式安装。它有趣,或者看起来很有印象,或者是他们的朋友这么做,所以他们也这么做。我很遗憾地说,这种说法在很大程度上是准确的。曾经有一段时期,许多软件以不必要的复杂和繁琐方式安装,而不考虑这一过程对业务的有效性。并不是说源代码编译没有其存在的价值,它确实有。但即使在二十年前或更久,这种方式也只是局限在一个小众的场景中,而不是大多数的部署情况。因此,从很多方面来看,这个坏名声是实至名归的,但并非完全如此。
然而,今天,源代码编译几乎被遗忘,几乎没有人知道如何使用标准流程来进行编译,并且相关工具的安装通常被禁止,或者这些工具并不容易获得,使得编译变得非常困难,甚至不可能。只有那些需要编译的强烈需求的软件才会以这种方式分发。因此,市场实际上几乎消除了这种做法。
但是,那些曾经进行编译的人仍然面临着恐惧和羞辱。说某人正在进行源代码安装,依然是一种贬低的说法。遗憾的是,为了进一步抹黑现今的软件,现在已经普遍将这个术语用于指代那些不需要通过源代码编译成二进制的脚本类软件。术语“源代码”暗示代码必须从源代码转化为二进制,而脚本在这个上下文中并不被认为是源代码。然而,从技术上来说,它们确实是原始代码、源代码,但不再有那个令人不悦的步骤。可是很少有人会进一步探讨这个问题,而这一小小的语言技巧很容易误导他人。所以,这成为了一种简单的手段,能够让一个仅仅寻求借口来做情绪决策的经理,被误导。这听起来很合理,而很少有人会真的去深思。
这个窍门实际上来自于语义简写,这是一个总是危险的东西,尤其是在 IT 领域。自编译软件的问题与源代码的可用性无关,而是与在使用之前需要编译它有关。如果没有这个步骤,源代码的存在对我们来说完全是积极的。人们随后错误地将编译过程称为源代码安装。这种语义错误为某些人打开了大门,他们将某个技术上确实是源代码安装的软件(没有编译)误解为安装源代码,而由于这个术语长时间被错误使用,它变成了一种负面的含义,应用到错误的事物上,最终没有人理解为什么这些东西是错的或反向的。
Linux 为我们提供了许多标准的企业级软件部署方法。尽管这些选项功能强大,但也使得标准化和长期支持的规划变得更加困难。
在所有生产环境中的 Linux 系统中,无论供应商如何,默认都会存在一个软件包管理系统。多年来,这些软件包管理系统已成为区分不同 Linux 操作系统的关键因素。存在多种软件打包格式,但其中两种,即 DEB 和 RPM,已经成为主流,其他格式则保持在非常小众的地位。
现在越来越多的 Linux 发行版要么有多个软件打包系统,要么在单一的软件包管理系统下使用多种格式。这种多样性是好的,因为它给我们提供了更多的选择来维护系统中的特定包,但也意味着更多的复杂性。
与所有软件部署一样,我们有一些对所有操作系统普遍适用的标准关注点。首先是软件是否自包含,或者是否需要访问其他包或库。传统上,大多数软件,尤其是在 Linux 和其他类 UNIX 操作系统上,都是通过利用扩展的系统和第三方库(统称为依赖关系)来减少其安装大小以及操作系统本身的大小。这意味着我们可以拥有尽可能小的软件,并且使用相同资源的其他软件可以共享它们在磁盘上的存储,从而最小化(有时显著地)我们需要存储和维护的内容。更新一个软件包或库时,所有使用该包的程序都会同步更新。另一种方式是让每个独立的软件包都携带自己的所有依赖项,并且这些依赖项仅在该软件包内可用。这会导致软件安装变得更大,并且可能会在系统中存在多次相同的数据。可能是很多次。这导致了臃肿,但也使得单个软件包更容易维护,因为不同软件组件之间的互动较少。
举个例子,数十个或更多的软件包可能都需要使用 OpenSSL 库。如果每二十个包中都有 OpenSSL,我们将把相同的代码存储在磁盘上二十次。此外,如果 OpenSSL 发布了更新,或者更重要的是,如果发现了漏洞需要修补,我们就必须修补二十次,而不是一次。相比之下,如果我们使用一个共享的 OpenSSL 库,无论我们有一个应用依赖它还是一百个应用,我们只需修补这个库,确保所有的漏洞或更新都已解决。
这两种方法都是完全有效的。过去,由于系统存储空间较小,共享库是一种“必要的恶魔”,因为共享资源不仅能减少磁盘使用,还能更好地优化内存,因为共享库有可能被加载到内存中,并且能被多个软件共享。如今,我们通常拥有更多的存储和内存,远超实际需求,这种小规模的效率优化已经不再必要,尽管它可能仍然有些许好处。非共享方法则将这种效率转化为每个软件包拥有自己的依赖项,从而避免了依赖冲突或共享资源不可用时带来的问题。
共享资源方法的最大优势可能在于,修补已知漏洞可能会更简单。举个例子,如果我们假设 OpenSSL(一个广泛共享的库)发现了一个关键漏洞并发布了更新。如果我们的系统使用共享资源,我们只需要找到安装了 OpenSSL 的系统并更新该包。所有依赖该包的系统都会自动一起修补。如果 OpenSSL 被单独打包并与数十个不同的应用程序一起使用,我们就需要找到这些应用程序中的每一个,确认它们都在使用 OpenSSL,并且要单独修补它们。这将是一个可能令人生畏的任务。我们依赖每个软件的包维护者进行适当的审查,快速修补依赖项,并立即提供更新的包给我们,但这并不是常有的事。
系统通常会使用一种包管理和软件仓库系统,如 DEB,当存在共享系统组件和需要处理许多依赖项时。它们会在将所有依赖项包含在最终包中时使用另一种包管理系统,如 SNAP。但这远比听起来复杂,例如,制作一个包含所有依赖项的 DEB 包,或者一个期望依赖项由外部提供并共享的包。DEB 通常作为软件包的共享库只是一种约定。在 Linux 中,我们还面临着一组完全不同的关注点,如果你来自 Windows 或 macOS 背景,可能并不习惯:一个与操作系统本身紧密相连的软件生态系统。在 Linux 中,我们期望操作系统(例如 RHEL、Ubuntu、Fedora、SUSE Tumbleweed 等)不仅包含基本的操作系统功能和一些极为基础的实用工具,还包括几乎所有可能描述的软件,包括核心库、编程语言、数据库、Web 服务器、终端用户应用程序等等。在很多情况下,你可能永远不会使用任何没有与你的 Linux 发行版一起打包的软件,当你添加第三方软件时,它通常是一个关键应用程序,代表着战略性业务应用,或者显而易见,是内部定制开发的软件。
因此,在 Linux 上处理软件时,我们必须考虑是使用内置操作系统的软件,独立获取并安装的软件(这包括定制软件),还是两者的混合,其中软件的许多组件来自操作系统,但一些组件由其他方式提供。
深入了解不同打包系统的具体细节没有太大意义,特别是因为它们在一般使用上往往有很大的重叠,但在实际使用中又非常独特。现在我们已经知道了它们存在的选择。软件包管理系统在 Linux 中比在其他操作系统中更为重要,如 Windows 或 macOS,因为在 Linux 运行的大型服务器系统中,通常存在更多的复杂性,而安装的软件通常使用更广泛的依赖集,从许多不同项目中拉取组件或支持库。Linux 打包系统维护在线软件、库、组件等的仓库,使这一切成为可能。
大型 Linux 软件包管理系统及其相关软件仓库最重要的方面可能是它们允许分发商在其精确的内核和组件选择与配置下,组装并测试大量的组合软件,从而提供一个庞大、可靠的平台来部署解决方案。
在这里,最佳实践是困难的。事实上,我们只能依赖经验法则,但这些法则非常强大。经验法则是尽可能使用供应商的仓库进行软件部署。这个方法看似简单和显而易见,但出乎意料的是,仍然有很多人会通过手动方式获取软件并安装,而没有供应商的测试和依赖管理的支持。
真正的最佳实践,正如你可能预期的那样,是深入了解你所选发行版的包管理生态系统,以便你能够充分利用其特性。这些特性通常包括日志记录、版本控制、回滚、补丁和系统更新自动化、校验和、自动配置等。
软件组件越常见和基础,越有可能由供应商作为分发的一部分提供。越是小众且接近业务核心,越有可能通过手动安装或非标准过程来安装它,因为最终用户产品不太可能被包含在供应商的软件仓库中,更有可能需要仔细管理版本和更新计划,而不仅仅是关注与系统其他部分的稳定性和测试。
软件供应商通常会为那些不包含在分发仓库中的产品创建和维护自己的仓库,允许你配置其仓库,仍然通过标准工具管理所有安装和补丁任务。
软件部署包含了许多特殊情况。人们很容易想要提供标准、明确的总是这样做的指导,但软件的工作方式并非如此。学习你系统的工具,能用时使用它们,为每个需要部署的工作负载准备做一些独特的工作或学习某些东西。有些,比如 WordPress,可能会变得非常标准,以至于你只需要使用发行版自带的软件包即可。其他软件可能会非常独特,你可能只需要部署一个基本的操作系统,下载供应商的安装程序,它会安装所需的所有软件,甚至可能会编译它!这一切都取决于情况,最重要的是,它取决于软件供应商如何构建和打包软件,以及你的发行版是否决定将该软件包包含在操作系统中,或是否需要单独安装。
现在我们已经了解了软件安装过程和相关注意事项,我们可以深入探讨关于补丁和更新的核心问题。
补丁理论和策略
有人可能认为打补丁是非常直接的事情,不会有太多可讨论的内容。但实际上并非如此。如果你与几个系统管理员交谈,你肯定会得到一些相当不同的看法。有些人每天打补丁,有些人每周打补丁,有些人会尽量等到最后才打补丁,还有些人则是随机进行补丁操作,甚至有些人认为根本不应该打补丁(嘿,如果它没坏,为什么要修呢!)
我们应该首先明确为什么要给软件打补丁。打补丁不同于更新或升级,它意味着我们对软件进行小范围的修复,以解决已知问题或漏洞,而不是实施新功能或特性。添加新功能通常被视为一次更新。
大多数软件供应商和操作系统供应商遵循这一系统,并维持仅在版本之间解决安全性或稳定性问题的补丁系统。在 Linux 生态系统中,这主要与操作系统的发布版本相关。例如,如果你使用的是 Ubuntu 22.04,并且通过其自身的补丁机制来修补随发行版一起提供的软件,那么你将仅获得现有软件版本的安全性和稳定性修复,而不会得到新版本、特性或功能。其逻辑在于,升级到新版本可能会导致软件出现问题、改变可用性,或使依赖该软件的其他产品失败。
升级到新版本通常只在操作系统本身发布新版本时发生,这时操作系统和所有其中的包可以同时升级。这样,操作系统供应商理论上可以将软件作为一个整体进行测试,以便让客户(你)确信,即使在将所有软件升级到新版本之后,所有的软件组件仍然能够协同工作。
因此,我们假设如果补丁已经提供给我们,这意味着供应商(很可能与我们的分发供应商合作)已经发现了需要修复的问题,已经创建了修复方案,进行了测试,现在正在分发补丁。然而,即使经过测试,众多目光监督错误,并且目标只是修复已知漏洞,事情仍然可能出错。补丁本身可能有问题,打补丁的过程也可能遇到意外的麻烦。这意味着,无论提供补丁的人有多么良好的意图,我们都必须对打补丁保持谨慎。
在打补丁时,我们面临着两个相互对立的担忧。一方面,如果系统当前对我们来说是正常工作的,为什么在没有必要的情况下还要引入补丁过程的风险(和工作量)呢?另一方面,既然补丁已经提供给我们,为什么还要继续运行一个存在已知漏洞的系统?我们必须权衡这些问题,选择一个合理的行动方案。
风险规避并不是这里的关键问题,我们并不是在权衡成本与风险,而是在面对两种几乎相等的行动方案(从努力和成本的角度来看),但它们会带来截然不同的结果。我们需要选择一个能够最大限度降低业务风险的方案,仅此而已。最重要的不是我们有多么规避风险,而是我们的风险特征是什么。如果我们的业务非常容易受到小规模停机事件的影响,那么可能会优先考虑推迟修补。如果我们公司拥有高度敏感的数据,这些数据可能成为攻击目标,或者我们非常关注在发生数据泄露时的公关危机,那么我们可能会采取非常积极的修补策略。为了做出明智的决定,我们必须了解每种方案是如何产生和缓解不同风险的,以及这些风险如何影响我们特定的组织。
推迟修补的风险
单纯推迟修补并不能消除某些类型的风险。虽然这可能带来一定的好处,但也可能根据情况引入更多的风险。通常情况下,新的修补程序会频繁发布,可能一天发布多次,至少也会每月发布几次。
如果我们经常修补,比如每周一次,那么理论上我们通常只需处理极少的修补程序,在任何给定时刻,任何故障或不兼容问题都相对容易识别和回滚,因为需要处理的修补程序很少。
如果我们在一段时间内积累修补程序,并且只在比如说一年一次时修补,那么我们会面临一些问题。首先,修补过程可能需要相当长的时间,因为可能需要许多修补程序。其次,如果出现故障,可能很难找出导致问题的修补程序,因为它可能会被一大堆需要部署的修补程序所掩盖。第三,一次性进行的大量更改以及与任何经过测试的场景的偏离(几乎没有供应商会针对像你这样具体过时的系统进行测试,并与大量突如其来的更改进行对比)意味着修补过程引发故障的几率更大。
因此,推迟修补在许多情况下会成为一种自我实现的预言,那些因为修补会破坏东西而避免修补的人,往往会看到这一点发生,因为他们创造了一个更容易发生的局面。
没有一刀切的方案。每个组织都必须根据自身需求定制修补流程。有些组织会通过构建无状态系统并简单地部署已经修补过的新系统,销毁旧的未修补实例,从而完全避免修补问题。但并不是每个工作负载都可以采用这种方式,也不是每个组织都有能力进行这种基础设施的跃迁,以支持这种流程。
一些组织会进行持续的补丁测试,查看补丁在其环境中的表现。一些组织完全避免打补丁,抱着侥幸心理,期望最好。一些则盲目地打补丁。我们将讨论这些不同的选择。
因为 Windows 而避免打补丁
最近几年,系统管理员中出现了一种避免打补丁的文化。考虑到打补丁在一般情况下的重要性,以及它对我们职业生涯的核心作用,这似乎有些反直觉。没有人比系统管理员更支持快速、定期打补丁。
在 Windows 世界中,打补丁的过程与 Linux 或其他操作系统截然不同。它通常是延迟的、保密的、缓慢的、不可靠的,最糟糕的是,常常存在漏洞和错误。Windows 的打补丁问题一直存在,但在 2010 年代变得如此严重,以至于它不再是确定性的,远远比直接部署新系统要花更长时间,而且经常失败。
Windows 打补丁失败可能意味着几乎任何情况,从补丁安装失败,需要投入资源使其正常运行,到导致软件故障,无法再继续使用。一些补丁可能需要耗费数小时来运行,但最终失败,然后又需要花费数小时回滚!
正因为如此,Windows 领域的系统管理员通常对补丁保持谨慎态度,甚至完全避免打补丁,几乎成为了一种普遍现象。这种现象不仅限于补丁,还扩展到系统版本更新。因此,现在发现许多 Windows 系统已经多年甚至十年未更新,已成为常态,导致整个生态系统中越来越多的安全漏洞。
微软的回应不是修复打补丁的问题,而是试图强行进行未经授权的打补丁,并且通过模糊补丁过程,制造了更多的可靠性问题,甚至在许多情况下,打补丁管理系统发生了严重故障,以至于即使是那些希望保持完全更新的管理员,常常也不确定如何操作,或者根本无法做到这一点。
这些问题今天是微软特有的,并且大多数是现代时代微软所独有的。我们不能让对这种独特糟糕情况的情绪反应影响我们在 Linux 或其他领域的实践,这些领域并未受到微软的影响。在微软孤立的行业领域之外,没有其他生态系统经历过类似的问题。无论是在 Ubuntu、Red Hat、Fedora、SUSE、IBM AIX、Oracle Solaris、FreeBSD、NetBSD、DragonFly BSD、macOS、Apple iOS、Android、Chromebook 等,都没有出现过这种情况。打补丁总是存在风险,我们应该意识到这一点,但微软的问题是独一无二的,与我们在其他行业的实践无关。
补丁可以是自动化的,也可以是手动的。两种方法都完全可以接受。自动化需要更少的努力,并且可以防止忘记补丁或降低其优先级。在大组织中,要求手动干预的正式补丁程序可能很简单,以确保一致性,但在只有几个服务器的小型组织中,补丁可能很容易被忽视,甚至几个月都没有进行。当考虑手动与自动化补丁时,只需要考虑流程的潜在可靠性和涉及的人力成本(通常是时间)。
手动补丁的好处在于,你可以让人类在每个补丁安装时检查每个包,并在补丁进行时实时测试系统。如果出现问题,补丁过程中的每个细节都会历历在目,因为他们刚刚执行过,而且他们知道在出现问题时应该测试什么,回滚或处理什么。
自动化的好处在于它可以自动发生,可能在非常可预测的时间内,并且即使没有人类在场工作,它也能发生。将自动化补丁安排在晚上、过夜、周末或节假日进行,可以最大限度地减少对人类的影响,同时加速补丁过程。自动化补丁不太可能被遗漏,而且在补丁发生时或出现问题时,容易发送警报。
在大多数情况下,自动化补丁比手动补丁更受欢迎,因为它成本更低,几乎所有手动的好处都可以以某种形式自动化,比如通过让人类待命,以便在出现问题时接收警报。
测试补丁很少是可行的
每个人都在谈论测试补丁的重要性。系统管理员常常要求这样做,并且尝试拒绝应用补丁,直到能够完成测试(这是避免完全补丁系统的一个方便方式)。如果补丁出现问题,管理层几乎总是要求了解为什么之前没有进行补丁测试。
这里有一个残酷的现实:没有任何实际可行的手段可以在任何规模上测试补丁。说到这,我说出来了。大声说出来,去告诉你的老板们。测试补丁的成本,无论是时间还是金钱,都远远大于任何人所认为的。为了彻底测试补丁,我们需要一个复制的环境,这样才能给我们提供一个与生产环境相同的镜像,以便我们能够对要部署的补丁进行测试,涉及的软件、硬件和配置。如果试图简化这一过程,是行不通的,因为正是所有这些部分的相互作用使得测试变得重要。如果你改变了任何东西,可能会完全抵消这一非常昂贵过程的好处(或者更糟糕的是,产生一种虚假的安全感)。
在真实的环境中,每个系统基本上都是独一无二的。虽然有例外,但通常情况下,这是真的。有许多可能的变量,包括硬件制造日期、不同的零部件、固件版本,以及更高层次的基础设施堆栈(即,接近最终应用的代码和组件)。今天的计算机系统如此复杂,可能有数百万种变量,导致补丁中的某个 bug 被触发。
这就是虚拟化如此重要的原因之一,它创造了一个标准化的中间层,使得系统中一些更复杂的部分能够标准化。这样,至少有一部分,涉及许多驱动程序的复杂部分,可以简化复杂性。
很少有组织会进行真正的补丁测试。这样做的成本很高。通常,这涉及到仔细复制整个生产环境,包括匹配硬件版本、固件修订、补丁历史等。每个可能的方面都应该是相同的。补丁必须通过一系列快速的测试,以测试公司范围内的各种场景中的给定补丁。
在实际操作中,这意味着要复制所有硬件和软件,并且需要有一个专门的团队进行补丁测试。很少有公司能承担这样的费用,能证明这种做法带来的一点点潜在保护的公司就更少了。
补丁的及时性
补丁工作是一项通常需要非常迅速完成的活动,随着行业的成熟,快速补丁的重要性持续增加。我们这些在 1990 年代及之前接受过训练的人,通常记得那个时候补丁几乎没有时间敏感性,因为大多数计算机都是离线的,补丁几乎完全是为了稳定性问题,如果你没有遇到过问题,那就不太可能遇到。所以,等待几个月或几年再给系统打补丁(如果你做了的话),通常并不是一件大事。
哦,时代变化多么迅速。今天,软件变得更加庞大和动态,层级之间的相互关联也更多,而且除了最罕见的计算机系统,几乎所有系统都连接到互联网,并且始终可能面临活跃的安全威胁和动态变化的环境。关于补丁的所有事宜,在过去二十年中发生了翻天覆地的变化,尽管大部分重大变化在 2001 年左右就已经发生了。
今天,修补工作往往主要集中在弥补最近发现的安全漏洞,每一步都在急忙将补丁推向市场,以防坏人发现漏洞并加以利用。恶意行为者知道,对于任何漏洞,补丁都会很快发布,因此漏洞利用完全是关于速度。在某些情况下,正是补丁的发布本身提醒了更广泛的社区漏洞的存在,因此发布补丁的行为触发了每个人都必须应用该补丁的紧迫需求,而这在几个小时前是完全不必要的。
因此,快速修补漏洞极为重要。基于漏洞修补的攻击很可能已经在发生,并且会在即将消失的漏洞最后一刻加剧,或者会在一个之前未知的漏洞成为公开知识后迅速开始。对许多人来说,这意味着我们希望将修补工作以小时而非天数来考虑。我们仍然需要考虑在生产时间内可能发生的潜在稳定性风险或影响,因此立即修补通常不是一种选择,但在合理的情况下,当然是可能的。
在 Linux 中,由于修补一般既快速又简便,且几乎总是可靠的,因此在某些情况下,可以考虑在生产日内进行修补,在大多数其他情况下进行每日修补。可能的智能方法包括使用内置的随机生成器,每四到八小时随机修补(为了减轻系统负载),或者每天晚上十点或其他合适的时间进行计划性修补。
在极端环境下,按周进行修补是可行的,这在一到二十年前的企业中很流行。如今,等待长达六天来修补已知漏洞几乎是鲁莽的,应该小心进行。六天在暴露系统漏洞的世界里是非常长的一段时间。
时间框架的选择通常基于工作负载模式。一些工作负载,如电子邮件或库存控制系统,可能对短暂的中断不太敏感,可以快速回滚或切换。因此,在一天中午间进行修补可能是合理的。大多数公司都有一天内周期性的工作负载模式,可以预测某个应用程序在凌晨一到两点使用非常少,或者也许到晚上七点每个用户都已注销,甚至十小时的停机也不会被人察觉。
无论是否存在日内模式,我们几乎总是会看到按周计算的日间模式。某些工作负载可能在周末较轻,而在工作日较重,反之亦然。有时,尤其是在金融应用程序中,模式更加偏向月度,通常月初的负载较重,而月中较轻。
每个工作负载通常需要评估,以了解何时进行补丁是合理且可行的。有时我们必须在时间安排上富有创意,以便在工作负载允许时进行补丁。如果工作负载无法中断进行补丁,那么它们也不能经历其他更不计划的停机事件,我们应该有一个连续性计划,允许我们在发生任何问题时进行补丁、修复或故障切换。在大多数情况下,我们可以通过这些方法进行零影响的补丁操作。
过去那种认为补丁可以作为一个特殊的每月活动来保存,或者只有在识别到组织的特定需求时才进行补丁的想法,已经不再现实。等待这么长时间会使系统处于危险暴露之中,任何声称每月只有一次补丁机会的工作负载都应该质疑,怎么会有既重要又无法进行补丁的工作负载。从概念上讲,这两者是无法并存的。工作负载越重要,及时进行补丁就越重要。
一个常见的缓慢补丁流程的借口是,补丁发布前需要进行测试。表面上看,这有道理,听起来也合情合理。你可能能将这个想法卖给非技术管理层。想要测试补丁本身没有问题。但我们必须考虑到,我们已经在支付(或免费获得)分发供应商来测试补丁,等我们收到补丁时。那些企业级操作系统供应商(如 Canonical、IBM、SUSE 等)拥有比任何但最大规模的组织更多的技能、经验和资源来测试补丁。如果我们的测试没有为我们已经依赖的广泛测试增加什么重要的内容,那么我们自己的内部测试过程应该避免,以免浪费资源并让组织面临不必要的风险,延误可能至关重要的补丁部署。
如果保持足够轻量并且绝不作为推迟及时补丁更新的借口,快速而轻量的测试是合理的。一种常见的有用补丁测试方法是,选取几个代表你组织中典型工作负载环境的系统,运行演示工作负载,在补丁发布之前先对每个补丁进行测试,以便观察安装成功并在最高级别进行测试。这可以在小型组织中仅仅是一台虚拟机。考虑是否有任何测试是有价值的,如果有的话,尽量保持测试轻量化,以确保生产环境中的补丁更新尽可能迅速地完成,前提是满足工作负载的需求。
标准的补丁策略通常会建议你先从高风险的工作负载开始,或者从低优先级的工作负载开始,专注于修复漏洞,或者使用低优先级工作负载作为测试对象,为更关键的工作负载做准备。如果你的环境中有一百台虚拟机需要补丁,你大概可以安排一个时间表,首先补丁那些不那么关键的系统,随着对补丁流程信心的逐步建立,慢慢接触更多关键或脆弱的工作负载。
把补丁管理看作是系统管理员最重要且简单的任务之一。不要让情绪或那些不了解补丁管理(或受 Windows 管理员影响)的企业或系统管理员的非理性建议将你引偏。补丁管理是至关重要的,任何不支持补丁管理流程的组织管理层都不了解该过程的风险与回报,我们需要准备好向他们解释这一点。
找到一个满足你所在组织需求的补丁管理流程。你不需要按照固定的时间表进行补丁更新,也不需要按照其他组织的方式进行补丁管理。找到适合你的测试方法以及手动或自动补丁流程,以确保你的系统在不对组织造成过度影响的情况下保持更新。
到现在为止,我们应该对补丁的概念有一个相当扎实的理解,你可能甚至已经感到一种紧迫感,想去检查一下你当前的服务器,看看它们最近是否有更新。这是可以理解的,如果你现在想查看一下它们,在继续之前,我愿意等你。安全总比后悔好。等你回来后,我们将讨论软件编译,并将该过程与补丁管理联系起来。
管理员的编译工作
还不久前,主要的系统管理员指南中包括了一项要求,即任何中级或高级管理员都必须熟悉标准软件编译过程的细节。当然,所有的知识都是有价值的,我们绝不会说不应该学习这些内容。然而,即使在当时,这也显得像是一种奇怪的幕后开发知识以及关于单个软件解决方案打包的知识,居然被期望由一个非开发角色的人来掌握。
这就像是从你最喜欢的汽车公司订购一辆新车时,要求它以零件的形式交付,并且每个潜在的新车主都需要在驾驶之前自己组装汽车一样。值得注意的是,这一过程仅在开源世界中才可能实现,而且除了 Linux 领域,大多数软件甚至 Linux 领域中的一部分软件根本无法由系统管理员进行编译。因此,整个这一要求的概念几乎只适用于一种非常特定的情况,并且在系统管理的广泛意义上并不适用,仅这一点就应当成为那些将其作为教育和认证标准的组织的一个严重警示。
作为系统管理员,要求我们从开发者那里获取源代码并进行定制编译,使用我们提供的编译器在我们自己的环境中进行编译,这几乎是荒谬的。在 Windows 环境中,这几乎是不可能的,谁会有权限访问合适的编译器或任何必要的工具呢?在 Linux 和 BSD 系统中,这通常是可行的,因为编译器或多个编译器可能已经包含在基础操作系统中。
曾经,目标系统上的编译有其价值。通常,通用编译的软件由于需要支持几乎任何潜在的硬件,效率往往较低,而通过在目标上编译,我们可以充分发挥非常特定硬件组合的每一点性能。然而,这也是一个由于 CPU 性能有限而导致编译时间很长的时代,这意味着系统的安装可能需要几天,而不是几分钟。软件部署是一个漫长、复杂且容易出错的任务。在现代世界,浪费时间和资源来编译大部分软件几乎是不可想象的。当我们可以在短短几分钟内部署整个服务器群,并且使用极少的系统资源时,仅仅为了完成相同任务而占用大量 CPU 周期并花费几个小时,从资源角度来看,这完全没有意义。
然而,编译带来的风险远不止浪费时间和系统资源。它还意味着,我们可能会在不同的系统上得到略有不同的结果,或者在不同的部署时间、我们测试过的系统上,甚至更重要的是,在供应商已经测试过的系统上。正如之前所讨论的,面对补丁测试场景的挑战时,编译使得测试变得更加困难。同样,补丁也变得更加难以应用。
一些软件今天需要进行编译以便部署,通常是那些依赖特定硬件驱动的桌面软件。这类软件通常出现在桌面端,而不是服务器上。并不意味着我们永远不会遇到它,但它应该是相当罕见的。从技术上讲,自行编译软件并不错误,但只有在绝对必要并且具有非常必要的目的时才应该这么做。它不应当是随意进行的,今天的系统管理员没有必要了解编译过程。
现在有一些新的额外因素出现,使得将编译作为一个标准过程变得不太可能。二十年前,Linux 生态系统中只有一个主要的编译器,大家都假设所有以代码形式部署的软件都会用 C 语言编写,并且由开发团队针对那个编译器进行测试。当时有一个非常标准的工具链,大家普遍认为它就是所需的工具链,而且几乎总是正确的。如今,不仅有多个标准编译器在不同的项目中使用,且各项目为了测试使用不同的编译器,还有一些常用的编译语言,它们也有自己独立的编译器和工具链。
编译从来都不是一个单一的标准过程,尽管曾经有这种暗示。然而,传统上它几乎就是一个标准过程。如今,正如之前提到的原因,编译已经变成了一个分散的过程。除此之外,许多需要最终用户进行编译的项目现在已经内建了一个编译过程,使得它更像是一个独立的部署工具,而不需要系统管理员了解编译过程,甚至不需要意识到所部署的软件正在进行编译!这个世界几乎在每个方面都发生了变化。
在现实世界中,我曾在成千上万台服务器上工作,跨越数千个客户,并且已经有超过十七年没有见过任何组织使用假定的标准编译过程了。即使在十七年前,编译过程也极为罕见,可以忽略不计,而且通常在系统管理员将业务视为个人爱好而非严肃事业时,才会在可疑的情况下使用。
编译时代
在 Linux 的早期,能够自己编译软件通常是一个重要特性,相比于封闭源代码系统,如 Windows 和 Netware,这些系统的编译器并不是免费的,且操作系统代码也无法获取。这意味着可以在不同的架构之间轻松迁移,而当时系统资源是宝贵的,因此通过定制编译获得的微小性能优势,有时意味着软件性能的真正差异。系统管理员曾经非常热衷于编译器标志和版本。
这种趋势非常显著,以至于整个操作系统的发布都围绕这一概念进行。最著名的例子是 Gentoo Linux,它每次部署时都要重新定制编译整个操作系统。这常常导致人们讨论安装完整操作系统需要多少天。初始安装的投资非常庞大。
在 1990 年代,操作系统的安装常常需要花费多天时间。我们很少使用虚拟化技术,因此安装通常是从物理介质到独特硬件的安装,即使一切顺利,这个过程也非常耗时,而且经常会遇到安装故障,导致需要多次尝试安装。在那个环境下,花时间编译软件,甚至是整个操作系统,也不像今天这样疯狂。但是放心,这样做也并不是完全理智的。
与由于资源限制而使编译有意义的那个时代相重合的,是互联网前的办公室世界和初步的互联网世界,那时环境威胁,特别是试图利用未打补丁的计算机的威胁,还是比较罕见的。当然,计算机病毒是存在的,且广为人知,但通过不在系统之间共享物理介质来避免它们,能在良好管理的情况下大大减少感染的可能性。因此,大多数时候,定制编译软件的打补丁问题并不构成困扰。这是设置并忘记软件的时代。编译过的软件更可能被遗忘,而不是被维护。安装过程的努力使得打补丁的潜在工作量巨大且风险极高。当你自己编译代码时,很多事情可能出错,最终导致你没有一个可用的系统。
过去,CPU 和 RAM 资源在大多数系统上都非常紧张,通常情况下,能够多等几天才能将系统投入生产是值得的,即使只是为了获得额外的百分之一的性能提升。往往被忽视的是,若编译初始安装需要消耗那么多时间和资源,那么未来编译补丁或更新时,可能需要相同甚至更多的资源。这带来了巨大的风险,通常会导致完全没有补丁更新,因为一旦系统部署完成,几乎没有办法停机几个小时或几天进行编译步骤,希望能更新系统。
在信息技术领域,常常有一种强烈的愿望,想要建立一座纸牌屋,并希望当它倒塌时,足够远的时间可以让它变成别人的问题。遗憾的是,这种做法逐渐成为一种可行的策略,因为公司很少将失败与造成失败的人联系起来,而是常常随机地责怪身边的任何人。正因为如此,创造风险情况通常是有利的,因为任何收益都会归功于实施者,而任何灾难则会在稍后随机归咎于某人。
现代的系统管理员仍然应该学习传统的软件编译方法,哪怕只是为了理解历史背景,并为可能出现的任何异常情况做好准备。但今天(以及多年来),将编译自己的软件作为标准流程应当避免,作为经验法则,这根本不是一种资源的好利用方式,而且会引入太多风险而没有实际的好处。
现在进行编译时,不能再像过去那样盲目地遵循通用过程了。过去那种保护了许多仅仅凭运气的管理员的惯例,如今已经不再适用。今天要进行软件编译,我们需要开发者的指导和指引,才能有任何希望了解需要哪些工具、配置、库、语言和外部包,以及如何使编译过程正常工作。这里有太多潜在的可变因素,所有这些知识都是开发者的知识,而不是 IT 知识,更不用说系统管理员的知识了。系统管理员需要掌握并深入理解的信息非常庞大,是技术领域中最广泛、最具挑战性的领域之一。让系统管理员深入学习一个完全不同领域的知识和技能,从来没有任何意义。如果所有的系统管理员都能同时完成这些工作,那开发者为什么还要存在呢?软件工程是一个庞大的领域,需要深厚的知识才能做得好;暗示一个完全不同的学科能轻松地担任开发者角色,而不需要同样的多年训练和全职投入,这不仅荒谬,而且对开发者极为侮辱。
工程部门编译
我们应该提到一个中间方法,它是合理的。那就是有一个工程小组,从开发者(通常是内部定制团队或开源项目)那里获取源代码,并进行内部编译,可能是为了额外的安全步骤,或者极端的性能调优,亦或是因为该软件需要特殊的编译方式,比如与内核版本或驱动程序相关联时。
通过设立一个中心小组,负责将源代码内部编译并打包成最终的二进制文件供系统管理员团队使用,可以让系统管理过程专注于标准化、可重复且快速部署的二进制机制,同时组织还可以享受定制化编译的优势。
这种方法通常只适用于能够维持快速软件打包工作流的大型组织,以便补丁、测试和定制化几乎能像由软件供应商直接完成一样迅速。在大规模环境下,这种方法可以带来好处。
这一过程之所以有效,是因为它避免将软件编译和打包交给管理员处理,而管理员在这方面会遇到很多麻烦和问题。
最佳实践是在需要时才编译软件,而不是随意进行编译,除非你有一个能够快速可靠地处理已编译软件打包的部门,且其速度足以满足适当的补丁管理需求,同时执行这项工作所产生的开销能通过规模效益得到弥补。
编译是有用的知识,但仅仅因为你能编译软件,并不意味着你应该。将这个技能保留在你的后备知识中,只有在真正需要时,或者当软件供应商指示你这么做时再使用。接下来,我们将讨论如何部署我们的 Linux 发行版本身,甚至更重要的是,在灾难发生后,如何重新部署一个发行版。
Linux 部署和重新部署
如今,我们有许多潜在的方法来部署,甚至更重要的是,重新部署我们的服务器(或者工作站)。在我看来,这个话题在过去相对不重要,因为大多数公司依赖于缓慢的部署方法,它们的灾难恢复模型依赖于恢复,而不是重新部署系统。但今天有了更多现代化的灾难恢复方法,这些方法依赖于能够快速部署服务器,因此我们必须以全新的眼光来看待这个话题。
借助现代部署技术和方法,能够在几秒钟内部署一个新的基础操作系统已不再罕见,而过去,即使是高度自动化的系统,往往也需要花费许多分钟甚至小时(更不用说定制编译系统可能带来的复杂性了!)。当然,今天的计算机速度更快,这在加速部署过程中起了作用。供应商也改进了安装程序。这不仅仅是 Linux 的特色,几乎所有操作系统都如此。
即便是做最传统的基于 ISO 的安装,我们通过 DVD 镜像进行安装,或者从 USB 媒体或虚拟媒体中安装,通常也能在几分钟内从头开始手动完成操作系统的完整安装。在正常硬件上,可能需要十到十五分钟。这与近二十年前的安装方式相比,已经算是非常快速了。
在较大的环境中,传统上会使用类似响应文件的方式来加速这些安装过程,使其更加高效且可重复。这个过程通常意味着将你的安装 ISO 文件存储在网络的某个地方,存储一套安装指令文件,并在其他地方定义系统,通常会列出 MAC 地址来分配适当的配置文件。基本上就是在执行传统安装时自动化人类的响应。有效,但略显笨重。
如今,任何形式的 ISO 或类似介质的安装通常仅用于真正的手动安装,这些安装一般由非常小的公司进行(这些公司通常只构建几个服务器,而且每个服务器可能都是独一无二的)或特殊情况。旧的响应自动化方法没有错,但如今有这么多更新的选项,它已逐渐被淘汰,并继续失去作为流行安装方法的吸引力。在虚拟化之前,它在安装自动化选项很少的时代确实最为有效,且安装通常是每个物理设备一个操作系统,这使得基于 MAC 地址的管理非常有效。今天,这种方法对于平台(虚拟化管理程序)安装仍然有效,但对于操作系统安装就不那么适用了。
虚拟化的出现意味着两个大变化。首先,安装到物理服务器裸机上的虚拟化管理程序很少会进行定制,除了最基本的选项,这减少了对自动化的需求(整个安装过程也变得更小)。其次,操作系统安装现在是在非物理空间中进行的,这为更多以前无法获得的特殊安装技术打开了大门。
在虚拟空间中,我们可以继续手动安装系统,许多人仍然这样做。我们可以继续使用响应文件,尽管我知道现在没有人继续这样做,但我相信这仍然是广泛实践的,特别是因为已经有许多大规模半自动化部署系统可供使用。然而,现在我们可以轻松地使用预构建的系统镜像,从库中调用它们来实现更快的安装。采用这种方法,已经构建好的系统只是被复制或克隆来创建新系统。初始镜像可以预先配置最新的补丁和自定义包,通常可以在一分钟内完成安装;有时甚至只需要几秒钟。如果使用某些类型的存储,它的执行速度可以快到几乎瞬间完成。通过容器,我们有时可以看到新系统被初始化得如此迅速,以至于几乎察觉不到有构建过程的存在(因为从实际操作来看,根本没有)。
你选择用于部署服务器的方法并不是最重要的因素。所有这些部署方法,包括更多的选项,都有其适用的地方。我们需要考虑的是,通过你选择的过程,如何更快速且可靠地构建新的系统。当需要新的工作负载时,知道我们可以在一定的时间内构建一个新的服务器,并对其最终配置充满信心,是一件很好的事情。如果一个文档齐全的手动过程能够达到可接受的结果,那也没问题。
对于许多企业来说,快速部署的能力并不是非常重要。真正重要的是重新部署的能力。当然,对于某些类型的应用程序,例如那些非常适合云计算的应用程序,快速的初始部署是至关重要的,但这仍然是一个小众的做法,而不是常态,并且在可预见的未来仍将如此。但重新部署通常意味着某种程度的灾难已经发生,系统需要恢复功能,而在这种情况下,我们几乎总是面临着尽快将系统恢复到生产环境的压力。
因此,在我们的环境中,通常是重新部署速度,而非部署速度,才是更为重要的。然而,由于灾难恢复很少以这种方式来考虑,这一点在唯一能够现实地影响的时刻——也就是说,我们只能在初始设计和实施阶段真正解决这个问题,但通常直到为时已晚才会注意到——往往被忽视。此外,重新部署需要有信心地进行,以确保我们快速构建的内容按预期构建并按预期运行。在这些匆忙和压力下,很容易遗漏步骤、忽视过程、走捷径并犯错。
我们的系统越快、越自动化,我们就越有可能在高压环境下反复交付相同的系统。在我们制定初始部署计划时,我们应该为这种情况做准备。能够重新创建系统,而无需依赖备份和恢复机制,对于许多公司来说可能是一个游戏规则改变者,尤其是当他们常常感到被迫依赖单一方法来将系统重新上线时,而在许多情况下,可能存在更优的替代方案。我们将在未来章节中深入讨论备份时详细讲解这一点。
允许我们快速恢复的过程还可以为我们的工作流带来更大的灵活性。测试补丁、部署、配置、构建临时系统等的能力,灵活性关乎于应对未知的风险。
最佳部署实践是评估时间,以设计最适合你环境的可靠部署方法,并根据实际情况简化这个过程,以便能够在适合你环境的时间内恢复基准操作系统。
一些环境能够如此快速地构建新服务器,并为其必要的工作负载进行配置,以至于它们实际上选择在执行诸如修补、更新,甚至可能是重启等活动时,直接选择这样做!相反,它们会迅速构建并部署一个全新的虚拟机或容器,并销毁旧的虚拟机。这是一个非常有效的做法,前提是你能让这个过程为你服务。
在接下来的部分,我们将讨论在常规、频繁和计划性的条件下重启和测试环境的重要性。
重启服务器
向普通的系统管理员,甚至是对技术感兴趣的非技术人员询问,他们会告诉你服务器长时间正常运行的重要性,以及他们希望看到这些超高的重启后的时间。这似乎很自然,几乎每个人都会为此自豪。我的服务器三年都不需要重启!
然而,这背后有两个关键问题。
第一个问题是,重启后的时间本身没有商业价值,而商业价值决定了 IT 价值。那么,为什么我们要在乎,甚至吹嘘某件没有价值的事情呢?知道一个系统在线多久或许很有趣,但投资者并不会因为计算机系统在长时间内没有重启而获得回报。我们为的是业务的好处,如果我们开始关注除了最终业务价值之外的事情,那我们就迷失了方向。这种情况发生在我们关注手段而非目的时,服务器的正常运行时间容易携带情感价值,看起来好像它可能带来好结果,因此,我们作为人类,常常喜欢在心中设置代理来简化评估结果,而正常运行时间常常被视为稳定性的代理,而稳定性又被视为商业价值的代理。所有这一切都是错误的,这些代理并不准确,甚至更糟,它们可能被颠倒了。
第二个问题是最大的——高正常运行时间本身代表了一种风险。这是未知的风险。随着时间的推移,我们的系统会发生变化,从硬件的磨损到补丁、更新以及软件的常规变动。可能会出现数据损坏或无法恢复的读取错误。也许会有配置更改不按预期工作。无论是否有人做出过系统更改,都会有许多不可预知的事情发生。而且,距离上次重启越久,我们对系统的反应就越没有信心。
我们必须在合理的范围内始终对重启的效果充满信心。我们并不总是能控制重启的时机。我们可以尝试使用冗余电源和冗余组件,但每个系统都有可能重新启动,当它们重启时,我们希望能够高度自信地确保它们能顺利重启。
重启过程会给服务器带来许多风险。它需要重新加载大量从磁盘或其他存储位置读取的数据,这些数据可能自上次重启以来没有被完全读取,因此潜在的损坏或其他存储问题的风险会增加。它对物理系统造成压力,尤其是当物理重启与软件重启结合时。此时你可能会发现某个文件丢失、文件损坏,或者内存条终于开始出现故障。
乍一看,我们可能会认为故意重启系统似乎很疯狂,为什么要故意促成故障的发生呢?但这正是我们想要的。我们故意诱发潜在的故障,以期在其他时候避免它的发生。
这里的逻辑是我们在一个方便或安全的时间进行重启,即一个绿色区间。如果在我们重启的时刻发生了硬件故障,或者发现了一个未知的软件问题,那时我们知道是什么触发了问题(计划重启),上次重启是什么时候(希望不是很久前),中间发生了什么变化(如果是软件或配置问题),或者重启就是硬件故障暴露的时机。这应该发生在我们为修复潜在问题而预定的时间段。
找到你的绿色区间
你的维护窗口或绿色区间是一个特定的时间段,在这个时间段内,工作负载被认为是不可用的,以便进行常规管理任务。典型的任务可能包括重启、软件安装、打补丁、数据库重新索引、磁盘碎片整理或其他需要高负载的任务。每个行业、公司,甚至每个单独的工作负载都会有不同的时间段适合分配绿色区间。不要期望一个公司正确的绿色区间能适用于另一个公司,甚至是同一公司内部的不同业务单元。
一个常见的绿色区间是周末。对于许多公司来说,一些甚至所有的工作负载可以安全地在从周五晚上到周一早上期间不可用,而不会对业务产生任何影响。通常,除非是 IT 部门,否则其他人甚至不会知道这个情况。如果情况确实如此,一个好的策略是,在周五晚上绿色区间开始时几乎立即进行任何打补丁或类似任务,接着立刻进行重启。如果重启导致任何故障,你将有超过两天半的时间来恢复系统,直到有人进来抱怨系统崩溃。两天的无影响时间可以让你进行更好的修复,而不是在压力巨大、资金损失、业务急需答案的情况下强行修复系统,而这时你还要集中精力解决问题。
根据我个人的经验,我曾管理过一个应用程序,在这个程序中,我们测量了数据库记录,发现这些记录每周至少有一分钟的时间内不会被使用,这个规律在所有系统客户中都存在。这使得我们可以有效利用仅仅 60 秒的时间窗口,但如果我们进行仔细规划,就能够在这个时间内进行系统重启、软件更新、打补丁等操作。虽然这样做并不特别方便,但相比于要求客户提供一个通用的维护窗口,或者为这一分钟运行额外的系统来进行覆盖,这种方式是非常具备成本效益的。
绿色区间可能具有创意性,且可能在你意想不到的时候出现。它们可能像长周末那样简单,或者可能发生在每周例行的周二午餐会议期间。与工作负载的客户合作,了解何时工作负载未被使用或不面临风险。
这实际上完全是关于规划的。只有在我们实际可以恢复系统时才触发问题。这样,我们就不太可能在我们无法提供支持或工作负载正在重度使用时,遇到相同的问题。绝不让任何业务说工作负载太重要而不能有计划的停机时间,这种说法是自相矛盾的。我们之所以有计划的停机时间,正是因为工作负载至关重要。如果某个工作负载不重要,那么直到出现故障才进行维护并不成问题。工作负载越关键,计划停机时间就越重要。事实上,任何没有停机时间(至少在系统层面上)的工作负载,都可以被认为是不关键的或非生产级别的,仅仅因为没有计划的维护。
相比汽车,你越重视一辆车,就越可能将其停用进行定期维护,比如换油和检查刹车。你这么做是因为计划性维护是微不足道的,而非计划性故障的发动机则不然。我们自然知道,维护汽车总比让它们发生故障要好。我们的服务器也不例外。
避免计划停机时间就等于为非计划停机时间做准备。
如果某个工作负载没有合理的停机时间容忍度,那么就需要采取额外的策略。例如,如果你是亚马逊经营全球在线商店,即使是一分钟的停机时间,也可能导致大量销售损失。如果你是一家投资银行,停机一分钟可能意味着订单未能正确完成,从而造成数百万美元的损失。如果你是一家医院,停机一分钟可能意味着危急生命支持系统失效,导致死亡。如果你是军队,停机一分钟可能意味着失去一场战争,因此有些类型的工作负载中断我们真的希望避免,这是毫无争议的。显然,在某些时候,我们需要采取极端措施,确保停机时间不会发生。
在这些情况下,我们需要一个高可用性水平,允许我们将基础设施中的任意组件下线。这可能是存储、网络,或任何数量的平台和计算资源。这意味着在应用层面也需要一定的高可用性,以便我们能够适当修补从硬盘固件到应用库的所有内容,甚至包括其中的每一环节。
关键工作负载需要平稳运行且高度安全的基础设施来确保其持续运行。一个良好的维护计划是确保工作负载可靠性的核心所在。
关于重启频率没有硬性规定。但一个好的起点是每周重启,并从中评估什么是适合你环境的。我们往往选择每周或每月重启,因为我们通常知道重启是必要的,但我们仍然认为应该避免重启。但在少数情况下,这种想法并不成立。我们真正想要做的是在被认为安全和明智的情况下,尽可能频繁地重启。
在当前的补丁管理制度下,每月重启大约是你可以考虑等待标准计划的最长时间。记住,任何计划都需要考虑到系统被错过的情况,必须等待额外的周期。所以,如果你计划每月重启,你需要接受有些系统偶尔会因为技术或物流问题而两个月没有维护。
每周重启通常是最实用的计划。大多数工作负载都有每周的使用模式,这使得分配维护窗口变得容易,或者至少是可行的。每周重启计划对用户也很有利,因为它们很容易记住。例如,如果一个系统每周六早上九点重启,用户就会习惯于此,即使他们当时想工作,也不会在此时使用系统。这会变成一种习惯。每周重启足够频繁,这样重启过程增加的风险很可能会暴露出即将在接下来的六天内发生的硬件或软件故障。这通常是方便性与可靠性之间的最佳平衡。
我们应该始终评估更频繁重启的机会。如果我们的工作负载安排允许,举例来说,每天重启是非常合适的。这也是我们通常处理终端用户工作负载的方式,鼓励系统在一天结束时重启,这样员工到达工作地点时(无论是虚拟的还是实际的都无所谓),系统已经焕然一新,准备好迎接新的一天。对服务器做同样的处理可能也是有意义的。
你的重启计划应该考虑到你的应用程序更新计划。如果你运行的软件更新很少,那么每月重启可能更为合理。如果你有几乎每天都在更新的工作负载,那么将系统重启与应用程序更新结合起来可能更有意义。
系统重启在软件更新和主要工作负载(通常假设不由操作系统供应商管理)之后尤为重要,因为有很多可能性会导致服务无法按预期启动,需要额外的配置,或者仅仅是在重启时遇到故障。如果你在进行软件更新时不重启,你就无法完全确认安装时重启是否成功。如果稍后出现问题,知道在上次系统更改时重启是成功的,这有助于加快恢复过程。
如果定期重启系统的遗忘是一个常见问题,那么忘记进行重启监控几乎是无处不在的。即便是那些认真对待重启计划的 IT 部门,通常也从未想到将正常运行时间监控添加到环境中的监控传感器列表中。重启监控通常非常简单,并且一般可以相对宽松地执行。例如,在我管理的许多环境中,我们希望服务器每周重启一次,我们会添加一个监控项,监测正常运行时间超过九天。如果我们的监控系统发现服务器的正常运行时间超过九天,它将发送警报邮件。错过一次重启事件并不是一个大问题,这样就有足够的时间避免误报,并有足够的时间规划手动干预,查找导致计划重启失败的原因,并在下次计划重启之前将问题修复。
这里的最佳实践是尽可能频繁地重启系统,除了有充分的业务需求外,不要避免重启,系统无法宕机的错误需求不能作为理由。争取每周重启,甚至是每日重启,如果只能做到每月重启,也要接受,并确保添加监控,因为没有重启的系统是难以通过日常检查发现的。
总结
系统的修补、更新和重启可能会让人觉得非常教条。在某些方面,我想它们确实是。但是,有时候真的很重要的事情也可能有些枯燥。实际上,修补和基本的系统维护应该是枯燥的,它应该是可预测的、可靠的和按计划进行的。如果可能的话,它应该是自动化的。
修补不应成为一个挑战或可怕的提议。通过适当的规划、备份、测试等,通常很容易拥有一个可靠的修补甚至更新流程,这样的流程极少会遇到任何重大问题。如果我们未能让我们的修补和更新变得定期和可靠,我们将开始害怕这一过程,而这几乎肯定会导致我们避免修补和更新,进而加剧问题。
在现代计算世界中,总有人试图利用我们的系统,虽然没有任何东西可以防御所有可能的攻击,但我们可以通过快速、定期和可靠的修补大大减少我们的暴露面。
现在,你应该能够自信地评估你的工作负载,确保它们都更新到最新,并开始在你的服务器群体中实施一个正式的修补、更新和重启计划。
在我们的下一章中,我们将讨论数据库以及它们应如何从系统管理的角度进行管理。
第六章:数据库
技术上,数据库系统是运行在操作系统之上的应用程序,对于我们作为系统管理员来说不应直接关注。这是一个很好的理论。然而在现实世界中,数据库与操作系统密切相关,往往是通用的知识项目,需要深入的技术知识,而总体上需要的时间相对较少。因此,普遍来说数据库管理的责任落在系统管理员身上;特别是在当今的 Linux 发行版上,因为我们可能使用的大多数数据库已经与操作系统捆绑在一起。
在本章中,我们将学习以下内容:
-
将数据库与 DBMS 分离
-
比较关系型数据库和 NoSQL 数据库
-
在 Linux 上发现常见的数据库
-
理解数据库复制和数据保护概念
在旧日的好时光,系统管理和数据库管理几乎总是两个独立的任务。系统管理员(SA)和数据库管理员(DBA)角色会密切合作,但是由于各自角色的专业技能和大量时间需求,它们通常是独立的、专门的工作人员。通常情况下,每五到二十名系统管理员只需要一个数据库管理员,因此团队规模较小,职业领域也总是较小,因为即使在没有数据库需要管理的公司中,系统管理员角色仍然存在。
随着操作系统和数据库管理系统变得更简单、更健壮,需要对数据库平台进行大量调整的需求已经减少到几乎可以忽略的程度,因此 DBA 职业道路几乎已经消失。今天已经不存在建立在单一数据库平台周围的职业需要。管理数据库的人通常会管理各种不同的数据库,可能在多个操作系统上。
随着时间的推移,大多数关键工作负载变得商品化。我们的意思是,它们从专门知识转变为通用知识。这些的典型例子包括电子邮件服务器(MTA)和网页服务器。二十年前(大约在 2001 年),运行这些服务器是高度专业化的知识,只有非常少的系统管理员才会理解其中的工作原理。通常你会有一个专门的操作系统管理员,然后有一个专门的电子邮件管理员或网页管理员,专门管理他们所擅长的单一应用程序。那时不会是所有电子邮件服务器之类的情况。管理一个单一的邮件服务器,比如 Postfix 或 Exchange,往往是一项专业技能。你的知识将完全集中在这个单一产品及其独特的特点和需求上。这种情况非常极端,以至于像 Postfix、Exchange、Apache、MS SQL Server、Oracle 数据库、IBM DB2 等产品,都有专门的认证和职业发展路径。如今,我们只是默认任何有经验的系统管理员都能够管理任何电子邮件、网页或数据库服务器。
由于数据库非常复杂,并且在过去几十年中已经发展成为远超其过去的形态,因此作为系统管理员,我们应该普遍理解其中的许多概念。数据库是高度状态化的,代表着文件系统和一般存储子系统的二级存储层。它们并不代表特殊情况,而是需要我们深入理解的通用情况的广泛应用。网页服务器、电子邮件服务器和其他应用程序仍然很重要,但它们代表的是应用设计中的标准预期情境,因此在这种情况下不需要特别的考虑。直白地说,数据库用于存储数据,并且极其脆弱。其他应用程序使用数据库或文件系统来存储数据,因此从管理的角度来看,它们比较简单。正因为数据库代表了第二层数据存储层,它才被视为特殊。
为了以系统管理员的方式处理这一问题,我们将从深入了解数据库是什么、它是如何工作的以及为什么它成为一种存储形式开始。然后,我们可以研究常见的数据库类型及其在 Linux 发行版中的具体情况。最后,我们将通过探讨数据库的最重要方面——如何保护它们,来结束本篇内容。
让我们开始吧,弄清楚数据库究竟是什么,以及为什么我们如此关心它们。
将数据库与数据库管理系统(DBMS)分开
就像生活中大多数事情一样,关于数据库的术语往往不准确,许多高度技术化且具体的术语被用来主要指代与其原本含义不同的东西。但通过深入了解数据库到底是什么,以及它们如何几乎普遍地工作,并在这个话题上建立正确的语义,我们将从系统管理员的角度,建立起对数据库需求的几乎内在理解。通常来说,找到准确的描述方式本身就能帮助我们理解。数据库并非魔法,但往往被当作魔法来看待。
数据库
我们必须首先问一下,什么是数据库?《牛津词典》对数据库的定义是在计算机中保存的一组结构化数据,特别是可以通过多种方式访问的数据。嗯,这样的定义并没有告诉我们太多。不过,从某种程度上说,它其实说了些东西。数据库不能是无结构的;这是最重要的一点,计算机存储的东西,比如文件,也都是结构化的。所以,数据库是计算机中存储的结构化数据,可以是存储在磁盘上的文件或文件集,或者它们存在于计算机内存中,永远不写入磁盘。在后一种情况下,数据库是短暂的,对系统管理员来说并不重要。但在前一种情况下,代表了百分之九十九以上的使用案例,这个问题就非常重要了。让我们给出一个作为系统管理员可以有效使用的定义:数据库是包含结构化数据的文件或文件集。
你可能会立刻跳出来说,但是我运行的是一个数据库,它是一个服务,而不是文件——我可以与它互动! 我们会很快解决这个问题。跟我走,数据库其实就是文件。
我们应该从一些例子开始,因为这有助于快速理解我们的意思。假设我们有一个标准的文本文件,也许是我们写下的一些笔记。这是一个文件,但它是数据库吗?不是的,它不是。没错,文件是用某种 ANSI 字符标准编码的,但数据是临时的,没有结构。我们可以手动给文件添加结构,这样做是可以的,但文件和读取该文件的工具并不知道这些结构。任何结构对于使用它的人来说是可访问或可见的,但对系统本身不可见。这是无结构的。
好吧,那么文本文件不是数据库。那么 Word 文件呢?一样的道理。它可能有比文本文件更强的格式,但 Word 文件中存储的内容完全没有结构。我们可以在文件中随意放入任何内容,放在任何地方。它是无结构的。
那么,电子表格文件呢?就像我们用 Excel 或 CSV 时得到的那样?这是一个棘手的问题。我们进入了一个灰色区域。在正常情况下,这些文件并不被视为数据库,但名义上它们是。我会把它们称为半结构化的。它们包含一些结构(你可以看到的是单元格),并且有一种方法来指定该结构中包含的内容,以及某些数据组(即表现为列或行的数据),这些数据被期望相互关联。但单元格内或单元格之间的任何结构都没有被建议或强制执行。因此,虽然有结构,但我们通常认为它没有数据库所需的结构那么多。我们称之为“也许”。不要在下一个 IT 鸡尾酒会上拿出CSV文件,并试图为它辩护是新的数据库格式,因为这是站不住脚的。它仅仅是作为一个思维实验有意义。但我们可以看到,电子表格格式很容易有潜力像数据库一样发挥作用。
通过稍微增加一些结构化,我们开始看到真正的轻量级数据库文件的出现。XML 就是一个很好的例子。XML 比 CSV 这样的电子表格格式更有结构,可以作为一个完整的数据库使用。有些数据库格式就是基于 XML 的。XML 仍然只是 ANSI 文本,但具有足够的特定结构,可以让我们走向非常简单的数据库。XML 可能不是最强大的数据库,也不是使用最快的数据库,但它非常简单,并且在合适的用途下可以非常有效。
专门构建的数据库通常避免使用 ANSI 或类似的文本格式的多余膨胀,因为这会在软件使用时减慢系统速度,而且数据库本身通常并不是为了让人类直接阅读的。通常,会使用某种形式的二进制格式或甚至压缩来减少存储的读写时间,并尽量减少今天所需的存储空间。一个很好的例子是SQLite,这是一个免费的开源数据库,它使用高度优化、但公开的格式,如果有兴趣,你可以研究它。它仍然只是一个文件,就像其他任何文件一样,但比 XML 提供的结构更加丰富。
所有这些示例使用的都是每个数据库一个文件。但数据库使用多个文件并不是没有理由的。这样做的一个常见目的可能只是将数据拆分开来,以避免将所有数据存储在一个过大、无法轻松操作的单一文件中,或者数据可以按用途拆分。想象一下一个存储用户地址和用户电话号码的数据库。一个只包含地址的文件和一个只包含电话号码的文件会是一个合理的磁盘存储设计。
数据库引擎
现在我们知道什么是数据库。它其实就是我们存储的一个文件(或者多个文件),这些文件包含我们的结构化数据。我们假设在生产环境中,我们将使用一种高效的数据库格式,这种格式不是为了让人类直接打开和读取,这样做显然是不明智的。所以,计算机会读取、写入并操作这个文件或这些文件。
那么,计算机如何知道如何处理那个格式如此具体的数据库文件呢?在回答这个问题之前,我们应该先来比较一下存储。
在存储中,我们有一个标准的原始格式,称为块存储。在此基础上,我们实现了文件系统。这些文件系统通过提供操作系统可以用来存储和检索数据的标准文件访问格式,与操作系统进行交互。每个文件系统可以以不同的方式执行此操作。为了让操作系统能够与文件系统交互,它必须有一个文件系统驱动程序。
数据库的工作方式相同,但通常是在更高一层的堆栈中进行的。对数据库来说,文件系统是通用存储。高度结构化的数据位于文件系统之上,包含在一个文件或多个文件中。但就像我们需要操作系统驱动程序来知道如何与文件系统进行交互一样,我们也需要一个驱动程序来让应用程序知道如何与数据库进行交互!我们可以将其称为数据库驱动程序,但它通常被称为数据库引擎或数据库库。
文件系统实际上是数据库
这就是那些我们在 IT 领域工作的人应该理解的奇怪事情,而你永远不能在那个所谓的鸡尾酒派对上提出来,因为你永远无法说服任何人相信这是真的,但它确实如此。文件系统本身实际上是一种数据库形式。它们是磁盘上的高结构化数据格式,可以包含其他特定格式的数据,以文件的形式存储,包含关于这些文件的结构化数据,并且通常包含复杂的机制来搜索数据结构。文件系统在各个方面都是数据库。甚至包括它通常的使用方式。它们只是具有独特但极为常见的目的的数据库,这个目的重要到我们已经忘记了它在背后究竟是什么。
这与网络服务器实际上是文件服务器的情况类似,但它们是如此特殊的案例,以至于没人谈论它们本质上就是这样。理解它们是如何工作的非常有用,因为这有助于我们更好地理解它们,并且避免大脑在意识到它们之间有重叠时感到困惑,进而搞不清楚它们是如何分开的——因为它们根本就不是分开的。
这一点非常正确,过去有些高性能数据库甚至会放弃使用文件来存储数据,而直接存储在块设备上,这样它们的位置和文件系统通常一样。但因为没有文件,它们实际上并不是文件系统。但在所有实际用途上,它们却是。
这种替代文件系统的过程曾经很流行,是为了提升系统性能,因为文件系统曾经会给服务器带来显著的开销。今天,文件系统的开销已经微不足道,而试图替代文件系统带来的复杂性和问题已经变得如此庞大,以至于几乎被完全避免。
一旦你将数据库看作是数据的某种文件系统,一切就都变得更有意义了。
数据库引擎才是真正的魔法所在。数据库本身仅仅是存放在磁盘上(或内存中的)数据。没错,它有结构,但这个结构已经存在。数据库并不创建、强制或以任何方式维护这个结构——所有这些工作都由数据库引擎完成。数据库引擎是数据库栈的主力军。这里是处理能力的来源,这就是我们需要安装的地方,也是魔法酱料被应用的地方。
在某些情况下,我们会大量讨论数据库引擎。在一些情况下,我们直接使用它们,比如SQLite或Berkeley DB,我们只需安装库(数据库引擎),然后使用它访问一个文件,哇,系统就能工作了,可以用作数据库。或者在其他情况下,比如使用MongoDB或MariaDB产品时,我们常常会讨论在背后选择的数据库引擎(WiredTiger、InnoDB、MyISAM等),它们是影响数据库特性和性能的关键因素。
数据库引擎在许多情况下得不到应有的关注,大多数人完全忽视了这一数据库服务栈中至关重要的一层,因为它很难理解,而且通常是隐藏在背后的。眼不见,心不烦,这里完全适用。
在某些情况下,比如我之前提到的 BDB 和 SQLite,我们作为系统管理员,需要负责将这些库安装到服务器上,以便软件可以访问它们。当然,这些库通常仅作为依赖列出,并由我们服务器上的包管理系统自动安装和维护,这些包管理系统来自我们的 Linux 发行版,使得这一过程变得简单,甚至对我们来说可能是透明的。正因为如此,系统管理员往往几乎对他们所维护的系统上部署或使用的数据库引擎一无所知。
这可能看起来显而易见,但值得注意的是,数据库引擎是代码库(即驱动程序),而不是运行的程序或服务。因此,在系统上检测特定的数据库引擎可能会相当困难。当然,如果通过 APT 或 DNF 安装了 SQLite,我们可以查询系统并轻松找到它。它是一个存储在磁盘上的库,拥有一个目录,并且在包配置日志中有所记录。我们无法在进程列表中看到它的运行,也找不到它在服务目录中,但我们总能以某种方式找到它。
但完全有可能,数据库引擎库的代码会被包含到并编译到某个软件项目中,使其几乎不可能被检测到,因为它只是某个应用程序内部磁盘上的二进制数据。当然,块级工具可以扫描磁盘上的每一部分数据,查找磁盘上的模式,但这属于极端级别,更适用于取证或执法,而在系统管理中并不太有用。从实际角度来看,一个编译进软件中的数据库引擎对使用该系统的任何人来说都是完全不可见的。
当我们讨论某个数据库的性能或特性时,几乎总是这些特性或性能特征来自正在使用的数据库引擎。在大多数情况下,数据库引擎还会实现查询语言或应用程序编程接口(API),用于查询磁盘上的数据。
对于那些跟随学习的人,你可能已经注意到,由于数据库引擎本身并不运行,因此你无法远程访问它。为了与数据库引擎进行交互,你必须在程序中使用驱动程序与数据库进行交互。
数据库管理系统
数据库技术栈中最显眼的组件,也是唯一完全可选的部分,是数据库管理系统,通常缩写为 DBMS。对于大多数人来说,甚至是那些具有丰富数据库经验的技术人员,唯一了解的数据库系统部分就是数据库管理系统。
在我们深入了解数据库管理系统究竟是什么之前,我们应该先举一些实际的 DBMS 例子:MySQL、MariaDB、PostgreSQL、Oracle DB、Microsoft SQL Server、IBM DB2、MongoDB、Redis、Firebase,以及更多其他的。这些名字对你们中的大多数人来说,比数据库引擎的名字更为熟悉。
DBMS 本身做的事情其实非常有限。DBMS 是一个程序,它使用一个或多个数据库引擎与磁盘上的物理数据库进行交互,然后提供对该数据库的访问控制。DBMS 可能有一个始终与之关联的单一数据库引擎,或者像 MySQL 一样,提供对一系列数据库引擎的访问,并为它们提供一个通用接口,使开发人员能够方便地使用它们。熟悉 MySQL 的人会知道,在 MySQL 中创建一个新数据库时,你必须告诉它你希望使用哪种引擎。确实,如果你不选择,它会有一个默认选项,但在这种情况下,不选择实际上也是一种选择。
在使用数据库引擎时,你必须指定你正在操作的文件或文件集。因此,任何与数据库引擎的交互都仅限于单一的数据库,不管那个文件中存储的是哪个数据库。DBMS 通常不是这样工作的。标准的 DBMS 会连接到多个数据库,这些数据库可能连接到多个实例的数据库引擎,这些引擎可能是相同的库被多次实例化,或者可能是不同的引擎用于不同的数据库,所有这些都可以同时访问。因此,我们所设想的数据库大部分来自 DBMS。
正是 DBMS 提供了(当然是可选的)通过网络或甚至通过互联网连接数据库的方式。任何网络功能都来自 DBMS。此外,DBMS运行,通常作为服务,在你的计算机上运行。这就是你看到内存消耗、CPU 使用情况以及其他数据库使用详情的地方。DBMS 通常提供一些引擎本身无法提供的扩展功能,例如内存缓存。
显然,在纯数据库引擎的场景中,数据库中数据的访问控制完全来自于文件系统的权限。这就像用 Microsoft Word 打开一个 Word 文件一样。如果你对文件有读写权限,并且能够运行读取文件的应用程序,那么你就可以读取文件并将更改写回文件。对于像 SQLite 这样的数据库引擎,也可以尝试同样的方式。要允许用户使用数据库,你只需给他们相应的文件系统权限即可。这非常简单,但也非常有限。
使用 DBMS 我们有更多的选择。大多数 DBMS 添加了网络功能,通过这些功能我们可以使用数据库自身的工具在粒度级别上控制访问权限,同时我们还可以使用操作系统和网络工具进一步控制访问。这变得更加复杂,但正是从这种复杂性中,我们获得了强大和灵活性。DBMS 通常会提供用户级别的控制和机器级别的控制,并且通常在其管理的数据库集合中提供非常精细的控制,例如行、表或文档级别的控制,具体取决于使用的数据库引擎类型。
数据库管理系统(DBMS)为数据库生态系统增加了强大的功能和灵活性,在大多数情况下也提高了易用性。在生产环境中,完全可以直接使用数据库引擎,很多人也确实这样做。但总体来说,DBMS 主导着企业的数据存储。当人们使用数据库服务器这一术语时,按照定义,他们指的是包含 DBMS 的主机。正是 DBMS 的网络能力使得数据库能够存储在专用服务器(或服务器集群)上并从中提供服务,而不需要数据库始终与使用它的应用程序本地化。这种灵活性在应用程序增长并需要更多资源时非常重要。对于小型应用程序,在资源充足的情况下,可以将整个应用程序及其数据库托管在单个服务器上,通常直接使用数据库引擎能获得最佳性能。但一旦超出这种规模,DBMS 则是支持数据库变得更大的关键。
数据库引擎本身并不严格是一个单连接受限的系统,但它实际上是这样。虽然多个用户可以同时连接到文件系统中的同一个文件,但这会带来明显的问题。如果两个人试图在差不多相同的时间进行修改,是否会互相覆盖?如何通知其他人正在进行的更改?等等。这些问题与在 SAN 中连接多个服务器到同一文件系统时遇到的问题类似。它通过数据库文件内部使用相同的集群文件系统机制来解决这些问题。(看吧,我告诉过你,数据库就像文件系统!)
文件级锁定和访问控制可以应对轻量级使用,最多支持大约五个用户,之后会开始出现明显的性能问题。对于重度使用,即便是两个连接也会变得有问题。微软 Access 以鼓励使用 JetDB 数据库引擎(通常称为 Access 数据库)而著称,且其文件锁定性能极差,导致系统无法承载超过少量用户的使用。相同的系统可以切换到使用MS SQL Server DBMS,并且能够处理数千个用户,毫无问题。
因此,对于任何真正需要多重连接的情况(这可能由单个用户或多个运行中的服务实例引起,它们需要从数据库中拉取数据),都需要使用 DBMS。DBMS 提供了更多的缓存、锁定和权限控制机制。
识别共享数据库引擎与 DBMS 的区别
如果你是数据库新手,可能不了解常见的识别方法来判断使用的是哪种方式。有些情况非常简单,比如如果你必须配置数据库的网络连接详细信息,包括主机名和端口,那么你就知道必须涉及 DBMS。但并非所有情况都那么明显。
很多应用程序处理自己的连接细节,而你可能很难了解它们在背后是如何工作的。所以,除了寻找开放端口或类似的东西外,你可能会一无所知。
然而,一个常见的机制是要求共享映射驱动器访问文件或文件。这在除了极少数情况下的数据库管理系统(DBMS)中是不需要的,如果确实需要,那么你就遇到了严重的性能问题。将数据库文件直接共享给用户或应用程序进行访问是直接使用数据库引擎的标志。这种情况常见于许多遗留或构建不当的应用程序,因此你可能已经遇到过,或者将来会遇到,并且了解数据库引擎的工作方式有助于解释这些部署中访问、锁定、性能或甚至是数据损坏的问题。
作为系统管理员,甚至可能作为数据库管理员,假设是除了安装数据库引擎库之外,我们与运行中的数据库的互动将全部通过数据库管理系统(DBMS)进行。在这里,我们需要管理和监控服务、资源利用、安 全、补丁、访问控制等。
现在我们已经了解了数据库是什么、它们是如何工作的,以及它们的组成部分,这样我们就可以批判性地思考安全性和性能的影响。缺乏对数据库的理解,会使得解决更复杂的问题,如性能调优或有效的备份措施变得非常困难。在下一节中,我们将非常高层次地讨论数据库的类型,给我们一些关于系统管理员如何处理这些不同数据存储形式的见解。
比较关系型和 NoSQL 数据库
数据库分为两大类:关系型 和 NoSQL。这些分类非常糟糕,但不幸的是,它们就是世界上看待数据库的方式。这些术语非常糟糕,原因有几个。首先,NoSQL 是指 非关系型。这意味着数据库要么是关系型,要么是非关系型。这本身就是一个很糟糕的分类法。更糟糕的是,SQL 是与关系型数据库常关联的 结构化查询语言;它是为查询关系型数据库而编写的语言。因此,NoSQL 这个术语指的是非关系型数据库,但这就像试图通过称人们为非英语使用者来指代那些不是来自英格兰的人。两者有时会重叠,但通常不会。
SQL 不是关系的内在语言;它只是用于查询关系的常见约定。你可以创建一个不能使用 SQL 查询的关系型数据库,同样,你也可以创建一个可以使用 SQL 的非关系型数据库!不仅可以,事实上,这非常常见。所以,为了明确一点,你可以在 NoSQL 数据库中使用 SQL,而且人们经常这么做!这是什么疯狂的事情?
在 NoSQL 世界中,通常每个数据库都会使用一种或多种查询语言。这些查询语言通常是特定于每个数据库的,但没有某种查询语言,就几乎不可能将数据导入或导出数据库。正是这些语言构成了数据库与应用程序之间通信的基础。例如,MongoDB 实现了他们自己的 MongoDB 查询语言。
所以我们必须接受这些术语从一开始就很荒谬,并意识到我们所讨论的,一方面是关系型数据库,另一方面是所有其他非关系型数据库,这是一种包含许多不同数据库技术的集合。这种奇怪的情况之所以存在,仅仅是因为大多数流行且知名的数据库都是关系型的,且很多年里人们一直认为只有关系型数据库才是足够好的,适合生产使用。事实证明这一观点完全不正确,但它在行业中仍然产生着影响。
因此,NoSQL 本身就让人感到望而生畏,因为它包含了这么多的内容和数据结构类型。话虽如此,我们并不需要了解所有的内容。我们真正需要理解的只是,NoSQL 数据库可以使用任何类型的磁盘上的数据结构(当然,除了关系型数据库),并且可能会使用 SQL 或其他查询语言,也可能不使用。这就留下了更多的问题而不是答案。作为系统管理员,我们通常只是被要求学习应用程序所需要的数据库。这可能是一些非常常见的数据库,关于它有大量的知识,或者它可能是一些非常冷门的数据库。
第一代数据库按今天的标准来看,实际上是 NoSQL 的。这就让人觉得很奇怪,为什么早期的数据库现在被认为与后来的数据库不同。早期的数据库功能非常有限。在 1970 年代,关系型理论出现,随之而来的是第一批真正的现代数据库。关系型数据库诞生了,并且证明它们既安全又高效,以至于其他类型的数据库几乎在短时间内都被淘汰了。关系型数据库成为了王者,且永远存在。
几十年来,关系型数据库几乎代表了所有商业级数据库,其他类型的数据库几乎只存在于历史注脚中。当它们应用于实际系统时,通常是由应用程序独立实现的,而不是由大型数据库供应商提供。因此,即使它们被使用,它们也相对不为人知。一个嵌入在应用程序中的数据库引擎对系统管理员来说基本是不可见的,因此即使这些数据库引擎被定期部署,只有原始开发者才会知道。事实上,我的职业生涯开始于 20 世纪 80 年代末期,当时我为一个 NoSQL 数据库引擎编写了代码,并为其开发了一个图形化数据检索系统。我亲眼见证了开发者使用 NoSQL 数据库,而信息技术部门对其毫无了解的现象,这正是在关系型数据库占主导地位的时期。
关系型数据库的优势来自于其存储数据的高效性,这在数据库早期几十年尤其重要,那时找到足够大的存储系统来容纳数据一直是一个挑战;同时,它还能很好地处理诸如事务和数据完整性等问题。这使得关系型数据库非常适合任何处理金融或其他关键事务的系统,这些系统需要高水平的保证,确保事务要么完全完成,要么根本不发生。早期的数据库自然非常注重金融事务,因为这些数据存储操作极为关键,足以证明使用昂贵计算机来确保数据准确无误的必要性。当数据库的实现成本达到几百万美元时,可以轻松理解为什么银行会使用它,但要为其运行一个博客就显得非常难以合理化了。
关系型数据库得名于它们用于指定数据之间实际关系的方式。例如,如果你创建了一个用户数据,你可能会创建一个电话号码数据,并在它们之间建立关系。接着你可能会创建更多数据,比如地址。这个地址也会与用户有关联。关系型数据库背后的基本理念是数据库引擎会主动控制这些关系。比如,如果删除用户,它可能会自动删除电话和地址;它可能会确保一个电话号码只能属于一个人,或者可以显示多个人住在同一个地址。它甚至可以阻止你创建不符合某种格式的电话号码,或者阻止你填写不完整的字段。
关系型数据库听起来可能简单且表面化,但当它们被精心设计并加以应用时,能够为数据完整性提供强大的保护。它们大大减轻了软件开发人员的负担,并且将数据完整性置于一个能确保保护数据的约束条件下,即使使用这些数据的应用程序被绕过了。关系型数据库是一种强大的机制,但这种强大是以复杂性为代价的。
NoSQL 数据库由于不受关系型数据库规则的约束,也不必使用 SQL 方言,因此可以探索各种数据存储和完整性方法。一些方法以一种享乐主义的随意态度处理数据,这对传统的数据库管理员来说简直是震惊。数据可以随意存储在任何地方,几乎没有任何控制。虽然可能存在某种结构,但这种结构更像是一种建议,而不是强制要求。从关系型理论的严格规则出发,例如,文档数据库就像是“荒野西部”:数据随意乱丢。一个文档的结构可能根本与下一个文档不匹配。这简直是数据逻辑的混乱。
NoSQL 的真正优势来自于这种灵活性。我们不再需要在一个强预定义的、严格约束的模式下工作,而是可以根据特定需求自由使用数据,选择最合适的方式。我们可以用博客作为一个极好的例子,它与财务数据在关注点上几乎是完全相反的。
对于财务数据,我们通常非常关注准确性、一致性和事务完整性。而对于博客,我们更多关注的是速度,其他的则不太重要。如果我们有一个受欢迎的网站,并希望让我们的博客在全球范围内快速访问,我们很可能会希望通过全球各地的节点来提供该内容,从而让大多数人能够从相对本地的副本中获取博客内容,而不是使用一个可能托管在其他大陆上的远程集中式博客。
一个通过复制到多个地区来提供内容的数据库,并且将速度作为首要优先级,可能会错过最新的更新,或在数据更新过程中短暂地出现顺序错乱,而这正是关系型数据库设计时会避免的情况。能够在时间允许的情况下复制数据,同时仍然提供本地可用的数据,可以带来显著的性能提升。对于许多工作负载而言,这种性能权衡是理想的选择。
随着越来越多的系统被计算机化,越来越多的工作负载使用数据库,这意味着数据库的使用方式正在变得更加广泛。如今,数据库的实现往往免费或成本极低,这意味着几乎所有事情都将在某个阶段使用数据库。如今,数据库不再是仅仅为高需求工作负载所专用的工具。
仅提供非常简单的查找、会话缓存等功能的数据库并不常见。或者是替代文本文件用于日志记录的数据库,能够更快速地访问日志数据,并且更重要的是,可以对这些日志进行强大的搜索,现在几乎随处可见。NoSQL 正在让数据库世界变得更加强大和灵活。
作为系统管理员,我们很少,甚至几乎不可能,有机会选择在任务中使用哪种数据库类型。即使了解哪些数据库类型在不同情况下最为有用,这通常也是不必要的,尽管这可能非常有趣。更重要的是,我们需要理解,数据库现在呈现出丰富的多样性,尽管它们之间有许多共同的系统管理特点,但不再有诸如 SQL 是通用语言的内建假设,而我们的应用程序将决定我们需要学习和支持哪些数据库类型和产品。
理解关系型和 NoSQL 数据库代表着我们两大阵营的数据库产品后,我们将简要概述目前在你的 Linux 生态系统中最有可能出现的实际产品。
在 Linux 上发现常见的数据库
大多数操作系统都有一两个非常流行的关键数据库产品与之相关。例如,Windows 上的数据库产品是 Microsoft SQL Server。Linux 在这方面则完全不同。Linux 不仅没有一个特定的数据库产品与操作系统紧密地在意识形态上相关,而且通常有大量的数据库选项已经包含在几乎每个 Linux 发行版中。这使得成为一名 Linux 系统管理员变得更加具有挑战性,因为人们期望你不仅要了解各种不同的数据库产品,还要能够管理它们。与此相对的 Windows 系统管理员通常只需要了解一个非常固定的产品,就可以声称自己具备了该领域的基础知识。尽管许多数据库可以运行在 Windows 上,但除了 MS SQL Server 之外的其他任何数据库都被视为特例和专业知识,通常不会期望你有任何相关经验或知识。
在 Linux 上,大多数情况下不会期望你对每个可能的数据库选项都具备非常深入的知识,但期望你了解其中的许多并能够准备好管理几乎任何数据库系统是相当普遍的。单个服务器上部署多个数据库管理系统是很常见的,因为它们是内建的,并且相比 MS SQL Server 更加针对特定目的,因此一个数据库管理系统负责某一特定任务,另一个负责处理数据存储需求截然不同的任务是常见的,并且非常有效。
我们将保持数据库类别的自然划分,考察常见的关系型数据库产品以及非关系型或 NoSQL 数据库产品。
Linux 上常见的关系型数据库
可能在 Linux 上最著名的四个数据库,甚至可能是全球最著名的数据库,是关系型数据库。这四个大牌是MySQL、MariaDB、PostgreSQL 和 SQLite。排名第五和第六的数据库(不分先后)是 Firebird 和 MS SQL Server。没错,你没看错,那个 Windows 生态系统中的关键数据库产品也可以在 Linux 上使用。
MySQL
与任何其他数据库相比,MySQL 与 Linux 系统几乎是同义词。MySQL 可能在 Linux 上最为人知,但它也正式提供 Windows 版本,并在 Windows 上有一定的使用量。MySQL 功能强大、速度极快且极其知名。几乎每个 Linux 系统管理员都曾经使用过它。MySQL 是一个完整的数据库管理系统,包含多个数据库引擎。
MySQL 首次真正流行是作为早期动态网站的数据库。它免费、速度快,且缺乏更高级的金融交易所需的功能对于内容管理引擎(如博客和类似的动态生成内容的站点)来说并不重要。MySQL 被称为首选产品,用于网站需求,但由于这种刻板印象,它常常被其他需求排除在外。
今天的 MySQL 已经成熟、先进,具备几乎所有你可能需要的功能,适用于任何类型的工作负载。如果你只打算学习一个数据库管理系统,MySQL 肯定是最好的选择(或者是 MariaDB,我稍后会解释)。MySQL 拥有最广泛的用户基础,几乎所有具备 Linux 经验的系统管理员,以及很多没有 Linux 经验的管理员,都能自信地管理它。针对它也有大量标准工具,比如 phpMyAdmin,当你想避免或超越命令行时,它能让你更轻松地使用 MySQL。几乎所有为 Linux 开发的主要应用项目都在某种程度上使用 MySQL,尽管它可能不是最常部署的数据库,但与 MariaDB 结合使用时,它是最常被有意部署的数据库,不仅在 Linux 上,在所有操作系统上都是如此。
MariaDB
真的很难谈论 MySQL 而不提到 MariaDB。MySQL 的社区和方向在多年前分裂,许多原 MySQL 团队成员离开了这个项目,将开源基础带走,创建了 MariaDB,旨在成为他们认为的 MySQL 的精神继任者。对许多人来说,MariaDB 才是真正的 MySQL,因为它在理念上与原始产品一致,完全基于相同的代码库构建,而且由原始团队开发。许多 Linux 发行版,可能大多数,放弃了 MySQL,改用 MariaDB。甚至现在,大多数声称使用 MySQL 的人实际上是在使用 MariaDB——往往连他们自己都不知道。
即插即用替代品
MariaDB 的真正亮点是它是 MySQL 的完整 即插即用替代品。这意味着它被设计成能够完全透明地在任何使用 MySQL 的地方使用。它使用完全相同的协议、接口、工具、名称、端口、约定等。理论上,所有的东西都是一样的。
MariaDB 做得如此出色,以至于许多人在说自己使用 MySQL 时,实际上他们使用的是 MariaDB。有些人说这有点像是一种代码;还有人说是因为管理层期望这样做,而解释为什么使用 MariaDB 而非 MySQL 是不值得的;还有一些人根本不知道自己安装的不是 MySQL。管理 MariaDB 最常用的工具是 mysql 命令行工具,这也是许多人接触系统时最接近实际系统的工具。一个数据库设计师或开发人员只需要知道该系统与 MySQL 兼容。没有真正的迹象让他们怀疑这到底是某个产品或另一个产品。它们看起来和运行起来的方式完全一样。
现在人们常常提到著名的 LAMP 堆栈,曾经是 Linux + Apache + MySQL + PHP,现在变成了 Linux + Apache + MariaDB + PHP。看起来 MariaDB 确实已经完全取代了 MySQL 在市场中的位置。但很难准确评估这一点,因为在 MariaDB 市场中,有一个不确定的大比例部分报告自己使用 MySQL,要么是因为他们没有意识到它们是不同的,要么是因为他们随意报告不准确,要么是他们根本不知道自己在使用什么。
即插即用的兼容性带来了额外的好处,即学习 MySQL 就意味着学习 MariaDB,反之亦然。你无需学习一个或另一个,因为你在一个系统上做的所有事情,在另一个系统上也完全一样。
PostgreSQL
无论看起来多么不相似,post gress 的发音使得 PostgreSQL 可以说是今天在 Linux 系统上最成熟和先进的数据库。PostgreSQL(最初写作 POSTGRES)始于 1980 年代,作为成功的 Ingress 数据库产品的继任者(Postgres 意味着 POST inGRESs)。
今天,PostgreSQL 常被认为是 Linux 系统上最快速、最稳定、功能最丰富的数据库产品,甚至可能是所有数据库中最优秀的。像这样的数据库区别通常更多的是个人意见,因为性能测量很少可以直接比较,并且功能差异往往比直接的查询性能更为重要,但 PostgreSQL 的声誉无疑是无可匹敌的卓越,代价是相比于其竞争对手,它更复杂且不太为人所知,而后者通常被认为是更简单的系统。
近年来,PostgreSQL 在流行度上经历了重大复兴。今天,你会发现越来越多的部署软件支持并甚至推荐它作为首选数据库,这是自十多年前 MySQL 的全盛时期以来,数据库界的一大变化。
作为一名 Linux 系统管理员,PostgreSQL 数据库生态系统是一个稳固的第二选择,甚至可能是首选,与 MySQL(以及与 MySQL 相同的 MariaDB)一起学习,因为大多数 Linux 系统管理员在某个时刻都需要管理 PostgreSQL。
SQLite
比大多数系统管理员意识到的更常用的是 sqlite 客户端工具,你可以用它来读取和修改 SQLite 数据库文件,但这与数据库服务器完全不同。
SQLite 的强大之处在于它的简单与微妙。除了安装其访问库外,系统管理员通常不需要了解系统中是否存在 SQLite。它不需要调优或配置。它就存在在那里。由于软件仓库和自动依赖管理的魔力,SQLite 通常会作为其他软件的依赖项被部署,我们甚至可能没有意识到它已被安装或可用。它自动出现并完成它的工作。甚至它可能被内建在使用它的应用程序中,且可能以我们无法在系统中搜索到的形式存在!
由于 SQLite 的存在和部署方式大多数时候是这样,普通用户对 SQLite 的部署情况一无所知。正常的安装并不会隐藏驱动程序:系统管理员如果想要发现它、修补它或仅仅是查找它在哪里,通常都不会遇到什么困难。但是除非你特别在寻找它,典型的服务器上可能会有数百甚至上千个类似的软件包,我们通常无法花时间去了解每个系统上存在哪些库,更不用说知道哪些软件依赖于哪些包了。这实在是不切实际的。
Firebird
相比 MySQL、PostgreSQL、SQLite 和 MariaDB,Firebird 的知名度要低得多。Firebird 是一个完整且成熟的数据库管理系统,基于 Interbase 6,但在 2000 年与该项目分离。尽管在 Linux 世界中被视为相对次要的软件,但 Firebird 依然是一个功能强大且成熟的数据库管理系统,其主要的特点是所需的系统资源非常少。
Firebird 在对话中出现的概率远高于实际部署到你的服务器上。它实在是不太常见。Linux 上有很多数据库选项,这使得即便像 Firebird 这样成熟且严肃的数据库选项也很难获得关注。
Microsoft SQL Server
这份榜单上的参与者总是让那些不了解其可用性的人感到震惊。长期以来,微软 SQL Server 被认为是市场上最好的数据库产品之一,但始终仅限于微软 Windows 操作系统。但近年来,微软试图在数据库许可空间(与操作系统许可相比更具吸引力)获得更多市场份额,开始将 MS SQL Server 发布到 Linux 以及 Windows 上。如今,MS SQL Server 对 Linux 系统管理员来说已经是一个完全合理且可行的选择。
像这份榜单上大多数传统选项一样,MS SQL Server 是一个完整的数据库管理系统,其内部有多个数据库引擎。它是一个功能强大的产品,具备许多高级功能和特性。
MS SQL Server 在 Linux 上仍然不常见,并且可能会在相当长的时间内保持这种状态。但它已经比例如 Firebird 要普遍得多。数据库部门通常非常专注于 Linux,或者至少是 UNIX 系统,因此如果应用程序需要 MS SQL Server,而团队通常不使用 Windows Server,则必须管理一个完全不同的平台,这是一个问题。
Linux 上常见的 NoSQL 数据库产品
如果关系数据库产品的列表看起来很长,那与我们可以讨论的 NoSQL 或非关系数据库产品的潜在列表相比根本不算什么。与关系数据库列表不同,其中所有产品都以类似的方式工作,并且适合由类似的软件任务使用,NoSQL 列表变化多端。对于一个任务来说是一个了不起的产品,对于另一个任务来说可能完全没用。
我们不可能详尽介绍这些数据库产品的所有细节,甚至只是涵盖这个类别的各种数据库类型。仅仅是 NoSQL 数据库的例子就可以轻松填满一本这样大小的书。我们将尽力快速概述并提供足够的亮点,让您了解存在哪些产品、为何重视以及如何开始自己的产品调研。
MongoDB
无疑,在 NoSQL 领域的头号领导者是 MongoDB。MongoDB 被称为文档数据库管理系统。像许多我们提到的数据库管理系统一样,MongoDB 可以使用多个数据库引擎,但如今几乎所有使用它的人都使用其WiredTiger数据库引擎。文档数据库是最接近关系数据库的 NoSQL 数据库类型之一,许多情况下两者都能胜任。文档数据库几乎就像我们把关系数据库和传统文件系统放在一起,它们在中间相遇。
文档数据库
文档数据库存储结构化文档。尽管每个文档数据库可以使用自己的格式和方法,但这一概念是通用的。一个好的例子是 XML。XML 可以是文档数据库中单个文档的格式。数据库可能会规定 XML 的结构,或者它可能是自由格式的。数据库可能包含数百万个这样的 XML 文档。
由于数据库知道其包含文档的预期用途,因此它能够使用文档中的共同字段生成索引和其他工件,使数据库能够执行更多操作,远超过你将这些 XML 文档简单保存到硬盘上所能做到的。
但只需要像这样的一个简单例子,你就会开始明显地意识到文件系统不仅仅是一个数据库,而是一个专门的文档数据库!
文档数据库通常易于使用,非常直观,使开发人员和系统管理员的工作变得轻松。它们已被证明是关系型数据库在许多常见工作负载中非常理想且有效的替代品。
MongoDB 在各种不同的场景中得到了广泛部署和使用。像我们最初提到的大多数关系型数据库示例一样,MongoDB 通常与第三方软件包一起使用,也会在 Linux 发行版供应商的软件包中出现,同时它也在内部软件团队进行定制开发时仍然很受欢迎。如果你打算在 Linux 上开始尝试 NoSQL 数据库,我通常会建议你从 MongoDB 开始,因为即使 MongoDB 最终没有成为你在生产环境中支持的数据库管理系统,它几乎肯定会提供最有价值的经验。
MongoDB 是探索许多替代数据库方法的绝佳途径,其中许多方法在 关系型之后 的世界中已经成为某种标准。
虽然文档数据库已被证明是关系型数据库在常见软件使用中的最常见替代方案,但并不是很多文档数据库都崭露头角。MongoDB 是唯一一个真正的大型、知名的例子。其他例子包括 Apache CouchDB 和 OrientDB 作为数据库管理系统,以及 NeDB,它是一个数据库引擎,数据结构几乎与 MongoDB 完全相同。
Redis
存储数据的另一种完全不同的方法是 Redis,它是一种所谓的键值存储数据库管理系统。这种类型的数据库作为辅助存储而非主要存储更加流行。键值存储的思想是,使用该数据库的应用程序提供一个键,数据库返回与该键关联的数据。与我们已经遇到的数据库类型相比,它是一种极其简单的机制,但却是非常有用的。
键值存储(有时称为字典查找)常用于高速在线缓存,是管理如会话数据等数据的一种极好方式。虽然应用程序仅使用键值数据库作为唯一数据存储机制的情况很少,但也不是不可能。几乎总是作为多部分数据库策略中的一部分。
Redis 为巨型在线应用提供了许多所需的高级功能,例如跨节点集群的能力和方便的访问方法,这使得它在大型应用中非常受欢迎。它的性能和简便性使其在网页托管领域广受青睐。
其他的键值存储仍然很受欢迎,例如memcached,它在 Linux 上用于网页托管非常流行,LevelDB,甚至是MS SQL Server下的一个键值数据库引擎。
Cassandra
一个与关系型数据库和文档数据库在通用应用领域的主要竞争对手是宽列数据库,最著名的就是 Cassandra。宽列数据库比我们在这里能涵盖的要更值得关注和描述,但无需多言,它们主要处理与关系型数据库相同的工作负载,并且在大多数情况下关注于更大的灵活性和可扩展性。
与 Cassandra 一起,Apache HBase和ScyllaDB是常见的 Linux 下的主要宽列数据库。你不会像看到键值和文档数据库那样频繁遇到这种类型的数据库,但它有一定的市场份额,且易于获取和实验,如果你希望扩展自己对数据库特性或类型的了解,它是个不错的选择。
更进一步:NoSQL 并不局限于定义,专用数据库和数据库类型不断涌现。我还建议你调查一下Amazon OpenSearch,这是一个搜索数据库,以及InfluxDB和Prometheus,它们是时间序列数据库。这三种数据库,以及这两类数据库,通常用于以高速和大容量存储日志或类似日志的数据。
不要害怕自己去搜索新的或有趣的数据库方法和产品。这个领域发展迅速,书本的内容很快就会过时。Linux 在数据库平台方面在市场份额、稳定性、性能和多样性等各个方面都是领先的。你应该对主要的产品有所了解,知道自己发行版中包含哪些内容,以及你的应用程序可能使用哪些数据库。同时要对你需要投入的工作有一个大致的了解。记住,一些组织会继续使用专职的数据库管理员来处理与系统管理团队分离的数据库任务,但几乎所有公司都会将这些角色合并,导致你需要理解多个数据库平台的情况通常会落在你身上。
我们现在对在 Linux 系统管理的实际环境中可能遇到的产品有了很好的理解。所有这些数据库概念都很有趣,并且很激动人心,能够接触到许多不同的产品总是令人兴奋,但真正重要的是我们如何保护这些系统,这也是我们在下一部分将要讨论的内容。
理解数据库复制和数据保护概念
从 Linux 系统管理员的角度来看,数据库保护将是最重要的事情,这包括,正如它对系统整体所做的那样,灾难避免和灾难恢复。因为数据库至关重要,而且非常普遍,此外它们的需求与我们通常在系统中遇到的需求截然不同,所以我们在这里单独讨论,以便能够处理与数据保护相关的数据库世界几乎独特的需求。
因为数据库存储的是结构化数据,所以它们面临着保护那些高频使用的存储系统的所有挑战,实际上它们就是这样的存储系统。由于数据库高度有状态,我们必须非常小心,以免在进行数据保护时破坏状态。
这些在最简单的术语中是什么意思?基本上,数据库就是用来存储数据的,为了有效地进行数据存储,它们需要同时保持代表其数据的文件在磁盘上打开,并且通常在任何给定的时间都要在内存中保持大量的数据。这给我们带来了在数据保护方面的几个挑战。
打开中的文件始终是备份的难题。没有好的方法来备份当前被应用程序打开的文件,因为我们无法知道文件写入时的状态。也许文件目前是完全正常的,或者可能它已经被部分修改,数据是乱码,直到更多的当前内存数据或可能尚未计算的数据被添加到文件中,或者文件的格式没有损坏,但文件中的数据已经不再准确。从使用该文件的应用程序外部,我们无法知道一个打开文件的实际状态,除了它无法被信任以外。
因此,大多数基于文件的备份将会忽略该文件,因为它们无法锁定文件进行备份。对于大多数文件来说,这并不是问题,因为文件只偶尔被锁定,如果你定期进行备份,通常会最终获得某个文件的有效备份。这可能不是确定性安全的,但它是统计学上安全的。如果你需要确定性,你可以使用日志查看关键文件是否已经安全备份。
基于块的备份,也就是从块设备层而不是文件层进行备份,并且不关注单个文件或文件系统的机制,能够轻松地备份打开的文件,但它们无法判断文件是否处于安全或准确的状态。所以,在第一种情况下,我们假设打开的文件会被简单跳过。在第二种情况下,我们假设会备份它,但该备份的准确性只能在恢复时确定。当然,这两种选择都不是理想的。两者都比什么都没有要好。
传统的将也许我们有一个好的备份或我们几乎总是有一个好的备份转变为完全知道备份是好的方法是使用一个代理,该代理通知应用程序完成事务,将所有数据写入磁盘并在备份操作期间关闭文件。有些应用程序具有执行此操作的机制,API 调用会通知它们准备进行备份,而对于其他应用程序,你需要通过暴力方式,在备份之前完全关闭应用程序,并在备份完成后重新启动它。这里的问题是,只有极少数应用程序支持这种通信方式,而任何备份软件代理必须分别支持每个独特的软件才能做到这一点。所以,这需要双方的合作,考虑到市场上应用程序和备份工具的数量,这种合作并不常见。因此,这种方法是不切实际的。
许多应用程序采取的做法是通过执行内部数据转储过程来获取它们自己的备份,并以安全的方式将数据保存到另一个存储位置。这些文件是应用程序中所有数据的完整副本,并且保持关闭状态,仅供备份软件读取和使用,而不是使用实时数据。这为绕过因打开文件导致的数据损坏问题提供了一种通用机制。它易于应用程序开发人员实现,并且与所有备份软件通用。
这种方法完全有效,但有一个重大警告:我们必须关闭应用程序才能使其工作。这意味着我们必须有一种方法,能够在正确的时间关闭应用程序,并在正确的时间重新启动它。这个部分通常是可行的,并且不需要太多工作,尽管除了少数常见的应用程序外,通常都是手动操作。但真正的问题是让组织同意定期关闭应用程序,以便进行备份操作。不同于系统重启,我们通常只希望每周或每月进行一次重启,我们通常至少希望每天进行备份,有时是每小时一次,甚至几乎是持续备份。这并不是我们总能做到的事情。
除了预定备份频率之外,通常我们还希望能够随时进行临时备份。如果临时备份会导致应用程序停机,这通常是不可接受的。因此,需要其他方法来处理。
所有这些因素共同作用,使得数据库备份成为一个严重的问题。数据库几乎总是你 IT 基础设施中最关键的幕后工作负载组件,最无法承受任何长时间或意外停机的影响,通常也是唯一需要无限期保持文件打开的组件,并且备份对它们来说至关重要。
这个挑战远远超出了备份问题。如果我们处理的是无状态的应用程序,而不是数据库,例如典型的网站,我们有许多复制选项,可以简单到仅仅是将应用程序目录在服务器之间复制。负载均衡选项可以简单到将部分流量引导到一个应用服务器或另一个应用服务器。在大多数情况下,非数据库应用程序的复制、备份甚至负载均衡都很简单。
对于数据库,我们没有简单地在系统之间复制文件的选项。为了确保数据一致性和更新,运行在每个主机上的数据库管理系统需要相互协调,确保诸如锁定、缓存和磁盘刷新等概念能够一致地执行,并在集群中进行通信。如果复制功能对你所使用的数据库管理系统来说是可选的,它通常相当复杂,并且有很多限制。没有简单的方法能够在不引入显著性能挑战的情况下实现数据库的复制或集群。
因此,既要保护数据库免受故障影响,又要确保在出现故障时能够轻松可靠地恢复,这是一个挑战。尽管实现这一目标的技术在最高层次上可能有些共性,但它每次都需要在特定工具层面上进行配置和应用。所以,了解一个生态系统如何处理这些问题,并不一定能反映到另一个生态系统中。
在所有情况下,备份、复制和集群将由数据库管理系统本身或专门为该数据库设计的工具来处理。系统的功能将是该数据库独有的。例如,一些数据库管理系统仅支持非常简单的集群,可能只是通过一对镜像服务器,或者仅支持单个节点能够进行磁盘修改,而集群中的其他节点则保持部分或全部数据的缓存副本,并负责提供读取请求。另一些系统具有巨大的可扩展性,可能允许数百个独立节点,每个节点都能完全读取和写入数据!
因此,由于这种复杂性,我们必须完全单独学习每个产品。NoSQL 数据库有一种强烈的tendency,即具备复制和冗余选项。这通常源于缺乏控制和约束。此外,大多数 NoSQL 数据库是在近年来构建的,而大多数关系型数据库则已有几十年历史,因此它们设计时的考虑因素截然不同。今天你所了解的大多数关系型数据库首先必须适应网络,然后是互联网,这一过程持续了许多年。几乎所有你将遇到的 NoSQL 数据库都是在互联网成为日常生活的一部分之后几十年才创建的。
在许多情况下,将数据库放入集群中时,会通过锁定数据库的某些文件、记录、文档、行或其他离散部分来工作,并向其他集群成员发出锁定信号。然后,原始系统等待所有成员以确认锁定的方式进行通信。一旦被锁定,系统就无法写入新数据到系统的至少某个部分,必须在解锁后才能继续执行数据存储请求。在某些情况下,这种锁定可能非常快速,或者可能对存储产生足够大的影响,从而影响应用程序的可用性。在单服务器数据库上执行此操作可能会产生显著影响。在集群中,由于集群节点需要相互等待以完成其锁定任务并相互报告,这种影响可能会放大很多倍。如果我们还需要在等待互联网延迟和可能发生的故障时进行相同的操作,锁定操作的潜在影响规模可能会再次放大很多倍。锁定可以确保一致性,但总是以性能和复杂性为代价。我们的数据库系统越大,即使是锁定系统的一部分,其潜在影响也越大。
传统上,尤其是在关系型数据库中,我们假设通过纵向扩展来提高性能——即增加更多的 CPU、更快的 CPU、更多的内存以及更多或更快的存储。这种方式在我们需要中心化地访问数据时非常有效,直到我们能够不断将更多、更快的 CPU 压入一个单一的盒子中为止。之后,我们就会遇到性能瓶颈,卡住了。
如今,我们越来越多地看到分布式设计,即向集群添加更多的较小节点,就像我们在早期章节中讨论的那样。关系型设计并不完全无法使用这种模型,但在期望写入和读取操作与系统扩展时,它们往往难以高效运行。NoSQL 已经采用了这种数据访问需求,并以非常高效的方式进行了处理。新的数据库从头开始设计,以此为基础,通过在顶层(例如通过 SQL 语言查询)提供通用关系接口,为旧设计增加了新的性能选项。
数据库集群引入了新的潜在数据保护计划复杂性。根据数据库和数据完整性设计,备份或复制操作可能需要一些戏剧性的措施,例如在备份过程中暂时冻结整个数据库集群。或者可能需要从各个节点收集数据,每个节点都包含独特的数据,以组装完整的备份数据,这些数据在备份操作之前在任何一个位置都不存在完整。这种方法通常称为分片数据库,从逻辑上讲很有挑战性,因为可能存在一定规模的数据,没有节点能够很好地处理,而且数据恢复也可能很复杂,因为数据必须重新输入到集群中并分发到节点上。重新组装数据可能是一项艰巨的任务。其他数据库可能只是随机应变,提供它们所拥有的备份,而不与其他集群节点进行检查。这一切取决于数据库及其设置。
当处理数据库集群时,有许多考虑因素。虽然我们可以在这里讨论高层次的方法,但在现实世界中,每个数据库甚至数据库部署都是独特的。我们需要查阅有关独特设置的文档,并注意确保整个收集和存储数据过程的一致性。
我们还必须考虑直接数据库引擎的情况,这些引擎不包括数据库管理系统。在这种情况下,没有数据库管理系统来创建一致的备份文件到磁盘或处理复制。任何数据保护功能都需要由使用数据库的应用程序处理,而不是由数据库产品来完成工作。对系统管理员来说,这种情况非常困难,因为每个应用程序都可能非常独特和具有挑战性。当然,我们可以随时通过关闭应用程序甚至整个服务器来进行备份,但这不是一个理想的过程。
使用数据库引擎时,如果我们希望在不关闭系统的情况下实现任何数据保护功能,我们需要依赖相关应用程序提供这些功能。这可能提供最佳的数据保护选项(当然,也包括在数据库管理系统上运行的应用程序提供类似功能),因为应用程序本身通常会拥有对数据库的独占访问权限,并且对整个应用栈的当前使用案例有全面了解。理论上,应用层凭借其对系统状态和预期使用案例的额外了解,可以在更有意义的时间进行备份,并以更动态的方式存储备份。
例如,应用层可以实时复制部分数据,只有那些被认为至关重要的数据,复制到一个任意的数据存储位置,可能是异地。也许它将数据记录在类似日志的结构中,以便重新创建。或者它知道何时会出现写操作的停机时间,并且可以锁定数据库,并用比数据库管理系统本身更智能的方式进行复制,或者应用层可以在将数据写入数据库存储之前,跨应用节点复制事务以确保一致性。应用层凭借其更深的洞察力和灵活性,可以使数据存储层变得更好。
应用层备份有可能做出一些有趣的事情,比如基于一天中的空闲时间进行备份,并能够自动化备份和恢复。如果应用程序允许,自动化新节点的设置将是一个巨大的好处。
正如在数据库集群的情况中所说,每种情况可能是独特的,并且需要了解应用程序,了解它为数据完整性提供的支持,并结合我们自己的知识,确保能够实现一致且完整的数据集。一个集群化的应用程序可能会呈现与集群化数据库相同的挑战和机会。
总结
数据库几乎是我们作为系统管理员需要处理的最重要的事情。无论是我们自己运行数据库,还是仅仅管理运行数据库的操作系统,它们都将需要我们更多的关注,并且比我们做的任何事情都更容易给我们带来压力。在处理数据库时,我们的技能和专业知识将变得尤为重要,且我们的技能范围在这里将会受到最严峻的考验。
无论数据库在哪里运行或使用,我们都需要评估数据如何存储在磁盘上,如何确保一致性,以及如何将这些一致的数据移动到备份位置,无论是磁带、在线存储还是其他。这可能是我们在系统管理中做的最重要的任务,无论是在 Linux 还是其他系统上。
我们关于数据库的最佳实践真正集中在数据保护上。我们很想讨论如何选择适合我们执行的任务的正确数据库类型,但除了最少数几种情况外,这些决策通常在任何事情到达系统管理团队之前就已经做出了。
数据库备份的最佳实践是确保使用完整、一致、完全安全的、封闭的数据集作为备份源,以确保数据保护是可预测的。无论是由数据库、使用数据库的应用程序,还是手动处理,都必须有一个机制,确保在数据获取时数据不会处于传输中。
在集群场景中,同样的逻辑适用。但现在我们必须确保,在整个集群的上下文中,节点可以访问的数据是准确且完整的。
在下一章中,我们将开始深入探讨那些不那么引人注目但极其重要的领域——文档、监控和日志记录。
第三章:有效系统管理的方法
第三章的目标是退一步,从业务背景出发,将其应用于我们对 Linux 管理的视角。通过这个背景,我们将以更好的方式考虑许多流程和设计决策,并展示传统思维如何常常未能适应现实世界的业务需求。
本书的这一部分包括以下章节:
-
第七章,文档编写、监控和日志记录技术
-
第八章,通过脚本和 DevOps 自动化提升管理成熟度
-
第九章,备份与灾难恢复方法
-
第十章,用户与访问管理策略
-
第十一章,故障排除
第七章:文档、监控和日志技术
现在我们进入了系统管理工作的真正核心部分,尽管我认为大多数人会觉得这只是基础。在本章中,我们将处理那些没人能在我们的服务器上看到的系统管理部分。这些是我们工作中几乎看不见的组成部分,虽然它们至关重要,但却能将初级人员与高级人员区分开来;当事情开始出错时,这些额外的步骤能带来决定性的差异。
在本章中,我们将学习以下内容:
-
现代文档:Wiki、实时文档、代码库
-
工具和影响
-
容量规划
-
日志管理和安全
-
警报和故障排除
现代文档:Wiki、实时文档、代码库
关于文档的一点是,大家都承认它很重要,大家都在谈论它,但几乎没有人去做,或者即使做了,也没有保持更新。文档无聊,往往比看起来更难做得好,而且由于几乎没有管理层会跟进并验证它,极其容易被忽视。因为优秀的文档没有人会因此晋升,没有人举办文档派对,也没有人会在简历上提到它。文档就是没有足够酷,人们不愿花时间讨论它。
尽管文档可能感觉不太酷,但它在许多方面都非常重要。它能够极大地帮助一个人从合格的系统管理员变成一个优秀的系统管理员。
文档具有一些有趣的功能。当然,它可以帮助我们回忆起系统如何运作以及需要执行哪些任务。它允许我们将任务交接给他人。如果我们度假、生病、跳槽甚至退休,它还能够保护公司。但除了这些显而易见的点外,文档实际上迫使我们以不同的方式思考我们所维护的系统。
在软件工程领域,编写测试用例再编写要测试的功能这一新技术已变得流行,并且证明它能够促使人们以不同的方式思考如何解决问题,从而提高效率。在系统管理中,我们也有类似的好处。更积极地进行文档编写能带来更快的流程、更好的规划、更少的时间浪费和更少的错误。采取“文档优先”的方法,即在系统构建或配置之前先编写文档,能帮助我们以不同的方式思考系统设计,并进行充分的文档记录:这是一个有意识的文档编写过程,目的是记录应该做的事情,而不是记录我们做过的事情。这提供了一种完全不同的思维方式,一种验证真实性的方式,以及一种促进文档完整性的实际过程。
如果我们强迫自己在将信息输入系统之前就进行文档记录,我们可以提高数据准确性和完整性的机会。避免回过头去试图记住在系统上所需的或已完成的所有内容是很重要的。使用文档优先的流程,我们有机会在实际使用文档时捕捉到遗漏的部分,这可能仅仅是在几分钟之后。如果我们先工作再进行文档化,就很容易忘记一些小细节,而且没有触发事件提醒我们验证文档中是否有遗漏。相反,如果我们先进行文档化,当需要将数据输入系统或配置时,就会有一个触发事件,提醒我们应该从文档中提取出相关内容。这并非万无一失,但比传统流程更为可靠。
没有人真正反对,至少在礼貌的场合中不会反对,文档是必要的,或者它是我们作为系统管理员,甚至在信息技术领域工作的过程中最重要的事情之一。它几乎成了我们反复提到的口头禅,然而很少有人真正将这个决定内化。相反,我们只是口头上承认文档化一切的重要性,却依旧将文档作为次要问题推迟到明天做,前提是如果在某个虚构的空闲时间感到无聊时再做。这正是问题所在。我们不能仅仅声称相信文档至关重要,我们必须真正相信并相应地采取行动。
我们可以整天讨论文档的重要性,但真正重要的是将这些知识付诸实践,无论对你和你的组织来说,这种实践的方式是什么。为了更有可能取得成功,我们需要使用好的文档工具。高门槛的文档要求会让我们回避它,或者认为它在正确的时间完成太过耗时。如果我们让文档变得快速且简单,我们更可能会去做,甚至可能在某种程度上享受这个过程。我个人知道,当我的文档完整且及时更新时,我感到非常满意——有那种随时可以把它展示给别人,并且对其中的内容感到自豪的满足感。
在选择文档平台时,我们需要考虑许多因素。文档将如何存储、备份、保护、安全、访问?将存储什么类型的数据:文本、音频、图像、视频还是代码?将有多少人使用它?你是否需要在办公室内部访问它?在多个办公室之间?全球范围内?是否需要第三方访问它?
维基
在过去的二十年里,维基已经成为文档的事实标准工具。维基的设计围绕快速和易于编辑展开,而在这方面它表现得尤为出色。维基传统上还使用简单的标记语言,例如 MarkDown 语言,这使得它能够在不被格式化系统篡改的情况下精确存储文本和技术数据。这会带来一个小小的学习曲线,但通过学习一些非常标准的技巧,能迅速制作出非常精确、格式良好的文档。
维基格式注重简单——尽可能简单的系统,仍然允许足够的格式化,足以用于几乎任何文档任务。这种简单的格式使得市场上有各种各样的维基产品,能够满足几乎任何特定需求。从小型、轻量级的免费开源产品,你可以自己运行,到大型的托管商业产品,你只需要注册并使用。它几乎涵盖了所有的需求。任何规模的组织都可以有效使用,并且几乎总是有与其他系统集成的维基选项可供选择。
维基通常会面临一定的组织需求,而这一点并不是平台的本地特性。维基的优势在于它既快速又灵活,但这也是它的一个重大弱点:数据过于容易被丢到不属于它的位置,并且没有留下任何能够再次找到该信息的痕迹。有些维基会超越基本功能,包含元数据标签选项或结构化数据组织选项。这些都是例外,而不是常态。
多年来,维基一直作为更大产品的组成部分,甚至是基础组件。一个很好的例子是微软的 SharePoint,它使用维基引擎作为核心渲染引擎,所有的界面细节实际上都是在维基之上渲染出来的高级组件。
维基的一个典型问题是,它们很少能够让多个用户同时修改相同的数据。它们的简化设计通常假设在编辑期间会有一个简单的使用场景——单一作者,唯一的读者。这使得维基在单用户环境中更加有用,或者在用户很少同时使用文档平台的环境中,或者在不同用户往往彼此隔离的组织中,这样他们就会在不同时间使用不同的文档页面。如果你的团队需要多个人同时进行实时编辑或查看更新的信息,那么其他文档选项可能会更适合。
实时文档
最新的文档处理方式看起来更像是倒退了一步:文字处理器文档。是的,你没看错。听我慢慢道来。
传统上,在 90 年代末和 2000 年代初,使用文字处理文档作为文档资料似乎是荒谬的,除非你是一个非常小的公司,只有一个人需要使用和访问这些文档,这种情况下,存储所有内容为文件相对容易。近年来,随着新技术的发展,几乎所有主流文字处理器已经变成了在线、基于 Web 的、多用户工具,这些工具在表面上仍然像早期的文字处理器,但在可用性或技术上大有不同。
这些下一代文档系统提供了一个令人惊讶的强大且稳健的机制,供文档用途使用。虽然没有统一的标准规定这些系统应如何运作,但一套合理的约定已经出现,并且被所有主要系统遵循,这些系统既有商业版,也有免费开源版本,并且可以在托管或自托管模式下使用。对我们来说,最重要的是这些实时文档能够被多个用户同时编辑、实时显示更改、拥有安全的访问控制、跟踪更改,并且使用可以轻松在线发布或在任何需要的地方发布的 Web 界面,同时能够将文档输出为易于携带或转移的多种格式。
现代文档处理系统,如此类系统,通常会在后台使用数据库,而不是依赖于一组单独的文档,只将单独的文档作为一个单一、大型数据集的视图,而不是完全独立的数据集。这些系统变得越来越强大,可以轻松融入其他文档管理或替代工作流程。今天几乎所有的组织都已经在处理其他业务部分对现代文档系统的需求,这些系统可以轻松地将系统文档加入其中,而不会产生任何额外的成本或努力。利用已有系统进行更多操作,是以低成本获得高价值的好方法。
由于这些现代文档系统允许多个用户同时在同一文档上进行编辑,它们在多个团队成员同时为单个客户或系统工作时尤其有用,而文档需要共享。在这种情况下,一个人所做的更改会保持所有人屏幕上的数据实时更新。文档系统本身变成了团队协作的机制,而不是因为某个人没有刷新视图而使用过时数据的风险。
类似数据的替代界面
随着这类工具越来越受欢迎,针对类似数据库驱动文档数据的替代界面开始出现。像记事本应用这样的流行替代格式开始变得更加流行。这些格式比传统的文字处理和电子表格工具知名度低,但对系统文档非常有用。
由于多媒体和经常变化的临时性质的文档,期刊风格的应用可能是理想的选择。随着时间的推移,我预计会看到更多围绕灵活文档设计的应用成为主流。
就我个人而言,我已经成为这些系统的忠实粉丝。它们利用几乎所有员工都已经熟悉的标准工具,这些工具很可能已经被用于许多其他用途,并重新调整它们的方式,非常适合它们。少量的再培训,更少的特例工具管理,以及易于访问和团队使用频率较低的易用性。
仓库
文档化的新标准是使用在线代码仓库系统。这些系统通常从一组松散格式的文本文件开始,但它们会集中进行更新和版本控制。这与之前给出的示例方法非常不同。这个系统并不解决团队成员之间的实时协作,但确实很容易使用标准开发空间中使用的工具进行离线使用。
文档领域对版本控制代码仓库的使用成为关注点的真正原因是,它已经在开发和 DevOps 领域被广泛使用,因此是一个自然的系统,适合用于 IT 文档化。使用本地阅读和写作工具轻松使用文档离线,并且还能够在线拷贝,使其非常灵活。
现在开始有办法甚至使用这种类型的文档在一些较新的编辑工具中以实时共享的方式使用。随着更多关注于扩展这一过程的鲁棒性,我们可能会看到这方面的显著进展。
票务系统
正如我们讨论的传统文档,实际上是状态文档:记录系统是或至少应该是的方式。还有更多需要记录的内容。我们应该使用的另一个系统是一个票务系统,或者换个角度考虑,变更文档。
票务系统是一种文档化工具,类似于你的 wiki。与 wiki 不同,票务系统专注于记录事件发生的时间点。它们记录错误、问题、请求、观察、反应、变化、决策等等。与传统文档不同,后者是最终的文档,展示了所有决策和变更的结果,直到当前时间;而你的票务系统应该反映你的系统和工作负载的历史,从而理论上可以回放事件的发生,不仅知道系统做了哪些更改,还能知道是谁做的、是谁请求的、谁批准的,以及为什么要做这些更改。
当票务系统使用得当时,它在系统管理员的工作中扮演着重要角色。虽然没有一个好的票务系统也能运作,但这样会增加很多不必要的工作。使用票务系统追踪分配的任务、完成工作的过程以及最终的处理结果,提供了文档化中缺失的一部分。
如果你的公司没有票务系统或不支持票务系统,考虑为自己实施一个私人票务系统。票务软件有很多种形式和种类,如果无法花费资金升级产品或增加更多功能,也有免费的软件和服务可以使用,效果相当不错。如果你觉得更合适,可以把你的票务系统当作一种个人工作日志工具。
如果无法获得高层的支持,或者它与公司运营的方式不符,你不必过度尝试将票务系统融入到公司更大的工作流程中,但很难想象任何一个 IT 部门不会从能够追踪 IT 变更事件中受益,包括被拒绝的事件,这能帮助展示部门的历史和活动,追踪由系统变更引发的潜在问题。
就像传统文档一样,票务系统有各种不同的形式和大小。试试看几个不同的系统,给它们一个机会,不要害怕切换到其他系统。找到一个适合你的系统,使你能够有效地记录你所做的更改,何时做的,更改花费了多少时间,为什么要做这些更改;所有这些都尽可能地减少工作量。
如何处理文档
很可能你今天的工作中有一些文档。更有可能的是,这些文档是不完整的、过时的,基本上没有用。没关系,几乎所有公司都面临着文档管理不善的问题。但这也是一个巨大的改进机会。
如果你像大多数企业一样拥有文档,最好的做法往往是从头开始。审视你的选项,思考公司如何需要处理文档和协作,并选择一个方法。这个方法甚至不需要是正确的。任何文档处理流程都是好的,即使你可能需要重新做一遍。选择一个系统并试试。看看它是否适合你需要存储的数据风格,使用起来是否方便,并且是否能支持你的企业所需的协作方式(如果有的话)。
不要试图立刻记录所有的内容。从一个系统或工作负载开始,尝试以非常好的方式记录这个项目。将它格式化得好看一些。组织数据,使得你需要的数据可以快速、清晰地在顶部显示,以便在解决问题时,别人不需要到处找才能找到需要的信息。去除冗余,确保数据只出现一次,且出现在单一、可预测的位置。把文档当作一个需要一定规范化的关系型数据库,第一个主要步骤是组织,第二个步骤是去除冗余。文档始终难以维护,数据的冗余几乎让维护变得不可能。试图更改同一信息的未知出现位置,无法提供找到所有信息和需要更新内容的线索。
当你找到适合自己的系统和流程时,就坚持下去。开始记录所有内容。把它作为一项重要任务,做任何事情之前都要有文档。增加工单,并开始让一切都被跟踪。
也许你在一家文档已经做得很好的公司工作。然而,通常情况下,你并不是。即便如此,如果你现在在一个这样的公司工作,可能将来再也不会遇到这样的地方了。良好的文档是稀有的,尤其是在我们还没有考虑到工单在整个文档体系中重要性之前。
对于使用哪些工具以及以什么格式记录文档,没有最佳实践,但有一些高层次的最佳实践需要考虑:
-
使用状态和变更文档系统来跟踪你系统的各个方面。
-
避免在状态文档系统中出现数据冗余(在变更系统中可以出现冗余)。
-
保持所有文档的更新和安全。
-
不要记录那些可以从其他数据中可靠重建的数据。
我们常常说需要对文档保持“宗教式”态度,大家都同意文档至关重要。然而,实际上从说到做是非常困难的。管理层很少在我们工作时验证文档,但他们会奖励完成其他工作的员工,并且对拖延表示不满。遗憾的是,通常我们职业生涯中最重要的方面,外界的人并不认为它们重要或足够有趣,因此它们往往被没有了解这些内容如何影响我们工作的人所忽视。
在下一节中,我们将从纯粹的手动系统跟踪转向开始使用工具来测量和跟踪系统,以便以更自动化的方式进行。
工具和影响
物理学的一个基本性质,以及工业工程中立刻学到的一条规则,是你不能在不以某种方式影响它们的情况下观察或测量事件。在计算中,我们面临着同样的问题。如果有的话,我们面临这一问题的程度比许多其他领域还要严重。
我们对系统进行更多的测量、记录或设置度量标准时,所需的系统资源会更多地被测量过程所占用。随着计算机的速度不断提升,能够进行测量而不会完全拖慢工作负载的能力变得更加普遍,现在我们甚至经常在操作系统度量之外,在应用程序内部追踪检查点。但我们始终需要保持对这种影响的意识。
有时,让我们拥有的系统尽可能快速地运行,而不是试图通过测量它们来判断它们的速度,可能更有价值。全速奔跑的短跑运动员比一边跑一边携带测量设备来检测速度的运动员更快。测量过程反而对他们造成阻碍。然而,获取更多反馈的短跑运动员可能会随着额外的知识不断改进。但你永远不会看到有人在试图跑过一只正在追逐的河马时(它们是最快且最危险的陆地哺乳动物之一,你知道的)先停下来开启测量设备。他们只会尽全力跑。知道如何跑得更快只有在它提供了潜在有用的数据,并且通过这些数据你能够实施改进时才有意义。而如果饥饿的河马追上你,那么所有的测量数据都将毫无意义。
不同的工具会产生截然不同的影响。有些我们在系统中使用的简单日常工具几乎不会产生任何影响,但一般只能给我们提供系统活动的极其高层次的概览。而其他工具,比如日志收集,可能需要大量资源,甚至可能对网络和存储资源造成显著的压力。
从系统中收集数据并不是唯一占用系统资源的活动。整理这些数据并以对人类有用的形式呈现它也需要资源,向外部系统传输这些数据同样如此。过程的每个步骤都需要我们使用越来越多的资源。在我们考虑检查数据所涉及的人工时间之前,这一切都已经需要大量的资源了。尽管我们总是很容易选择尽可能多地深入观察和监控系统,但除非我们能从这一过程中获得真正的价值,否则这样做实际上是有负面影响的。
一般来说,我们会在系统上使用各种工具来提供一定程度的常规度量。包括像 sysstat SAR 工具这样的数据收集工具,以及 top、htop 和 glances 等即时的、现场观察工具,它们让我们能够实时监控系统的行为。这两类工具都提供了巨大的价值。
当然,市场上有大量的免费和付费软件及服务工具,可以将你的监控工作提升到另一个层次。研究这些工具会非常有帮助,因为即便是开源工具,也已经变得异常强大和健壮。性能工具通常在本地处理,因为它们很少用于告警或安全考虑,且用来进行事后调查往往徒劳无功,因此为了性能数据的中央数据收集而产生的成本通常是不值得的。尽管如此,中央化工具仍然存在,并且在某些情况下非常有用。使用这些工具时,通常是为了便于人类操作,而非为了解决特定的技术需求。去中心化的工具能够选择性地利用“单一视图”界面,显示来自多个位置的数据,这些工具在这个特定需求上非常受欢迎。
Netdata
我通常不想深入探讨具体产品,但我觉得Netdata是一个非常出色的案例,能够展示当今市场上为 Linux 系统管理员提供的各种强大工具。
首先,Netdata 是免费的且开源的。因此,作为一个系统管理员,可能需要为任何软件购买提供合理解释,而这款工具可以免费下载并实施,从而增强我们的监控能力,而无需任何审批或通知。安装也非常迅速且简单。
第二,Netdata 提供了开箱即用的极具美感的仪表板。这些仪表板让我们的工作变得更加有趣。比如,当我们需要向管理层展示数据或在会议中展示时,几乎没有什么比 Netdata 的仪表板更能令人印象深刻和精美的了。这是一个让我们更容易向业务推销我们所做工作的工具。
第三,Netdata 使用的资源非常少。对于它所生成的惊人图形输出,你永远不会想到这样一个轻量级的工具能够做到这一点。
第四,Netdata 是去中心化的。它在每个服务器上本地运行,而不会将数据发送到中央位置进行收集。你可以将多个系统的数据汇总成一个视图,但这个过程完全在查看者的网页浏览器中进行,浏览器会主动从每个系统中拉取单独的仪表板并直接显示不同的系统。没有使用中央服务器来聚合数据后再显示。
我喜欢以 Netdata 为例,作为真正有用的、免费的、开源的、开创性的工具,它让我们在系统管理中的日常体验变得更加高效。它展示了一种模式,可能适用于许多其他产品和产品类型,从而使去中心化比初看起来更具可行性。
作为系统管理员,你要做的一件更为重要的事情就是学习如何选择工具、何时使用以及如何读取它们。我多年来发现的最有价值的事情之一,就是变得熟悉健康系统的表现,无论是在历史记录中还是实时状态中,并且能够通过查看各种工具,直观地感知系统的行为。除了谈论观察空闲系统、标准负载下系统表现的价值之外,很难有其他方法来教会这一点;当然,你对系统组件和软件工作原理的理解越深入,你就越能以有意义的方式解读你所看到的内容。
通过足够的练习和理解,基本上可以感知一个系统的行为,并对系统为何这样表现有一定的信心。这不是一本书能够教会的内容,而是需要投入大量时间与系统打交道,仔细关注你从监控工具中观察到的内容,并结合系统的性能观察,再加上对物理组件交互的深刻理解。
我发现一些短期工具,比如默认几乎所有系统都包含的top,是观察运行中的系统执行任务的完美方式,帮助我们习惯于如何在适当负载下,CPU 的使用率如何波动,进程如何变化,负载如何变化。有时,最复杂的系统故障排查仅需通过不断观察进程列表的变化(并适时截图)来完成。
这是一个能够显著区分初级和高级系统管理员的领域。它与了解基础知识的关系远不如将这些知识真正内化,并且能够在系统表现不佳时,或者仅凭别人描述问题的情况下,迅速直觉地运用这些知识!例如,硬盘在不同条件下的表现,CPU 在不同负载下的行为,缓存的命中情况,内存的调优,分页何时有利或不利等等。
理解所有这些因素是一个不断变化的目标。每个系统都是独一无二的,新一代 CPU 调度器、NUMA 技术、硬盘技术等常常会改变系统的表现,以及我们应对它们的预期。经验无可替代,获得经验的唯一途径就是实践。
选择工具可能很困难。除非我有非常具体的工作需求,否则我倾向于保持工具的简洁性。你应该尝试使用许多不同的测量工具,以便对可用的工具有一个良好的了解,并随时准备在需要时为自己和当前任务选择合适的工具。对我来说,许多情况下,像free、top和sysstat 工具集这样最简单的工具足以应对我所做的几乎所有事情,而且这些工具在我遇到的每个系统中都有超过十年的使用历史。但在我自己管理的系统环境中,你通常会发现我也会使用一些更具图形化和趣味性的工具,比如 Netdata。
最佳实践:
-
在你需要它之前学习测量工具,并学会迅速高效地使用它。
-
将测量工具的使用限制在真正有用的工具上。没有充分的理由,不要影响性能。
现在我们已经讨论了如何衡量我们的系统在做什么,接下来的部分将开始使用这些工具来规划未来。
容量规划
当我们将系统资源使用的知识从眼前的状态中抽离出来,并开始将其应用于系统的长期方面时,我们便开始思考容量规划。容量规划应该至少在理论上是系统管理中的一个相当重要的方面。然而,许多组织会将容量规划视为一种非技术性活动,将其从系统管理员手中剥离。让我感到吃惊的是,系统管理员常常告诉我,他们收到了自己没有指定的硬件,现在必须使其正常工作,尽管该硬件是由一个完全不了解其用途的人设计的!在系统管理中如此多的系统设计知识和培训被忽视,重要的采购也在没有任何道理的情况下进行。
购买时已经设计好
我经常遇到的最奇怪的问题之一是系统管理员问我,应该如何设置他们已经指定、订购并收到的硬件。最关键的是,他们问如何配置 RAID 和逻辑磁盘的划分或拆分物理阵列。我总是对此感到惊讶。
显然,服务器的不同配置会改变其在硬件层面的配置需求。服务器运行的软件、软件的数量、软件所需的性能、所需的存储量、备份如何工作以及几乎所有与服务器在预期生命周期内使用相关的内容,都必须被充分理解,才能开始指定购买硬件的过程。你是如何知道要购买多少 RAM、多少核心、CPU 应该有多快、应该选择哪些 CPU 型号,甚至是哪些品牌适用的?在许多情况下,人们会因为过度购买而浪费大量资金,结果看似一切正常,因为这些错误表现为没人去调查的金钱损失。给定了服务器预算后,没有人跟进确定所购买的服务器是否物有所值,只关心是否在预算内。因此,过度购买往往是一种弥补未进行容量规划的方式,而这种方式可能会给公司带来巨额损失。
最显著的变化是 RAID 配置。当有人问我如果为这个项目专门购买了新的硬件,推荐哪种 RAID 级别和配置时,我不知道该如何回答。关于 RAID 配置的所有决策肯定是在购买服务器之前就已经做出。只有了解每个 RAID 级别的性能、可靠性和容量特征,并结合可用的物理驱动器和控制器选项,才能开始考虑购买服务器存储部分。
为了决定存储需求,首先必须了解自己的需求。然后,必须知道你指定的硬件如何满足这些需求。当有人说他们已经购买了硬件,但还没有指定任何设计时,以下是我脑海中浮现的一些问题:
你是如何知道该购买哪个硬件 RAID 卡?或者甚至是你是否需要硬件控制器?
你是如何确定购买多少缓存的?
你是如何知道哪些类型的驱动器最有用的?
你是如何知道需要什么速度的驱动器以满足吞吐量和/或 IOPS 需求的?
你是如何知道该购买多大尺寸的驱动器的?
你是如何知道该购买多少个驱动器的?
你是如何确定缓存容量的?
你是如何确定分层存储容量的?
你是如何确定热备份需求的?
做出这些决策所需的前提是必须先做出所有其他决策。最终的结果是整体的产物,例如,RAID 级别的任何改变都会极大地影响可用容量、系统性能和整体可靠性。每一个小的变化都会引发其他所有事情的变化。没有任何一项是可以单独决定的,更别提改变了。哪怕是最不起眼的变化,也可能导致系统容量不足,或者处理工作负载的速度不够;更危险的是,存储系统的可靠性可能在极端安全和极端危险之间剧烈波动。
很难形容这个过程有多疯狂;更疯狂的是意识到,这可能已经成为人们购买服务器的常态!我能想到的最好比喻是,就像为一辆 1978 年的法拉利买一个变速箱,却期望它能正常工作,而你甚至还不知道自己是买到一辆车、一艘船还是一架小飞机,更别提是什么年份和型号的法拉利了!
容量规划不仅仅是为了省钱,至少间接上是如此。它关乎确保我们购买的系统能够在合理的时间范围内满足我们业务的所有预期需求。显然,这是一个非常难以确定的数字,因为什么是合适的预期,未来可能会发生什么变化,以及为系统设定合理的时间框架,都是相当灵活的概念。
在商业中,使用空中楼阁式的数字作为硬件投资基础,并利用硬件的最大合理使用寿命进行计算,从而展现天文数字般的增长,已经成为一种常见趋势。虽然我们无法控制驱动企业运作的政治过程,除非在极少数情况下,但我们可以控制的是我们向决策者提供的数字质量。
晚些时候购买
好的商业逻辑告诉我们,除非极少数例外,否则 IT 中的所有成本随着时间推移都会下降。它下降得非常多。与几年前相比,今天内存、计算周期或存储的成本微不足道,这一趋势实际上从未停止过,也不太可能逆转。由于制造或物流危机带来的短期稀缺问题确实可能发生,但这些事件非常罕见且持续时间极短。只要有时间去做购买,几个月后的系统成本肯定会比今天更低。无论是我们花的钱变少了,还是我们为这笔钱得到的东西更多了,结果都是我们通过推迟投资来获得利益。
我们可以使用一个常见的例子:假设我们今天购买一台服务器,计划使用它八年,并且我们预期会有增长,因此我们购买一台满足八年需求的服务器。为了获得这样一台强大的服务器,我们今天可能需要花费$20,000,或者,如果我们只预期服务器能用四年,可能今天花费$8,000 就能买到。差距很大。当然,这是一个假设的例子,但在现实世界中,这类成本在许多常见场景中是非常典型的。
在这个例子中,我们假设在四年后我们可以再花$8000 购买一台新的服务器,满足接下来的四年需求。虽然这个例子有点牵强,但通常是成立的。成本通常会按这种方式计算。
购买更少、更短时间内使用的设备的优点是无法过分强调的。首先,由于服务器定价的特点,购买更少的设备、更加频繁地更换往往能节省硬性成本,因为现代服务器的运营生命周期内,会发生一些价格上的优惠。接着是货币的时间价值理论,这意味着如果你花费相同金额的钱,但推迟了支出,你就可以在此期间用这笔钱赚取更多的钱,而且未来你所花的钱,其价值比今天的钱要少。最后,还有更新的技术——如果我们等几年再购买新的服务器,我们可能会得到更多更新的技术,不仅能提升容量,还能带来更低的能耗、更好的耐用性等优势。
然后是拥有两台服务器的优势。我们假设第二台服务器将替代第一台,或许会是这样。但我们也可能只是用这次购买来扩展容量,第一台仍然可以继续投入生产服务。如果我们是替换第一台服务器,它可能会在组织内的其他角色中重新部署,或者作为新服务器的备份。几乎总是可以找到一种高效的方式来利用最初的投资。
最大的优势很可能在于延迟决策。通过推迟几年的开支,我们获得了在任何时候投资这笔钱的灵活性,甚至可以选择永远不投资。与其做一个八年的预测,这种预测极其不准确,甚至毫无用处,不如做两个四年的预测,虽然仍然相当不准确,但其准确性提高的幅度却是显而易见的。在第一个四年检查点时,我们可以评估上一个预测的质量,并根据新的数据和新的起点做出新的预测。我们不仅能根据四年的新见解重新评估自己的组织,还能获得四年内行业的变化和新技术的洞察。很少有公司会在四年后做出与今天相同的决策。在商业中,这种延迟决策的方式可能带来天文数字般的好处。
可悲的是,对于大多数企业来说,预测变成了一种情感上的练习,因为这样做有政治上的好处,能让人们感到愉快,并表现出对企业或领导层的信任;而且,想象自己必定会取得的成功也让我们感觉很好。而更好的预测通常意味着更大的影响力、更大的预算、更多的资源可以使用。这些资源会持续多年。几乎没有企业会回过头来评估过去的预测,看看人们是否做得好,所以过于乐观的预测会带来奖励,而且如果这些预测被为了个人利益(无论是情感、财务还是政治上的)伪造,几乎没有惩罚的风险。这种系统使得预测变得非常危险,因此,我们做任何能够减少对预测依赖的事情都很重要。
最终,推迟购买服务器资源直到真正需要时,是我们在技术采购中可以采取的最佳实践策略之一。从纯粹的财务角度来看,这种方法是最好的,从决策和规划的角度来看,也是最优的,最能让技术和制造进步为我们所用。
在这一过程中,系统管理将提供三个关键数字。第一个问题是 我们目前使用了多少资源? 第二个问题是 我们过去使用了多少资源? 第三个问题是 我们认为未来会使用多少资源?
事实上,回答这些问题中的任何一个都出乎意料地困难。仅仅统计我们今天所购买和拥有的资源并没有提供任何有用的信息。我们需要真正理解我们的 CPU、RAM 以及存储的各个方面是如何被使用的,它们如何影响工作负载。
例如,如果我们正在运行一个大型数据库实例,数据库可能会非常乐意将大量存储缓存到内存中,以提高数据库性能或减少存储磨损。但是,减少可用内存可能对数据库性能没有影响。正因为如此,仅仅测量内存利用率可能会非常复杂。我们使用了多少有效内存?存储比较容易测量,但也存在类似的挑战。CPU 是最简单的,但没有什么事是完全直观的。仅仅因为我们在某个水平上使用系统资源,并不意味着我们知道它们的实际需求程度。
在使用 CPU 时,我们可能会遇到一个系统平均 CPU 利用率为 50% 的情况。对于某个公司或一组工作负载,这可能意味着我们可以在该系统上放置两倍的工作负载,使其利用率接近 100%。而对于另一个公司或一组工作负载,这可能意味着我们已经超载了系统,系统出现了足够的上下文切换和等待时间,导致一些应用程序注意到延迟。许多公司通常以 90% 的利用率作为宽松的平均目标,但对于其他公司,可能需要将目标设定为仅 10%。
在这种情况下,权衡的关键是等待吞吐量还是延迟。可用的 CPU 周期意味着 CPU 可以执行更多的任务,但如果 CPU 始终忙于处理任务,那么当新任务突然到来时,它可能并不完全可用。如果你正在处理低延迟系统,确保系统资源随时可用以处理刚出现的任务可能是一个必要条件。为了评估系统的容量使用情况和需求,我们不仅需要深入了解系统被使用了多少,还要理解这些使用对工作负载的最终影响。
与系统管理的许多方面一样,关键是要全面了解我们的工作负载。我们必须知道它们是如何工作的、如何消耗资源、以及它们如何响应更多或更少的资源。我们在容量规划中的一切操作都取决于此。
当然,我们有一些前面提到的工具,能够帮助我们判断系统的性能表现,通过应用测量工具和/或人工观察,我们可以合理地确定当前工作负载所需的资源。
我们使用的许多工具也可以用来收集系统性能的历史记录。如果我们总是这样做,可能会产生大量的数据,而我们永远也无法准备好去利用这些数据。有些组织会一直收集这些数据,但这是例外,而非常规。更实际的做法是在大多数情况下随着时间的推移开发并跟踪基准。这通常意味着进行某种活动,记录测量数据,并记录系统的最终用户应用性能,以便你可以回顾并了解系统的利用情况。这些数据应该在长时间内收集。至少几周或几个月,以便找到热点和冷点。常见的冷点可能是在星期天的晚上,当许多应用程序根本不被使用时。常见的热点则是月末的财务处理时间。每个组织的利用模式都不同,你需要了解自己的模式。
有了这些收集的数据,我们可以分析系统利用率如何随时间变化。变化通常来源于应用层利用率的增加或减少。但这远不是唯一可能发生变化的方面。需要意识到的是,应用更新、操作系统补丁、系统配置变化等应当被记录并与数据记录一起标注,以使得这些数据在评估时更有意义。
长期的数据收集必须考虑到努力成本。收集数据并整理这些数据,无论规模多大,都可能非常耗时并且可能会消耗大量资源。收集了所有这些数据后,它可能不会提供有用的见解,或者分析它的技能可能缺乏。如果一个系统管理员在处理持续使用的系统时,能够凭记忆追踪系统性能数据,这是完全合理的。在某些情况下,这种做法会更为实际。
过多的数据开销的风险
在进行容量规划时,我们有可能创造一个情况,即我们为自己制造了更多的开销,这通常意味着更高的成本,甚至可能比如果一开始就没有收集数据的情况还要高。我们需要找到一个适当的平衡点。
大型组织通常会在大量数据收集中找到巨大的价值,从而在大规模上节省资金。在大规模的情况下,自动化数据收集和分析通常相对简单。小型企业则往往会觉得这种做法不切实际。收集单个服务器的任何合理全面的系统数据,可能会导致支出大到与系统本身的成本相当。显然,这是行不通的。常识必须占上风。
许多小型组织可能只有一个主要的工作负载,并且可能永远无法充分利用最小的服务器,从容量的角度来看,通常会过度配置,直到他们放弃使用自有硬件,若那时变得切实可行的话。大组织则是在运营大规模的服务器集群,他们有许多途径可以通过尝试不同的软件选项、使用更多小型服务器或更少的大型服务器、使用不同的处理器型号甚至架构等来改善整体成本。
节省开支的努力必须与数据收集的潜在价值保持平衡。这对于所有决策过程都是如此。要小心,数据收集是决策高成本的组成部分,你必须时刻记得保持这一成本远低于该决策的预期价值水平。
在评估数据收集的成本时,我们需要考虑收集数据的时间、存储成本和分析这些数据的成本。我们不能忘记,还得考虑考虑这些的成本!
有些供应商专门提供工具来解决这些难题,它们可能非常有效。戴尔(Dell)便是其中之一,著名的戴尔为客户提供可以长时间运行并生成非常详细报告的工具,报告内容包括系统如何使用,当然,工具也提供建议,但这些建议实际上是推销,目的是为了卖给你更多的产品。如果使用得当,这些工具可以非常有价值。
当然,自然的问题也会是“那么云计算呢?难道这不会改变一切吗?” 是的,考虑到云计算非常重要,它确实会影响这一过程。
随着云计算进入到组织的规划中,从某种程度上来说,我们需要考虑的复杂性增加了。从另一个角度看,云计算能够让容量规划过程变得更加简单,甚至可以说不再重要。
在云计算中,或者至少在几乎所有的云计算中,我们按需或几乎按需购买容量。这就是云计算的魅力。只使用你所需要的,让系统实时决定需要什么。这在理论上是很棒的。但仅仅让系统自行决定仍然需要我们预测这种方法的成本,以便在财务上与其他替代方案进行比较,并且预测成本以便正确预算。
如果你的组织目前正在使用云计算,这将大大简化我们的过程。通常,你的云平台本身能够告诉你大量的系统使用率信息。即使没有传统的报告形式,云计算的账单也常常能提供你所需要了解的关于许多类型规划的信息。
我们的容量规划最佳实践纯粹是数学性的。利用我们对系统和工作负载的合理测量和理解,以及对商业预期和来自其他团队的输入,来规划明天及未来的容量需求。研究并理解不确定性锥,结合对未来越来越难以预见的感觉以及对时间价值等金融概念的良好理解,使用这些来为你组织的未来容量投资需求提供最佳努力评估。
容量规划通常是枯燥的,且比技术性更具政治性,但这一角色很少有人能胜任,除非是系统管理员,因此,在专业生活中,它注定要让我们与系统硬件采购预测紧密相关。它本质上是我们企业内部的小规模计算未来市场。在下一部分,我们将从容量和性能需求转到安全和故障排除工具,首先是系统和应用日志。
日志管理与安全
如果你在酒吧和系统管理员闲聊,你可能会认为,系统管理员的主要任务之一是收集所有系统日志,并每天花费几个小时,手动且熟练地逐行查看日志,寻找系统错误和恶意行为者。现实情况大不相同。没有人在做这件事,也没有公司愿意为此支付费用。日志阅读是一项严肃的技能,且是一项极其无聊的活动。人类在这类任务上的表现非常差。
如果你试图让人类在没有已知系统问题的情况下实际读取日志来进行日志管理,你会遇到一些问题。首先,现实情况是,没有人类能以足够快的速度读取日志来真正有效地工作。系统记录了大量数据,试图跟上这种无意义信息的流动会使人类容易出错。然后是成本问题。任何足够熟练以处理这种日志阅读的人都会处于薪资的高端,且由于这一工作非常痛苦,它必须是一个高薪职位,而由于服务器通常是全天候运行的,你可能需要为每台服务器配备四到五个全职员工才能勉强做到这一点。这种成本超出了任何人的想象,完全不切实际,甚至可以说是毫无用处。因此,没人会这样做。
这并不意味着日志没有价值。相反,事实恰恰相反。日志非常有价值,我们需要收集、保护并知道如何使用它们。
在处理日志时,我们需要知道如何读取它们。这看似微不足道,但当你遇到紧急情况,需要读取日志时,那可不是发现自己不理解日志内容或如何解读它的好时机。Linux 上的系统日志相当一致。真正的挑战开始于不同应用程序也在记录日志时。这些日志可能是独立的,也可能被合并到其他日志中。每个应用程序负责自己的日志记录,因此当我们开始运行多个不同的应用程序时,日志的多样性可能会带来相当大的潜力。此外,如果还有定制的内部应用程序进行日志记录,事情可能会变得相当复杂。
在这里没有必要教你如何读取日志。这是任何阅读本书的人都应该非常熟悉的活动。不过,你现在应该做的练习是,浏览你的日志并确定哪些日志的格式对你来说是陌生的,确保你随时准备好读取任何系统日志,而无需在读取前进行额外的研究。快速高效的日志读取将大大提升你成为一名更好的系统管理员的能力。
仅仅知道如何读取日志是不够的。你还应该足够熟悉你的日志,以便识别正常活动的表现。当你先知道正常的表现是什么样子时,你将更容易识别问题。许多公司在问题发生后聘请专家来处理这些问题,但这样做会带来更多的挑战,因为没有日志基准来与当前的情况进行比较。
如果没有一个可靠的基准,定期发生的错误可能会浪费大量时间,因为诊断时间将被花在研究它们上,以确定它们是正常的日志噪声、真正的问题,还是正在诊断的问题的组成部分。当出现问题时,我们希望更加高效。这正是我们最不希望花时间去弄清楚正常表现是什么样子的时刻。
准备好直接登录到服务器并使用传统工具,如 vi、view、cat、head、tail 和 grep 来查看日志,始终是一个好习惯。你永远不知道未来会遇到什么样的情况。
在今天的许多现代系统中,我们期望看到围绕日志的广泛工具支持,因为我们可以做的远不止仅仅将日志存储在本地服务器上,并在发生问题后进行查看。
今天,日志记录是服务器系统中发生巨大变化和进步的领域之一。相比二十年前,日志记录已经取得了飞跃性的进展。像高性能的图形化日志查看工具这样的简单进步,使得查看日志变得更快、更容易。同时,还有先进的集中日志管理,将日志从服务器本身转移出去,还有自动化的日志处理。
无论日志是本地的还是远程的,现代的日志查看工具在我们使用日志的效率上都带来了巨大的改变。无论是使用本地桌面 GUI、终端上的字符界面会话,还是现代的 Web 界面,日志查看工具都在不断改进,在过去十年甚至更长时间里,它们使得阅读日志变得既愉快又简单。令人惊讶的是,只有极少数的组织提供这些工具或支持其使用,因此,系统管理员使用这些工具的情况比应有的要少得多。如果你和系统管理员交谈,不要感到惊讶,如果发现很少有人真正有机会在拥有超出基本系统日志文本文件和操作系统自带的标准文本文件处理工具之外的环境中使用日志工具。
良好的日志查看工具是日志管理旅程中的重要起点。让日志能够快速查看,使其查看过程尽可能简单和愉快。当事情出错时,你肯定不想花费比绝对必要的更多时间去访问日志或深入挖掘日志。你更不想在系统出现问题时,还在忙着安装日志查看工具。
日志查看应用程序只是大多数组织的起点。日志管理的真正飞跃发生在引入集中日志收集时。这才是真正的日志革命发生的地方。当然,即使回顾几十年,基础日志聚合的潜力和工具也早已存在。这可以简单到使用网络复制命令或网络映射驱动器将老旧的文本文件存储到中央文件服务器上。所以,集中日志的基本思想并不新鲜。
最初,集中日志的限制是服务器没有网络连接。后来是性能和存储问题。集中日志需要大量的网络带宽和存储容量,在某些情况下,对于日志服务器来说,这也是一个性能噩梦。那些日子早已成为过去。今天,随着我们系统各方面容量和性能的自然提升,这些问题变得微不足道,而日志的大小和复杂性增长却远远小于过去。如今,日志的大小其实并没有比几十年前大多少。
早期的日志集中化系统非常基础,无法优雅地扩展。大量聚合的日志数据对大多数系统来说是一个巨大挑战,因为它们需要能够持续从多个来源摄取大量实时数据,同时还能回溯并展示这些数据。
现代的日志集中应用程序都使用了围绕数据流和存储需求设计的全新现代数据库。没有单一类型的数据库被用于此目的,但许多新型数据库在处理这些需求时表现出色,它们允许传统上作为大型、笨重的文本文件存储的数据被压缩成更小、更高效的数据库条目,带有元数据、缓存、整理等功能,这些特性使得可以处理比以往更多的数据量,同时仍然能够有效地展示数据。这一变化,加上系统性能的整体提升,使得集中式日志管理不仅在局域网中得以有效实施,在许多情况下,甚至适用于托管服务器、云服务器或其他不在传统局域网中的服务器。
使用这种系统有几个好处。一个是日志读取的速度和效率。一个(或至少较少的)地方来查看日志意味着系统管理员比以前更快地查看日志,而更快的日志读取意味着更快的解决方案。通过将来自多个服务器、系统、应用程序等的日志集中在一个地方,我们还可以在这些系统之间关联数据,而无需人工查看来自多个来源的日志并手动建立这些联系。
新工具,如流量图,也让我们能够看到以前可能未能察觉的模式。如果多台计算机的日志流量突然激增,可能是应用程序突然变得繁忙,或者也可能是出现了故障或正在发生攻击。集中式日志工具不仅让我们更容易理解单个系统的基准是什么,还能帮助我们理解所有系统结合起来的基准是什么!这为系统理解增添了更多层次。
一旦我们将这些现代工具集中化,下一步逻辑就是使用自动化工具来读取日志。安全信息与事件管理(SIEM)是通常用于自动化日志监控工具的术语。日志自动化并不新鲜,甚至美国政府早在 2005 年就已经制定了相关规定。但对于许多企业而言,日志自动化远远超出了他们当前的计划或能力。
当然,像任何自动化一样,我们使用它的程度可以有很大差异。简单的自动化可能仅仅在日志中发生某些触发事件时发送警报,或对不符合特征的活动模式进行警报。复杂的自动化可能使用人工智能或威胁模式数据库,跨多个系统同时扫描日志,寻找恶意活动。
为什么要进行日志集中?
鉴于集中式日志记录带来了如此大的网络开销,并且实施成本通常很高,很容易质疑将日志集中到单个服务器或一组服务器的价值,而不是将日志保留在各个主机上并寻找更好的方法来检查它们的日志。这是一个非常合理的问题。当然,集中式日志记录并不适合每个组织。但它确实适合许多组织。
虽然许多进展使得中央日志记录比以往更具能力,但也有许多进展使得去中心化的日志记录变得更好,包括带有报告、告警、吸引人的用户界面的设备端日志查看器,以及显示来自多个来源数据的聚合工具,尽管这些数据本身分散在不同地方。
然而,中央日志记录提供了独特的优势。最大的优势就是数据不与设备绑定。如果设备出现故障、离线,或者设备被攻破,我们的日志就可以实现隔离。经常会遇到需要重新启动一台服务器并让其恢复运行,只是为了查看该服务器的日志。
如果服务器完全崩溃,我们可能根本不想再费心让它恢复在线。或者如果日志告诉我们发生了灾难性故障,我们可能就知道我们不应该尝试恢复已失败的设备。又或者,我们可能希望一个人专注于恢复失败的服务器,同时另一个人则扫描日志以确定导致故障的原因,或者确定恢复服务所需的条件。
如果服务器或应用程序被攻破,存在日志机制或存储系统也被一起攻破的风险。实际上,这种情况通常是非常可能发生的。修改日志以掩盖入侵是高级攻击中非常常见的手段,而简单的攻击则通常通过删除日志来实现。大多数情况下,日志会被攻击,因为它们是最容易识别入侵发生或正在发生的地方,并且可以判断如何进行缓解。如果日志中从未显示出攻击的任何迹象,你可能永远不会发现入侵已经发生。
如果我们将日志(无论是全部还是至少复制一份)实时发送到远程日志服务器,那么我们就可以将日志存储在与应用程序和服务器存储隔离的地方,并且通过气隙(air gap)使得若要修改这些日志,必须攻破一个完全无关的系统,且不能被发现。这比直接修改日志要困难几个数量级,特别是当任何外部日志系统的存在及信息通常在入侵发生时才会被发现,这时可能已经太晚,无法避免被检测。
由于日志不仅仅是查找错误的方式,更是审计和追踪安全漏洞、恶意活动、渗透尝试等的关键安全记录系统,因此,必须确保这些数据免受意外丢失和故意破坏。
日志分离的一个可能最重要的目的,至少在那些足够大的组织中,足以拥有多个 IT 团队时,就是职责分离。如果日志完全由控制服务器的同一个系统管理员(假设是你)控制,那么对日志进行重大修改并隐藏这些修改的证据就变得非常简单。如果日志被发送到一个我们不是管理员的外部系统,那么我们就很难隐藏这些更改,因为我们必须在不让日志记录失败的情况下,防止它们被记录下来。
对于这种级别的安全性,严格的职责分离听起来可能是大公司特有的事情,但即使是非常小的公司,甚至那些没有足够大到拥有一个全职系统管理员的公司,也可以通过使用外部托管的日志平台来利用这种系统特性,而不是自己运行日志系统。这样,所有必要的系统管理和日志平台的安全性不仅与个别系统管理员隔离,而且也与 IT 团队以及整个公司本身隔离开来!
因为每个企业都有其独特性,所以根据你的需求,日志管理和日志管理的层次会有所不同。我们的 IT 座右铭必须是:一刀切并不适合所有情况。
所以,我们的日志最佳实践是一个具有挑战性的任务。我们需要评估日志需求。我们如何高效地利用日志来更快、更好地解决问题?我们如何提高安全性?是否存在使本地日志存储超过远程日志存储的优势因素?我们是应该托管自己的日志系统,还是使用第三方 SaaS 应用程序,让他们为我们管理?SIEM 或类似解决方案的安全性收益是否值得其成本和复杂性?
我们唯一真正的最佳实践是确保在需要之前就做好阅读日志的准备,并且不时查看日志,以了解对你而言一个健康系统的表现。
在日志管理方面,我们不得不更侧重于经验法则而非最佳实践。一般来说,中央日志收集对于几乎任何有多个关键工作负载的环境都是值得投资的。这可能意味着一个拥有多个工作负载的公司,或者较小的公司一般应当使用某种形式的外部支持供应商,而该供应商理论上会有多个客户,并且通常会受益于类似的方式,允许他们为客户集中日志。
最小的 IT 部门
这是一个超出系统管理职责范围的话题,但每个 IT 人员都应该真正理解它,因为几乎每个 IT 角色在某个时刻都会面临成为一个组织的一部分,而这个组织无疑过于小型的局面。
在大多数领域,我们可以谈论任何专业团队的最小规模。医生、律师、汽车修理工、兽医、软件工程师等等。在所有这些例子中,我们都可以讨论让某个职位成立所需的人员和团队。一个没有护士或任何助手的医生将非常低效,并且缺乏某些医疗训练的维度。兽医也是如此,如果你是一个独立的兽医,没有接待员、收银员、兽医技术员等等,那么你将被迫在自己价值的很小一部分上承担多个角色。软件工程也是如此,涉及到软件设计的广泛离散任务和角色,这些工作即使在一个小项目中,也不可能由一个人合理地完成。
IT 是其中一个最具戏剧性的领域,因为 IT 涉及的知识面如此广泛,涵盖了许多完全不同的领域。而且每个公司都需要一大范围的 IT 技能。一些技能是特定环境所独有的,但大量基础技能几乎适用于任何公司。
这其中最具挑战性的一方面是,几乎没有空间容纳未成熟的技能。因为信息技术(IT)是围绕核心业务功能、基础设施、支持、效率和安全进行决策和指导的,所以在任何时候,你都希望有专家和成熟的指导。一个看似简单的错误,几乎发生在整个基础设施中的任何地方,都可能成为一个突破口、一个过度支出的风险,或者一个从小错误开始却导致一系列连锁反应的决策,这些决策都将基于那个错误。
大多数企业不需要大多数技能,甚至几乎不需要任何个人技能,某些技能(如 CIO)可能一年只需要几个小时。显然,如果某项技能每年只需要几个小时,甚至每天只需要几个小时,那么全职支付这项技能的费用显然是没有意义的。
接着是覆盖的问题。许多企业只需要在每周工作四十小时内提供支持,并且严格的办公时间内,所有系统都可以在下班时离线。然而,这种情况并不常见。大多数企业需要每周运营六到七天,每天长时间工作,并且全天候运行是完全合理的。为了提供完全的支持,仅仅让某人回答支持票,甚至做出决策或解决实际问题,就需要至少五个人来轮班,忽略任何技能要求。
当你考虑到即使在最简单的 IT 环境中也存在的所有独立角色:系统、网络、CIO、帮助台、桌面支持、终端用户支持、应用程序支持,以及任何专业角色如云应用、备份、灾难恢复、项目管理等,你会发现很多公司试图寻找一个可以胜任所有这些角色的人,一个通才。这是一个很好的理论:有一个拥有众多技能的人,可以做每个角色的一点,合起来就是一个完整的人。
在现实世界中,这根本行不通。首先,因为真正具备所有这些技能、能保持技能更新并且在所有这些技能上都很出色的人,估计在全世界可能得用一只手就能数得过来。其次,任何具备良好 CIO 水平或系统管理技能的人,单凭这些技能就能有很高的按小时计费价值。一个员工的价值总是基于他们的最高技能的全职价值,而不是最低技能的价值。而拥有额外技能可以提高你的最大价值。所以一个具备所有这些技能的 CIO,从理论上讲,应该比只有 CIO 技能的人更有价值。所以即便你找到这样一个人,你要么得支付他们一笔巨额薪水,才能让他们做这个工作,要么他们得愿意以自己价值的极小一部分薪水做这份工作,而从雇佣角度来看,这毫无意义。
其次是覆盖问题。一个人能工作多少小时,通常意味着业务大部分时间没有得到支持。即使你有一家只在每天八小时内运营的公司,且愿意在这段时间内做所有支持和主动维护,仍然存在这样一个问题:一般来说,一个人被要求执行的许多角色需要同时进行。
令人惊讶的是,各种规模的公司都在尝试这种方法,并普遍得到了糟糕的结果,尽管很多公司从未衡量过他们的结果,甚至不了解 IT 部门应该呈现的良好表现是什么,或者该部门应该完成什么任务,因此往往忽视甚至赞扬这些领域的失败。
找到一个理论上有效的 IT 部门最低规模是很困难的。作为经验法则,如果你不至少需要三名全职 IT 员工,且他们从不做任何 IT 之外的事情,那么你就不应该尝试组建一个 IT 部门。
许多 IT 企业,如管理服务提供商和 IT 服务提供商,为只需少量各种资源的企业提供 IT 技能、管理、监督和工具。更小的公司不应该因为求助于这些公司而感到难过,这些公司为实现良好的 IT 运作所必需的规模和分工提供了必要的支持。话虽如此,正如雇员一样,普通公司的表现不会太好。因此,你希望确保你雇佣的不仅是好员工,也要雇佣一个好的服务提供商。服务提供商很像雇员,但更可能与你的业务需求保持一致,并且通常有更长的潜在服务期 - 一个良好的服务提供商关系可能比一个员工的职业生涯更长。
从两面重新审视不合适的 IT 部门可能会提升整个行业。许多雇主对基于他们施加的 IT 结构而预料到的不良 IT 结果感到不满。而许多 IT 从业者对他们的职业或至少是他们眼下的工作感到不满,因为他们觉得他们必须或被鼓励在根本没有任何意义的环境中工作。
将服务提供商视为内部 IT 团队的一部分,可以让你以实际可行的价格获得所需的 IT 团队。IT 实际上并不超出任何公司的预算。如果看起来 IT 费用将会太高,那肯定是出了问题。IT 的工作是为企业赚钱。
我看到的公司与服务提供商合作时最常见的错误之一是假设许多不正确的参与规则,比如假设当地资源更好或者服务提供商必须匹配你计划使用的技术 - 如果你这样做,你怎么会确定要雇佣哪家服务提供商,因为只有他们才有决定使用的技术的专业知识!这确实是一个进退两难的局面。另一个关键错误是将服务提供商(提供 IT 服务的公司)与增值再销售商(供应商销售代表)混淆。后者通常会自称为前者,但很容易区分。第一个公司的业务是提供 IT 作为服务。第二个公司的业务包括销售硬件、软件和第三方服务,可能还包括添加一些 IT 服务。
最佳实践:
避免运行过小以支持必要角色和分工的 IT 部门。
永远不要雇佣转售商来做 IT 服务提供商的工作。
决不允许你的 IT 员工(内部或外部)存在利益冲突,并且还销售他们推荐和选择的硬件、软件和服务。
现在我们大致了解了为什么日志记录对我们的组织至关重要。良好地使用和理解日志,并为日志建立一个适当、深思熟虑的基础设施,是我们真正看到 IT 部门在挣扎与卓越之间分水岭的领域之一。
目前并不涉及太多技术性的讨论。实际上,这完全是关于坐下来投入精力来制定和推出日志记录计划。让日志记录在您的组织中发生。无论是集中式的、去中心化的,还是自动化的,任何适合您组织的方式。开始着手,确保您的日志成为一个强大的工具,使您的工作更加轻松。
在接下来的部分,我们将从日志记录继续,探讨更一般的监控。两个高度相关的概念共同作用,真正将我们的管理提升到另一个层次。
警报与故障排除
在刚刚讨论过日志之后,我们现在需要考虑与之高度相关的系统警报的概念。我必须提到,当然,日志系统本身也可能是警报的来源。如果我们在日志系统中使用自动化,那么这些自动化通常会被期望直接发送警报,或将警报添加到警报系统中。
警报从根本上来说,是我们的监控系统与我们这些人类沟通的方式,告诉我们它们出现了问题,是时候让我们介入并发挥人类智能的魔力了。虽然我们希望系统能够自动化并修复许多问题,但现实是,在可预见的未来,几乎所有公司都必须在一个需要定期进行人工干预的系统管理环境中工作。无论是登录并清理已满的磁盘、停止一个损坏的进程、识别一个损坏的文件,甚至是触发故障转移到另一个应用程序,或通知业务部门预期的影响,人类在系统中仍然扮演着重要角色。
拥有良好的机制来发现严重问题并提醒人类是高质量支持的关键。为了理解良好的警报机制,我们必须讨论如何发现问题并如何接收到通知。
设备端和集中式警报系统
我们可以从设备端和集中式警报开始进行比较。传统上,回溯到几年前,系统通常会单独处理自己的警报。系统已经设置为将问题记录到中央日志中,因此让它们在检测到坏事时也发送电子邮件或类似的通知是一个自然的延伸。警报非常简单,每个系统都会单独处理自己的检测和警报。虽然集中式监控和警报已经存在很长时间,但外部监控的普及直到需要监控托管的互联网资源(如网站)时才变得非常主流,网站的停机通常首先由客户察觉,而不是由员工察觉。当停机首先被内部员工发现时,推迟发现的决策会更加灵活。
设备端警报的简单性很有吸引力,对于较小的组织或那些可以承受较慢错误检测的组织来说,它是非常适用的。设备端警报的关键问题在于,许多严重的故障或攻击可能会完全禁用警报,或者至少会延迟警报。例如,一个简单的例子是失去电力的服务器或其 CPU 融化的情况,系统下线是我们想要接收到警报的情况,但系统下线的突然发生排除了系统通知任何人发生了坏事的可能性。网络连接突然丢失时也会发生同样的情况。在系统被破坏的情况下,黑客可能会在被发现之前关闭警报功能,留下一个仍在运行的系统,但无法发出求助信号。
设备端警报通常便宜且简单。它通常是内置的,只需少量配置。如果使用简单的机制,如电子邮件发送警报,即使是简单的脚本也能增加很多警报功能。这种方法使用的系统资源非常少,对于小型企业或那些不必担心员工报告功能丧失的潜在停机情况的企业,它是足够的。
对于大多数企业或工作负载而言,设备端警报的局限性过大。无论系统是面向客户的,你希望最大化客户信任,还是系统是内部的,你希望将问题的发现从员工转移到 IT 部门以提高性能,或者系统几乎没有最终用户,可能永远也不会发现它无法正常工作,你都需要确保工作继续进行(例如扫描安全系统或过滤器),因此外部监控是必要的。
外部监控允许我们在系统完全失败时仍然能够传播报警。由于完全失败在报警事件中非常常见,这一点非常重要。完全失败可能意味着硬件故障、电源丢失、软件崩溃或网络断开等。这些都是常见的故障情况,所有这些情况都会导致设备内部报警失败。外部报警为我们提供了一种信心,使我们在发生故障时能够获得警报,而这种信心在没有外部报警时是缺失的。
当然,外部系统也可能发生故障,导致没有报警,但我们可以通过一些方法有效地对这种情况进行规避。一种选择当然是对外部报警系统进行外部报警。基本上是备份报警。并且,通过只使用单一的报警来源,我们可以简单地检查该来源是否正常工作。一个外部报警机制,如果与其监控的系统解耦,极不可能与另一个系统同时发生故障,虽然不是完美的,但这种方式可以轻松消除 99.99%以上的漏报,对于大多数组织而言,这已经足够了。
带外设备报警
在报警管理中,可以有一定的折中。如果我们把系统视为一个层次结构,那么每个层次较低的设备都能够以非常微小的方式监控其上方运行的服务。例如,应用程序可以告诉我们数据库连接是否正常,操作系统可以告诉我们应用程序是否仍在运行,虚拟机管理程序可以告诉我们操作系统是否仍在运行,而在堆栈的底部,带外管理硬件设备可以告诉我们核心系统组件是否已发生故障。
该系统并非万无一失,且通常相当基础。操作系统对应用程序进程的工作了解非常有限,通常只能告诉我们应用程序是否已完全崩溃并返回错误代码给操作系统,或者它可以告诉我们应用程序是否使用了过多的资源,例如突然增加内存请求或消耗大量的 CPU 周期,但操作系统无法判断应用程序是否仍在运行,但却向最终用户抛出错误或乱码。
对于不熟悉的人来说,带外管理实际上是一个外部计算机,它安装在机箱内,与服务器硬件同处一体,但它有自己的小型 CPU、RAM 和网络。由于它与服务器本身几乎是完全独立的计算机,因此带外(OOB)管理系统可以直接或通过某些监控系统报告服务器本身的关键硬件故障,例如主板、CPU、内存、存储或其他通常会导致服务器无法发送报警的组件故障。
然而,OOB 管理系统确实与服务器共享机箱、位置和电源。这意味着它仍然只能有限地监控系统中某些类型的常见故障。正如许多事情一样,对于许多企业来说,这可能足够了,但对于其他企业来说则可能不够。
推送和拉取警报
警报系统与我们之间也有两种基本的交互方式,作为被警报的接收方。我们通常想到的是推送警报。也就是说,警报是以吸引我们注意力为目的,在我们没有想到警报时发送给我们的。
通常,推送警报通过电子邮件、短信(SMS)、电话、WhatsApp、Telegram、Signal、RocketChat、Slack、Microsoft Teams、Zoho Cliq、MatterMost 或其他类似的实时通讯渠道发出。有些警报系统拥有自己的应用程序,用户可以将其安装到桌面或智能手机上,这样它们就能快速可靠地推送警报,而无需集成或依赖其他基础设施。你可以想象一个组织运行自己的电子邮件和消息平台,而这些平台又被我们的警报系统监控,并且也成为我们接收警报的路径。即便警报系统本身没有失败,但它可能无法告诉我们发生了故障,因为它监控的系统也是将警报送到我们这里的系统。这就是为什么有时会采取减少失败路径和减少警报传递依赖的做法。
警报系统实际上是一个令人惊讶的复杂系统。如果警报是由人工而非计算机处理的,我们会很快发现呼叫中心有复杂的多分支决策树,指引他们在无法告诉某人有问题时该怎么做。然而,依赖人工时,我们知道在极端紧急情况下,总会有人拿出个人手机,给某人发短信,叫某人打电话或敲门叫醒别人,或者做其他类似的事情。计算机也能做这一切,但它们需要访问这些工具、做出这些决策的算法,以及知道如何联系到人。这说起来容易,做起来难。
为了解决这个特定的问题,许多公司选择在通信路径中加入人工。虽然这是一种昂贵但有效的工具,有时候人类的决策和灵活性会占上风。总是有人值班的人工呼叫中心,代表技术团队和管理人员接收警报,并将联系路径管理到需要接收警报的人,是一个很好的选择。显然,混合选项也是可行的,其中计算机系统直接提醒最终接收者,但始终有人参与验证警报是否已发送、是否收到确认,或执行其他可行操作。
推送警报的替代方案是拉取警报。拉取警报指的是系统在最终用户登录查看时,显示任何已打开或记录的警报状态。这些系统要可靠得多,因为最终用户在查看系统时,能够知道是否存在无法查看警报状态的情况。如果系统出现故障,他们可以立即开始处理问题。如果没有故障,他们就能看到警报,并知道是否需要采取行动。
安静即成功
使用纯粹的推送警报所产生的基本问题是,我们依赖安静来告诉我们一切正常。我们并没有得到确认,表明一切都已检查且目前没有问题,而是依赖于没有被联系到来假设一切没有问题。这是一种危险的做法。
我们都知道那种感觉:醒来后,或长时间开车后,或者在派对上没有积极查看手机,心里大致觉得办公室没联系我,没有人打电话,应该没问题。然后几个小时后你看看手机,发现电池没电了,没信号,或者手机处于静音状态。然后 panic(恐慌)袭来。你插上手机,恢复信号,打开铃声,发现自己错过了一个又一个电话、语音邮件和短信,告诉你发生了大紧急,你离开办公室时更改了一个重要密码却没告诉任何人,系统崩溃了,除了你没人能登录,而你没有回应!
仅仅相信没人能引起我的注意,因此没有问题是行不通的。但一直盯着控制台、不离线也同样不可行。必须找到一个平衡点。显然,仅仅希望自己能被联系到,这是一场灾难的食谱。也许这是一个需要很多年才会发生的灾难,但几乎可以肯定,这种灾难最终会发生。毕竟,出错的变量太多了。
因此,拉取监控和警报系统非常重要,它们既能验证推送警报是否正常工作,也能用来绕过已知的断开问题,或者用于运行一个主动监控站点。
警报系统也在努力定义成功的警报。许多机制,如电子邮件和短信,只会确认消息是否已发送,或者可能已被接收方的基础设施供应商接收,但它们并未表明消息是否已传送到最终用户的设备,或最终用户是否已看到该消息。即使消息从头到尾都传送了,它是否被过滤到垃圾邮件文件夹并隐藏了?除非有人工确认警报,否则我们几乎无法有信心确认警报确实已被看到。
拉取警报系统,通常以仪表板的形式显示,通常我们将其想象为红绿灯系统。通常会以图形方式显示监控的系统或组件,并将被认为健康的系统显示为绿色,将遇到问题但尚未指示故障的系统显示为黄色,而将通过传感器测试失败的系统显示为红色。这不仅使人类能够快速浏览警报的范围,而且还使得系统能够轻松地将大量警报汇总为单个显示。只要显示为绿色,你就知道该组中的所有系统都健康。如果显示为红色,你可以深入查看具体问题所在。在最高层次上,理论上,你甚至可以有一个大的单一指示器,显示为绿色或红色。如果所有系统完全正常则为绿色,若有任何系统失败则为红色。简单来说:是否需要采取行动。如果大部分时间都能保持绿色,这可能正是你需要的,将可靠的监控与低验证开销相结合。
大多数警报系统都会提供仪表板来显示拉取的警报,同时也提供推送通知,以提高响应速度并联系那些没有主动检查警报的人。拉取警报系统通常用于呼叫中心的核心,在这里,值班的工作人员全天候监视拉取的警报,并将推送警报传达给相关方,或跟进确保自动警报的送达。很少有组织将拉取警报开放给许多员工,这可能是一个错误,因为这样会降低压力并提高警报的可靠性。
同样,监控系统与被监控端点之间的互动可以是双向的,也可以是单向的。监控系统可能拥有远程访问端点的能力,并主动请求端点的状态。或者,运行在端点上的代理程序可能主动联系监控服务器,将其状态推送过去。
内部和托管监控
监控和警报在某些方面是两个独立的部分,有些软件和服务仅执行其中之一,也有些同时执行两者。监控组件决定一系列传感器是否检测到我们的工作负载中存在问题。警报组件则基于监控结果,尝试通知相关方。过去,这两个组件总是合并成单一的产品,但近年来,随着越来越多的系统类型需要被监控(不仅仅是 IT 系统),以及警报需求的增加和需要变得更加稳健,某些供应商已开始分别独立构建这两个组件。
目前,监控解决方案有很多种包和风格。你可能很容易决定,使用多个解决方案对你有帮助。选择一个合适的解决方案可能是你监控工作中最困难的部分。监控软件有商业版和免费版,有封闭源代码和开源版本,并且可以在几乎任何平台上运行。
监控是一项功能,通常你会希望将其托管在你的主要基础设施之外,因为你希望它的响应速度较慢且更可靠,并且相比其他工作负载,它与其他系统的独立性更强。你可以在自己的设备上托管,选择第三方云或 VPS 托管的基础设施,或者从服务提供商处购买 SaaS 应用程序。你可以根据组织的需求选择任何合适的方式来处理这个问题。但很少有人希望将监控解决方案与其他工作负载共享同一硬件,更不用说共享同一个数据中心了,否则在你丧失其他系统时,也会失去监控功能。
是否自行运行和维护监控系统,或选择托管产品,通常是由成本和组织内部的政治因素决定的。即使是免费的开源监控解决方案,对于最苛刻的组织也足够强大。你需要判断构建、维护和监控一个监控解决方案的成本是否对你的组织合理,还是直接购买现成的功能更划算。在大多数情况下,这取决于规模。如果你监控的工作负载数量非常大,或者你的监控需求非常独特,可能会受益于内部培养专业知识,并有全职专家专注于这个项目。通常,要让这样的项目在内部保持成本效益,你需要有完全专职的员工,或者有大量专职员工,他们有足够的时间和资源深入学习产品,并妥善维护它们。通常,监控和日志记录会捆绑在一起,无论是作为单一产品,还是由一个人或一个团队负责,因为它们有很大的重叠,而日志记录可以视为监控的一个专业功能。两者可以独立操作,也可以结合使用。通过相同的警报渠道使用它们通常是合理的,因为它们可以共享相同的工作和基础设施。
就像本章中的大多数内容一样,最佳实践的真正难点在于找到我们能提炼出的最佳实践,因为这里的指导非常广泛且模糊。没有“一刀切”的方法。听起来像是作弊,但事实是,真正的最佳实践是根据成本、功能、支持、与生产环境的分离,评估你业务的需求,并确定适合你的监控和警报机制。
RMM 和监控
如果您在内部 IT 工作,可能从未听说过 RMM 这个术语,但如果您曾在服务提供商行业工作过,那么 RMM 就是客户支持中预期使用的核心工具。
RMM(远程监控和管理)是一类工具,专为服务提供商设计,服务提供商几乎总是需要远程工作到客户站点,并能够同时快速监控多个不同的客户系统。这与内部 IT 需求通常大不相同,内部 IT 通常不远程操作,即使是远程,系统也通常是集成的。
很少数非服务提供商仍然依赖 RMM 工具作为监控机制。通常 RMM 工具非常简洁且不灵活,但本质上,它们也是我们在这里讨论的那种监控系统。因此,您当然可以考虑使用购买的或自己运行的 RMM,或者如果您有服务提供商,这可能是您已经支付的服务的一部分。RMM 甚至有免费的开源产品。因此,任何规模的公司都不能说他们没有资源至少进行最基本的监控。
在某些情况下,专为内部 IT 团队设计的传统监控工具如此强大,以至于它们实际上取代了服务提供商中的 RMM。或者,这两者也可以并行使用。
经验法则是,监控越多越好,最好将托管放在外部环境中,确保警报有多个渠道,以便找到通向人工的方式,确保至少可以验证推送是否正常工作的拉取监控,并考虑让监控系统自动为支持团队创建可操作的工单,以便跟踪后续事项。
是否有最佳实践?是的,最佳实践简单而广泛:如果工作负载有一个明确的目的,那么它就应该被监控。监控由于不直接影响生产的运行,所以如果不存在监控,容易被忽视。几乎没有人因为做好监控而获得晋升,也几乎没有人因为缺乏监控而被解雇,但实施适当的监控能有效地将优秀的管理员与普通管理员区分开来。
去设置一些监控吧!
摘要
在这一章中,我们已经讨论了围绕系统本身的一系列关键非系统组件。文档编制、系统测量、数据收集与规划、日志收集与管理,以及最后的监控传感器和基于它们的警报。这些几乎可以视为系统管理领域的软技能。
在我接管的环境中,我们发现文档几乎不存在,测量系统几乎没有人提及,容量规划是一个没人讨论过的过程,监控通常最小且可靠性差,日志收集虽然被理解,但在实际实施中依然是一个空想。然而,一位几乎没有资源的系统管理员,只需要一些时间,就能通过一些免费的开源软件独立解决这些问题,且几乎没有预算限制,如果需要的话,还能将工作负载隐藏在系统中的某个地方。
本章并不是关于如何让你的系统运行得更好,而是关于其他方面。我们如何知道它们运行得更好?我们如何知道它们现在在运行?我们如何知道,如果中了大奖,我们能将工作交接给别人?我们如何自信地说,我们正在做需要做的事情,以最好方式应对恶意攻击?本章的主题让我们思考如何在我们所做的一切中变得更好,而不仅仅是最显眼的部分。
提升你的可见度
我们在 IT 中的工作常常对其他团队的人,甚至是我们汇报的管理层来说是完全不可见的。也许是因为根本没有可以展示的东西。或者可能我们做的事情太难、太复杂,外部的人无法真正理解。又或者我们之所以不可见,是因为我们选择接受这种隐形的状态。
本章中的大多数话题都为我们提供了完美的机会,走出 IT 的地下室或储藏室,走到管理层面前,做一点 IT 团队的自我宣传。从监控仪表板到漂亮的文档,再到容量图表、日志细节展示,几乎总有些东西我们可以打印出来或在大屏幕上展示,展示自己已实施的项目,给人留下深刻印象。
吸引管理层的注意,并展示我们是积极主动的,遵循最佳实践,这正是我们可以为自己赢得组织价值的机会。不要害怕做自我宣传,你应得的。制造一些声音,展示你如何为企业的最大成功做好准备。
去确保本章中提到的所有系统都已在你的环境中实施。刚开始时保持简单,但不要跳过任何系统。
在下一章,我们将进入脚本编写和系统自动化,包括 DevOps,我知道你一直在期待这一部分。
第八章:通过脚本编写和 DevOps 提升自动化以改进管理成熟度
我认为,对于我们大多数系统管理员来说,脚本编写和自动化是我们自然倾向于思考如何改善整体系统的最佳机会。这可能会被视为一种重要的工作方式,自动化毫无疑问非常重要,但它也并不是系统管理的终极目标。可以说,随着我们不断学习脚本编写和自动化,我们将拥有更多的自由时间,集中精力去处理只有人类才能完成的任务,同时也能更深入地理解开发人员的工作,这对于我们 IT 领域的从业者总是非常有帮助的。
系统自动化是一个领域,在这里我们更容易获得炫耀的资本,展示我们每天的任务清单。当我们坐在比喻的系统管理员鸡尾酒酒吧里,向同伴们讲述我们如何编写了一些非常清晰且易于阅读的文档时,我们并不会感到满足。但当我们解释如何编写一个复杂的脚本,将我们每周工作量中需要几小时的任务,转化为计算机调度器自动运行的任务时,我们会获得称赞、关注、彩带、报纸横幅游行、同事们为我们买来一杯杯最爱的饮品,如果非常幸运的话,还有一个打击乐器。
自动化通常是我们大多数人在系统管理中既感到兴奋又感到害怕的领域。与系统管理的其他领域相比,自动化涉及更多的构建模块和需要理解的概念。大部分情况下,系统管理很像上历史课,确实,了解更多历史片段有助于你在学习新内容时拥有更大的背景,但通常你可以单独学习任何特定事件,而不需要全面了解与之相关的所有事件和导致这些事件发生的背景,依然能够从中学到有价值的东西,并且本质上理解它。当你学习罗马历史时,即便你没有先学希腊历史,也不会感到迷失。然而,脚本编写和自动化更像数学课,如果你没有学会加法,那么学会如何求平方根将是完全不可能的。脚本编写是一项累积的技能,要真正发挥作用,你需要学一些基础内容。
我们将首先通过对比未编写脚本的命令行管理与使用图形用户界面(GUI)来作为基础,进一步学习如何进入自动化领域。
在本章中,我们将学习以下内容:
-
图形用户界面与命令行界面:管理最佳实践
-
自动化成熟度
-
基础设施即代码(IaC)
-
文档优先管理(DFA)
-
现代自动化工具
图形用户界面与命令行界面:管理最佳实践
如果你是从 Windows 环境转向 Linux,你可能没有意识到几乎所有操作都应该通过命令行完成,而不是图形用户界面。但实际上,即便在 Windows 上,微软早就明确表示,桌面体验主要是为最终用户设计的,而不是为系统管理员设计的,并且他们推荐在直接操作本地系统时,使用 PowerShell 作为首选管理工具,或者使用通过 API 连接的远程管理工具。微软强烈建议过去几代安装其操作系统的人,在安装操作系统和虚拟机管理程序时完全不使用图形用户界面。
图形用户界面,或者现在我们简称为 GUI,给系统管理员带来了许多问题。
GUI 的第一个问题是膨胀。在安装企业操作系统时,如果有 GUI 可用,它往往占据了系统中一半以上的代码。每增加一行代码,就意味着我们需要存储更多的数据,存储的数据越多,我们就需要备份更多;更多的代码意味着更多的 bug、缺陷或故意的后门要担心;更多的代码需要打补丁和维护,等等。
接下来是性能。GUI(图形用户界面)在运行时需要的计算能力和内存消耗要比非 GUI 系统大得多。GUI 通常需要额外 2GB 或更多的系统内存,这比系统工作负载所需的内存还要多。这听起来可能微不足道,但特别是在多个系统合并到一台硬件上时,这个问题可能会迅速加重。如果我们有二十台虚拟服务器运行在同一物理服务器上,那么在 Linux 环境下,平均工作负载可能仅为 2 到 4GB 的内存。每个系统再增加 2GB 内存,不仅意味着接近 50%的增长,而且在所有机器上将增加 40GB 的内存。
系统整合与压缩系统的时代
在 1990 年代和 2000 年代,虚拟化普及之前,我们处于一个服务器性能快速增长的时代,但每台系统只能运行一个操作系统,无论该系统的工作负载有多小。随着系统性能的增强,远远超过了软件使用资源的速度,系统膨胀的趋势越来越强烈,因为至少在硬件方面,膨胀并不那么重要。
CPU 和内存资源通常是以离散块的形式提供的,要拥有足够的资源,我们通常需要购买更多。过去,系统很少会接近其极限运行,因为那个时候扩展系统非常困难。因此,系统通常设计得有很多备用资源,以便留有大幅度的误差空间,当然也为将来的增长留有余地。由于这些原因,在服务器上运行 GUI 几乎是微不足道的。
自那时以来,许多因素发生了变化。我们或许可以写一本书,专门讨论为何在使用命令行数十年后,行业短暂地从命令行转向图形用户界面(GUI),尤其是从 1990 年代中期到 2000 年代初,GUI 似乎一度成为服务器管理的主流方式,直到 2005 年左右又重新回到命令行。忽略社会趋势推动的变化,我们在这里关注的是容量问题。
一旦虚拟化成为主流,尤其是随着云计算开始成为一个重大趋势,操作系统的空闲资源几乎在一夜之间变得不再常见。这看起来似乎与直觉相反,因为虚拟化本身为我们提供了更多的灵活性和计算能力。但它也赋予了我们非常有效地缩减规模的能力,这是我们之前所没有的。通过虚拟化,我们很少会处于拥有大量过剩系统资源的情况,特别是那些可以预测的过剩资源,因此保持每个虚拟机尽可能精简就显得尤为重要,这意味着不运行一个庞大且大多无用的 GUI 进程。仍然无法将工作负载合并到单一服务器的有效下限的小型企业是这一规则的例外,它们仍然有足够的开销来实现 GUI,除非它们是云计算的良好候选者。
在传统的企业环境中,多个服务器是常见的,虚拟化的一个主要优势是整合,避免安装 GUI 意味着可以在一台物理服务器上安装 50 或 60 个工作负载,而不是在相同硬件上安装 30 或 40 个。这相当于减少了购买服务器的需求,从而节省了成本,不仅降低了采购成本,还减少了电力消耗、制冷费用、数据中心房地产费用、软件许可费用,甚至 IT 人员成本。
如果我们以公共云计算为例,我们可以更容易地看到没有 GUI 的优势。小型工作负载,比如邮件服务器、Web 服务器、代理服务器、电话交换机等,每月运行成本可能仅为 5 到 10 美元。如果加上 GUI,云托管虚拟机的成本可能轻松翻倍,从 5 美元涨到 10 美元,或从 10 美元涨到 20 美元等等,因为 GUI 需要更多的 CPU、存储,最重要的是更多的内存。很容易看出,从每月 10 美元到 20 美元的工作负载成本上涨会迅速积累。由于大多数基于云的工作负载都非常小,给每个工作负载添加 GUI 可能会对容量产生巨大的影响,甚至可能使公司的基础设施计算成本翻倍!
GUI 不适用的程度如此之大,以至于许多供应商传统上甚至没有为云空间提供连接 GUI 的机制。亚马逊以其不允许在标准云实例上使用 GUI 而闻名,这实际上迫使组织学习命令行,甚至是更先进的管理技术,而不需要登录。但几乎所有云用户都会选择通过如 SSH 之类的技术进行远程登录。云计算比任何其他方式都更能证明 GUI 的风险和成本。
在虚拟化和云计算普及之前,系统管理员,尤其是那些在 Windows 环境中的管理员,会争辩说 GUI 根本不会增加太多开销,如果它们能让某人的工作变得更轻松,那它们就是值得的。这个神话已经被揭穿,今天没有人能诚实地再做这种声明。GUI 在任何广泛意义上都是不合逻辑的。
对于管理层来说,命令行管理的最大卖点通常是关于安全性的。GUI 为恶意攻击者提供了更大的攻击面,增加了突破系统的可能性。仅仅是多出的那些代码,就让潜在攻击者的工作变得更加容易。而且,当然,GUI 的功能本身就需要更多的访问手段,这自然形成了非常诱人的攻击面。更多的代码行、更多的访问方式、更多的管理路径、更低的性能等,都共同增加了整体的安全风险。综合来看,虽然这可能不是非常严重,但风险的增加是真实的,也是可以衡量的,或者至少可以估算的。
命令行管理成为事实上的标准的最终主要原因是效率。是的,正是许多人选择保持图形用户界面(GUI)的理由。现实是,系统管理不是一项轻松的任务,也不是你可以轻松地四处摸索并猜测应该使用什么设置的工作。要做好这项工作,甚至做到安全,你必须对大量的项目有相当扎实的理解,从操作细节到一般的计算和网络知识。
管理中的 GUI 传统上被宣传为一种工具,旨在帮助那些不习惯环境的人能够更快地高效工作,减少培训和知识要求。如果你谈论的是清洁工,这个概念是很不错的。在系统管理中,我们最不希望看到的就是没有深厚知识和经验的人能够表现得像是他们知道自己在做什么。这在多个层面上都是危险的。遗憾的是,GUI 实际上让许多组织更难评估哪些候选人至少符合技术职位的基本资格。
图形用户界面(GUI)不仅存在着未经授权的人员可能会随意操作的风险,对于那些知道自己在做什么的人来说,命令行的速度要快得多。它在执行简单任务、执行大多数复杂任务时更快,而且更容易编写脚本或自动化。命令行管理与脚本编写如此契合,以至于人们常常分不清两者的区别。如果你真正对比任务,你会发现命令行工作完成相同任务所需的时间通常不到使用 GUI 的百分之十!
命令行不仅对系统更高效,它还使多系统管理变得更加容易,因为命令可以在不同的系统间复制,这些是 GUI 操作所无法做到的。命令行管理还可以轻松录制、归档、搜索等等。虽然在 GUI 中做同样的事也是可能的,但需要长时间的视频录制,这会导致大量存储需求,而且没有简单的方法来解析或转化为文档等。
在现代时代,我们开始面临需要远程执行大部分或所有系统管理任务的问题。这无意中恰好迎合了命令行的优势。命令行需要传输的数据量和对网络延迟的敏感度远小于 GUI。远程 GUI 会话通常会消耗显著的网络流量。远程 GUI 会话是视频流,通常具有相当高的分辨率。在某些情况下,即使是一个用户也能引发网络问题,尤其是当服务器位于网络连接较差的地区时。远程命令行管理的标准方法是 SSH。
即使通过古老的拨号上网连接,SSH 远程会话也能正常工作。即使是最慢的现代互联网服务,也足以处理数十甚至数百个同时在线的 SSH 用户。这是一般远程 GUI 会话做不到的。命令行在全球另一端通过微弱的网络连接几乎同样有效,而 GUI 远程管理则容易受到网络波动、限制或距离的明显影响。
命令行将持续存在,但理解其存在的真正原因非常重要。我们容易忽视它远不止依赖于一两个小因素。实际上,有很多充分的理由说明为什么在可能的情况下你应该使用命令行。来回切换并不利于提高这两种方法的效率。从个人角度来看,理应尽可能避免使用 GUI,以便专注于学习命令行技能。持续使用命令行是提高效率的必要条件。
现在我们必须承认,Linux 有许多不同的命令行选项。我们可以使用BASH、Fish、zsh、tcsh、PowerShell 等。正如我们所知道的,Linux 是关于选项和灵活性的。这是一个“少即是多”的情况。有些 Shell 非常好用且有用,但我们必须记住,我们是系统管理员,我们需要确保对在紧急情况下可能接触到的工具非常熟悉。在 Shell 之间切换并不特别难,特别是在 Linux 环境下,但我们仍然应该警惕花时间学习像Fish或zsh这样的 Shell 中的便捷键、自动补全和其他特性,因为我们可能在下一个工作中无法使用这些技能,这始终是一个需要考虑的因素。而且,如果在紧急情况下你被叫去处理一个你之前没有机会设置的系统,你可能唯一的选择就是 BASH。对我来说,这意味着 BASH 是我唯一想学习的工具。
就是这样。所有的逻辑和推理都在这里,这样你就可以回到管理层,解释为什么你需要从命令行工作,为什么你需要那些能从命令行工作的员工,为什么你的系统应该很少安装任何 GUI 环境。在下一节中,我们将讨论系统自动化的成熟度等级。
自动化成熟度
虽然没有正式的系统来衡量自动化成熟度,但我们可以讨论一些自动化成熟度的基本概念。这里的观点是,组织在自动化程度上大致处于一个连续体中,从没有自动化到完全自动化,大多数组织处于中间位置,但更可能趋向于没有自动化,而不是完全自动化。
不是每个组织都需要,甚至应该,完全实现自动化。但一般来说,当自动化实施成本足够低时,更多的自动化是更好的。自动化并不是免费的,实际上,组织可能会发现,投入自动化一个流程的成本要高于手动执行这个任务的成本,尤其是在系统的生命周期内。我们不希望仅仅为了自动化而盲目自动化。
然而,通常情况下,我们发现组织几乎在所有情况下都会跳过自动化,而选择使用人工劳动,承受所有成本和风险。这是一种自然倾向,因为在当下,任何任务如果手动做都会更简单。如果我们不着眼未来并进行投资,我们根本就不会去自动化,而这也是许多公司看待 IT 需求的方式。如果一个任务手动完成需要一小时,自动化需要三小时,那就相当于三个任务的时间,忽略这个事实是很难证明合理的,因为同样的任务每个月都会发生,四个月后,自动化不仅会减少工作量,而且自动化还能让任务更可靠和一致。
几乎任何组织都将从比今天更多的自动化中受益。没有必要把自动化看作是非做不可的全有或全无的选择。可以做的就自动化,做不了的就跳过。要务实。首先做最容易实现的部分。你自动化的越多,未来你就能有更多的时间去自动化其他事情。随着实践的积累,你的自动化技能也会提升,使得每一次新的自动化都比上一次更容易。自动化正是一个典型的例子,第一次做起来确实很难,但随着时间的推移,它会变得越来越容易,直到它成为处理事情的显而易见的方法,并且变成第二天性。
自动化的成熟度并不完全是一个直接的连续体,每一步都比上一步更加成熟。例如,如果我们看看调度任务和脚本任务,这两者可以独立于对方执行。每个任务单独完成都有其用处。我们可以编写复杂的操作脚本并手动运行它们,或者可以调度简单的独立命令来触发事情的发生,无需人工干预。然后,我们可以将两者结合起来,自动启动执行多项任务的复杂脚本。我们首先考虑哪个,第二考虑哪个其实是随意的。
本地与远程自动化
如果这不够明显的话,我们有两个选择:要么在本地实现自动化,通过调度任务或触发任务在目标服务器上运行,要么我们可以从外部来源推动自动化,从而实现某种形式的自动化集中化。还有一种混合方法,本地调度器或代理向中央服务器请求自动化信息,虽然从技术上讲仍然是本地的,只不过是有一个集中存储来模拟控制。
常常被忽视的是本地自动化的优势,即即使远程系统不可用,甚至本地系统完全失去网络连接,本地任务仍然能够运行。我最喜欢保留为本地自动化的任务之一就是系统重启。虽然将重启集中管理会更方便,且我见过一些组织选择这么做,但我非常欣赏有一个本地的、强制性的重启任务,它每周至少会执行一次,有时甚至是每天。这让我非常安心,即使服务器出现完全崩溃的情况,只要它以任何形式仍能运行,最终重启过程都会尝试重新启动机器,并希望能够让它重新上线。这是一个非常小众的需求,可能对你来说永远不重要,但我见过有些系统即使远程管理无法访问,仍能继续提供工作负载,而一个自动化、本地调度的重启任务将它们重新带回线上,并使其再次可访问。
一种越来越流行的中庸之道是拥有一个中央控制库,包含所有所需的自动化内容,然后由终端的代理拉取进行自动化。这些库既包含自动化本身,如脚本,也包含调度信息或触发器。然后,信息通过本地脚本得以实现,即使远程库出现故障或不可用,本地脚本仍能独立运行。通过这种方式,你真正面临的风险只是无法更新调度任务列表、对它们或调度进行更改。只要不需要发布新的自动化更新,就不必担心库会离线。
命令行
这不仅仅是一个合法的成熟度级别,更像是一个基本的起点,因此我们可以把它看作是零级,指的是进入命令行并使用一个适当的 Shell 环境进行交互式操作(即:非自动化)。正如我们刚刚讨论的,处于命令行并学习命令行语法和工具是所有后续自动化构建的基础。理解如何在命令行上执行任务、如何操作文本文件、如何过滤日志以及其他常见的命令行任务,会迅速发展成显而易见的自动化能力。
定时任务
开始自动化的最佳且最简单的地方就是任务调度。这听起来可能是最简单、最显而易见的一步,但令人惊讶的是,许多组织甚至没有做到这一点。Linux 长期以来一直是可靠且易于管理的本地调度的堡垒,cron不仅内建于 Linux 中,几乎所有的 UNIX 系统都可以使用它,已经有近半个世纪历史(自 1975 年发布以来)。Cron 快速高效、无处不在且广为人知。任何有经验的 UNIX 管理员都应该能够在需要时至少调度一个基本任务。Cron 甚至能处理启动时的任务。
各种简单任务都可以通过 cron 执行。在大多数环境中,常见的任务可能包括系统更新、数据收集、重启、文件清理、系统复制和备份。你当然可以安排任何任务,但这些对于第一次进行自动化的用户来说,都是一些非常适合的建议,特别是对于那些显然是周期性系统需求的任务。
另一个常见的简单计划任务领域是通过像 git 这样的代码库进行代码更新。当我们拉取新代码时,代码更新及随后的数据库迁移都可以轻松地安排定时执行。
脚本编写
当我们谈到自动化时,每个人总是立刻想到脚本编写。归根结底,自动化中几乎所有的内容都或直接,或在幕后以某种方式是脚本编写。脚本编写提供了动力,当我们想要超越最简单的任务或只是调用别人写的脚本时,脚本编写就显得至关重要。
我们不可能在这里教授脚本编写本身,因为那是一个完整的主题。脚本编写是 IT 与软件开发领域交集的最接近的地方。将 IT 命令行任务结合起来在哪一点变成了编程呢?从技术上讲,这一切都是编程,但它是以纯粹专注于系统管理任务的极简编程形式出现的。
通常在 Linux 上,我们会使用 BASH shell 编写脚本。BASH 是一种非常简单的语言,设计上主要用于交互式操作作为一个实时 shell,BASH 是我们假定所有 Linux 命令行交互都会通过的方式。BASH 相对强大且功能丰富,几乎可以用它编写任何脚本。至少在开始时,大多数 Linux 管理员会使用他们在命令行环境中已经在用的 BASH shell,并有机地将脚本元素添加进来,从单一命令、一组基本命令串联到逐步进入完整的脚本编写。
任何 shell,如 tcsh、ksh、fish 和 zsh,都允许你进行脚本编写,并且在许多情况下,比 BASH 提供了更多的功能和灵活性。传统的 shell,如 tcsh、ksh 和 BASH,可能非常有限且笨拙,尝试用它们进行高级脚本编写可能会有困难。Apple 在其 macOS UNIX 操作系统上最近转向使用 zsh,以便与其他 UNIX 系统相比进行现代化。通常情况下,Linux 系统默认不会安装更现代、更先进的 shell,尽管它们几乎可以在任何基于 Linux 的操作系统上轻松获得。
你可能在一个始终提供或提供了其他 shell 的环境中工作,或者你可能有机会自己添加它。如果是这样,尤其是在你需要进行跨平台脚本编写时,特别是与 macOS 一起工作时,你可以考虑使用 zsh 而不是 BASH;或者如果你做了大量 Windows 脚本编写,PowerShell 作为 Windows 的本地 shell 也可以在 Linux 上使用。
Linux 上的 PowerShell
你可能遇到的最奇怪的事情之一,就是在 Linux 上运行微软的 PowerShell。很多人感到困惑,认为它根本无法运行。实际上,PowerShell 在 Linux 上运行得很好。PowerShell 在 Linux 上的问题在于,Windows 上的 PowerShell 用户实际上几乎没有时间学习 PowerShell,而是把大部分时间用来学习各种 CommandLet 或小程序,这些程序可以通过 PowerShell 调用,并与其他小程序轻松结合,赋予系统强大的功能。
在 Linux 上,当然也会发生类似的事情。如果你在 Linux 上进行脚本编写,肯定会使用像 sed、awk、cut、head、tail、grep 等工具。这些工具类似于 CommandLet,但实际上只是日常的系统可执行文件。如果你将 BASH 或 zsh 移植到 Windows 上,你会发现你习惯在 Linux 上使用的工具仍然不可用。那是因为它们是你从 BASH 调用的小程序,而不是 BASH 本身的一部分。BASH 只是编程语言。
反过来也一样。如果你在 Linux 上运行 PowerShell,你仍然需要使用 sed、awk、cut、grep、head、tail 等工具。改变的是语言,而不是操作系统的工具和组件。
所以,尽管学习一种脚本语言并尝试在不同操作系统之间反复使用它是有价值的,但其价值并不像人们想象的那样大。你可能会花费更多时间去解决集成怪癖、误解和糟糕的文档,而这些时间远远超过了语言学习效率所能带来的回报。如果你尝试在 Linux 上使用 PowerShell,书籍、在线指南、示例代码等都不会对你有帮助。它们会假设你正在尝试用 Windows 工具来做 Windows 任务。PowerShell 从本质上来说,是一个真正现代的 Shell,利用操作系统对象来完成繁重的工作。而 BASH 则专注于文本处理和操作,因为 Linux 传统上是建立在文本文件上的,需要一个能够轻松处理这些文件的脚本引擎。
在 Linux 上使用如此陌生的 PowerShell 是一个很好的工具,可以揭示我们通常只视为 命令行 或 Shell 的不同组件的本质。如果我们在 Linux 上使用 zsh,几乎所有 BASH 内建的功能都可以在 zsh 中找到,并且它们都惯常使用相同的操作系统工具。而 PowerShell 几乎没有任何内建的命令可以复制,也没有共享的惯例,这使得它非常明显地区分了来自 Shell 的部分和操作系统中属于 Shell 之外的部分。
然而,一般来说,最推荐在你所在环境中得到良好支持的语言中进行所有脚本编写。就像我们在其他系统管理领域所说的那样,使用那些无处不在、被广泛理解并且适合该环境的工具非常重要。对于大多数人来说,这意味着仅使用 BASH。BASH 是唯一一个在你遇到的每个 Linux 系统上都可以绝对使用的脚本环境。其他的 shell 或脚本语言可能很常见,但没有哪个能像 BASH 那样普及。
当 BASH 对于更高级的脚本编写显得过于局限时,转向另一种 shell(例如zsh)并不常见,因为其他 shell 非常罕见,且通常缺乏在放弃 BASH 后你可能需要的强大功能。传统上,作为 BASH 替代品的高级脚本编写语言通常是非 shell 脚本语言,如Python、Perl、Tcl、PHP和Ruby。Ruby 一直未能获得太多青睐。PHP 虽然在某些任务中非常常见,但作为通用的系统自动化语言却比较少见。Perl 和 Tcl 的受欢迎程度急剧下降,但曾几何时,Perl 是系统自动化语言中的领头羊。这使得 Python 成为了高级脚本需求的一个非常明确的领先者。
Python 总体上有许多优势。它的运行速度相当快。它几乎可以在任何平台或操作系统上使用(包括所有 Linux、其他 UNIX、macOS 和 Windows)。它相当容易学习(通常被用作新程序员的第一门语言)。它非常常见,很多 Linux 上的应用和工具都依赖于 Python,因此即使它不是作为标准安装,也经常会发现它已经预装好了。由于它在这些任务中如此常用,Python 在这方面的文档逐渐增多,围绕它编写的其他工具也应运而生,使得它越来越适合承担这一角色。
目前,几乎所有 Linux 系统的脚本编写都尽可能使用 BASH,而在需要更多功能或灵活性时则使用 Python。其他语言基本上都是小众应用。这意味着 BASH 和 Python 也有额外的理由让我们在选择自己的脚本语言时应该重点考虑它们:标准化。
系统自动化不同于一般的编程。广泛的编程开发人员花费多年时间学习多种语言、语言家族、构造,并且将所有时间都投入到编程环境中。在不同语言之间切换、学习新语言、适应语言变化等,都是开发者日常生活的一部分,而在语言之间切换的开销非常小。对于系统管理员来说,这有些不同。从理论上讲,我们花在学习编程上的时间非常少,而且很少接触到真正的语言多样性。因此,对于管理员来说,拥有一两种常用的语言是非常重要的,这样有助于我们在未来找到资源、示例、同行评审等,支持我们的自动化工作。当然,这些语言并不是唯一可接受的选择,但它们相较于大多数其他选项,确实有着相当大的优势。
当然,脚本编写是一个非常广泛的话题,脚本的内容从几行简单的按顺序执行的命令到包含复杂代码的大型程序都有。提升脚本编写技能是一个值得专门投入大量时间的话题。好的脚本通常会包括自己的日志机制、错误检测、函数、可重用组件等。你可以在系统自动化脚本上不断地投资更多的编程技能。
开发人员的脚本编写工具
无论你是在编写一个非常简单的脚本,还是在为你的组织中代代相传的自动化杰作而努力,你都值得迈出额外的一步,学习一些软件开发中使用的工具,以帮助脚本编写过程。
最简单的一方是像集成开发环境(IDE)这样的工具,它们能让编写代码变得更快、更容易,并帮助你避免错误。开发人员几乎总是使用这些工具,但系统管理员往往会忽视它们,因为他们认为自己编写脚本的时间很少,学习另一个工具可能不值得。而也许确实不值得,但你学会的工具越多,你就越可能使用它们,进而编写更多的脚本。一款好的 IDE 可以是免费的并且非常易于使用,因此它是一个很好的起点,你可以将它整合到你的工作流程中,而不需要花费太多时间或金钱,下载并安装一个也不过几分钟的事。
另一个开发人员几乎普遍使用、而系统管理员很少使用的真正庞大工具集是代码仓库和版本控制工具,如 Git 和 Mercurial。借助这些工具,尤其是将代码托管在这些工具所关联的中央服务器上,我们可以在编写和管理脚本方面实现飞跃。这些工具对于管理我们环境中其他形式的文本数据也非常有用。尤其是 Linux 使用基于文本的配置文件,可以像脚本一样处理,并将其纳入版本控制系统进行管理。这是跨领域技能共享的一个优秀应用。
版本控制无疑是软件开发世界中最必须掌握的技术,对于我们自己的脚本编写至关重要。版本控制让我们可以跟踪随时间变化的代码,测试代码并轻松回滚,它允许多个团队成员共同管理同一份脚本,按用户跟踪变更,支持代码审查和审核,简化数据保护和部署等等。如果你只采用一种开发技术,那就选这个。刚开始时可能会觉得有些繁琐,但很快它会变成第二天性,让你做的许多事情变得更加轻松。
开发世界中有许多我们可能会用到的其他工具,如持续集成、自动化部署和代码测试,这些工具根据我们编写的脚本可能会非常有用,但几乎所有这些工具都是小众的,即使在高度自动化的环境中,它们也是完全可选的。了解这些工具可以让你接触到可能对你的工作流程有意义也可能没有意义的选项,同时还能让你深入了解你的潜在开发团队可能的工作方式。
将软件工程作为获取如何更好编写脚本的灵感来源,但不要觉得你必须或者应该采用每一个工具和技术。自动化和产品开发的脚本编写确实有交集,但它们最终是不同的活动。
编写脚本并没有什么秘密,唯一的秘诀就是不断实践。市面上有许多优秀的书籍和在线资源可供参考。可以从最简单的项目开始,寻找过去可能手动完成的工作中可以通过脚本实现的机会。系统任务,如部署或系统设置检查清单,可能是一个很好的起点,或者编写用于部署一组标准工具的脚本,或许是编写一个收集多台机器特定数据的脚本。我经常发现自己在编写数据处理脚本。一旦你开始寻找,你可能会发现许多新的脚本技能可以派上用场的地方。
使用非计划脚本的最佳起点之一是基本的构建和安装任务。使用脚本来执行初始系统设置和配置,包括安装软件包、添加用户、下载文件、设置监控等等。这些任务通常在相对较小的努力下提供了大量的收益,并且可以作为一种文档形式,列出系统所需的任何软件包和配置更改。以这种方式完成的文档具有很高的权威性,因为它真正记录了实际使用的过程,而不是预期或假设的过程。
文档优先
在软件工程领域,有一个概念是编写测试来验证代码。虽然并不完美,但运行测试使得软件出现 bug 的可能性大大降低,因为测试会检查预期的行为并确保其发生。我们仍然可能遇到 bug,这绝非百分之百的保证,但它是一个很好的步骤。在经历了几十年的代码测试后,提出了在编写代码之前编写测试的可行性这一想法,研究发现这样做不仅能够减少 bug,还能提高代码编写的效率,仅仅因为编写测试促使我们以更好的方式思考问题解决方法。测试优先编程被认为是软件开发方法的一次突破。
这个概念可以在系统管理领域中以某种方式延续下来,我称之为文档优先工程。在这个概念中,我们首先编写文档,然后使用这些文档来构建系统。如果没有文档,我们就不构建它。就像测试驱动编程一样,这种方法迫使我们提前思考系统应该如何工作,这给了我们另一个机会,确保我们正在做的事情是经过良好规划和合理的。而且它还让我们有机会验证我们的文档是否完整且合理。当我们事后编写文档时,往往更容易制作出无法真正执行任务的文档。
在某些情况下,比如自动化程度较低的情况,这可能意味着仅仅在 Wiki 或文字处理软件中记录我们能记录的内容,并在部署系统时依赖这些文档。如果我们有更高的自动化水平,那么我们实际上可以将代码作为文档来编写,这些代码会为我们构建系统。由于代码本身就充当了文档,它不仅仅是文档优先,而是文档实际上完成了工作,这完全可以保证文档的完整性和准确性!
自动化的内在特性是鼓励更好的文档编制,并将文档从事后记录转向事前记录,进一步转变为将文档本身作为构建机制。这也意味着我们有可能看到效率上的双重提升,因为我们希望用于文档和脚本的版本控制、备份以及其他机制可以自动应用于两者。
使用高级工具进行脚本编写在某种程度上也可以被视为自动化成熟度的更高阶段。
脚本与任务调度的结合
希望显而易见的下一步是将任务调度和我们新获得的脚本知识结合起来,以获得更强大的功能。让复杂的任务能够自动运行,而无需任何人工干预。
以这种方式自动化的常见任务通常包括软件更新。拥有一个脚本,能够查找最新的更新,下载它们,准备环境,并在预定时间自动部署,十分方便。几乎任何应当一起执行的复杂任务都可以以这种方式进行调度,无论是每分钟一次,还是每月的第三个星期二。脚本也非常适用于处理条件性情形,在这些情形下,只有在特定条件下才执行某些操作,例如,只有当存储超过某个水平,或者某些特定人员登录时才执行。
几乎是一个特殊情况,因此我认为非常值得提及的是使用定时脚本来管理备份或复制。
状态管理
我们在系统自动化中经历的最令人惊叹的变化之一是引入了状态机和系统的状态管理。状态是一个难以解释的概念,因为这远离了 IT 和系统管理中的常规思维方式。然而,状态通常被视为系统的未来。
在传统的系统管理和工程中,我们谈论和思考任务:我们如何让系统从 A 点到 B 点。在状态理论中,我们不讨论如何管理系统的方式。相反,我们只关注预期的结果或结果状态。
换个角度思考:我们开始关注结果,而不是关注过程。我们从以过程为导向转向以目标为导向。
这种方法迫使我们真正改变几乎所有我们关于系统的思考方式和认知。它在各个方面都是一个游戏规则的改变,让我们这些人能够更好地专注于我们擅长的领域,同时让计算机在它擅长的领域做得更好。
所有这些魔法都是由所谓的状态机完成的。在系统管理的背景下,状态机是一个代理或代码片段,它接收一份或一系列文档,这些文档规定了系统所期望的状态。状态可以指系统的几乎任何方面,例如已安装的包、当前的补丁级别、配置文件的内容、防火墙中打开的端口以及应当运行的服务列表。
状态机会根据这些描述目标状态的文档,确保(或至少尝试)系统处于期望的状态。如果缺少某个包,它会安装该包。如果某个服务没有运行,它会启动该服务。如果配置文件不正确,它会进行修正。相反,如果某个不该安装的程序出现在系统中,它会被删除。如果某个不该运行的服务被启动,它会被关闭。
状态机通常每隔几分钟或几秒钟运行一次,扫描其状态文件并确定系统应该是什么样子,然后扫描系统以验证其已知的状态与预期的状态是否匹配。如果发现不一致,状态机会采取必要的纠正措施。当然,在背后,这一切都是通过复杂的脚本和系统工具完成的,这些脚本和工具组合在一起提供了强大的能力来强制执行状态。状态机能够采取纠正措施的程度取决于它可以访问的脚本的能力。这并不是无限的,但通常在 Linux 系统上,状态机具有足够的能力来应对现实世界中非攻击场景中的实际需求,并且在缓慢或阻止许多低强度攻击方面仍然非常有效。
从理论上讲,状态机通过保持系统处于我们所期望的几乎恒定的状态来实现这一目标。使用状态机时,我们花时间编写文档,描述我们希望系统具备的特性,然后让状态机本身负责如何使系统按预期方式运行。这包括机器的初始设置,将一个基本的、原始的操作系统安装转变为特定工作负载的功能组件。状态机也可以在虚拟化管理程序和云级别运行,从而使我们不仅能在单个系统内维护标准化的概念方法,还能在提供系统的平台级别保持这一标准。
登录的终结
状态管理的本质是鼓励(如果不是强制的话)彻底取消为了管理目的而登录服务器的概念。然而,在我们考虑消除登录之前,状态管理系统的作用是通过状态来改善传统的远程管理方式。
传统上,远程管理中最大的风险是需要开放端口,并且必须灵活地保持这些端口开放,以便在任何必要的时刻从任意位置进行管理。虽然将端口数量减少到最少,并将其限制为单一的 IP 地址在理论上看起来是一种很好的安全措施,但在实际应用中几乎没有用处。为了让管理员能够在紧急情况下从任何位置快速登录,要么需要暴露太多,要么需要过多的步骤来限制访问。
进入状态管理。通过状态管理,系统可以通过存储在集中式仓库中的状态定义文件指示开启 SSH 服务,开放一个用于 SSH 服务的随机端口,并将其锁定为管理员或管理员组的当前 IP 地址。版本控制系统将轻松追踪变更请求的时间、请求人以及变更的内容。在理论上,机制中还可以包含一个审批步骤。变更记录后,系统将授权指定管理员的访问权限。一旦他们完成操作,或者按照预定计划,状态管理系统将在完成所有文档记录后恢复变更,并完全关闭所有访问通道。增强安全性的潜力是巨大的。
但这仅仅是一个过渡步骤。通过完整的状态管理,我们理论上应该不再需要登录到系统。我们应该能够通过状态系统本身执行任何必要的管理步骤,或者更合适地,这些步骤应该由状态引擎自动执行,以确保保持适当的系统状态。
要完全实现这种无需登录的机制,我们必须将状态管理与上一章中提到的一些概念结合起来,例如远程日志收集和告警系统,这样即使是像容量规划这样的任务,也无需登录到单个系统。对于传统的系统管理员来说,这听起来通常像是亵渎神明,几乎不可能实现,但今天许多公司正是如此运作,并且通过事先做好的工作,这完全是可行的。
对于运行在办公室内物理硬件上的系统来说,这听起来可能像是过度防护,也许确实是。但对于运行在云服务器上的系统来说,这在许多情况下非常实用。对于一个经过充分测试、文档化且正常运行的系统来说,不应需要人工干预。手动管理既难以文档化,又很难重复操作,并且极容易出错。当然,人工干预可以作为最后的手段,但今天完全可以通过完全依赖重新部署来避免人工干预。
自动化成熟度模型为我们提供了一种从当前状态到希望达到的状态的路线图。当然,并不是每个组织都必须达到管理所有需求的状态管理水平。并不是每个环境都需要脚本化!大多数组织将继续受益于我们所处的任何成熟度水平。
我们将为成熟度模型的最终级别留出独立的部分。将我们所学到的内容应用到实际中,我们最终会得到…
基础设施即代码
从我们在这里讨论的概念出发,从另一个角度看,我们发现了基础设施即代码的概念。意味着我们可以编写代码或配置文件来表示我们的基础设施的整体。这是强大且解放性的。
很容易将基础设施即代码的概念与状态机的概念混淆,因为它们在许多情况下会有相当广泛的重叠。然而,它们之间存在着关键的区别。
基础设施即代码可以与状态机并行使用,但状态机不允许命令式的系统定义。基础设施即代码可以用来定义状态,也就是基础设施即代码的声明性方法,或者通过命令式的方法定义操作,而不是最终状态,使其更像传统的系统管理,关注的是手段而非结果,即关注 如何 而非目标。
平台与系统
基础设施既指我们运行的系统,即操作系统容器,也指承载这些系统运行的平台,即虚拟机管理程序和物理机器。对于我们在本节讨论的内容,特别是像基础设施即代码这样的概念,其适用性是针对基础设施的两个方面的。
我们在系统级别应用的工具和技术可以与我们的平台级别一起工作,反之亦然。这意味着我们不仅可以依赖这些优秀的工具和技术来配置操作系统和应用程序,还可以利用它们来实际部署和构建虚拟机容器(包括完整虚拟化和容器化),无论是在云环境还是传统的非云环境中。
在这两个领域应用相同或相似的工具,意味着通过概念整合获得更大的整体能力,并呈现我们基础设施的更完整的图景。现代计算的一个关键好处是,从单纯将操作系统视为工作负载构建块,到将虚拟机管理程序也视为直接参与工作负载的角色。虚拟机管理程序不仅仅为操作系统提供一个容纳工作负载的空间,而是作为一个了解工作负载的工具,能够分配资源并作为工作负载组件的一部分。
例如,虚拟机监控程序或甚至虚拟机监控集群级别的管理将意识到它正在为应用服务器、代理、处理节点、存储、备份、数据库等提供工作负载容器。由于平台级别对工作负载有感知,它可以做出智能的资源配置决策,不仅知道需要什么样的资源,还知道将工作负载部署到哪些节点。如果我们有一个三节点的虚拟机监控集群并且我们配置了三个应用虚拟机,那么配置应该知道将这些虚拟机分布在不同节点上,每个节点一个虚拟机,以增加冗余;而且它还应该知道,对应的数据库也应该这样配置,确保数据库与应用服务器分布在相同节点上,并且配置这些应用服务器连接本地数据库实例,而不是随机的非本地数据库实例。从应用程序通过操作系统一直到平台都具备工作负载感知,这意味着更好的性能、更少的工作量和更强的数据保护。
通常,当我们进入基础设施即代码时,我们自然会开始合并系统和平台管理团队,因为将它们视为更大、更整体的基础设施愿景的两个部分是合乎逻辑的。
命令式基础设施即代码设计为我们带来了许多与状态机相似的前期好处,但初期设置工作量较小,而长期维护则需要更多的工作。因此,当基础设施即代码首次推出时,命令式系统被认为是常见的,但随着市场的发展,声明式(有状态)工具集和预构建的命令式结构的出现,转向声明式基础设施即代码是不可避免的。
当然,在底层,所有这样的系统最终都会是命令式的。任何声明式系统最终都会使用预定义的命令式步骤来达到所需的状态。因此,为了拥有一个供我们使用的声明式系统,我们或其他人必须编写命令式脚本和工具,这些脚本和工具可以将我们从多个不同的起点引导到同一个终点。即便设计了基础状态引擎,构建这些组件仍然需要大量的时间和测试。
这些脚本必须为每个任务存在。如果你想定义一个文件必须存在,那么我们需要在后台有工具来检查文件是否存在、判断如果文件不存在该怎么做、如何查找文件、如何复制文件、将文件放在哪里、文件复制失败时该怎么处理等等。这可能是最简单的使用案例,你可以轻松地想象,处理任何其他任务时它将变得多么复杂。即使是一个简单的声明式系统,也将由无数管理员可能永远不会知道的命令式脚本构成。或者它可能是管理员为了特定的需求而为特定系统构建的。这个概念是灵活的,但也很复杂。
理论上,我们可以拥有声明式的状态管理,而不需要像基础设施即代码那样深入。尽管这听起来有些奇怪,但实际上,那些刚开始使用状态系统的人常常几乎是手动进行的,尝试以接近命令式的方式发出有状态的指令,以通知系统所需的状态,而在此之前并没有将所有方面记录在代码中。
这些技术的工具通常会被部署,甚至被使用,但往往是非常不完整的。这可能是由于挫败感、缺乏规划、公司内部政治等等原因。因为完全在这种模式下工作非常密集,并且需要前期的充分规划,所以很难获得足够的时间和来自上层的支持来进行完整的实施。因此,我们经常看到这些工具被用来推出基本的、众所周知的功能,使用预构建的第三方脚本,但复杂的、通常是组织特有的配置仍然以传统方式进行。急于部署系统的压力通常会驱动这种行为。
这引出了关于基础设施即代码的真正关键最佳实践。最重要的是获得广泛的组织支持,并在工作负载投入生产之前,投资于适当的文档编写和代码的完整性。
就像我们在软件工程领域讨论的任何代码一样,我们的基础设施即代码也需要在使用之前进行测试。然而,测试系统管理代码通常比其他类型的应用程序更为简单。为新工作负载创建代码,然后从零开始部署该工作负载是相当直接的,直到结果完美为止,可以一遍又一遍地尝试。然后可以测试系统修改、故障和其他潜在场景,以确保系统能够在潜在的实际问题下良好响应。
这种测试的一个重要好处是,我们代码的功能就是从大致“什么都没有”的状态中创建基础设施。所以我们所要做的就是从一张白纸开始,如果一切正常工作,我们的基础设施就会自我创建,我们可以从那里进行测试。
即使我们无法像希望的那样创建一个完全自我创建、自我修复、自我配置和销毁的基础设施,我们至少可以使用这些工具和技术走一部分的路。从简单地从零开始构建基础设施,并不维护或退役它,这是一个很好的第一步。
基础设施即代码作为灾难恢复
我们在其他地方已经提到过这个概念,并将在下一章关于备份和灾难恢复中深入探讨,但它非常重要,以至于我们在讨论现代系统中灾难恢复的组成部分时,必须始终提及它。我们谈论基础设施即代码时,实际上是在讨论自动化创建以前不存在的系统。
这正是灾难恢复场景中所需要的。当我们的系统消失时,我们需要将其恢复。将我们的系统、它们的标准文件、它们的配置等,作为代码存储在一个能够轻松恢复的地方,或者更好的是,在正常的灾难期间完全不会丢失,这意味着我们已经准备好在任何我们想要的地方,以极短的时间建立一个新的系统。
因为这些类型的构建系统大部分时间用于为测试和生产部署构建工作负载,它们通常具有快速、高效、易用、易懂并且经过大量测试的优点。以这种方式构建的系统在测试中构建时与生产中的构建完全相同,在紧急灾难恢复时也是如此。我们在前期就做好了所有艰苦的工作,确保系统快速且可重复构建,这样当发生可怕的事情时,我们就不需要偏离既定的流程。
传统的灾后系统恢复需要通过一个独特的过程来构建系统,而这个过程与最初构建系统的过程完全不同。这种做法容易出错,原因有很多。这是一个很少经过良好测试或文档化的过程。通常是在没有充分规划、且承受很大压力的情况下进行的。这是经历这种情况的最糟糕时机,因为此时是对一切做到完美要求最大的时刻。
通过创建一个每次第一次、第二次、每次几乎瞬间并完全相同地自动构建自己的系统来避免这些问题,的确是一件大事。如果有什么能够证明自动化和基础设施即代码的好处,那就是这个。拥有系统能够快速且正确地恢复的信心是今天大多数公司所没有的。担心备份无法恢复,缺少正确配置工作负载的系统启动知识,许可证或系统细节没有文档记录,或是所需的软件包不容易获得,都是非常严重的问题。我们有一种现代的方法,能够让这些问题迎刃而解,而不是忽视它们并希望问题自行解决。
将我们的组织带到真正实现基础设施即代码的水平是一个巨大的步伐,但这就是未来。做到这一点的公司拥有更快的构建速度、更快速的灾难恢复、更好的安全性、更强的灵活性、更快的扩展速度,所有这些意味着它们有更大的机会赚取更多的利润。归根结底,作为系统管理员,我们的唯一工作就是以一种方式来做我们的工作,借此通过我们的努力,无论这种努力多么间接和难以衡量,都能提高组织的盈利能力。
现在我们知道了这些技术是什么,是时候谈谈那些实际存在的、已经准备好进行测试的工具,它们使得状态机和基础设施即代码成为可能。
现代自动化工具
所有这些强大的功能主要来自于过去十五到二十年内引入系统管理领域的现代工具。Linux 世界非常幸运,从一开始就处于这一运动的前沿。这自然源于 Linux 社区倾向于在创新上蓬勃发展并专注于创新,也因为基于命令行接口和简单文本文件进行配置和软件仓库的系统本质,使得自动化变得更加简单。Linux 的设计可能并非有意鼓励自动化,但几乎每一个主要方面,无论是系统实现还是生态系统的行为,都使它具备了理想的组合因素,几乎总是成为新的自动化工具和策略的领导者。
配置管理系统
新的工具不断涌现,技术也会随着时间而变化,因此在此列出一个权威的工具清单并不可能,但有一些重要工具已经成功地在行业中树立了自己的名声,值得作为调查适合你环境的工具的起点。目前,最流行的基础设施自动化工具(基础设施即代码)包括Chef、Puppet、SaltStack、CFEngine、Ansible和Terraform。其中最古老的工具CFEngine,早在 Linux 内核发布不到两年时就首次推出!
所有这些工具,通常被称为配置管理系统,共享一种共同的方式,即允许你编写代码和配置文件来定义你的基础设施环境,并且它们基于这些代码管理基础设施的自动化。它们中的大多数提供多种功能行为,比如可以选择以命令式或声明式的方式工作。大多数还提供从被管理系统拉取配置或从中央管理位置推送配置的选项。因此,你可以获得各种功能选项以及多种产品选项。
这些产品之间的最大区别实际上是用于记录你基础设施的编码风格,以及产品的成本、支持或授权方式。大多数这一领域的产品最初都是开放源代码,或者后来转为开放源代码。开放源代码是有道理的,因为这个领域发展得非常迅速,而管理工具也自然倾向于开源,因为它们主要是由最终用户或来自开源社区的人开发的,并且主要用于技术圈子里。封闭源代码的产品则更适合面向客户的产品,其中经理而非工程师在选择这些工具。大多数基础设施即代码工具的一个关键优势是它们是免费的、开源的,并且通常包含在 Linux 发行版中,因此工程和管理团队通常可以选择测试并将其部署到生产环境中,而无需管理层的批准,甚至管理层可能并不知道它们正在这样做。由于授权和使用场景,这与部署 OpenSSH 或其他日常系统管理中使用的标准组件没有太大区别。
当然,这里最简单的方法就是简单地了解一些工具,下载并安装一些,看看你喜欢什么。同时使用多个工具并不是一件坏事,大多数概念都可以从一个工具转移到另一个工具,即使脚本编写和文档编制的风格有所不同。许多这些工具都是跨平台的,虽然它们通常以 Linux 作为主要平台进行部署和管理,但其他平台,尤其是 BSD,以及 Windows、macOS 和其他平台,也可能被管理。考虑选择一个能够扩展以满足您组织未来所有需求的平台。如果您是一个异构商店,您可能希望投资您的技术知识到一个平台上,该平台可以跨领域管理所有内容,而不仅仅是管理 Linux,即使 Linux 是您的起点。
桌面就是服务器
把桌面视为服务器的一种形式可能会有点令人困惑,但从某种意义上说,它们确实是如此。它们只是一对一终端用户图形用户界面服务器,通常部署在桌面或家庭而不是数据中心。这只是一个微不足道的语义问题,直到我们开始试图理解桌面如何或不如何适应我们更大的支持战略。
但是,当我们考虑到桌面实际上只是服务器的一种特殊类别时,很快就会意识到,将它们归为通用管理也是有道理的。当然,例如,如果我们在桌面上使用 Linux 发行版,这一点比在使用 Windows 时更为明显,但事实仍然如此。如果我们可能会支持同时使用相同工具的 Linux 和 Windows 服务器,那么无论部署在哪种操作系统上,为桌面也采用同样的方法并不存在实际障碍。
传统上,但出于我所知的原因,服务器和桌面通常使用完全不同的工具集进行管理。我可以假设为什么会是这样。通常情况下,两个不同的团队提供此管理,并且每个团队都独立选择其自己的工具。服务器在一个世界中发展,而桌面支持在另一个世界中发展。供应商希望销售更多工具,并且迎合傲慢总是使销售变得容易。最有可能的因素是:服务器通常从命令行进行管理,而大多数桌面支持团队希望纯粹从 GUI 操作。
当我们退后一步看待桌面(和其他终端用户设备)就像它们是服务器时,很容易看出,管理、文档化和监控服务器的同样工具同样适用于桌面。没有真正的理由对待它们有所不同。当然,桌面支持团队始终需要能够远程查看,并可能与终端用户的图形桌面进行交互,以直接帮助解决终端用户的问题,但这与管理职责完全不同。
桌面计算机可以,甚至应该,使用与任何其他服务器相同的高级工具和技术进行管理,例如基础设施即代码和状态机。没错,当我们理解它们实际上是服务器时,适用于所有服务器的规则同样适用于桌面计算机。良好的语义使一切更容易理解。
事实上,甚至有充分的理由认为,终端用户设备是应用这些技术的最有价值领域,因为它们最可能需要重建、修改、共享配置文件、经历变化、被攻击或需要在没有与中央服务通信时进行管理。最后这一点尤其重要,因为那些保持现有状态并继续运行的状态机,可以为脱离网络的设备提供安全性和自我修复的特性,并能够独立执行策略。传统方式虽然也可以做到这一点,但实现起来更困难,且实现的可能性较小。
由于基础设施即代码系统的部署方式,这些系统更有可能在桌面或笔记本电脑脱离公司局域网时仍能继续运行,而传统的管理工具通常完全围绕局域网概念构建。由于终端用户设备传统上具有较高频率的在局域网中上下线或根本不连接局域网的情况,因此使用非局域网中心的工具,在终端用户空间通常比在数据中心空间更为重要。
在某种程度上,移动设备管理(MDM)通常被看作是尝试使工具更倾向于基础设施即代码和状态机的尝试,但这些工具呈现得更像传统工具,并通过更传统的渠道销售,专注于终端用户管理。我觉得这些工具之所以成功,是因为它们在很大程度上复制了该领域的技术和常见做法,一旦我们使用这些工具,我们通常会发现,除非我们在组织中缺乏这些能力,否则移动设备管理工具是没有意义的。
当然,任何新系统的许多优势都来自于约定,而非严格定义。基础设施即代码领域的最大约定之一,就是从以局域网为中心的管理转向网络无关的系统管理部署。通常,基础设施即代码系统的工具都会以某种公共形式托管,无论是在云、VPS,还是在机房托管,并且与可能存在的任何局域网隔离开来。
将托管管理基础设施置于局域网(LAN)之外,意味着我们可能会意外或随意建立的任何局域网中心的连接将不再可能,除非我们部署类似 VPN 这样的局域网扩展技术。这一做法自然促使我们远离部署仅在局域网内有效或利用局域网边界作为安全功能的技术。消除局域网边界使我们能够从一个平台透明地管理多个站点、移动用户甚至多个组织,只要这些系统使用互联网。传统系统在许多情况下会崩溃,并且有共同的安全漏洞,既因为它们容易崩溃或在利用上存在漏洞,也因为局域网中心的思维并不是良好的安全做法。
版本控制系统
我们在自动化主题中真正需要解决的另一个工具类别是代码仓库和版本控制系统。它们在技术上是两个独立的东西,但几乎总是密切相关。
从本质上讲,版本控制系统只是跟踪我们已拥有文档所做的更改,以便我们跟踪一些重要数据,例如谁做了更改,何时做了更改,以及在更改之前、当时和之后文档的样子。仅此一项就非常强大,但今天大多数实现此功能的系统还会用于分发代码和版本控制,使其可以被多人在多个地方使用。在能够做到这一点的同时,它也可以用来填充一个中央存储库,该存储库可以作为主存储位置,以便不需要将任何人的终端视为数据保护的关键位置。这个中央位置还可以作为备份和恢复的地方!
版本控制系统影响了许多现代文档系统,我们在早期的文档章节中介绍了两者,但在这个背景下,我们可以看看现实世界中的产品,例如 Google Docs、Microsoft Office Online 和 Zoho Docs,它们都呈现传统的文档文件类型或界面,但都提供文档的版本控制。为了编码和代码管理,这些系统的使用非常笨拙,但如果你只想迅速开始使用你已经部署的工具,它们也能应急。这些系统本质上是在复制传统代码版本控制系统的机制,并将其应用于电子表格和文字处理。
由于这些办公文档类型非常知名,因此几乎可以将它们视为标准(但它们并非如此),并认为代码版本控制系统是这些文档工具的代码特定修改版(事实上并非如此,它们早于文档工具)。这些系统通常(在我知道的每种情况中)处理标准文本文件,因此无论你使用的是像vi或nano这样的简单文本编辑器,还是使用像Atom或MS Visual Studio Code这样提供全面图形化编程环境并具有深度编辑功能的强大工具,都可以使用版本控制系统。一些高级环境实际上会将版本控制直接集成到应用程序中,以便你从一个地方自动化整个过程,让它看起来和感觉上更接近办公风格的工具!
在实际应用中,目前为止,两个版本控制协议已经崭露头角,几乎感觉市场上只剩下两个选择:git和mercurial。实际上,还有许多其他协议,但只有这两个值得一提。你可以自由地研究其他工具和协议,但请确保这两个协议出现在你可能有的任何研究简短名单中。它们都是免费的,功能类似,支持你今天通常期望的所有功能,包括中央仓库、用户机器上的副本、自动化部署、版本元数据等。
除了所使用的协议,今天版本控制系统的强大功能还来源于支持它们的在线仓库服务。这里有更多选择,而且你也可以自己运行本地服务。两大关键参与者是微软的 GitHub 和开源的 GitLab。两者都是托管服务,提供广泛的免费服务,GitLab 还提供免费的软件,可以让你在自己环境中托管(如果这是你的业务或技术需求)。这两项服务及类似的其他服务提供了中央 git 和 Mercurial 仓库位置、备份的集中位置、用于代码操作和管理的简单 Web 图形界面,以及围绕代码自动化的一系列流程、工具和服务。很多功能在系统管理环境中可能是多余的或无用的,但其中许多功能确实具有潜在用途。你当然可以在没有这些类型服务的情况下获得所需的好处,但这会更困难,几乎所有成功的环境都依赖于它们多年。这些服务对于系统管理的需求几乎总是免费的,别避免它们。作为托管服务,它们的使用也是突破局限,摆脱局域网思维的另一种方式。
在讨论工具时,并没有太多最佳实践或经验法则可以探讨。测试多种工具,跟踪市场上现有和即将推出的工具,评估适合你组织的工具,并深入学习所选择的工具,都是标准的良好做法。
一些经验法则:
-
管理工具几乎应该始终是开源的。这是一个安全至关重要的领域,而许可限制本身就可能带来安全风险。因此,在这个领域,开源比大多数领域更加重要。
-
以与网络无关的方式部署管理工具。这意味着将它们部署到互联网上,选择一个任何位于任何地方的机器都能合理访问的地方。除非绝对必要,避免依赖传统局域网网络连接或安全性。
最佳实践:将所有类型的代码进行版本控制,并保存在代码仓库中。
现在我们已经介绍了这些技术,并简要讨论了一些你可以用来启动调查的实际工具,这些工具可以帮助你在自己的环境中尝试部署并学习。
总结
在本章中,我们探讨了自动化为何如此重要。我们研究了应如何接近自动化并从哪里开始。我们讨论了成熟度建模。我们深入探讨了相当复杂的状态机和基础设施即代码等话题。最后,我们讨论了你今天就能下载并学习的实际工具,这些工具可以将你的编程水平提升到一个全新的高度。
在下一章中,我们将讨论系统管理中最重要且最常被回避的主题之一:备份与灾难恢复。如果有一件事是我们在管理中必须做对的,那就是我们的灾难避免或恢复能力,请不要跳过接下来的章节。
第十章:用户与访问管理策略
在Linux世界中,我们很容易忘记我们依然有用户,而这些用户仍然需要我们在Windows或macOS世界中期望的所有监督、安全和管理。在基于 Linux 的操作系统中,用户通常是被忽视的,因为这些系统常常被视为黑盒服务器工作负载或奇怪的设备,最终用户不需要关心。这当然并不正确。用户在任何 Linux 系统中都很重要,就像在其他任何系统中一样。
在本章中,我们将讨论服务器和最终用户设备的用户及用户访问管理。我们将研究在 Windows 世界中常见的方法,以及在 UNIX 世界中常见的方法,并且我们还会谈到一些在行业中开始出现的替代方法。
我们还将讨论 Linux 的远程访问——即支持或从我们的系统进行远程工作。当然,所有这一切都将在安全的背景下进行,因为用户管理本质上是一个安全话题。
在本章中,我们将学习以下内容:
-
本地用户与远程用户
-
用户管理机制
-
远程访问方法
-
SSH、密钥管理和跳转服务器
-
替代的远程访问方法
-
终端服务器和虚拟桌面基础架构(VDI)
本地用户与远程用户
从最高层次来看,任何系统上的用户账户有两种基本的思考方式。第一种是本地账户,存在于本地系统上并被使用。第二种是用户账户,存储在某种远程服务器上,本地系统通过网络进行引用。当然,也有将这些技术以各种方式结合的混合方法。
我们应该首先谈论这两种方法的明显好处。对于本地管理的用户账户,我们可以迅速访问账户信息,并且不依赖于网络。这带来了明显的性能优势、更好的安全性,并且防止了其他服务的故障影响到我们的本地系统。本地用户是稳健且简单的,快速且易用。直到 1990 年代,甚至很少有人考虑其他可能性。
远程管理的用户今天占据了绝大多数的情况,因为这种模式使得不同组织之间的用户可以有一个单一的真理来源,有时候甚至可以跨组织使用!这有许多好处,比如允许用户创建一个复杂的密码,他们有可能记住并在多个地方使用,修改一次密码就能在所有地方生效,同时也使得支持团队(这可能是我们这些系统管理员)可以轻松重置、锁定或禁用账户。
在现代企业中,假设只有远程用户账户是可行的已经成为常见做法,但本地账户依然完全可用且可行,对于各种规模的组织来说,仍然是一个不错的选择。不要仅仅因为你的规模或现代化程度而认为某种方式适合你的使用场景。当然,几乎所有现有组织都已经在他们将要使用的架构上进行了大量投资,改变架构是一个非常庞大的工作。我们很少能有机会在一片空白的环境中实施类似用户管理的项目,但偶尔也会遇到这种情况。
本地用户管理需要的网络带宽更少,但今天这基本上已经不是一个问题。更为重要的是安全性和可用性问题。如今,大多数网络非常快,用户管理所需的资源也很少;这导致供应商将用户管理提供为一种服务,通过托管服务商通过互联网提供集中式用户账户。如果互联网能够为这些服务提供足够的带宽,那么基于局域网的版本应该也不会有问题。
安全性成为问题的原因是,多个地方共享同一个账户意味着有一个账户会成为攻击的目标,而如果这个账户被攻破,实际上将无限制地访问所有使用该账户的地方。如果我们使用本地用户账户,并且在不同地方重复使用相同的密码,那么这就模拟了这个问题,因此在很多情况下,除非我们遇到一种情况,用户在不同位置使用不同的凭证,否则这个问题并不成立。对于传统的终端用户来说,这种情况不太可能发生。对于系统管理员来说,这可能相对容易做到。经过培训并理解凭证重要性的高安全性用户,可能很容易利用本地账户的灵活性。你必须了解你的用户及其参与意愿,才能真正评估这种情况中的安全潜力。
围绕安全性的更大问题是支持远程账户的具体机制,它们可以单独受到攻击,而与其支持的账户是分开的。无论你选择哪种机制,都必须通过网络进行通信,以便这些账户能够集中化。在几乎所有情况下,还会有某种形式的本地回退机制——例如凭证缓存——它也可能成为攻击的目标,因此远程存在的账户几乎从未能完全消除本地账户及某种机制的需求。如果缺乏这样的机制,那么就有现成的方法可以通过攻击网络访问来中断登录。
远程用户管理的优势在于拥有一个中央存储库,这个存储库可以接收更专注的安全关注,并且能够更轻松地防止物理暴露给攻击者。终端设备通常最多只会缓存少数的用户账户或紧急访问账户,而不是整个用户列表,从而减少了盗窃笔记本电脑或桌面被攻击时,影响超出设备上缓存的账户列表的风险。
这两种方法都不能算作最佳实践。两者都是完全可行的,并且应当在组织层面以及工作负载层面进行评估。企业选择使用不同的方法来满足不同需求并不罕见。通常没有必要实行单一机制,因为大多数组织足够庞大,拥有多样化的需求,且可以合理地在组织内部实施多个机制。通常,这种混合方式效果最佳,因为集中账户对于大多数终端用户最有利,而本地账户则更适合 IT 和其他技术部门。
在我们掌握了这些基础知识后,我们准备好讨论可以管理这些用户的机制,无论我们选择在哪里实现它们。
用户管理机制
在现实世界中,有许多用户管理机制的实现方式需要考虑。有些是 UNIX 或 Linux 原生的,有些在 Windows 世界中常见,有些是新兴的,还有些则是通用且中立的。
需要说明的是,任何探讨用户管理机制的旅程,首先要研究的就是 Linux 用户系统本身。简单而通用,每个值得一提的 Linux 系统都会自带此系统。当然,这个系统是可以被替代的,但实际上它几乎从未被替换。这个系统有着巨大的优势:它始终内置、速度非常快、安全性高,且为每个 UNIX 管理员所熟知。系统中几乎没有出错的地方,也没有复杂的设计。虽然有一些过时的组件可能会因为早期的遗留而存在,如果有必要进行手动配置,可能会让人感到有些困惑,但如今几乎没有人手动操作这些系统(尽管了解如何手动操作总是有备无患)。本地用户通常可以通过自定义脚本、现有工具或状态机等方式非常轻松地自动化。
使用自动化将本地用户转化为远程用户
这正是我们无法区分本地用户和远程用户之间差异的一个典型案例。对本地用户管理的一种重要方法是将主用户列表存储在其他地方。这个列表可能是一个简单的文本文件,我们对其运行脚本,或者更可能是一个配置文件,在基础设施即代码的实现中作为状态管理系统的一部分。
在这个例子中,我们的中央管理系统可以用于将用户账户、权限和细节从中央配置系统推送到我们网络中的每台主机上。系统可能会将所有用户推送到所有机器上,或者只将分配给这些机器的用户推送上去。这些决策在实施过程中完全由你来决定。
在这个例子中,是的,我们仍然在每台计算机上使用本地用户机制,并且在任何给定时刻都不需要通过网络进行登录,然而账户仍然是以一种几乎完全模仿像 Active Directory 这样的系统的方式进行中央控制的。我们可以集中执行密码规则,可以集中创建或撤销账户,可以集中控制哪些机器可以或不可以登录,等等。我们本质上有一个中央用户系统,而不是本地系统。
关键的区别在于,像 Active Directory 这样的真正中央用户目录中,用户活动会被导向中央系统,只有在系统离线或处于某种降级状态时,才会可选地触发本地缓存。当可能时,网络活动会支持登录过程。我们所描述的机制中,所有的登录都是通过本地资源进行的——也就是说,非网络化的资源,而中央系统仅用于更新本地登录列表和细节。虽然“本地账户”和“本地缓存账户”之间存在精确的语义差异,但这两者的行为确实是不同的。这是一个非常有趣的思维实验。假设本地维护的账户必须在每台设备上包含所有用户,但实际上有许多方法可以将其限制为仅几个用户,甚至有时仅一个用户,同时假设没有用户或只有少数用户会从远程用户管理系统缓存到本地设备,但在某些情况下,整个用户列表可能会被缓存到本地。这里的区别在于用户列表是如何本地创建的,了解这种机制在你案例中的工作原理,再加上了解系统的使用方式,就能告诉你两种方法对你的暴露程度。
然而,这种自动化本质上提供了一个相当重要的机会,让我们重新思考关于本地用户限制的假设。在这种情况下,我们或许能够仅通过本地用户重新创建许多或所有通常被认为仅由更重、更脆弱的远程用户系统提供的期望功能。在现代环境中,应用程序通常不会对操作系统认证系统的扩展进行身份验证,这种方法可能会非常奏效,尤其是在基于 Linux 的操作系统上,在这种系统上,这种集成并不常见。如果你的网络架构采用共享认证方法,例如通过 Active Directory 提供的方式来允许访问网络资源,那么这种方法将无法提供与这些模型通常所具有的平滑、集成体验。依赖这些共享认证过程的网络资源设计模型在如今的主流方法中正逐渐失去其地位,因为随着居家办公的增加、用户的流动性增强以及安全问题的关注,用户体验的格局开始发生变化。
在超越本地用户之后,实际上只有默认机制可用时,我们开始看到各种遗留的和更现代的用户管理选项,随着这一领域的升温,未来肯定会有更多选项出现,因为新的基础设施需求正在推动许多企业对用户管理优先级的转变。
在 UNIX 环境中,当然包括 Linux,传统的用户集中管理服务是网络信息服务,最初称为 YellowPages,后来简化为NIS。NIS 由SUN Microsystems于 1985 年推出,并迅速在 UNIX 世界中普及,改变了人们对跨系统用户的思考方式。NIS 是推动 1990 年代 IT 发展运动的先锋,当时目录服务成为那个时代的热门战略技术。NIS 可能不是第一个目录服务(尽管也许是),但它无疑是第一个广泛应用并且从根本上改变了行业的用户管理范式的服务。
NIS 非常基础,但灵活且易于管理,几乎没有现代所需的所有安全性——这些特性在当时使其非常有效。NIS 几乎在所有 UNIX 系统上都普遍可用,包括 Solaris 和 AIX 等商业产品,以及 BSD 和基于 Linux 的开源操作系统。学习 NIS 意味着你可以轻松跨操作系统进行工作,NIS 还提供了不同 UNIX 版本之间的互操作性。
考虑到 NIS 的巨大历史以及它在安全性和可扩展性方面的不足,似乎 NIS 早已过时,成为人们围坐篝火旁给老一辈讲述的故事,但事实并非如此。NIS 至今仍在使用,尤其是在一些历史悠久的大型企业中,NIS 的实现可能早在 1990 年代就已开始使用,那时它仍是关键技术。新的部署可能早在十多年前几乎就消失了,但旧的实现仍然存在。事实上,在撰写本文时,每个主要的基于 Linux 的操作系统仍然包括 NIS 的包和支持,既可以使系统作为 NIS 客户端使用,也可以创建新的 NIS 服务器!有人提出 RHEL 将在未来几年弃用 NIS,但目前这仍然只是一个提议,离实际发生还有一段时间。NIS 为自己创造了相当深远的影响。
NIS 存在许多不足,特别是在安全性和可扩展性方面,以至于它的设计者在仅仅七年后就尝试用 1992 年推出的 NIS+来替代它(我告诉过你,1990 年代是目录服务的黄金时代)。然而,NIS+并不是 NIS 的直接升级,并且管理起来非常困难,从 NIS 到 NIS+的升级过程也并不顺利。NIS+从未获得足够强大的支持,未能成为主流技术,实际上 NIS 在现实世界的使用和软件支持方面超越了 NIS+。制造 NIS 和 NIS+的 SUN 公司宣布 NIS+将在 2002 年停止使用,虽然它在几年后仍然得到官方支持,但已经逐渐衰退。毫无疑问,NIS+推动了集中式用户管理技术的发展,但它本身从未成为关键技术。它的黄金时代是在 1990 年代中期,但由于当时涌现了大量的技术,NIS+在来自各方的竞争中逐渐被遗忘——包括来自 Novell 和 Microsoft 等新兴厂商的竞争。
为了避免深入讨论 1980 年代和 1990 年代那些复杂且大多被遗忘的目录服务历史,我们只需关注 1993 年推出的一项主导技术——LDAP(轻量级目录访问协议)。LDAP 在许多方面改变了游戏规则。首先,它是厂商中立的,允许任何系统自由实现。其次,它具备许多先进的数据库、协议和安全特性,既能够灵活使用,又能保证安全,同时具备良好的可扩展性。虽然当时也存在其他技术,但到了 1997 年 LDAPv3 发布时,其他目录服务几乎不再成为新闻头条。LDAP 被视为局域网目录市场的明确胜者和未来。
LDAP 在 1990 年代开始取代 UNIX 世界中的 NIS 和 NIS+,包括在基于 Linux 的操作系统中,尽管当时可用的实现复杂且尚未广为人知。LDAP 真正取得突破是在 2000 年,Microsoft 宣布他们将用名为 Active Directory 的 LDAP 实现来取代传统的安全账户管理器(SAM)系统(该系统以有主备域控制器(PDC 和 BDC)而闻名)。Active Directory 被证明是一个制作精良且易于管理的 LDAP 实现,它完全主导了市场,并且超越了 LDAP,甚至到了今天,很少有人意识到 Active Directory 本质上只是市场上众多 LDAP 实现之一。
基于 Linux 的操作系统几乎可以使用任何 LDAP 服务器作为目录服务源,甚至可以使用 Active Directory 本身,后者是一个 LDAP 服务器,但除了 LDAP 系统部分外,还有像 Kerberos 这样的高级要求,赋予了它比普通 LDAP 更强的功能和安全性。自 1990 年代末以来,LDAP(以某种形式)一直是 Linux 系统需要认证到基于局域网的目录服务时的通用标准。今天,有多种 LDAP 服务器实现可以在 Linux 上运行。甚至还有用于 Linux 的 SAM 和 Active Directory 实现,可以作为服务器运行!
如果选择使用本地目录服务器作为方法,那么在基于 Linux 的操作系统中,几乎可以肯定实现 LDAP 的方式是唯一合理的选择。如果目的是与其他系统(如 Windows 或 macOS)进行集成,那么带有额外特殊功能的 Active Directory 版本的 LDAP 几乎可以肯定是必需的选项——无论是直接来自 Microsoft 的版本,还是可以在几乎任何 Linux 上运行的开源 Samba 实现。如果是为了实现全 UNIX 设备的集成,那么更传统的 LDAP 服务器产品更可能是合适的选择,例如 OpenLDAP 或 389 目录服务器。
一般认为 LDAP 不适合暴露给公共网络(如互联网),通常被认为是局域网中心化的,这意味着它至少部分依赖于网络防火墙来提供一个安全的操作空间,以便它能够执行其工作。暴露 LDAP(即使假设通过升级版 LDAPS 协议支持 SSL/TLS)也有一定的风险。一些公司仍然这样做,虽然它可以工作,但需要大量的规划和对暴露范围的理解。许多公司通过第三方代理不小心暴露了 LDAP 组件,导致了无意的暴露(也突显了局域网中心化安全方法的围墙花园理论的风险)。
著名的 RDP 暴露风险
在 Linux 或 UNIX 圈子里,RDP 暴露风险的例子并不像在 Windows 世界中那样广为人知,因为通过微软的远程桌面协议(RDP)远程访问系统是非常常见的。然而,RDP 通常相关的概念和问题,如容易受到暴力破解攻击和对潜在攻击者的高可见性,实际上与 Windows 本身无关,而是与架构设计有关。
问题在于,将 RDP 暴露在一个公开可访问的 IP 地址上被认为是非常高风险的。然而,RDP 协议的安全性与 SSH 相似,SSH 通常被认为是可以公开暴露的(在合理范围内)。为什么这两种用途和安全性相似的协议会导致两种如此不同的安全态势?
秘密在于,Windows 世界中的一个惯例是普遍使用 Active Directory(一个 LDAP 实现),或者是微软标准的多用户 RDP 环境RDS(远程桌面服务)要求 Active Directory。提到 RDP 时,Active Directory 几乎成为了一个不言而喻的结论,但使用 SSH 时,通常假设不会使用 Active Directory 或某种形式的 LDAP(至少不是作为外部认证方法)。
为什么底层的安全方法会产生不同的效果,而 Active Directory 和 LDAP 本身都是高度安全的,RDP 也是一个非常安全的协议?答案在于,RDP 以一种与其在内部局域网中的使用方式截然不同的方式强制暴露了对 Active Directory 的访问。
在局域网内,我们基本上有一个自动白名单,它包含了我们局域网中的设备。在许多环境中,这个白名单会被 VLAN 进一步限制,将不必要的设备(手机、物联网设备等)隔离在终端用户设备之外。在更大的环境中,网络访问控制可能进一步限制潜在的暴露,从而为我们的 Active Directory 提供一个非常安全的环境。此外,Active Directory 本身通常通过限制对任何给定账户的登录尝试来保护自己,在允许进一步尝试之前,会将账户锁定一段时间。远程攻击局域网中的 Active Directory 通常是相当困难的。
当我们将 RDP 开放到互联网时,所有这些控制都会完全消失。当然,可以通过 IP 白名单、VPN 封装或其他技术来限制这一点,但标准部署将会大范围地暴露我们的系统(如果没有这样做,暴露它的目的通常就会丧失)。通常被忽视的是,在一定数量的失败尝试后锁定机制,这对于确保 Active Directory 的安全至关重要,但它也为对我们的用户发动拒绝服务(DoS)攻击提供了手段(也就是说,外部用户可以轻易地阻止我们的用户登录)。为了减轻这种攻击风险,我们必须禁用 RDP 的此机制,从而允许来自公共空间的无限攻击!两种选择都不完全可行,因此,尽管 RDP 和 Active Directory 在各自的领域内都相当安全,但在传统方式下使用 RDP 仍然具有很高的风险。
SSH 和其他机制通常与中央用户账户系统(如 LDAP 和 Active Directory)解耦使用,使它们能够保持一个完全独立的安全机制和姿态,相较于其他用户认证方法。RDP 当然也可以这样使用,但由于 Active Directory 的存在,通常假设它具有中央用户账户访问功能,这使得将其视为解耦服务变得困难,因为我们组织中的许多人会期望它与 Active Directory 有即时的集成。
今天,我们生活在一个后 LAN 和通常是后 LDAP 的世界里。即使是 LDAP 的最大支持者微软,也在尽可能避免使用它,并且可能比其他任何公司都在投资 LDAP 替代方案,主要是他们自己的 Azure AD 服务,这个服务令人困惑地保留了“Active Directory”这个名字,尽管它与 Active Directory 完全不相关(但可以与之连接以扩展它)。
对行业公认的认证系统的最大变化是,大多数系统是托管产品,而不是企业需要自行部署和维护的软件;而且大多数现代系统都是基于互联网的,允许用户几乎位于任何地方,只要他们有互联网连接,就能连接到认证机制。
这些新的机制来自许多不同的供应商和供应商类型,以不断增加的多样化形式出现。在完全不涉及服务器、仅限桌面的 Chromebook 世界中,Google 自身拥有一个独特的认证机制,并且今天代表了基于 Linux 的最终用户市场的一个非常重要的部分。
操作系统登录在现代世界中还有意义吗?
作为一本关于 Linux 管理的书,我们无可避免地要讨论操作系统级别的用户管理,并且我们必须(按照最佳实践)质疑这个概念今天是否仍然重要(或从历史角度来看是否重要),或者登录操作系统是否很快就会成为过去式。说实话,这个问题并不容易回答。直觉的反应是得出结论,操作系统用户是极其相关的,并且是所有安全的基础。但它们真的是吗?
首先,我想先说:是的,通常来说,操作系统的登录和用户管理今天仍然很重要,而且一直以来都是如此。
然而,我们对用户登录的思考方式发生了巨大的变化。今天的用户环境与一到两十年前大不相同。让我们从一点历史开始。
在 1990 年之前的时代,即古老的计算机世界,极少有系统使用用户身份验证机制,至少在操作系统级别没有。像 UNIX 和 VMS 这样的系统是特殊案例,是被视为先进和令人印象深刻的大型企业系统。大多数用户接触到的,甚至是使用像 Mac、Amiga 或 MS-DOS 这样的系统,都是单用户、没有身份验证的系统。直到 2001 年,微软的 Windows Millenium Edition(ME)发布时仍不支持真正的多用户(因为它仍然只是 MS-DOS 上的图形化外壳)。总的来说,操作系统需要管理多个用户的想法曾是一个陌生的概念。
在 1990 年代,随着网络的普及、互联网逐渐成熟,用户对更高级功能的需求显著增加,用户安全性和访问控制的转变非常重要。如果说 1990 年代有什么特征的话,那就是用户管理的时代(我们之前提到过)。突然间,每个人都开始关心如何处理多个用户共享同一设备,如何在多个设备之间使用户体验变得可移植。系统管理几乎被完全颠覆。
到了 2000 年代,操作系统级别的用户体验期望已经深深扎根,用户管理从竞争优势转变为商品化功能。最后那些没有支持原生多用户功能的操作系统逐渐消失,即便是面向娱乐用户的普通终端产品也开始鼓励用户管理和安全性。
当智能手机首次进入市场时,它们是对 1980 年代无用户系统的回顾。设备的持有者被假定为其普遍且未命名的唯一用户。即使是手机也已经至少转变为一个以用户和安全为中心的设备,即使它们仍然聚焦于单个用户,但也会考虑访问控制和用户身份。
在服务器端,用户管理在过去几十年里确实失去了光彩。在 1990 年代的巅峰时期,Linux 及其 UNIX 亲戚系统曾风靡一时,直接的终端用户登录和服务器上的用户管理占据了系统管理员大部分的工作时间。这个趋势逐渐消退,如今,终端用户需要在操作系统级别上访问服务器的账户或登录的想法,最多也只是显得过时。例外情况总是存在,但它们少之又少,并且越来越罕见。
即便在其巅峰时期,所有管理员必须使用单独的用户账户登录这一必要性也从未得到普遍接受。或许所有管理员共享单一账户从未真正成为常态,但也从未真正罕见过。共享 root 账户(默认的管理员用户账户)访问一直是一个普遍的做法,尽管很少有人愿意承认自己见过,它在 Linux、Windows,甚至可能在所有其他环境中都很常见。这种做法(并且肯定仍然存在)如此广泛,以至于通过外部机制管理用户访问单一账户的技术和工具甚至有点流行(比如登录到一个第三方控制台,按需访问多个服务器上的 root 账户!)
由于我们这本书是关于最佳实践的,我想花一点时间指出,作为系统管理员,维护用户身份和访问控制在我们的服务器上绝对是最佳实践,而且共享账户即使管理得当并且安全,通常也不是一个好主意。为了维持更安全和可审计的系统所需的努力并不大,我们完全没有理由去避免它。尽管如此,共享账户的访问并不一定像听起来那么危险,因为即使在这种情况下,仍然存在审计控制和访问控制的潜力,而虽然我真的怀疑是否存在实际正当的使用案例来支持这么做,但确实可以让共享访问变得足够安全,以便有效运作。
更重要的是,对于服务器(以及终端用户工作站的管理功能),现代设计技术如状态机、基础设施即代码、应用封装(如应用容器)、MDM(移动设备管理)甚至RMM(远程监控和管理)工具,可能完全消除了登录的需求,从而使整个用户管理讨论变得不再重要。如果我们从不登录,如果我们从不创建用户,那么我们就不需要考虑用户账户访问安全的问题,无论是远程的还是本地的。
因此,值得考虑的是,从服务器的角度来看,用户的需求可能不过是一个过时的时尚,或是那些无法保持最新技术的商店所依赖的备用支撑。这些当然是管理用户,但这长期以来一直是服务器上唯一预期存在的用户。
在终端用户设备上,用户的概念也开始发生剧烈变化,但原因完全不同。传统上,终端用户设备上的工作主要集中在本地安装的应用程序上,这些应用程序本身没有用户控制,而只是运行在操作系统提供的安全控制环境下。这可以是任何类型的应用程序,从文字处理、图像编辑到视频游戏。这个环境主要由可访问的本地存储位置来定义。对许多用户,尤其是家庭用户而言,这几乎已经完全改变。
如今,大多数应用程序是 Web 应用程序,即在浏览器中运行而不是完全安装的应用程序。用户可能会登录到应用程序,但这几乎总是与任何操作系统登录分开。即使是本地安装的应用程序,也开始通过互联网连接进行身份验证,越来越多地依赖于服务。
随着这一变化的发生,操作系统用户作为定义安全访问上下文的主要组成部分的概念正在迅速消退,用户需要在应用程序级别存在的想法已经成为常态。随着这一过程的推进,我们必须开始考虑操作系统用户账户的功能不再是精细的访问控制机制或用户管理的终极方式,而只是为了尝试确保一个安全、受保护的环境,从中我们可以启动我们的 Web 或网络应用程序,并在应用程序层面进行登录,在那里用户和访问控制才是更加相关的。将用户访问控制转移到应用程序层面至关重要,因为数据智能就存在于此,在这一层面可以进行更细粒度的控制,而不是在整个应用程序层面授予访问权限。
随着操作系统在用户管理中的传统角色逐渐消失,强大的用户管理和控制系统的优势也开始削弱。这不仅仅是因为行业和软件成熟导致了用户访问控制从操作系统上移到应用程序中的变化。还有其他因素在起作用。曾几何时,计算机被期望大量使用打印机,但这种情况已经不再普遍。打印机现在只是一个事后考虑的设备,如果它们存在的话,而不再是计算机的主要功能。同样,现代应用程序也不像过去那样使用操作系统管理的存储,严格管理本地存储和映射远程存储资源的需求已经减少。
即使是在十年前,用户管理系统,比如 Active Directory,首先用于协调打印和映射驱动器资源给终端用户。今天,随着应用现代化、工作力量的流动性和计算的普及,这些功能已经成为遗留功能。在家工作的笔记本用户可能完全不需要映射驱动器或打印机,而为了让移动用户能够以这种方式工作,办公室内的工作人员也不得不做出相应的适应。访问控制机制的趋势正在远离传统的操作系统级用户使用方式。
总结来说,用户仍然很重要,但他们的相关性已经不像过去那样强烈,未来看起来是一个用户价值将继续减弱的趋势。
知道哪些远程访问方法最适合你,需要的不仅仅是理解这些系统是如何工作的,了解它们的实现如何适应你的环境只是确定应该为你的组织选择哪种机制的第一步。了解市场上目前有哪些产品,它们的当前功能、局限性、定价和其他商业因素都是必要的。用户管理迅速发展成为一个市场,在这个市场中,我们更多的是需要了解现有的产品供应,而不再是自己来实施。
在接下来的章节中,我们将超越用户身份验证,深入探讨如何为这些用户提供远程访问他们所需系统的方式。
远程访问方法
假设我们没有采用基于状态机技术的无访问方法,我们有几种常见的途径可以用来访问我们的 Linux 系统。在大多数基于 Linux 的操作系统中,我们将讨论系统管理员,像你我一样,如何能够登录并交互使用操作系统,但我们所使用的任何典型方法,最终也将成为终端用户的选择。终端用户的需求通常与系统管理员的需求截然不同,但我们能使用的工具通常会有所重叠。
对于我们这些系统管理员来说,访问通常需要非常快速地设置,使用时也非常临时,重点是确保系统具有高度的可访问性并以命令行驱动。对于终端用户,我们则会期待相反的需求。管理员通常需要登录到多个不同的操作系统,可能是一个接一个地登录,也可能是同时登录多个系统。访问过程过长可能会显著妨碍我们发挥作用。
传统上,终端用户通常只会登录到单一系统,并在整个工作期间(通常是一个工作日或类似时间段)保持连接。虽然他们可能需要花更多时间进行一次登录,但优先考虑的是提供更稳定的终端用户体验。由于需求差异,远程访问技术可能是分开的,实际上没有必要强求将它们合并。
远程访问有两种主要类型。一种是直接连接,即我们暴露端口并使用像 SSH、RDP 或 RFB(VNC)这样的协议,通过软件客户端连接到我们的系统。这是最为人熟知的技术类型,也是最直接的管理方式。它不需要复杂的配置,且易于理解。在这种方法中,我们在目标虚拟机上(或者可能是在虚拟化管理程序上,但结果大致相同)运行传统服务,外部客户端访问该系统。
另一种访问方法是间接访问,其中使用访问服务器来管理操作系统和客户端的访问。该方法需要一个公开托管的服务器(通常是以服务形式提供,但也可以自托管),终端用户和客户端都作为客户端连接到它,从而确保只有访问服务器需要对外暴露。
两种解决方案的优点非常明确。直接连接较为简单,出错的可能性较低。间接连接则需要更多的基础设施,但能减少潜在的暴露点,整合连接,并隐藏网络的存在,使得基于远程访问发布的网络更难被发现和攻击。
出于多种原因,普通终端用户倾向于使用直接连接技术,如 RDP 和 RFB(VNC),而系统管理员则倾向于使用间接连接技术,如 MeshCentral、ConnectWise 和 LogMeIn。对于终端用户而言,直接连接技术通常能提供最稳定的体验,仿佛他们直接操作硬件,就像它就在面前一样。对于系统管理员而言,增强的安全性和对跨多个物理位置系统的访问整合是非常有益的。
然而,需要注意的是,我们在所有情况下都在说趋向。这里没有硬性规则,只有强烈的趋势。然而,由于我们正在处理 Linux,我们还需要考虑其他因素。例如,RDP 在 Linux 上的管理通常比在 Windows 上更为复杂,而间接访问方法可能更容易实施,但理解程度较低。此外,我们的用户群体可能有不同的固有期望——例如,Windows 用户可能期望使用 Windows 原生工具,而基于 Linux 的操作系统用户可能对不太熟悉的访问选项持更加开放的态度。
和许多 IT 领域的事情一样,理解基础技术只是第一步。在接下来的部分中,我们将讨论如何使 SSH(一种直接连接技术)变得更加灵活和强大,并从某些角度来看,我们将通过直接连接模拟间接连接。它们之间的差异并不大。
即便是经验法则在这种情况下也很难适用,远程访问的讨论通常会依赖于许多因素,例如如何使用这种访问,这些基础设施是否会与最终用户共享,可能存在的安全需求,是否还有其他访问方式如 VPN,是否有价值创建一个与其他技术或平台共享的统一连接过程?
然后,我们还需要考虑使用多种访问方式的可能性。为了确保即使一种方法失败,仍然能保持可用,使用不止一种方法是很常见的。某一种可能是方便但脆弱的访问方式,而备份方法则可能是高度安全、操作繁琐,但作为关键备份,能在其他方式都失败时派上用场。
我如何处理远程访问
在这样一个缺乏明确指导的主题下,我觉得花时间分享我自己常用的访问选择是有价值的。我这么做并不是要建议我的方法是理想的,而是希望为大家提供一些现实世界决策过程的洞察。
在我负责管理 Linux 服务器的系统行政工作时,我们通常需要远程访问正在运行的系统,而不是完全依赖于状态机或基础设施即代码的方式,通常会选择一种双重方法,一个是直接访问,另一个是间接访问。
对于间接访问,我们使用 MeshCentral,它本身是开源软件,运行在我们自己托管的 Linux 操作系统上。这使我们在与大多数解决方案相比,具有广泛的灵活性和成本节省,并且因为我们能够在与内部和客户部署相同的操作系统上运行它,我们能够利用其他地方已在使用的流程、工具和技能,从而最大化效率。像许多间接远程访问解决方案一样,使用 MeshCentral,我们可以进行远程终端访问、如果服务器上安装了 GUI,还可以进行远程图形桌面访问,并且有许多工具用于监控、文件传输和远程命令执行。
通过这种间接访问,系统管理员几乎可以立即访问我们所维护的所有服务器,跨越高度不同的技术栈和物理位置。一些服务器被隔离在局域网内,无法进行端口转发,一些有公共 IP,一些有图形桌面,大多数只有命令行接口。不管它们的地点、使用场景或配置如何,MeshCentral 都能为我们提供所需的访问权限,帮助我们管理系统。
对于主要涉及紧急访问的情况,我们还保持对几乎所有系统的直接 SSH 访问。这一点非常重要,因为当间接访问方式失败时,重新配置、打补丁或重启系统的能力通常至关重要。这种访问几乎总是会限制为仅从直接托管工作负载的本地 LAN 上进行访问,甚至可能在该网络范围内进一步限制,使得 SSH 只能从某些特定工作站或其他指定为高度安全远程访问用途的服务器访问。在某些情况下,SSH 服务可能甚至默认不会运行,只有通过更改状态机设置或通过某种带外管理方式手动开启;或者它也可能通过某种自动化方式启用。SSH 对某些自动化任务也可能非常有用。
拥有两种截然不同的访问方式,并且配备深度安全控制,为我们提供了访问性、保护性和安全性的最佳平衡。你必须意识到,每增加一种访问方式,意味着恶意攻击者的攻击途径也会增多,因此增加不必要的访问方式通常不是一个好选择。你需要确保可靠的访问同时又不危及系统安全。
在这类讨论中常常被忽视的一点是,有些直接远程访问工具的工作方式往往是我们没有预料到的,比如基于网页的直接访问工具。这些工具包括 Cockpit 或 WebMin 等产品,它们为我们的系统提供基于网页的界面。这些工具可能允许通过网页界面配置系统,甚至可能允许通过网页界面进行交互式控制台访问,从而使我们能够以完全不同的方式发布和确保远程访问。
在 Linux 世界里,跨越房间或跨越全球访问计算机最常见且假定的方法就是广泛使用的 SSH 协议。接下来,我们将探讨一些方法,让 SSH 比原生更强大。
SSH、密钥管理和跳板机
使用 SSH 进行 Linux 操作系统的远程管理是如此普遍,以至于它值得特别关注。单独使用 SSH 是高效且非常安全的,但它是一个广为人知的工具,通常会暴露出如此强大的功能,因此常常成为有针对性的攻击目标。我们在使用 SSH 时不能掉以轻心,尤其是当它暴露在互联网上时,风险实在是太高了。
使用 SSH 时,我们几乎有一长串的方式可以保障其安全。我们将探讨其中几种方式,以及它们如何协同工作,使得 SSH 极其难以被攻破。在 Linux 上,SSH 通过 OpenSSH 提供,它是一个成熟且经过实战检验的工具,接受的审查比几乎所有软件包都要严格。大多数角度来看,SSH 从一开始就是一个非常坚固的软件包。
我们确保 SSH 安全的第一个工具是完全取消基于密码的访问,而改为使用密钥。密钥快速高效,允许管理员比使用密码更快速、更安全地访问服务器。密钥还支持密码短语,作为一种两步验证的形式。如果根据安全需求,这对于你的组织是可行的,那么这就要求某人同时知道加密密码并拥有私钥,才能尝试通过这一通道攻击系统。密钥在远程访问认证中已经使用了很长时间,但它们并没有得到应有的普及。许多公司采取了如果你愿意,可以为自己设置密钥的做法,导致太多管理员根本不愿意利用密钥所提供的效率和安全性。
我们的第二个工具是来自失败尝试的帐户锁定。基于 Linux 的操作系统中用于此的标准工具是 Fail2Ban。Fail2Ban 处理 SSH 和其他具有标准登录模块的服务,与它们一起检测针对我们系统的可疑恶意尝试,并自动化我们本地的(即 Linux 基础操作系统上的防火墙)防火墙,阻止来自受影响 IP 地址的流量一段预定时间,通常是三到十五分钟。这种方法是我们对抗暴力破解攻击最有效的工具。
你是否仍然需要同时拥有网络边缘防火墙和操作系统防火墙?
你可能会对这个问题出现的频率感到震惊。让这个问题如此令人惊讶的是它总是出现在什么样的背景下。
首先,了解一些技术。在现实世界中,出于多种实际原因,所有路由器实际上也是防火墙。所以,没有硬件防火墙的网络边缘环境几乎是不可能的。在某些情况下,例如安装 VPS 或云服务时,我们可能默认一个完全开放的防火墙,但至少防火墙还是存在的。我们必须从一个假设出发,即所有操作系统实例通常都位于网络防火墙之后,而这个防火墙可能非常无效。
其次,稍微了解一下历史。由于性能影响,操作系统防火墙在 1990 年代末期之前极为罕见。它们也不太重要,因为在那之前,计算机网络化的程度远远较低。即使网络防火墙已经是普遍的假设,操作系统防火墙还是被引入了,因为它们能提供更细粒度和自动化的功能,例如我们在 Fail2Ban 中所得到的功能,而且它们保护的是已经突破网络防火墙或更可能的是来自局域网内部的攻击。
考虑到背景、技术限制和历史,认为两个防火墙不需要的想法显得荒谬。如果我们有能力绕过网络防火墙,理论上是可以做到的,但在这一层跳过安全性是没有意义的;虽然我们可以选择不使用操作系统防火墙,但这样会带来无法通过其他方法缓解的风险。操作系统防火墙在抵御本地和远程威胁方面具有独特的能力,而网络防火墙只能防御远程威胁。虽然没有什么比同时拥有两个防火墙更好的,但从安全角度来看,我们最关心的是操作系统防火墙。我们主要关心网络防火墙的原因是为了减轻操作系统防火墙的负担。
重要的是,今天的基本防火墙功能并不会产生任何可测量的系统开销。这曾是使用防火墙的缺点(大约二十五年前)。如今,使用防火墙没有有效的限制条件。
最佳实践非常明确且极其重要:网络防火墙和操作系统防火墙是绝对需要的。没有任何情况是可以移除或禁用其中一个防火墙的。
操作系统防火墙常常被禁用,因为系统管理员不愿意花时间了解网络需求或正确地保护工作负载。这从来不是一个有效的借口。我们都曾感到懒惰,也都希望避免在系统中维护另一个支持点,但这涉及到基础的安全性,能够正确地支持生产环境中的系统就要求我们具备启用并配置防火墙所需的所有知识。任何认为禁用防火墙有价值的情况(当然不包括故障排除)都应该被视为一个巨大的警告信号,提示我们需要解决某些问题。
在 SSH 的安全性方面,继基于密钥的认证和账户锁定后,我们的第三种工具是网络限制,通常以限制连接到 SSH 的请求来源 IP 地址的形式存在。这可以通过多种方式实现。通常,我们会在 Linux 系统上的防火墙上实现这一点,但它也可以由网络边缘的硬件防火墙或云服务提供商的网络防火墙等提供。
IP 限制通常最好通过白名单来设置,尽可能的话。白名单允许我们将 SSH 流量限制到一个单一的 IP 或一小组我们认为是已知且安全的 IP 地址,例如管理员的家庭、信任的数据中心或办公室的 IP 地址。这大大减少了我们系统的攻击面,使它们在第一时间难以被发现。
然而,对于某些人来说,白名单可能不可行,或者至少不太现实。在这种情况下,黑名单可以用来屏蔽那些肯定不需要访问的 IP 范围,依然能提高安全性。在这种情况下,系统管理员可以使用国家 IP 范围来阻止来自某些国家和地区的流量,这种做法是可行的。我从不推荐在面向客户的系统中使用这种做法,因为你可能会无意中阻止客户或商业伙伴,从而招致反弹(记住,对于试图从黑名单所在地点使用服务的人来说,他们并不会认为自己被阻止,而是认为服务失败了或离线了),但对于系统管理访问来说,管理员的位置应该大致已知,并且应始终有备选的沟通渠道,安全性更为关键,这种做法是非常有意义的。
第四,使用sudo要求在执行提升权限的命令之前进行额外验证是非常有用的。通过sudo,我们可以在已有的密钥或更好的密钥加密码的基础上增加更多的保护。如果我们使用拥有sudo权限的用户账户登录 root 超级用户账户,那么我们在成为普通用户之前已经证明了一个或两个认证因素。使用sudo时,我们可以选择要求该用户输入另一个独立的密码,以便获得提升权限的权限。这提供了很多潜在的保护。Sudo还帮助我们避免了直接以 root 用户身份运行时可能发生的危险错误,通常是由于打字错误。Sudo更可能保护我们免于自身的错误,而不是来自外部的攻击。它是一个非常有用的工具。
第五,由于上面提到的sudo的强大功能,我们可以完全禁用通过SSH登录的 root 用户,将最著名、也是目前风险最大账户完全排除在风险之外。当我们拥有sudo机制来保护 root 用户,并且在其被访问时进行日志记录时,就没有必要将 root 用户暴露在外了。
更改 SSH 默认端口有效吗?
你会发现许多人和文章告诉你应该始终更改 SSH 的默认端口,或任何访问协议的默认端口,以便使攻击者更难发现。这种做法通常被认为是一种“安全性通过模糊化”手段,但这种方式一般被认为根本没有安全性。
但实际上,这两种做法都有些被夸大。更改默认端口对于实际安全并没有什么作用,因为任何具有一定复杂性或力度的真实攻击都可以在几秒钟内发现一个非标准端口,而攻击者甚至可能不会意识到你试图通过更改地址来阻止攻击。就像你把家门移到房子的侧面,大多数闯入的小偷甚至不会注意到门的位置变得奇怪。门还是那扇门,非常明显。
认为使用非标准端口作为安全措施是错误的。充其量,它在名义上改善了安全姿态,最糟糕的情况可能是暗示你通过混淆来进行安全防护,并可能成为更有针对性攻击的良好目标。非标准端口潜在的好处在于减少了击中我们端口的流量量,使得存储和过滤日志变得更容易。
当然,通过减少日志混乱可以增强安全性,因为这样可以更快地发现或诊断令人担忧的攻击,并且减少存储需求总是一个不错的好处。因此,更改 SSH 端口可能是有益的,但应保持在适当的背景下考虑其益处。
除了 SSH 的所有这些最佳实践安全方法外,还有许多其他标准的加固选项可以使用,但我认为,除了这些,我们很难再定义更多作为最佳实践而不是强烈推荐或值得考虑的选项。稍作调整,SSH 对几乎任何组织需求都可以极其安全。
要提升 SSH 安全性的另一种方法是通过工具如 Google Authenticator 应用一次性密码进行多因素身份验证,这非常简单。还存在许多第三方安全增强措施,SSH 可以像你想要的那样安全。
SSH 密钥管理
一般认为,如果我们要使用 SSH,则需要使用密钥来保护对其的访问。如前所述,它们快速且非常安全。没有理由不使用它们。然而,并不仅仅是简单地使用它们。当我们选择使用密钥时,我们必须确定如何管理这些密钥。这如何才会有意义主要取决于我们组织的规模,或者至少取决于我们的系统管理团队的规模,以及使用这些密钥访问的系统数量。
在其最简单的形式下,SSH 密钥管理可以由个人自行管理。如果用户已经可以登录操作系统,则可以自由创建和管理自己的密钥。对于较小的组织或仅与少数系统管理员合作的情况,这可能是有意义的。
使用 SSH 密钥时,管理涵盖了两个组成部分,即公钥和私钥。通常用户会管理自己的私钥,确保安全,而公钥可以采用几乎任何方式管理。
对于希望改进密钥管理而基础设施较少的小型组织,最简单的方法可以是将用户(包括系统管理员)的公钥存储在维基或其他简单文档系统中,以便根据需要轻松获取。单单这一步就能极大地简化密钥的使用。
密钥也可以存储在类似管理服务器或工作站的文件系统中,并通过简单的自动化推送出去,比如通过 SSH 远程执行的脚本,将密钥复制到指定位置。脚本也可以从网页、文件共享中提取公钥,或者使用像 GIT 或 Subversion 这样的工具从仓库中获取密钥。密钥本质上是文本文件,因此管理它们非常灵活。
在更高级的设置中,可以使用状态机和基础设施即代码的方法,通过与其他自动化工具相同的工具来自动化密钥部署。密钥可以仅仅作为一组文件处理,并不需要特别对待。像状态机和基础设施即代码这样的 DevOps 流程是简化 SSH 密钥管理的极好机制。
然而,所有这些实际上几乎不值得考虑。一旦你在任何规模上使用密钥,并且你的系统管理中出现了密钥管理的问题,那么可能是时候考虑使用公钥基础设施(PKI)系统来管理证书,而不是密钥了。SSH 使用 TLS,这是与 HTTPS 以及无数其他安全协议相同的机制,因此它可以使用与网站相同的 PKI 系统。
当然,在几乎所有情况下,使用公共托管的 PKI 证书系统对于我们 Linux 基础设施中的几乎所有私有和内部主机来说都会是一个问题。因此,我们需要运行自己的证书授权机构,称为 CA,但这是一个标准的做法,成本和开销极低,虽然这种技能并不广泛存在,但它是可以轻松掌握的。使用 SSH 证书而不是SSH 密钥(这里的“而不是”是因为证书包含了密钥,密钥始终隐藏在背后)为我们提供了一个机制,能够快速扩展许多管理员和可能的许多最终用户的 SSH 密钥安全性。
我不会过于夸张地说运行自己的证书授权机构并建立 PKI 基础设施是最佳实践,但对于那些不仅仅是几个用户连接到几个 SSH 主机的组织来说,这是一条不错的经验法则。许多用户连接到不同操作系统实例的网络效应,可能导致 SSH 密钥数量激增,如果不采取措施,可能会无人管理。例如,十个管理员、二十个开发人员、十个测试人员和一百个虚拟机,光是这些就可能需要监控四千个 SSH 密钥组合!
随着几乎所有操作系统今天都支持 SSH,强大的 SSH 安全策略的好处更加显著。SSH 越容易安全地使用,就越有可能被采用,取代其他技术。
跳板机
跳跃盒子是一个重要的安全和管理工具,可以简化系统管理的许多方面。作为一个概念,它们非常常见,但作为一个术语,即使是经验丰富的系统管理员也可能不熟悉。跳跃盒子是一个系统,系统管理员(或普通用户,但通常只供技术支持人员使用,因为其设计较为繁琐)通过远程访问该系统,并授予访问权限到要管理的其他系统。
它被称为跳跃盒子,因为你在跳跃到另一个系统之前,首先登录到它。它是你任务的起点。跳跃盒子不仅用于访问,还常常作为工具的中央存储库、临时存储位置,或者运行自动化脚本的公共位置。
跳跃盒子通常用于提供一个中央访问点,以便直接访问系统,获取类似于间接远程访问技术和传统直接访问之间的混合特性。从技术上讲,跳跃盒子只是一个两阶段的直接访问系统,但它非常有用,可以避免使用像 VPN 或复杂代理这样的网络路由器来实现访问整合。
通过访问整合,我们可以更实际地保护我们的第一道访问防线。跳跃盒子通常会收到最复杂的 IP 过滤、严格的 Fail2Ban 规则、详细的日志记录、双因素认证、快速修补等,以紧密保护最脆弱的进入点。以这种方式,系统管理员可能会通过登录到他们的跳跃盒子开始一天的工作,然后快速轻松地从该点连接到他们管理的系统。
由于其设计,跳跃盒子通常容易存在于局域网内,托管在共置数据中心,甚至可以是云托管的。它们可以被放置在任何实际需要的地方,并可以在任何地方访问资源。它们可以被加固、监控,并通过直接访问协议,甚至 VPN 或多个 VPN 连接到系统和网站,根据需要进行访问。
由于跳跃盒子是一个单一系统,因此管理的系统可以允许从它的单一 IP 地址连接,即使使用直接访问技术时也能保持良好的安全性。
基于 Linux 的操作系统的跳跃盒子通常用于 SSH,因此它们可能被构建为精简的服务器。没有图形界面的 Linux 跳跃盒子可以运行在最小的虚拟机上,这些虚拟机几乎不占用任何资源,使得它们非常容易在需要的地方部署且成本低廉。
跳跃盒子还可以处理其他协议,通常是 X 或 RDP 协议。例如,这在 Linux 系统管理中并不常见,因为图形界面通常对我们来说只是负担,而当使用跳跃盒子时,提供中央图形界面源的资源需求和复杂性通常会让我们重新考虑是否提供图形界面。
跳板机不是最佳实践,但它是一个常见的安全和管理工具,在需要直接访问以加快、简化和提高安全性时非常有用。
替代性远程访问方法
至少从我们通常的理解来看,传统远程访问完全是围绕终端用户的需求设计的,用户需要通过远程会话来替代他们的本地桌面。作为系统管理员,能够在合适的场景下使用这些工具对我们来说是非常有帮助的,并且我们必须理解这些工具,因为它们通常是由我们来管理的组成部分,但就我们自身使用而言,这些工具可能不是最实用的。
当然,我们可以将大多数间接远程访问技术归类为替代性远程访问方法,但它们本质上只是经过调整的传统访问方式,以使其更适合我们的使用场景。作为管理员,我们希望减少与远程机器的登录或交互式会话,期望最终完全消除这种访问,至少在理想状态下是这样。
为此,我们今天有了其他方法来在我们的服务器上运行命令。这些方法并不会在所有情况下取代我们现有的方式,但它们可能是帮助我们从当前状态向未来目标过渡的一项过渡性技术。
使我们大多数系统访问方法看起来传统的原因,实际上是它们涉及完全的交互性。这意味着无论我们使用 RDP、Splashtop 还是 SSH 会话,我们都假设正在与需要管理的系统建立完全连接,包括用户级别的环境设置,并在一个持续的输入和输出过程中进行工作。这种假设已经深入人心,许多应用程序或工具实际上也假设使用这种方法,可能需要一些不合逻辑或不合适的会话环境变量。
除非像我们之前讨论的那样完全移除访问——即通过基础设施即代码的方式——否则我们的过渡性访问步骤是远程命令执行或使用非交互式命令。这与我们其他访问方法一样有效,但没有交互能力。远程命令执行使我们能更轻松地从手动任务过渡到自动化,并且非常适用于审计、安全性和可扩展性。
从最简单的角度看,远程命令执行可以通过 SSH 处理,使用与交互式会话相同的基础设施。SSH 设计得能够优雅地处理这两种方法,并且由于它是透明地执行的,它可以是从一种方法平稳过渡到另一种方法的便捷工具。这些方法可以根据情况混合使用,或者一位管理员使用一种方法,另一位使用另一种方法。
使用远程命令执行,我们可以获得所有命令都在源系统上执行的好处,因此可以被记录。非常适合像跳板机或管理服务器这样的工具,可以记录所有执行的操作。然而,交互式会话,即使是从跳板机启动的,也会将所有重要的会话信息记录到最终的操作系统中,跳板机只会知道远程会话已启动——对于到底执行了哪些命令及其响应的详细信息,将会丧失在中央日志平台的可见性。
在许多方面,远程命令执行是系统管理员在软件开发世界中的函数式编程类比。交互式会话更像是过程式编程,其中动作被视为一系列事件。远程命令执行则是使用单一远程函数来执行任务。如果你不熟悉这些编程范式,这个类比可能难以应用,但对于那些使用过这些范式的人来说,我认为这个例子是有价值的。
SSH 可能是悄然引入远程命令执行的理想方式,并且本质上始终可供系统管理员使用。即使在高度严格、结构化和正式的流程驱动环境中,政策法令通常也不太可能不允许管理员在允许传统交互式 SSH 会话的情况下,随时随地使用这种方法。
其他工具,尤其是越来越流行的工具,今天也允许远程命令执行。这已成为大多数间接远程访问工具的标准选项,从大型商业软件服务产品到小型开源自托管产品几乎总是包含某种形式的远程命令执行。在某些情况下,还具备扩展功能,如能够同时对一组或列表中的多个系统运行相同的命令或命令集。
远程管理工具(RMM)通常以相同方式构建远程命令执行系统。这比创建自定义交互式会话机制要容易得多,并且可以被吹捧为更先进的选项,同时实现起来也更简单。
在我看来,最有趣的远程命令执行应用场景是状态机系统。正如 SSH 可以被视为具有远程命令执行作为可选策略,远离交互式会话,逐步过渡到一种稍微不那么熟悉的方式,状态机也可以并且确实将远程命令执行作为一种方式,保持在更传统的操作模式中,为系统管理员提供在状态定义过于复杂或耗时时的备用方法。
从状态机进行远程命令执行也是一种测试状态机访问或功能的方法,尤其是在开发状态文件时。状态是通过在被管理的系统上运行命令来维持的,不管是哪种方式。在某些情况下,命令是通过一个远程代理来执行的,而远程命令虽然被执行,但具体的命令并不是由状态管理中心系统发送的。在其他系统中,命令可能直接按照管理系统上输入的内容发送,状态机只是作为执行助手。
远程访问,尽管一开始看起来很简单,并不是“一刀切”的解决方案,我们甚至可以在同一个组织内使用不同的解决方案。考虑跳出固有思维,尝试新的或不同的方法来提升工作流程的安全性、稳定性和效率。
现在我们已经准备好从各种方法中获取系统管理员访问和安全性的概念,我们应该讨论一些更适用于终端用户访问系统的技术:终端服务器和虚拟桌面基础设施。
终端服务器和虚拟桌面基础设施(VDI)
与 Windows 世界不同,在基于 Linux 的操作系统中,远程 GUI 访问相对较少。这只是因为 Linux 并不将此视为其核心功能,在这种自我实现的情况下,客户没有需求,所以供应商也没有在此方面做专门化,导致客户觉得这方面的可用性很低,从而形成了一个循环。然而,这并不是说终端服务和VDI(即虚拟桌面基础设施,但它通常更为人熟知并直接以缩写形式使用)选项在 Linux 系统中不存在,它们当然存在。
概念上理解终端服务和 VDI
终端服务器和 VDI 架构交织在一起并不罕见,这主要是由于市场营销部门试图在不适用的场景中推销 VDI,并且因为常常使用重叠的技术。VDI 被作为一种新的热门技术来推广,好像它并非一直存在一样,这也加剧了混淆。而作为该领域领导者的微软,将其核心产品从终端服务器重命名为远程桌面服务器(RDS),也没有起到任何帮助。这导致了一个问题,即许多 Windows 管理员,更不用说用户,常常将 RDP(远程桌面协议)与 RDS(微软的终端服务器产品)混淆。一个是由多种不同产品实现并使用的通信协议;另一个是一个具体的产品和许可工具,必须从微软购买,可能会使用 RDP,也可能不会。
所以我们必须从定义这些技术开始。两者都涉及远程访问计算机。两者都可以使用相同的一套潜在协议来实现这一“魔法”。两者的基本目的是相同的,但实现方式有所不同。
终端服务器一直意味着一个单一服务器(即:一个单一操作系统实例),可以被多个远程用户同时访问。在最初的时代,这通过使用串行连接到哑终端来远程显示文本来实现。后来出现了诸如 telnet、RSH,最终是今天我们使用的 SSH 等技术。这些技术推进了安全性和可访问性的状态,但从根本上讲,远程访问仍然是一个类似于原始串行物理终端的命令行活动。几十年前,图形桌面环境的远程使用成为终端用户的常态,新的协议如 RDP、RFB、X 和 NX 变得流行,但本质上没有什么根本变化。许多用户仍然连接到一个单一的操作系统实例,并共享其资源。只有一个操作系统需要修补,所有人共享相同的内核和应用程序。终端服务器采用的是多对一架构。
VDI(虚拟桌面基础设施)是一种替代方法,用户可以远程访问仅为他们存在的虚拟化操作系统实例。在 VDI 中,每个用户的操作系统实例可以完全不同,具有不同的补丁级别,甚至可能是完全不同的操作系统。一个用户可能使用Windows 11,另一个用户使用 Windows XP,另一个用户使用 Ubuntu。VDI 意味着一对一架构。
在大多数情况下,这两种方法之间的概念和区别几乎完全是出于管理微软软件许可限制的需要。在 Linux 世界中,终端服务器或 VDI 部署之间的区别纯粹是根据系统在访问时如何使用即时决定的。每个 Linux 设备本身已经是多用户的。Linux 缺乏 Windows 生态系统中始终存在的一次只有一个用户的框架。这些概念在非 Windows 环境中往往会被忽视或造成混淆。对于 Linux 管理员来说,任何 VDI 系统其实就是多个轻度使用的终端服务器。在 Windows 世界中,许可规则以非常复杂的方式支配了这个方程式的各个方面。
在 Windows 世界中,Windows 7、10 或 11 的最终用户工作站许可证总是单用户许可证,没有例外。远程访问总是允许的,但只允许单一用户使用,绝不允许替代或附加用户。一个用户坐在控制台前,或者该用户远程访问,但一次只能有一个用户使用。即使是 Windows Server 许可证也只允许一个用户同时使用(另有一个额外许可证仅供系统管理用途),除非购买了 RDS 许可证以支持额外用户。RDS 只能作为附加许可证用于 Windows Server。由于这些许可证规则,Windows 世界中什么是服务器,什么是最终用户工作站,界限非常明确且显而易见。
当然,在 Linux 中并不存在这样的许可证限制。任何工作站都可以作为服务器使用,任何服务器都可以作为桌面或供多个用户使用。任何机器都可以灵活地在任何时间以任何方式使用。诸如终端服务器和 VDI 之类的术语仅指我们打算如何使用系统或系统在任何特定时刻的使用方式,但对于大多数非 Linux 管理员来说,它是一个固定、石沉大海、昂贵的、以许可证为驱动的设计和决策过程,因此我们必须能够理解这些术语和概念如何影响那些处于我们自由灵活的环境之外的人们的认知。
当然,还有一个显而易见的第三种选择,它没有名称。终端服务并不考虑系统是物理的(也就是说,直接安装在裸机硬件上)还是虚拟化的,在这两种情况下它都是一个终端服务器,虚拟化是无关紧要的。对于 VDI,虚拟化是名称的一部分,因此我们只有在系统没有明显理由进行虚拟化时,才会将其视为 VDI。如果我们在裸机操作系统安装上做与 VDI 相同的逻辑架构,那么这个架构没有名称,至少没有一个广为人知的名称。没有虚拟化的一对一远程访问实际上是最常见的远程访问基础方式,甚至以至于大多数人都不会将其视为一种架构。它基本上不需要规划或协调,通常用于各种目的。这个没有名称的设计在任何操作系统中都很常见,无论是 Linux、Windows、macOS 还是其他。
基于 Linux 的操作系统将支持我们所需的任何远程访问架构,甚至支持通常与其他操作系统相关的协议:即来自 Windows 生态系统的 RDP。在 Windows 生态系统中,RDS 技术上与 Active Directory 绑定,导致用户管理与远程访问策略紧密耦合。在 Linux 中,我们没有这样的约束。部署基于 RDP 的终端服务器可以使用我们想要的任何用户管理系统。
像终端服务器和 VDI 这样的工具,更有可能被终端用户使用,从办公室工作人员到开发者,而非系统管理员,但这并不是唯一的情况。在我当前的部署中,我们同时维护这两者,专门供系统管理使用。我将以此为示例场景,展示这些技术如何在管理方面有效地使用。
有时,系统管理员可能会从拥有图形会话中受益。这可能是因为图形工具,如记事本、截图、网页界面等,使工作更高效,或者在某些情况下,工具本身需要图形会话。不幸的是,许多系统,虽然 Linux 本身不常见,但常常是为 Linux 系统管理员所需的系统,只提供基于 Web 的 GUI 界面,或者更糟的是,像 Java 应用程序界面或甚至原生应用程序。我们在主信任数据中心内部,拥有一个专为多用户 RDP 支持构建的 Linux 终端服务器,并且具有静态 IP 地址,这使得我们的管理团队可以随时随地为所有团队成员提供访问权限,在受信任的位置打开图形会话,执行任何必要的工作。
拥有图形界面在进行文档编写、通过屏幕共享进行培训或类似任务时,往往会非常有益。
终端服务器非常适合,特别是在基于 Linux 的操作系统中,提供一个干净、标准的共享环境。VDI 提供了一种竞争的方式,我们和许多公司一样,使用 VDI 提供高度定制化的环境,满足个别系统管理员的需求,例如替代操作系统或桌面环境,这些在共享服务器环境中实施时可能会与其他用户发生冲突。VDI 在某些情况下也更适合,个别系统管理员可能需要成为自己环境的管理员,通常是为了测试,但在共享环境中,这从安全角度来看可能不明智或不可行。
无论是图形界面还是仅命令行的终端服务器和 VDI,都可以作为跳板、管理站、远程执行环境等平台使用。当然,我们还可以将它们用作向终端用户提供基于 Linux 的桌面环境。简单来说,完全没有理由在概念上将这些技术仅限于 Windows,Linux 在这里也能大放异彩,而且在许多情况下,表现得更为出色。
摘要
Linux 操作系统上的用户和用户访问是一个复杂的话题,主要因为 Linux 给我们提供了极大的灵活性。我们可以从多个角度探讨用户的存在位置、如何创建用户、如何管理用户、我们信息的来源以及用户如何以多种方式访问他们的系统。我们有古老的技术,也有极其现代的技术。我们几乎可以使用任何机制,来自任何时代、任何生态系统,我们甚至可以自己构建并且是独一无二的。我们可以遵循传统的流程,也可以轻松地构建自己的流程,并以独特的方式工作。
在 Linux 上没有简单的最佳用户管理实践。相反,我们的最佳实践通常是,我们需要理解技术的各种可能性,了解不同的风险和利益如何适应我们独特的组织,了解市场上现有的产品——从开源到商业,从软件到服务,并从各个方面评估这些需求,以确定适合我们组织的解决方案。没有预设假设。使用本地用户帐户并不错误,即使是在非常大规模的情况下。使用远程用户并不错误,即使是在非常小的规模下。我们不必为安全性维护和运行自己的基础设施,但也不必依赖第三方供应商来为我们做这件事。天空才是极限——大多数方法都有其优点,但所有方法都有其局限性,因此它们都值得彻底调查。
总是有一种倾向,认为任何系统都需要过度复杂化。我们被教导复杂就是好,因为它显得先进,而且感觉是对的。但最终,简单通常能提供最低的总体拥有成本,同时承载最少的风险。使用简单的系统和设计,部件更少,出错的机会也更少,这通常会取得成功。
我希望通过这些信息,你能拥有知识和勇气,从不同的角度来看待用户管理。太多的用户管理解决方案是因为误解了行业趋势应该驱动决策,或者认为常见的解决方案比实际更加安全。最好的解决方案永远是最适合你情况的,而适合你的是很少是适合别人(你所比较的对象)的,只有在极少数情况下,任何你所比较的对象都花时间真正评估过他们自己的需求,因此,允许他人的决策过度影响我们往往是非常危险的。
在我们的下一章节中,我们将要讨论一个极其复杂且常常令人困惑的话题——故障排除。
第十一章:故障排除
在系统管理中,故障排除是最具挑战性的任务之一,尤其是在问题出现时。故障排除即使在最理想的情况下也很困难,但作为系统管理员,我们的工作几乎总是需要排除一个系统中的问题,系统要么正在生产环境中运行并且必须在我们尝试修复某个方面时保持正常运行,要么系统已经宕机,我们必须尽快让它恢复生产环境中的运行。通常我们并没有足够的能力在不让业务因此丧失收入的情况下进行修复,即使有,这也是例外而非常态。故障排除既困难,又至关重要,还充满压力。
故障排除不仅仅是解决明显的技术问题,应用商业逻辑同样至关重要。我们必须在更大的工作负载和业务背景下理解我们的故障排除,并应用不仅仅是简单的技术知识。既有解决问题的方式,也有解决工作负载的方式,还有评估工作流需求的方式,最终的目标是保持业务的可行性。
在本章中,我们将讨论以下主题:
-
避免灾难的高成本
-
初步评估技能与员工
-
逻辑性故障排除方法
-
调查与修复
避免灾难的高成本
在本章中,我们将详细讨论灾难发生后该做些什么。在本书中,我们考虑了如何避免灾难的方法。一个容易被忽视的事实是,保护工作负载免受故障的过程中是有成本的,我们必须将这一点与故障本身的成本以及灾难发生的可能性进行权衡。
我们常常被告知,或者暗示灾难必须不惜一切代价避免。这是荒谬的,绝不应当如此。避免灾难是有成本的,而且这个成本可能相当高。灾难本身也会带来成本,虽然这个成本可能相当高,但并不总是如此。
我们所面临的风险是,避免灾难的成本有时会超过灾难本身的成本。曾经有一段时间,公司常常花费数万美元购买容错解决方案,以保护那些常见故障场景只会造成少部分损失的工作负载。灾难本身实际上比避免灾难的成本更低!而且灾难避免是一个确定的成本,而灾难只是一个潜在的成本。如果我们将两者视作成本进行比较,我们可以简化评估为一个简单的问题:今天损失 50,000 美元,还是明天可能损失 10,000 美元,哪个更好? 这样比其他方式要简单得多,并且能去除大部分情绪化反应。
我喜欢用一句话来形容在灾难避免上过度消费,那就是:今天为了避免明天可能的头痛而对自己开枪。
永远不要将灾难防范计划中的灾难视为必然发生,它并非必然发生。它只有可能发生。评估并运用数学方法。
在本章中,我们将深入探讨支持在企业中的运作方式,如何改善 IT 组织的支持姿态,了解急救需求,讨论如何找到合适的人来组成故障排除团队,然后深入讨论何时调查问题,何时解决问题。
这是我们要覆盖的一些最困难、最模糊且最终最重要的内容。
解决方案的来源
作为系统管理员,我们从哪里获得解决问题的方法呢?我想通过我自己的职业故事来开始这段话题,因为我认为每个人对 IT 支持在广义上的运作方式有非常不同的看法,理解这些不同的视角在我们开始定义“好的支持”是什么之前是非常重要的。
当我刚开始从事 IT 工作时,尤其是在前近二十年,大家普遍认为任何和所有问题都应由 IT 部门来解决。当然,也有一些情况需要应用厂商的补丁、更新或修复,但获取这些补丁、测试它们、应用它们等工作总是由 IT 员工全权处理。甚至认为可以请求厂商提供帮助、指导或建议的想法也显得陌生,更别提实际去做了。联系厂商寻求支持被认为是绝对的最后手段,只在认为硬件或软件中存在未知且尚未解决的缺陷时才会使用,这时将问题交给厂商修复,然后再由 IT 部门应用更新或修复(如果有的话)。
在这个时代,IT,尤其是系统管理员,预计能够全面了解系统的运作,能够解决可能出现的任何问题,坦率地说,还要弄清楚需要做什么。没有如果,没有但是,当然没有“也许”。如果你不知道一个系统如何工作或可能出现什么问题,那么你就需要依靠知识和逻辑去找出问题的根源。对系统的工作原理有透彻的理解,即使有时缺乏具体的细节,良好的逻辑通常也能让你解决问题。
直到 2000 年代末,我才首次遇到那些依赖供应商和经销商来提供某些方面支持的 IT 部门。公司和其 IT 组织(无论是内部的还是外部的,都不重要)无法安装、配置和支持的系统,这个概念对我和我多年来在行业中的大多数同事来说都是完全陌生的。如果你偶尔需要供应商的支持,为什么你不需要全天候的支持呢?如果 IT 团队不具备实施和运营他们负责的系统所需的知识,那它们的存在有什么意义?你需要更多的知识来规划和考虑所有解决方案选项,而不仅仅是修复你最终部署的那个单一方案。如果你需要供应商来处理日常任务,那显然你缺乏进行更为重要的高层决策所需的技能和经验,而这是供应商无法提供帮助的。遗憾的是,许多组织最终在解决方案规划方面完全缺乏能力,这也解释了为什么那么多明显无法满足业务需求的糟糕解决方案会被部署。
今天,似乎大家都将焦点放在了来自销售组织和供应商的支持上,而不是来自 IT 部门,但这带来了两个关键问题。首先,如果 IT 不在关键的支持路径上,它到底是做什么的呢?它们真的有必要存在吗?其次,当供应商仅仅支持他们自己生产的产品时,怎么可能具备满足内部 IT 需求的所有技能呢?这里的脱节是相当显著的。
并没有魔法支持
经常会有一种不言而喻的信念,通常是在管理者中间,甚至有时是 IT 人员中,也会认为有一些神奇的公司,在技术领域内可以提供类似于无限的支持,而这种支持是内部 IT 无法提供的。我猜想,大家可能以为这些公司并非由人类组成,或者认为服务器、存储和操作系统的供应商拥有一些不公开的秘密手册,里面充满了那些不公开的信息,包括秘密代码,可以让失常的系统重新开始工作。
在现实世界中,硬件和软件供应商基本上不知道他们的客户不了解的事情,至少在设备操作方面是如此。这和你打电话给福特或丰田,问他们如何驾驶一辆赛车是一样的,而不是去问赛车手。当然,汽车公司会有一些员工对赛车在性能条件下如何驾驶有一定了解,但他们没有任何人比实际的赛车手掌握更多的知识,他们显然也不会比正在赛道上绕圈的车手有更多的实践经验。
硬件和软件供应商只是一些由 IT 人才组成的团队,和任何其他公司从相同的人才库中招聘的人一样,事实上,如果你在行业中工作了一段时间,你会发现你认识的人可能会从现场工作转到供应商公司,反之亦然,而且很有可能这种情况也会发生在你自己身上。我自己曾在至少六家大型供应商公司担任过工程师,在这些公司中,没有任何特殊的“秘密”知识被隐藏起来。我们所有的客户支持甚至内部支持知识,获取方式和客户一样。有时候,客户实际上比我们还更能接触到我们的文档!
如果供应商知道如何让他们的产品在现场工作得比目前好得多,他们会尽一切可能将这些信息传递出去。几乎所有主要供应商都有广泛的文档、培训、认证和其他项目,希望现场的 IT 工作人员能够独立完成工作,且不出现任何问题,尽可能自己解决问题。供应商并不希望人们说产品无法正常工作,供应商必须介入修复问题。供应商迫切希望 IT 能够在没有供应商介入的情况下,正确地部署、配置和维护产品。这对市场营销有好处,也能带来最大化的利润。同时,这也有助于建立与 IT 的最佳关系,而 IT 大体上是硬件和软件采购的最大推广者和最大门槛守卫者。
也许有人误以为,最优秀的 IT 人员会自动被供应商吸纳,剩下的领域只会留下那些无法胜任的人。这听起来可能有些道理,但实际上完全不是这样。首先,很少有供应商像人们想象的那样有雄厚的资金,而且往往有些客户比供应商更愿意支付并吸引顶尖人才。其次,供应商的支持工作通常与普通 IT 工作有很大的不同,很多人进入 IT 行业时并不喜欢这些工作,因为技术和商业方面的差异,虽然这两个职位高度相关,但也存在显著的区别,因此并没有形成自动的流动。第三,任何供应商提供的支持工作都没有 IT 职位那样技术性强。供应商的职位通常涉及销售和客户管理、遵循详细的规则和流程,并按照预定的方式实施,目的是为了适应销售流程,而非 IT 流程。总的来说,最优秀的 IT 人员很少愿意进入供应商工作,而那些愿意的人往往并不是因为供应商的工作更符合他们的 IT 理想,而是因为他们看到了一个利用自己专业知识的机会,同时离开了 IT 领域。许多供应商根本没有真正的 IT 支持。
记住,供应商生产产品,而不是提供 IT 服务。因此,供应商通常能提供的支持与 IT 部门在其组织中应做的事情有很大不同。即使他们的员工拥有强大的 IT 资源,这些资源也不太可能被允许为客户提供真正的 IT 支持。供应商通常只希望并且往往只能在按预期操作其产品的非常狭窄范围内提供支持。IT 组织知道的关于供应商产品的知识,甚至如何最好地实施这些产品,往往与供应商知道的一样多或更多,这并不罕见。供应商根本没有必要掌握这些知识。比如,制锤工并不可能像木匠那样了解如何使用他们的锤子钉钉子。丰田的工程师也不太可能像职业赛车手那样驾驶他们自己的车。Canonical 相比你们的内部系统管理员,不太可能知道在你们的组织中如何最佳地部署 Ubuntu。
供应商的技能,主要是硬件工程或软件工程(或者两者兼有),与 IT 技能不同,即便是最优秀的供应商也没有特别的理由在 IT 任务上表现出色。那根本不是他们的擅长领域,他们为什么要具备这些技能呢?这不是他们业务的一部分。对于我们这些从事 IT 工作的人来说,这才是我们的业务。
供应商应该擅长的,并且通常也擅长的,是了解他们的产品。他们知道什么时候有缺陷需要修复,他们知道大多数公司在如何使用他们的产品方面的趋势,他们知道未来会有哪些变动(但可能无法向客户透露这些信息)。供应商是一个宝贵的资源,但前提是要在合适的逻辑框架下使用他们。
因为供应商卖的不是 IT 服务,而是产品,所以没有理由在任何规模上,甚至完全没有,保持高度专业化的 IT 资源。即便他们能够做到内部 IT 所能做的任何事情,这种想法也是相当荒谬的,根本没有意义。供应商在提供一定量的 IT 帮助时,通常会聘用中级和初级人员,因为没有必要聘用更昂贵的资源。来找供应商寻求 IT 资源的客户不可能把 IT 当作优先事项或做出合乎逻辑的选择,因此也没有理由为他们提供昂贵的资源——这些资源他们并没有准备好利用:销售低成本服务的利润远大于高成本服务。而那些足够成熟,真正需要高端 IT 资源的客户,通常知道不应该向供应商寻求这种帮助。
所以,没有什么魔法。供应商并不知道我们不知道的事情。通常,他们知道的内容要少得多,至少在我们环境中重要的东西,他们知道得更少。他们几乎没有获取必要的业务知识来做出合理的 IT 决策的权限。他们不能以跨行业的广泛技能和产品来处理问题或解决方案,而只能依赖他们提供的产品、互补产品以及鼓励更多使用其产品的流程。他们与 IT 的价值观没有对接,并且在财务上鼓励他们为自己的利益工作,而不是为你的利益工作。没有捷径,IT 资源应该提供的支持水平是无与伦比的,没有任何其他组织能够像你的 IT(通常应包括来自非供应商的外部 IT 资源)那样支持你的组织。
支持我们系统的方式本质上有三种。首先,我们有内部 IT 员工。根据本书的背景,这指的是系统管理员或团队。第二,我们有来自付费 IT 公司的外部 IT 资源,这些公司提供外部 IT 服务,而非销售服务,且他们为扩展内部 IT 团队而收费,可以是临时性的,也可以是长期的。第三,我们有供应商和增值经销商(供应商代表)。
我们必须记住,IT 不是一个特殊的例外,产品销售商也不是我们的商业顾问。就像房地产中的销售代理不能代表买方,买方代理也不能代表卖方一样,IT 领域也存在利益冲突和对立的代理关系。内部 IT 部门和任何外部 IT 服务提供商的职责是代表企业的需求,他们在法律和道德上都有义务这样做。另一方面,供应商和经销商通过销售利润或佣金获得报酬,代表供应商的需求,他们在法律上有义务这样做,从道德上讲,他们对供应商负责,而不是对客户负责。当然,这并不意味着供应商和经销商不能友好、有用、重要或专业,他们当然可以,也应该这样做。这仅仅意味着他们是产品销售商的代表,而我们作为 IT 专业人士,则是我们所服务企业的代表。
我们可以合作,最好的方式是理解彼此的角色和职责。在其他行业中,我们很少觉得销售人员或产品代表是为我们的最佳利益着想,而不是试图推广他们的商品,但在 IT 领域,这却是一个常见的混淆点。
当然,供应商及其经销商代表(准确来说称为 VARs,但常常以 MSPs 的身份出现,但要小心不要将真正的 IT 服务公司与那些只希望客户不质疑其名称的经销商混淆)可以是宝贵的盟友,我们不应完全忽视他们。他们可以成为我们解决方案的一部分,尤其是在获取特殊工具、测试版组件、补丁、发布信息、错误修复、更换硬件以及其他来自工程团队的组件(而不是 IT 处理的部分)时。
形象化 IT 负责的部分和工程负责的部分
即便作为 IT 专业人员,有时理解什么属于 IT 范畴,什么属于供应商工程(或软件工程部门)范畴,也可能令人困惑。但这里的答案应该非常简单。
作为 IT 专业人员,我们使用他人制作的产品,并将这些产品组装成完整的解决方案。我们不制作 Linux,我们不创建新的数据库引擎,我们不编写企业运行的应用程序。我们也不制造钣金,不运营芯片厂,或以其他方式制造计算机硬件组件,但在少数情况下,我们可能会购买部件并将其组装成计算机(就像机械师可能组装汽车零部件,但不实际铸造金属做零件一样)。
供应商负责制造 IT 部门负责使用和操作的工具和产品。供应商编写操作系统,我们在 IT 部门安装它们。供应商制作应用程序,我们安装它们。供应商参与的是产品的制造,而不是解决方案的创造。IT 解决的是组织性挑战,而不是生产产品。
如果我们谈论的是汽车,也许会更清楚。汽车供应商制造汽车。顾客乘坐汽车。这两者显然有着重要的相互关系,但显然,设计和制造汽车是一个非常不同的任务,而不是规划路线并开车到目的地。我们显然可以看到供应商为我们制造工具,而我们是使用这些工具来解决交通运输问题的汽车买家。将这种逻辑应用到 IT 领域,便能一目了然。
真正的支持,最重要的支持,始终来自我们自己的 IT 团队(这其中通常也包括外部 IT 工作人员)。我们自己的 IT 团队不仅具备做出关键支持决策所需的广泛业务知识,而且还拥有解决供应商限制的潜在解决方案范围。解决方案通常是一个单一产品供应商无法单独处理的。
举个例子,如果你是一家物流公司,需要将一个集装箱从纽约运送到洛杉矶,而你的卡车坏了,当然你可能会向卡车制造商咨询修理信息,但你不会就此止步。你会考虑更换卡车、租用卡车、寻找其他卡车供应商,考虑在维修期间使用其他物流伙伴为你运输,或考虑改用铁路或海运!在所有这些选择中,只有修理或许更换你的初始卡车,才可能是卡车制造商的支持范围,甚至从他们那里修理它的范围也远远不如你从修理工那里得到的帮助。一个熟练的修理工可能会提出部分功能的恢复、第三方配件,或者一些原厂供应商无法提供或批准的替代修理方案。原厂供应商在这里有其价值,重要的价值,但只是整体部门价值的一个小小部分。
处理大多数灾难需要更广泛的范围。我们很少愿意坐等供应商判断问题是否属于他们,然后再决定是否有有效的支持,再决定他们如何处理这个问题。即使是优秀的供应商,拥有出色的支持,相比于 IT 员工应该做的事情,他们的能力也是受到极大限制的。IT 部门拥有或应该拥有足够的权限,做任何必要的事情来保护公司。这可能涉及与现有供应商合作,或者可能需要绕过供应商,或者仅仅是协调多个供应商的工作。即使需要供应商介入,IT 部门也应当负责监督这些供应商。
IT 供应商管理
与其他 IT 部门相比,系统管理部门更常与供应商互动,也更需要直接监督这些供应商。同时,系统管理部门也是最可能没有任何供应商的部门,至少在传统意义上是如此。
供应商不应被视为一个部门,而更像是一个特定的工具。一个需要监督并在适当时使用的工具,但使用权和决定权在 IT 部门。单独的供应商缺乏方向和控制。
管理 IT 部门的硬件、软件和服务供应商应当是该部门的日常任务。这个层级的供应商关系非常重要,因为这是技术知识应当交换的层级。对于我们 Linux 系统管理员来说,这意味着与像 IBM Red Hat 和 Canonical 这样的供应商的操作系统供应商对接,他们可以让我们及时了解补丁、即将发布的更改、发布日期、安全警报等,有时也可能成为我们依赖的专门技术资源。
系统管理可能还涉及许多其他类型的供应商。我们可能需要与服务器硬件、存储、数据库,甚至应用程序供应商合作。供应商众多,强调了 IT 管理供应商的重要性。没有 IT 的监督,这些供应商之间没有协调,也没有要求他们进行合作或朝着共同目标努力。此时,推动业务发展的责任完全在于 IT。只有 IT 才能确保在适当的情况下,利用供应商资源为业务发展提供帮助,而不是让其成为供应商的销售行为。
最佳实践是支持应当来自内部。根本上,所有的核心内容应该是,我们应将 IT 团队(包括内部和外部工作人员)视为解决方案团队,不仅是为了前期设计解决方案,也是为了在出现问题时处理它们。当供应商需要参与解决方案过程时,他们应当由 IT 团队进行协调、管理和监督,并且作为另一种资源进行管理。
分类技能和人员
大多数公司在灾难发生时会遭遇严重失败,因为分类流程要么不存在,要么非常不完善。日常运营所需的技能与危机中实时决策所需的决策过程是不同的:几乎没有时间开会,几乎没有与不同方协商的能力,规划根本不可能进行。在这种模式下,我们需要的是一个值得信赖、能应对压力且更倾向于观察而非规划的人——一个能快速决策、且不需要提前规划事件的人。规划固然重要,合理的规划应尽可能提前完成,但从初级 IT 人员到高级管理人员,每个人都应该明白,真正的紧急情况是无法充分预见的,现实生活中会有很多未知情况需要即时评估。
当发生灾难时,我们的第一个过程就是进入分类模式。我们需要准确知道什么地方出了问题,发生了什么,影响是什么——基本上,我们需要知道一切的状态。我们认为这能在几分钟内解决吗?需要进行调查吗?人们受到了什么影响?我们在失去金钱、生产力或客户吗?
灾难可能会对我们产生多种影响。能够迅速掌握业务影响,了解各个部门在大局中的作用,哪些团队能正常运作,哪些团队处于停滞状态,哪些团队能运作但在艰难维持,等等,都是至关重要的。这一点可能意味着从大家都站在那里不知所措到一个分类经理迅速解决问题的巨大差异。我们需要状态信息,并且需要大量的信息,且非常迅速地获得。
在大多数情况下,我们真正用于解决技术问题的时间竟出乎意料地少。这可能是因为只是硬件故障,我们只需要等待替换硬件到达。或者可能是完全的软故障,我们只需重建系统。有时候,深入的技术调查是有价值的,而且确实需要很多专业知识来查找问题的根源,但这并非大多数情况。我们更可能遇到相对快速的修复,至少在管理员需要投入的时间上是相对快速的。当修复时间很长时,通常是因为需要等待第三方的支持。
通常,我们会将注意力集中在停机的技术方面。停机的其他方面通常更为重要。一些组织拥有操作分诊专家,他们介入并处理停机的这些方面,使我们作为系统管理员能够专注于我们职责范围内的技术问题。然而,对于大多数企业而言,处理 IT 灾难从头到尾都需要 IT 的监督。在大多数情况下,我们希望帮助 IT 解决问题并管理操作环境分诊的团队,反而成为了寻找解决方案的障碍,而不是解决方案的一部分。
我可以提供状态更新,或者我可以解决问题。
每个曾经处理过任何形式的停机、灾难或其他影响企业的事件的人都知道,预期的反应不是让高管和管理层冲进来,开始寻找保护企业的方式,或在你突然被指派处理问题时提供帮助,而是我们依赖的那些人,应该创造一个最小化影响的环境并让我们有效工作,但几乎普遍会转而要求我们提供解释、状态报告、更新、估算、承诺和奇迹,所有这些充其量是无用的,最坏的情况是完全破坏了业务。
即使在理想情况下,报告、状态更新、测量等也有成本,并且这些成本通常会从生产力中扣除,哪怕是极小的部分。在灾难发生时,除了那些在最关键岗位上试图减轻和解决灾难的人,很少有人能提供状态更新。所以,最常见的情况是,所有人都会集中在那些少数关键岗位上,要求状态更新。
这里有几个问题,对于我们这些从事这些职位的人来说,这些问题显而易见,但对于那些现在正在经历生产力受影响的人来说,往往是无法察觉的。我们有两种工具可以帮助解决这个问题。第一,把这本书展示给管理层,让他们花时间理解情况。第二是规划。确保在灾难规划和准备过程中,管理层有相关培训,以及政策和程序计划,明确如何提供状态更新、谁可以索取这些更新,以及从谁那里获取。考虑指定 IT(及其他部门)的官方发言人,他们可以将所有时间用于提供更新,因为他们不参与灾难恢复工作的其他方面。也许他们会亲自主持一个战情室,或者维护一个电子邮件消息组,管理一个聊天室,或者主持一个电话会议,其他人可以根据需要拨入。
然后,任何现有的更新可以主动传递给这些指定的报告人员,他们可以为组织维持这一状态。整个组织应当理解设立一个指定报告点的重要性,这样,真正试图解决问题并让公司恢复正常运作的团队,可以将时间用于拯救公司,而不是报告公司的失败。显然,企业有一些业务需求,需要尽可能多地了解发生的事情。更具影响力的是内部的政治问题,管理者会觉得他们也必须提供他们无法获得的状态,而组织中的多个层级往往会有情绪化的人,他们可能会故意造成重大的财务损失,希望看起来更关心,或只是为了满足自己想要知道更多信息的欲望。
在培训管理层时,解释为什么 IT(及其他部门)不能提供详尽的更新,我们需要他们理解,作为试图解决问题的人,我们不能花时间提供状态更新。
我们没有任何信息可以提供。基本上,这是这个问题的最大难点。虽然我们可能会有一个简单的答案,比如替换部件计划明天到达,但通常我们对修复需要多长时间一无所知。IT 中的大多数问题在我们知道是什么问题时,本质上就已经解决了。直到完全修复,我们通常只是从假设中工作。向我们索要信息,实际上就等同于要求我们故意提供虚假的信息,因为我们没有其他可以提供的东西。这就像是在折磨一个不知道任何信息的囚犯,如果你折磨他们,他们很可能会编造些东西,只是希望折磨能停止。
我们都很忙。如果事情还没有解决,很可能我们正在全力以赴地试图解决它们。用来提供状态更新的时间必须从解决问题的时间中挤出。这不仅仅是浪费时间,它还会造成中断,打击那些在解决问题的人士的士气。它传递了一个巨大的组织信息,那就是问题并不那么重要,而且解决问题的努力没有得到应有的重视。这会让 IT 部门产生如果管理层都不优先解决问题,我们为什么要做?的想法。
政治风险。在试图让所有想要获得灾难信息以便做出规划的人能够从那些正在解决问题的人那里获取信息时,他们通常处于一个非常困难的境地,需要大胆猜测最终问题何时能解决。大多数组织都会对这种无法避免的不确定性采取非常消极的态度。故意提供错误信息往往会得到奖励,而诚实则常常受到惩罚。将信息提供者置于可能不得不只告诉人们他们想听的或提供不准确的信息以保护自己政治利益的位置,意味着公司可能会用错误的数据运营,从而导致不必要的额外财务损失。在这个时候推动错误的数据而不是没有数据是非常糟糕的,但这正是最有可能发生的时刻。
优先事项。如果组织开始从管理层开始优先考虑那些报告、状态会议、电话和其他无法解决问题的事情,而这些事情并不能帮助公司恢复正常运转,那么这将自然而然地,也应该绝对改变 IT 或任何其他部门处理问题的方式。如果任何问题都是如此琐碎,以至于我们开会讨论时间表而不是修复系统,那么随着时间的推移,加班、重新安排家庭活动,甚至跳过午餐,都会成为显然对公司没有价值的 IT 牺牲。我们绝不会仅仅为了某个会议而做这些事情,如果那个会议比找到解决方案更重要,那我们就有了相对价值评估,能够帮助我们找到行动的方向。
那么管理层应该如何行动呢?管理层需要做完全相反的事情。如果状态更新重要,我们理解它通常确实很重要,那么就让那些没有参与修复工作的人来处理这些沟通。保持优先事项清晰。指定团队来进行干预,避免所有打扰到正在修复系统的团队成员。让人们为他们送餐、饮料、咖啡,或者做些杂务,无论需要什么——让他们感到重要,而不是暗示他们不重要。不要因为传递坏消息而惩罚信息传递者,要奖励他们的诚实。站在他们的立场,考虑对公司最有利的结果。
这些都是容易说却难以做到的事情,尤其是在灾难发生时。提前规划,进行这些讨论,制定计划,在事情发生之前获得高层批准。制定一个行动计划,明确谁负责,事情如何进行,等等。
我们的首个分诊阶段是评估。我们是否有一个快速恢复在线的计划?我们需要了解当前的情况,然后需要以某种方式将这些信息传达给管理层。从这里开始,情况变得复杂。由于变量太多,教学分诊并非易事。擅长分诊的人需要能够评估现有的情况,找出解决当前问题的方法、可行的替代方案,并且在许多情况下,如何调整组织以便更好地应对。
这的确是一个跳出框架思考的情景。此时我们需要从大局出发,找出如何最好地保持企业的财务运转。这看起来可能像是管理层的任务,理想情况下确实是如此,但 IT 部门也应发挥作用,因为我们具备一些其他部门可能缺乏的见解。
除了技术修复外,应对策略会根据业务类型、影响类型等因素有很大差异。我们是不是应该让大家去喝咖啡?也许计划一个长时间的午餐?现在就让大家去休假,以节省保险费用,因为可能要过一段时间才会有人重新变得高效?也许可以让大家从纸质工作转到即时消息,而不是继续使用电子邮件?利用一种任务的空闲时间来集中精力做其他任务。也许在大家有空的时候,我们可以进行一次彻底的办公室清洁——拔掉那些电缆,真正把地方清理干净。
大规模紧急情况也可能带来大机会。我曾多次看到公司将灾难性停机当作机会,执行本来需要长时间审批或会导致大规模停机的重大更新和变更,但这些操作可以在反正已经发生的停机事件中顺利进行。有一次,我甚至遇到一个 ISP 故障,预计会持续很长时间,结果一个团队从纽约开车赶往华盛顿 D.C.,将一排服务器装入卡车,赶到纽约一个准备好的新地点,成功地执行了一个本因必需停机而被无限期搁置的数据中心迁移,并在 ISP 恢复华盛顿 D.C.服务之前,将工作负载从纽约恢复上线。一次看似小规模的停机,反而变成了部门的巨大胜利。一个大项目在艰难地等待安排和审批时,恰巧作为意外的好处被成功执行,同时团队通过迁移到备用数据中心,克服了原始地点由 ISP 租用线路所带来的限制,实现了一个重要的修复。
急救很难,因为它要求我们具备创造性、开放的思维、避免恐慌、广泛地思考并跳出常规框架,并且通常没有太多的规划或准备。如果你的组织没有一个合适的人来担任这个角色,而实际上很少有人适合,那么这应该是你外包的工作,但系统管理员是最有可能胜任此角色的人,因为系统管理员的技能和素质往往更适合急救和灾难恢复,而非工程和规划。
在许多情况下,停机不仅仅意味着一个工作负载无法访问,还需要在技术领域进行优先级排序。你的急救人员或团队需要深入了解各个工作负载之间的相互关系,哪些依赖于其他工作负载,哪些可以绕过,哪些可以跳过,以及这些工作负载如何与业务本身相关。只有了解技术范围和业务的关系,才能为修复顺序、优先级排序以及业务如何潜在应对提供有价值的见解。
我希望我们能够提供具体的指导,告诉大家如何在灾难中生存,但我们做不到。灾难有各种形式和大小,我们应对它们的方法也更多。最好的方法是学习如何思考、如何反应,并尽可能为任何可能的情况做好准备。
急救人员的招聘:感知者
我曾经有幸在一个大型 IT 部门工作,在那里,深度心理分析是管理过程的一部分。这听起来可能是件可怕的事,但这种方法非常优秀,公司运用了适当的心理分析来了解人们的工作方式、他们如何一起工作、谁在不同领域可能是强者或弱者,以及如何最好地组合人员以取得最佳结果。
我不想详细讨论这些技巧在何种情况下有帮助或可能有帮助,但我想提到的一个具体概念是迈尔斯-布里格斯性格测试中的“评判者”和“感知者”量表。我不是心理学家,所以我建议你自行研究这个测试及其解释,并理解像所有心理学一样,它的有效性既被广泛接受,也受到激烈争议。我在这里不会辩论赞成或反对,只是想说理解“评判”与“感知”偏好对的确非常有价值。
我通常将评判者描述为一个计划者,喜欢在事件发生前整理和安排事物。感知者则更像是一个反应者或应答者,喜欢按部就班地接受世界的挑战,并在当下做出反应。
在我们的世界里,工程师和大多数经理人都是判断型人格(Judgers)。他们的角色和价值在于提前思考,并组织业务或技术,以便完成需要做的事情。知觉型人格(Perceivers)则往往更擅长做管理员,而不是工程师,他们正是你在灾难发生时所需要的人。知觉型的人格是处理紧急情况、临场应变的自然候选人。人类天生是多样的,彼此互补,共同应对生活的多个方面,这正是这一点的典型例证。
成为合适的人选或团队成员,远不止是符合某项能力测试中的个性类型。迈尔斯-布里格斯评估仅仅是一个工具,用来识别哪些人可能在不同职位上表现得强或弱,并解释人们通常如何思考和感受。对我而言,发现自己是一个强项知觉型和弱项判断型的人,帮助我深刻理解自己,也让我学会如何将我的特点传达给他人。它还为我提供了工具,帮助我理解生活中的其他人,以便更好地沟通,并在他们的行为与我不同的时候,设定更好的期望。
无论你的公司是否使用正式的流程,还是你仅仅通过在线调查来了解自己,我都推荐使用迈尔斯-布里格斯(Myers-Briggs)等工具,至少可以帮助你更好地了解自己。你越了解自己,就越能在擅长的领域做好准备,并在薄弱的地方寻求帮助。如果你是团队领导或经理,这类信息对于帮助你更好地理解团队成员以及他们如何协作以变得更强大也很有帮助。
不要过度解读心理学工具或试图将它们广泛应用。总的来说,这些工具在应用于自己时最有效,当你以开放和诚实的态度,带着学习自己弱点的愿望,而非仅仅是发现自己的优点时,使用这些工具能起到自我提升的作用。记住,这类测试并不是关于结果的比较,某个结果并不比另一个更好或更差;每个人都处于不同的维度中,维度的两端或中间都没有好与坏之分。然而,强大的团队通常由多种不同的能力和个性的组合组成,以满足多方面的需求。
我希望我刚才所说的能让你充满信心和灵感,让你能够将分诊过程提升到一个新的水平,而不是让你对处理灾难的复杂性和不确定性感到恐慌——这不是你应该从中学到的重点。把现在的恐慌当作动力,立即开始你的计划和文档工作,并与管理层展开对话,争取利益相关者的支持。把这作为优先事项,你可以迅速从没有准备好转变为在几乎任何情况下都能最佳响应的领先企业。
不要觉得必须由你来处理分诊工作。也许你是做这项工作的最佳人选,也许你不是。很少有人拥有合适的个性,而分诊是一项非常特殊的能力。重要的是要确定你的分诊人员或团队,不管他们是谁。每个人都有自己的角色,找到你的定位,并找到合适的人来填补你需要的角色。
关于人员配置的最佳实践是,在灾难发生之前就确定你的分诊人员,并确保他们的角色已被文档化并随时可以接管,且有足够的权限在时机成熟时接管。不要等到停机时钟开始倒计时时才开始寻找具备分诊能力的人,也不要让政治成为焦点,而不是解决方案,因为时间至关重要。
故障排除的逻辑方法
作为系统管理员,可能最困难的事情就是故障排除。能够最初部署一个系统是一回事,但当问题出现时,能够排除故障则完全是另一回事。在系统管理中,我们有太多地方可能出问题;我们坐落于众多技术和无数可能性交汇的地方,追踪问题的源头可能非常具有挑战性。
毫不奇怪,经验使得这一切变得比任何事情都容易。你在维护和管理系统上经验越丰富,就越能快速地感知一个系统,并且通常能够在情况变得复杂时就能感觉到可能出问题的地方。没有什么比真正了解一个系统在正常情况下的反应以及根据其行为感知问题更有价值了。资深的诊断专家通常正是因这一点而被召集。通过足够的经验,你往往能直觉地感觉到是索引、缓存、磁盘或内存不足的问题。
除了纯粹的经验,我们的下一个最佳工具是深入理解我们自己的系统及其相互作用、对适用于我们情况的技术基础知识的深入了解,以及逻辑性的故障排除方法。
当然,在许多情况下,故障是迅速且明显的。停电了,硬盘坏了,关键的数据库被删除了。没有什么需要追踪的,只有需要解决的事情。但在其他时候,我们会遇到一些复杂的问题,可能由几乎任何因素引起,我们可能需要追踪到一个真正难以定位的问题。
让我吃惊的是,我经常被叫来协助故障排除,但发现已经做过的工作往往是杂乱无章的,而且通常存在冗余。当然,有时候,一些对容易测试的故障点的猜测,或者对已知常见故障点的早期测试,确实能加速发现问题,但我们必须小心,不能迷失方向,而是要从我们测试的内容中系统性地学习。
故障排除的故事
作为作者的一个好处就是我可以和你分享我自己的故障排除历史故事,而且没有人会翻白眼或者打断我,你也不能在感到无聊时就离开。所以,来吧。
有一次,我被叫去处理一个用于超低延迟应用的系统,团队发现应用在接收其他系统响应时会偶尔出现问题。问题是在每隔几分钟后,响应会比预期晚几纳秒到达。没错,纳秒!没有任何崩溃,结果也没有错误,只是有一个非常微小的延迟,且并不常发生。
经过大量研究,我们最终通过研究和系统理解的结合找到了问题。最终,通过数小时盯着 top 命令的监视器,观察在延迟发生时活跃的进程,我们成功地找出了问题。
最终,经过缩小可能的过程范围,发现内核中一个很快被废弃的内存垃圾回收过程在其默认设置下消耗了过多的系统资源,并导致系统在处理内存清理时暂停几纳秒。
我通过将垃圾回收过程设置为每次清理部分内存,使其运行得更快,从而解决了这个问题。之所以会出现这个问题,是因为服务器上有大量物理内存,导致垃圾回收过程占用了可测量的时间,而这通常是意料之外的。
在这种情况下,良好的研究和耐心无疑是重要的。能够基于测量工具感觉到系统中的延迟(没有人能真正感觉到如此短的延迟),然后运用逻辑推理来判断进行内存垃圾回收的过程如何以及为什么会影响这种性质的进程,所有这些必须结合起来才能使故障排除成为可能。如果没有对系统运行机制的深入理解,这是不可能做到的。
在进行故障排除时,我发现有两个关键技巧我总是反复告诉大家使用。第一个是要有条理,工作时从一端或另一端开始。避免四处跳跃或随意测试。例如,如果你在测试网络连接,可以从网络栈的近端开始,并基于测试逐步建立知识基础。
在网络故障排除的例子中,我们可以从检查网络连接是否正常开始:它是否有 IP 地址?能否 ping 通网关?ISP?公共 IP?是否能够解析 DNS?是否能访问它应该连接的系统?是否能够访问正确的端口?是否得到了合适的响应?
与其四处跳跃进行不同的测试,不如从最近的点开始,逐步探索,这样有助于我们准确地了解问题在哪一刻发生了故障,并迅速给出反馈。
另一个我总是教给大家的关键技巧是从已知的事实开始工作。基本上,要先确认事实。你可能有很多不知道的事情,但不能因此而担忧。这些未知总是存在的。然而,总是有一些你可以确认的事实,我们必须从这些已知的事实开始,利用它们来逐步建立更大的知识体系,找到越来越多我们能确定的事情。
例如,如果你能 ping 通远程服务器,那么你就知道你的网络连接、路由工作正常,且你和远程服务器之间的所有设备都在正常工作。或者,如果你知道某个特定的数据库正在运行并且一切正常,那么你也知道它的操作系统在正常运行,承载它的虚拟化管理程序也在正常运行,而虚拟化管理程序所安装的裸金属服务器也在正常运行。
让我感到惊讶的是,在故障排除过程中,人们总是会花时间确认事实,但之后又质疑这些事实。在上面的例子中,他们可能会觉得看到一个问题后,可能是虚拟化管理程序出现了故障,然后再次去检查它,尽管他们刚刚已经证明它依然在正常工作。或者在网络问题中,他们可能会说服自己需要检查一个路由器的状态,而他们之前刚刚用这个路由器验证过网络是否能正常通过。
深入“兔子洞”并让自己(或团队)一遍又一遍地证明你已经知道的事情是否正常,是在浪费时间,最好的情况下,这会非常令人沮丧。一旦你开始反复确认自己已经确定的事实,而不是去探寻新的信息,你很可能会一直这样做。很容易将注意力集中在这些事情上,从而忽略了扩展与当前问题相关的知识体系。
我发现,将我们知道的事实写下来,无论是作为起点还是从调查中得出,都是一个很好的工具。如果我们觉得必须再次测试我们已经证明的某个事情,那我们就有问题了。为什么我们不信任已经证明的事实?如果现在我们怀疑它,那当初为什么觉得它已经证明了?如果我们不打算相信测试结果,那测试又有什么意义呢?
如果我们测试、证明,然后又在原地打转,那就是无意义的时间浪费,而在系统停机期间我们是无法承受这些浪费的。我们要么需要以不同的方式看待我们认为是事实的事情,要么就需要信任这个评估。通过建立可信的事实,我们可以利用它们来缩小可能的问题范围。
故障排除之所以困难,一方面是因为它非常技术性,许多因素可能未知,另一方面也因为在压力甚至是恐慌的情况下进行的操作带有情绪性。通常,这种情况还会被我们组织的额外需求和压力加剧。保持清醒的头脑是关键。深呼吸,集中精力,喝点咖啡,把问题说出来,发布到技术同行评审社区和论坛,甚至可以与供应商沟通。把你的资源写下来,因为在紧张时容易忘记步骤。
技术社交媒体在问题解决中的作用
超过二十年来,我处理严重问题的一个最强大的资源竟然是技术社交媒体。我并不是指传统的社交媒体平台,而是专门为技术思想交流建立的论坛。当面临设计挑战或更重要的,系统故障需要修复时,我发现对我和我的团队来说,将这些问题发布到论坛上是非常宝贵的。
这一点之所以如此重要,原因并不总是显而易见的。最明显的好处是,许多经验丰富的专业人士愿意为你的问题提供新的视角,可能轻松发现你忽略的某个细节,或者提供一些见解或建议一些你之前不知道的工具。
然而,真正的好处在于请求帮助的过程。往往,必须写出问题所在、需要清晰表达并记录我所采取的步骤的行为本身,会让我在别人回应我之前,自己就能发现问题所在。将步骤写下来鼓励我更加有条理,也让我考虑到别人可能会问的显而易见的问题,这促使我尝试填补空白,遵循良好的流程,并记录比我平时为自己做的更多的内容。
我也会将这个公开评审的过程用于我的团队,并要求其他人也这么做。当然,有些细节不能公开发布,有时候即使没有可识别的细节,整个过程也过于敏感,不适合公开,但通常至少有一定程度的灾难可以公开供他人协助审查。使用这种方式在团队内部进行沟通非常有效,并且鼓励大家认真思考已做的工作,尝试不同的方式解释问题,并迫使团队成员之间对故障排除过程的文档进行更清晰的记录,因为即使是文档过程也会在实时中公开审查。
这个相同的过程随后提供了故障排除的文档和自动时间线,用于事后分析。我经常也邀请事后分析的审查,通常是通过相同的机制进行非正式的审查。人们总是乐于批评决策。你必须准备好接受一些严厉的评价。
没有人比我更支持在专注的环境中进行公共同行评审的价值了。我从 1990 年代末开始倡导这一运动,并在这些社区中通过公共平台度过了我的职业生涯。它教会了我很多我从未接触过的东西,并且迫使我以不同的方式工作,因为我知道我所做的一切都将被审查、评估和质疑。准备好解释每一个决策,捍卫每一个结果,依靠逻辑和数学来支持你的决策,无论是赞成还是反对,因为你的论点将永久记录供审查,这会促使你重新思考自己的话语,我相信,这也促使你在所有工作中变得更加优秀。因为当你认为没有人会质疑你,或者没有人会注意时,很容易做出不合理的论点。
故障排除的最佳实践很简单:要有条理,记录一切,并在需要依赖资源之前将其准备好。
接下来,我们将探讨何时开始执行这个过程是合理的,或者我们是否应该直接从头开始。
调查与修复
当我们开始处理宕机、数据丢失或其他灾难时,最自然的倾向是集中精力找出根本原因,修复这个根本原因,然后将系统恢复到正常状态。这是合乎逻辑的,是显而易见的事件进程,且情感上也令人满足。
这个过程的问题在于它基于一些错误的信念。这是一种源于像汽车或房屋在受损或发生事故后进行维修的做法。其基本原则是,相关的物体或系统非常昂贵,而修复相对便宜。
它还侧重于确定发生某些问题的原因的价值,胜过让系统重新运行的价值。假设如果某件事发生过一次,它很可能会再次发生,通过了解发生了什么和为什么发生,我们可以避免未来几乎不可避免的重复故障。
当然,在 IT 和商业系统中,通常构建的成本低于修复的成本。更重要的是,构建的成本比修复更具可预测性。如果我们进行了良好的规划和文档记录,我们应该能够在已知的时间内,以极高的可靠性实现新系统。修复问题可能很快,也可能不快,它代表着许多未知因素。修复可能需要很长时间,而且修复可能不可靠。根本原因分析可能是耗时且不可靠的。
在大多数情况下,尽快让系统恢复运行具有很大的价值,而确定问题发生的原因并找到未来避免它的潜在方法的价值较小。商业基础设施在硬件、软件和系统设计等各个方面经历着巨大的变化。今天发生的硬件故障不太可能以相同的方式重复发生。软件可能会被快速修补、更新和修改,虽然担心旧的 bug 会重现是可能的,但这并不是值得过多关注的情形。
如果我们处理的是汽车、房屋、道路、桥梁或其他此类大型物体,故障可能会随着时间的推移在系统几乎没有变化的情况下再次发生。我们需要确定故障点,评估重复发生的风险,并找到防护措施。很难摆脱这种思维方式。
我们必须评估对业务的价值。让系统恢复运行的价值是什么?找到根本原因的价值是什么?我们需要比较这些价值,通常情况下,我们会发现解决方案优于调查。
当我们拥有更现代化的基础设施,包括镜像系统、状态机和基础设施即代码时,修复与调查的决策将越来越偏向修复。我们的自动化质量越高,重建系统的速度越快、成本越低,调查问题的价值就越低。
我们还必须考虑到,凭借合适的基础设施,我们可以重建一个镜像系统,用于必要时的诊断。我们可以创建一个初步重建来让系统重新运行,并在有意义的情况下创建一个镜像,以便用来尝试重现故障,并确定是否有方法或原因来防止未来的类似故障。在停机期间,花费时间尝试识别原因并修复问题,可能并不是实现这一目标的最佳方式,即使它被认为是必要的。
这完全是成本分析,但必须非常迅速地完成。这里的未知因素是非常困难的难点,因为确定根本原因的时间完全不可知,可能需要几分钟,也可能需要几天。
这种从头开始的逻辑不仅适用于桌面,也适用于服务器。即使是最终用户工作站,也有机会做到可互换,并设计成能够快速重新部署的方式。如果我们使用镜像、自动化软件安装和其他自动化方式,那么桌面、笔记本或任何我们为最终用户使用的设备,都能在几分钟内进行新的部署。全新的部署不仅仅是让这些系统以最大效率恢复运行,它还提供了一个全新安装的机会,作为额外的福利。任何可能发生在机器上的冗余、恶意软件、损坏或类似问题都会被清除,最终用户将像机器刚从生产线下线一样全新地开始。通过这种方式,我们得到了一个银色的边际:一个全新的重建过程,我们通常很难安排,但理想情况下,我们应该定期进行。
可重建的系统,无论是桌面、服务器还是云实例,都意味着我们只需要可用的硬件就能从大多数灾难中恢复并继续前进。这也意味着,假设我们的备份存储在某个在线或异地的位置,我们有能力进入一个新的站点,并在那儿重建整个公司。这种灵活性和舒适感是一个改变游戏规则的因素——几年前,几乎没有公司能考虑到这一点。知道从 头开始 重新开始始终是可能的,让我们在灾难恢复中完全不同地看待我们所做的一切。
根据我的经验,即使是在十五年前,在我们拥有今天这种自动化和复杂环境之前,我们几乎完全被迫 仅仅快速恢复,只有在恢复上线后才进行检查,而实现这一点的能力从那时起就一直在增强。今天,在几乎所有情况下,我们应该把从头重建作为默认的假设起点,只有在情况要求时才 resort 更复杂的恢复方式;我们还应该仔细评估今天为什么会有这样的需求。这并不意味着重建应该是我们工具箱中唯一的工具,重建是大多数情况并不意味着它是唯一正确的解决方案,只是它最有可能是正确的。
传统上,重建存在某种污名化,好像这意味着我们放弃了或是力不从心。我们必须抗拒这种不正确的情绪反应。恢复环境的正确方法是创造对整个组织最有利的局面。就像我们做的所有事情一样,情感在这里不起作用。这只是一个财务和风险计算的问题。我们做的是对公司最有利的事,仅此而已。
最佳实践:
-
评估每种情况,但在低谷时,应倾向于彻底重建。没有一种方法适合所有情况,但在大多数情况下,重建应该是更好的选择。
-
设计系统时要确保它们能够快速、轻松、自动地重建。
概要
灾难恢复、紧急分类、为紧急情况配备适当的人员、组织准备工作、在灾难情境下的管理过程监督,以及应对关键故障场景的其他各个方面都是困难、令人恐惧且压力重重的。公司如何处理这些时刻,往往决定了哪些公司能生存下来,哪些公司会失败。我们必须确保有合适的人在岗,尽可能多的组织流程和程序,出色的文档,深入的系统知识,以及应对困难时期所需的灵活性,以使公司度过难关,取得真正的成功。
每个公司都在与这些问题作斗争。这些不是我们能一夜之间就能应用的简单战术。它需要组织利益相关者的支持,需要专业精神和规划,不仅在事件发生之前,而且在压力使几乎每个人都可能做出非理性行为的恐慌时刻,也要维持这些流程和专业精神。从一方面来看,我们可以将此视为充满压力和困难,但从另一方面来看,我们可以认识到它的本质:这是几乎所有组织都在挣扎的地方,大多数组织失败,而这是我们闪耀的最大机会。
灾难规划和灾难恢复无疑是你承担系统管理角色并将其发展为比原本角色更大,甚至通常比 IT 部门本身更大的机会。你无法仅将灾难准备工作局限于 IT 部门;它需要跨部门的合作。系统管理可以领先,而不是跟随,使 IT 成为应有的核心业务单元。
我意识到,对于许多人来说,IT 部门的能力和范围深受政治因素的影响,难以轻易变得灵活。挑战自己,至少要评估并考虑一下,推动组织朝新的方向发展需要什么。没有任何组织应该强迫 IT 戴上销售帽,仅仅为了说服组织做对自己有利的事,但在现实世界中,我们推销自己、我们的部门和我们的想法的能力,往往决定了我们是否会被誉为公司的救世主,或者只是被忽视。
记住,解决方案来自于你,而不是供应商。牢记供应商及其范围,并记住,虽然灾难是你挽救组织的绝佳机会,它们也是供应商在恐惧和情绪主导下找到新销售机会的巨大机会,此时周全的规划几乎不存在。重新思考你如何看待供应商,把支持关系的背景放在心中最重要的位置。时刻了解谁代表了你的利益,谁在寻找你为他们提供服务的最佳机会。
事后分析
在总结中加一个边栏可能显得不合适,但我认为事后分析本身就像是灾难的总结。那么为什么不在这里讨论一下呢?
大多数公司跳过了执行事后分析这一极为重要的任务。事后分析不是为了归咎于谁,如果公司想要用它来做这种事情,那么最好避免进行事后分析,但在健康的组织中,它们作为一个多层次的关键学习工具。
一次好的事后分析将揭示系统设计、文档、规划、政策、流程以及我们系统的几乎所有其他方面的错误。它还应该帮助我们识别在危机期间表现强或弱的人员。我们应该通过事后分析过程来发现我们在哪里存在弱点,如何改进,或者有可能决定不做任何更改。
事后分析还应允许我们评估导致我们今天处境的决策过程。这几乎是普遍被忽视的,而实际上这才是事后分析真正的价值所在。改变个别计划或决策的结果是好的,但通常只是微小的,但发现整个决策过程的失败则为我们提供了一个机会,能够对所有未来的决策产生影响并进行改变。
学会做决策很重要,但很少有组织或个人关注决策过程的质量,更少的公司跟踪并试图随着时间的推移改善这一过程。这是一个巨大的失误。决策是一个不断发生的过程。定期做出更好的决策比修正个别决策更为重要。
事后分析需要深入探讨我们为什么做出当初的决定,然后评估这个决定是否正确,但我们不能陷入用当前的知识来评判过去的决定的陷阱。如果我们早知道的话这种推测游戏是非常危险的。我们必须评估当时我们能知道什么,并确定是否做了足够的调研、是否充分考虑了、是否应用了真正的商业目标等等。
在事后很容易做出推测并说看,事情失败了,我们损失了钱,这是某人的错。从情感上看,这似乎是必须正确的,但实际上并非如此。它可能是对的,但这通常不是一个有生产力的判断。坏事发生了,风险是商业的一部分,并非总有某个人在背后导致这些坏事的发生。在 IT 行业,我们每天都在处理经过计算的风险。在事后分析中,我们需要知道的是我们是否做出了正确的计算并抓住了正确的机会。
一个关于良好风险的好例子是我们需要从纽约旅行到洛杉矶。我们可以乘飞机,也可以开车。如果我们主要关注旅行中的安全,飞行会让人感到害怕,而开车则似乎一点也不可怕。然而,在这么长的距离下,发生车祸的死亡几率远远高于飞机失事的风险。如果我们坐飞机,而飞机确实发生了坠机事故,我们可能会用这次飞行即将坠毁的知识来判断,正确的决定是应该开车,但那是错误的。飞行依然是正确的决定。这两种方式都有风险,而飞行的风险明显较低。我们之所以会用这次飞行会坠毁的知识,是因为在事前无法知道这一点。我们是在规避风险,做出了正确的决定;但没有任何选项是没有风险的,而因为做出了正确选择而惩罚别人,是一种糟糕的结果。
人们需要因做出艰难决策而获得奖励,尤其是在他们做出了正确的艰难决策时。如果我们寻求归咎于某人,就有可能因为某人做出了任何决定而惩罚他们。如果我们这样做,就会推动他们避免那些有助于保护业务的决策,以避免成为错误指责的对象。当然,如果做出了真正糟糕的决策,我们是希望能够发现的。保持专注于组织和个人改进,而不是将事后分析用来寻找替罪羊或推卸责任,确实是一个非常困难的任务。
如果正确使用,事后分析是一个强大的工具。如果使用不当,它会浪费时间,甚至可能更糟。即使组织没有能力进行良好的事后分析,也可以仅在 IT 部门内部进行。如果 IT 部门本身存在让这种分析不可能的政治因素,也可以仅在系统管理层内部进行。即使没有其他人参与,也要为自己进行事后分析。
记录你的事后分析。人们倾向于消极地记住灾难,并情绪化地归咎于并不存在或不应承担责任的人。保持事后分析的文档,因为它通常在以后为保护个人、团队或流程提供帮助。即使是事后,良好的文档依然是一个强大的工具。
记住,事后分析不仅需要问我们是否能够避免这场灾难,还需要问即便我们能,是否应该避免?通常,避免灾难的成本往往大于灾难发生的风险成本。事后分析应当涵盖决策过程、决策本身以及对灾难的应对。
我希望本章中的思想和概念能帮助你打破传统角色的思维定势,拆除框架,让你在灾难恢复方面的方式体现出你和你的组织所能展现的最佳能力。
在关于 Linux 的书籍中,显然缺少对 Docker 和其他现代容器技术的讨论。这并非偶然,而是经过设计的。其原因在于,Docker 及其同类技术是应用容器技术,它们利用了我们已经讨论过的其他技术,而它们的实践则是它们自己的问题。从系统管理员的角度来看,应用容器只是另一种工作负载——它恰好使用了 Type-C 虚拟化并管理自己的依赖关系和更新。Docker 或其他应用容器管理超出了本书以及一般系统管理的范围。
在大多数情况下,系统管理员负责管理这些技术,但它们并不是特殊的案例。工作负载与我们在本书中讨论的其他工作负载相同。尽管它们可能有自己的名称、机制和管理工具,但所有这些仍然受到我们作为系统管理员应当已经掌握的一般情况准则和规则的约束。如果你打算与这些技术打交道,且如果你现在是系统管理员,几乎肯定会这样做,你将需要学习许多与应用容器平台及其管理工具特定相关的知识,并将这些知识应用到我们已经学到的内容上。
最佳实践专注于学习一般情况,即总是适用的规则,然后弄清楚不同的技术、技术方法和产品如何符合这些一般情况。

订阅我们的在线数字图书馆,全面访问超过 7,000 本图书和视频,以及行业领先的工具,帮助你规划个人发展并推进职业生涯。欲了解更多信息,请访问我们的网站。
第十三章:为什么订阅?
-
通过来自超过 4,000 位行业专业人士的实用电子书和视频,减少学习时间,增加编程时间
-
通过专为你打造的技能计划提高你的学习效率
-
每月免费获取一本电子书或视频
-
完全可搜索,方便访问关键信息
-
复制、粘贴、打印和收藏内容
你知道 Packt 提供每本书的电子书版本吗?PDF 和 ePub 文件可供下载。你可以在 packt.com 升级到电子书版本,并且作为纸质书客户,你可以享受电子书的折扣。有关更多详情,请通过 customercare@packtpub.com 联系我们。
在 www.packt.com,你还可以阅读一系列免费的技术文章,注册各类免费的新闻简报,并获得 Packt 图书和电子书的独家折扣和优惠。
你可能会喜欢的其他书籍
如果你喜欢本书,你可能对 Packt 出版的其他书籍感兴趣:
](https://github.com/OpenDocCN/freelearn-linux-pt3-zh/raw/master/docs/linux-adm-bst-prac/img/9781789530384_Cover.png)](https://packt.link/9781789530384)
精通嵌入式 Linux 编程 - 第三版
Frank Vasquez,Chris Simmonds
ISBN: 978-1-78953-038-4
-
使用 Buildroot 和 Yocto 项目创建嵌入式 Linux 系统
-
排查 BitBake 构建失败并优化你的 Yocto 开发工作流
-
使用 Mender 或 balena 在现场安全更新 IoT 设备
-
通过阅读原理图、修改设备树、焊接突破板以及使用逻辑分析仪探测引脚来原型化外设扩展
-
无需编写内核设备驱动即可与硬件交互
-
将系统划分为由 BusyBox runit 监督的服务
-
使用 GDB 远程调试设备,并使用 perf、ftrace、eBPF 和 Callgrind 等工具衡量系统性能
Linux 系统编程技巧
Jack-Benny Persson
ISBN: 978-1-78995-128-8
-
了解如何使用各种系统调用为 Linux 系统编写程序
-
深入了解 POSIX 函数的工作原理
-
理解并使用关键概念,如信号、管道、进程间通信(IPC)和进程管理
-
了解如何将程序与 Linux 系统集成
-
探索高级主题,如文件系统操作、创建共享库和调试程序
-
全面理解如何使用 Valgrind 调试程序
Packt 正在寻找像你这样的作者
如果您有兴趣成为 Packt 的作者,请访问 authors.packtpub.com 并立即申请。我们与成千上万的开发者和技术专业人士合作,帮助他们将自己的见解与全球技术社区分享。您可以提交一般申请,申请我们正在招募作者的具体热门话题,或提交您自己的想法。
分享您的想法
现在您已经完成了 Linux 管理最佳实践,我们很想听听您的想法!如果您是从 Amazon 购买的这本书,请 点击这里直接前往 Amazon 评论页面 为这本书分享您的反馈,或者在您购买书籍的站点上留下评论。
您的评论对我们和技术社区非常重要,将帮助我们确保提供优质的内容。


浙公网安备 33010602011771号