Ansible实战之 自动安装部署MooseFS 以及 与Salt的相关比较


前段时间,了解并学习了Salt,感觉非常不错,于是有了想法和打算要替换掉线上的Puppet。
可是最近情况不妙,一名新加入的同事,极力推荐Ansible,并列举了很多Ansible比Salt优越的地方。当时我对Ansible还不了解,因此不能与其争论,到底谁好谁坏也无法做出判断。
于是,我就选择了之前在Salt上实现过的同一个案例 “自动安装部署MooseFS”,来将它用Ansible实现一遍。在经历了一段时间的学习和填坑的过程之后,终于完成了,同时也有了一些心得。

我参考的是官方文档,从 Getting Started 开始,接着重点参考了 ModulesPractices ,以及 官方的Hadoop示例

我的相关Ansible代码都放在了GitHub上,具体结构如下:
$ tree

.
|-- group_vars
|   |-- all
|   `-- moosefs_all
|-- moosefs.hosts
|-- moosefs.yml
|-- roles
|   |-- common
|   |   `-- tasks
|   |       `-- main.yml
|   |-- moosefs_chunkserver
|   |   |-- handlers
|   |   |   `-- main.yml
|   |   |-- tasks
|   |   |   `-- main.yml
|   |   `-- templates
|   |       |-- mfschunkserver.cfg.j2
|   |       `-- mfshdd.cfg.j2
|   |-- moosefs_client
|   |   `-- tasks
|   |       `-- main.yml
|   |-- moosefs_common
|   |   `-- tasks
|   |       `-- main.yml
|   |-- moosefs_master
|   |   |-- files
|   |   |   `-- index.html
|   |   |-- handlers
|   |   |   `-- main.yml
|   |   |-- tasks
|   |   |   `-- main.yml
|   |   `-- templates
|   |       |-- httpd.conf.j2
|   |       |-- mfsexports.cfg.j2
|   |       |-- mfsmaster.cfg.j2
|   |       `-- mfsmetalogger.cfg.j2
|   `-- moosefs_metalogger
|       |-- handlers
|       |   `-- main.yml
|       |-- tasks
|       |   `-- main.yml
|       `-- templates
|           `-- mfsmetalogger.cfg.j2
`-- site.yml

乍一看,可能还不是很明白。虽然Ansible也是用Python实现的,并且也用的是YAML格式的配置文件,但其实Ansible与Salt还是有很多不同之处的,我通过实践所体会到的有以下一些方面:

1. Ansible默认是通过SSH通道来管理的,也就是它所说的免客户端方式管理,这一点Salt其实也可以通过其SSH模块来实现的;而Ansible通过SSH通道来管理的方式,很有意思,是通过 在远程主机上根据playbooks(相当于Salt的states)生成对应的Python临时代码,然后远程执行这一段临时代码,并在执行完成以后删除;可以通过我下面的记录看出来:

$ ps aux | grep yum
dong.guo 53694  0.0  0.2 106112  1336 pts/3    Ss+  21:34   0:00 /bin/sh -c sudo -k && sudo -H -S -p "[sudo via ansible, key=mllvsspinbocwxqpnlsksgllrhjzxwtm] password: " -u root /bin/sh -c '/usr/bin/python -tt /home/dong.guo/.ansible/tmp/ansible-1377610468.9-249905898759642/yum; rm -rf /home/dong.guo/.ansible/tmp/ansible-1377610468.9-249905898759642/ >/dev/null 2>&1'

$ file .ansible/tmp/ansible-1377610468.9-249905898759642/yum 
.ansible/tmp/ansible-1377610468.9-249905898759642/yum: a /usr/bin/python -tt script text executable

2. Ansible比较灵活,没有入口文件的概念,但是定义了一系列的文档结构,这一点跟Chef有点相似,我觉得其实还好。Ansible主要是通过一个inventory来定义role和主机之间的匹配,通过一个ini风格的配置文件来管理所有的主机,通过一个group_vars下与主机组同名的文件来管理变量,或者host_vars下与主机同名的文件来管理变量(和pillar类似),然后按照固定的目录结构在角色名目录下创建好files, handlers, tasks, templates, vars(角色级别的变量)等目录;最后通过ansible命令再跟一系列的参数指定好inventory, playbooks, user等来触发对所有主机的配置。

3. Ansible默认是自上而下运行的,因此没有require,这一点需要自己从最开始的inventory就组织好上下顺序就行了(Salt也即将支持这样的方式);而notify中所引用的配置项,就必须放到handlers里面去,一般用来存放restart service这种配置项,我觉得这一点做的就不如Salt了;

4. Ansible目前就已经有了一套比较成熟的UI,不过是商业版,这种软件应该在设计之初就考虑了UI。而Salt的CTO在我们上次freenode上的交谈中,说过Salt在最初设计时并没有考虑UI,因此目前都还没有一个比较成熟的UI系统;不过说实话,我对UI并不怎么感兴趣,以前用Chef的时候那UI就很强大,但是我们都没用过;

5. Ansible目前的模块很多,但是很多地方还不及Salt完善,比如说command模块(相当于salt的cmd),连个unless的判断都没有,只有一个creates来判断文件是否存在,逼得我只能用raw模块通过管道命令来实现;

6. Ansible的配置文件风格是,每个单独的配置项都要在单行中搞定,所以一旦参数很多的时候,代码会撑的很长,可读性很差,这可能与Ansible的作者有关,个人风格很重,Ansible源码里面就有很多地方一行代码撑到github显示框外面去了,需要拉下面的横条才能看完。作者是一个大牛,但可能不太喜欢换行吧。我刚学Python的时候就看的Google Style Guide,超过80个字符都觉得该换行,因此Salt的多行配置我更喜欢一些;

7. Ansible的源码结构看起来也没有Salt那么清晰,二次开发起来感觉也稍微难了一点;

8. Ansible也支持添加一个ZeroMQ以及Agent,但如果采用这种方式的话,相比而言我觉得Salt要好用的多。

还有一些,不过重点都说的差不多了。或许是因为我的个人风格和Salt更接近,也或许是我先入为主的思想占了上风。我在用Ansbile编写配置的时候不是很愉快,而且,基于SSH配置的,体验很不好,真的是很慢很不稳定。
如果大家有对Ansible更熟悉的,欢迎加入讨论。

,

  1. #1 by is on 2013/10/06 - 00:14

    Ansible 1.3该进了fireball的连接方式,做了一个accalerate mode,
    其实差不多,部署使用方便很多.

    • #2 by mcsrainbow on 2014/08/27 - 11:26

      你具体使用过么?fireball目前已经被官方弃用了,而accalerate mode只不过是减少了配置的网络传输成本,很多常用的配置项只需通过解释即可生成Python脚本,不需要scp传输过去再执行,节省的只是网络传输部分的速度。

  2. #3 by denny on 2014/06/10 - 02:10

    Puppet, Chef, Ansible, Salt, Cfengine, heat。 茫茫多的配置管理工具, 就不能杀出个王者出来,一统江湖吗?

  3. #4 by non on 2014/08/27 - 00:10

    第5点作者为什么不用shell模块?
    [root@rh6 ~]# ansible all -m shell -a 'if [ -s a111 ];then echo good;else echo not good;fi'
    192.168.255.124 | success | rc=0 >>
    not good

    192.168.255.123 | success | rc=0 >>
    not good

(will not be published)
*