在我们构建了事物后,我们会开始优化它。在这里做些调整,那里做些更新,并监控一切以确保其正常运行。在大多数情况下,这最终会涉及到一定程度的自动化,而这正是工具箱脚本和开发发挥作用的地方。我们编写一些代码来自动化手动任务,将其放入生产环节,并移动到下一个目标。
理想情况下,我们应该尽可能多地对代码进行错误检查,但很多时候,开发人员并不会进行真正的错误检查,这可能带来巨大的灾难。
我们看一个真实的例子。我们有一个虚拟服务器模版(用于进行自动服务扩展),当web应用程序的负载增加时,该模版会用来增建web服务器。这是简单的事情—我们只需要能够按一个按钮(或者自动执行它)。
假设我们已经部署了程序来调整负载均衡器,以及添加新的web服务器,我们真正要关注的是确保这些服务器上的应用程序堆栈的稳定性和正常运行。我们编写了一些代码,并将其放入到init脚本,让每台web服务器可以下载某些需要的变量因素,以便可以正常运行。这又是简单的事情。我们可以自动化anrsync或者scp进程。我们可以非常快速方便地测试这个代码。
但是,如果我们没有对该代码进行足够的错误检查,我们可能会发现,在半年内,整个应用程序开始间歇性崩溃。也许文件名更改了,或者服务器被替换,或者某人更改了authorized_keys文件。这些都是看苏无害的变化,当这些web服务器启动时,它们将无法访问它们需要的东西,从而无法正常运行。
在这种情况下应该会发生这样的事情:服务器通过SNMP或者电子邮件显示错误,并不会打开web服务。这个问题将会显而易见,也许一些调试就可以解决。然而,如果服务器继续打开所有服务,并加入到负载均衡组,它可能无法正常工作。
根据所遇到的实际问题,这可能意味着新服务器上的所有服务都崩溃了,可能让服务、内容和应用程序监控框架无法检测到攻击。服务器可能看起来没问题,但实际并不是这样。
如果这种影响相对较小,可能更加令人不安,这意味着通过该模版生成的新服务器启动时,又会出现错误报告,或者只会有小部分用户受影响,因为已经运行的服务器没有相同的问题。这些问题很难发现。笔者更愿意看到这样的情况:启动十几台服务器、发现一个错误、发送警报,然后破坏应用程序。与损坏的可能破坏数据库的快速应用程序相比,容量较低而减缓运行的应用程序更可接受。
这个问题的关键是,看似微小的自动化工作可能能够完美地工作很长的时间,但最终还是会带来破坏。自动驾驶仪是伟大的发明,但我们还是希望由人来驾驶汽车,以确保事情的正常运行。对于简单的自动化任务,我们应该尽可能多地进行错误检查,因为这和自动化本身一样重要。
自动化确实能够带来很大的满足感。我们能够构建一个机智的框架来简化一些工作,然后看着其运作。但就像乐高车一样,如果我们不重视,它最终将会碰壁。最好一开始就做好规划。