3 自动管理和预置
许多服务编写的目的是为了在故障时向运营部门发出警报,以得到人工干预完成恢复。这种模式凸显出在24 x 7 小时运营人员上的开支问题;更重要的是,如果运营工程师被要求在充满压力的情况下做出艰难的决定,那么有20%的可能他们会犯错误。这种模式的代价高昂,容易引入错误,而且还会降低服务的整体可靠性。然而,注重自动化的设计会引入明显的服务模型约束。比如说,当前某些大型服务依靠的数据库系统,会以异步方式复制到次级备份服务器,因为复制以异步方式完成,在主数据库无法服务请求后,故障转移到次级数据库会引起部分客户数据丢失。然而,不把故障转移到次级数据库,则会引起数据被储存在故障服务器上的用户面临服务停工。在这种情况下,要自动化故障转移的决策就很困难了,因为这个决策依赖于人为判断,以及对数据损失量和停机大致时长相比的准确估计。注重自动化设计出的系统会在延迟和同步复制的吞吐量开销上付出代价。在做到这一步以后,故障转移变成了一个很简单的决策:如果主服务器宕机,将请求转到次服务器上。这种方式更适用于自动化,而且被认为更不容易产生错误。在设计和部署后将服务的管理过程自动化可能是一件相当具有难度的工作。成功的自动化必须保证简单性,以及清晰并易于确定的运营决策;这又要依靠对服务的谨慎设计,甚至在必要时以一定的延迟和吞吐量为代价作出牺牲,让自动化变得简单。通常这样的折中方案并不容易确定,但是对于大规模服务来说在管理方面的节约可能不止数量级。事实上,目前根据我们的观察,在人员成本方面,完全手动管理的服务和完全自动化的服务之间的差别足足有两个数量级。注重自动化的设计包含以下最佳实践:
3.1 可以重启动,并保持冗余。
可以重启动,并保持冗余。所有的操作都必须可以重新启动,并且所有持久化状态也必须冗余存储。
3.2 支持地理分布
支持地理分布。所有大规模服务都应当支持在多个托管数据中心运行。我们所描述的自动化和绝大多数功效在无地理分布的情况下仍是可行的。但缺乏对多服务中心部署方式的支持,会引起运营成本显著提升。没有了地理分布,很难使用一个数据中心的空闲容量来减缓另外一个数据中心所托管的服务的负载。缺乏地理分布是一项会导致成本提高的运营约束。
3.3 自动预置与安装。
自动预置与安装。手动进行预置和安装是相当劳民伤财的,故障太多,而且微小的配置差异会慢慢在整个服务中蔓延开来,导致问题的确定越来越困难。
3.4 将配置和代码作为整体。
将配置和代码作为整体。请确保做到:
l 开发团队以整体单元的形式交付代码和配置;
l 该单元经过测试部门的部署,并严格按照运营部门将会部署的方式;
l 运营部门也按照整体单元的方式部署。通常说,将配置和代码作为一整个单元处理并且只把它们放在一起修改的服务会更可靠。
3.5 生成环境的变更必须审核和记录
如果配置必须在生产环境中变更,那么请保证所有的变更都要产生审核日志记录,这样什么东西被修改,在什么时候被谁修改,哪些服务器受到影响,就一目了然了。频繁扫描所有的服务器,确保它们当前的状态与预期状态相符。这样做对捕获安装和配置故障颇有裨益,而且能在早期侦测到服务器的错误配置,还能找到未经审核的服务器配置变更。
3.6 管理服务器的角色或者性质,而不是服务器本身
管理服务器的角色或者性质,而不是服务器本身。每个系统的角色或性质都应当按需要支持尽可能多或少的服务器。
3.7 多系统故障是常见的。
多系统故障是常见的。请做好多台主机同时发生故障的准备(电源、网络切换和首次上线)。遗憾的是,带有状态的服务必须得注意它们的拓扑分布。有相互联系的故障一直以来都是不可避免的。
3.8 在服务级别上进行恢复。
在服务级别上进行恢复。在服务级别处理故障,相比软件底层来说,其中的服务执行上下文更加完整。例如,将冗余纳入服务当中,而不是依靠较低的软件层来恢复。
3.9 对于不可恢复的信息,绝对不要依赖于本地存储。
对于不可恢复的信息,绝对不要依赖于本地存储。保证总是复制所有的非瞬时服务状态。
3.10 保持部署的简单性
保持部署的简单性。文件复制是最理想的方式,因为这样能带来最大的部署灵活性。最小化外部依赖性;避免复杂的安装脚本;避免任何阻止不同组件或者同一个组件不同版本在同一台机器运行的情况。
3.11 定期使服务停转
定期使服务停转。停掉数据中心,关闭柜式服务器,断掉服务器电源。定期进行受控的关闭操作,能够主动暴露出服务器、系统和网络的缺陷。没有意愿在生产环境中测试的人,实际上是还没有信心保证服务在经历故障时仍能继续运转。此外,若不进行生产测试,在真正出事时,恢复不一定能派上用场。