这样理解Ansible更容易
滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。—— 《临江仙》 电脑店 从前,有一家电脑店。原来你即是老板,又是店员时,拿到清单,你就必须亲自动手采购,然后一个个零件组装。每天都做着即重复又辛苦的活。 虽说你的组装技术已经很娴熟了,但是偶尔还发生装错的情况(大概是那天和老板娘吵架了),把一个客人要求的 CPU i5 装成了 CPU i7。结果是你亏本或者赚得少了。 后来,你采购了一个自动组装电脑的机器人。你只要告诉它电脑的配置,并把零件放到指定的箱子中。接着启动这台机器,它就自动帮你组装好电脑了。它每天都干重复的活也不会叫辛苦。 最重要的是准确,它不会因为心情不好,而装错。因为它根本不会闹情绪。 这样,老板就可以从重复的工作解放出来。然后将多出来的时间花在与人的沟通上,为有不同需求的人设计更合适的电脑配置清单。毕竟游戏发烧友和办公小白领的需求是不一样的。 在运维领域,不少运维人都干着即是老板又是店员的工作。如果在运维领域也能有这样的“机器人”该多好。事实上,Ansible、Puppet、Check 就是这样的机器人。 为什么要从零设计一个运维机器人 本文并不想生硬地罗列 Ansible 的各个知识点。因为那样,大家不如直接看 Ansible 官方文档就好。 笔者采用从零设计一个运维机器人的方式来告诉你,为什么 Ansible 会是现在这个样子。当然,现实中的 Ansible 不会像本文所写的那样一步步设计。 为什么要这样呢?因为笔者觉得只有知道一个工具背后的设计原理,真正用这个工具才会得心应手。 运维机器人的最终模样 首先,需要确定一下实现这个运维机器人的目的是什么。我们并不是希望所有的运维工作都交给运维机器人,而是希望运维工作中重复的那部分尽可能的交给机器人,把创造性的工作全部交给人。如下图所示。 以终为始是一种非常有效的实现目标的思考模型。根据此思考模型,我们首先必须探讨运维机器人的最终模样。然后,再讨论可能的解决方案。 那么,什么样的运维机器人能帮助我们实现上述的自动化运维目标呢?想像一下。是不是只要我们对着运维机器人说一句:“我要部署一个 Nginx 到 192.168.12.11”。它就可以帮我们完成了? 但是它怎么知道如何连接到 192.168.12.11 呢?是使用用户名密码的方式,还是使用私钥?它又怎么知道 Nginx 需要什么样的配置呢?一问下来,其实,语音运维只适用于启动一些预定义的动作。就像汽车的一键启动。你不可能使用语音来对 Nginx 进行大量的配置。 而纯文本才是进行大量配置的最好媒介。 所以,运维机器人的最终模样是:我们将部署的主机 IP、登录方式、Nginx 的配置放在一个文本文件中,然后运维机器人读取这个文本文件,然后根据配置进行部署。如果部署的是业务系统,我们还需要准备该业务系统的二进制包。如下图所示。 那么,我们在文本文件中使用何种语言描述我们的配置需求呢?可以分成两种。一种是利于人类学习的自然语言(如英语)。另一种是利于机器读取的结构化数据(如YAML、JSON)。 按当前的技术实现的可能性,不论是运维机器人,还是交给其它程序,都需要将自然语言转到结构化的数据。就像程序员,需要将业务知识翻译成编程语言;像编译器将编程语言翻译成机器真正能识别的二进制代码。 运维机器人的真正核心不是将自然语言转成结构化的数据。所以,文本文件中,我们直接写结构化数据。同时,我们决定使用 YAML 格式作为结构化数据的载体。因为它是非常流行的配置文件格式。降低人们写结构化数据的难度。 当然,好的设计不应该与具体配置文件格式耦合。 实现运维机器人要解决哪些问题 以上只是确定了运维机器人的最终模样及使用方式,解决的是用户的问题。但是因为我们是运维机器人的设计者,我们必须考虑如何实现它。 回想一下,平时我们的运维人员是如何实现自动化的?是不是写好了 bash 脚本后,然后将脚本上传到目标机器,最后在目标机器上执行该脚本。 这个 bash 脚本其实也可以算是一种结构化的数据格式,而且是一种不需要再做编译,目标机器能直接运行的格式。 在平时的自动化方式基础上进行抽象。我们觉得要实现运维机器人要解决的关键问题有: 需要将 YAML 转成目标机器可执行的程序(或脚本)。 需要将可执行的程序上传到目标机器,并执行。 为什么一定要将 YAML 转成目标机器可执行的程序呢?直接写 bash 不就可以了? ...