写在前面的话
关于安装和基础的使用请参考,上一篇ansible,本文只记录一些ansible的扩展知识
动态inventory
1 | Cobbler 外部 Inventory 脚本 |
使用配置管理系统经常有一种需求,可能要在其他的软件系统中保存自己的 inventory 配置信息.
Ansible 本身通过基于文本的方式来记录 inventory 配置信息,这在前面已介绍过(详见 Inventory文件 ).
除此之外,Ansible 也支持用其他方式保存配置信息.
在其他软件系统保存配置信息的例子有:
1 | 1, 从云端拉取 inventory |
对于这些需求,Ansible 可通过一个外部 inventory 系统来支持.在 ansible 的 “/plugins” 插件目录下已经含有一些选项 – 包括 EC2/Eucalyptus, Rackspace Cloud,and OpenStack,我们稍后会详细介绍它们. (说实话我没找到,估计是通过编译安装或者是git安装才有,我自己git安装的ansible/lib/ansible/plugins有这份插件目录,)
Ansible Ansible Tower 提供了一个数据库来存储 inventory 配置信息, 这个数据库可以通过 web 访问,或通过 REST 访问. Tower 与所有你使用的 Ansible 动态 inventory 源保持同步,并提供了一个图形化的 inventory 编辑器. 有了这个数据库,便可以很容易的关联过去的事件历史,可以看到在上一次 playbook 运行时,哪里出现了运行失败的情况.
关于如何编写你自己的动态inventory源,请参见http://ansible-tran.readthedocs.io/en/latest/docs/developing_inventory.html
AWS EC2 外部 inventory 脚本
(里边有用到几个脚本,放在GitHub上,但是由于GitHub被微软收购原因,一直链接不到,这部分职能暂时放弃,之后去英文版的找找看吧.)
使用 AWC EC2时,维护一份 inventory 文件有时不是最好的方法.因为主机的数量有可能发生变动,或者主机是由外部的应用管理的,或者使用了 AWS autoscaling.这时,使用 EC2 external inventory 脚本是更好的选择.
脚本的使用方式有两种,最简单的是直接使用 Ansible 的命令行选项 -i ,指定脚本的路径(脚本要有可执行权限):
playbook
Playbooks 是 Ansible的配置,部署,编排语言.他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组IT程序运行的命令集合.
如果 Ansible 模块你是工作室中的工具,那么 playbooks 就是你设置的方案计划.
在基础层面, playbooks 可以被用来管理用于部署到远程主机的配置文件.在更高的层面上,playbooks 可以依次对多层式架构上的服务器执行上线包括滚动更新在内的操作并可以将操作委托给其他主机包括在此过程中发生的与监视服务器,负载均衡服务器的交互操作在内.
虽然这里讲发很多,但是不需要立刻一次性全部学完.你可以从小功能开始,当你需要的时候再来这里找对应的功能即可.
Playbooks 被设计的非常简单易懂和基于text language二次开发.有多种办法来组织 playbooks 和其附属的文件,同时我们也会提供一些关于学习 Ansible 的建议.
这里强烈建议在阅读的 playbook 文档的时候同步参阅 Example Playbooks https://github.com/ansible/ansible-examples (这个git的内容真的特别棒,强烈建议去看一看)章节. 这些例子是最佳实战以及如何将各种概念灵活贯穿结合在一起.
简介
Playbooks 与 adhoc 相比,是一种完全不同的运用 ansible 的方式,是非常之强大的.
简单来说,playbooks 是一种简单的配置管理系统与多机器部署系统的基础.与现有的其他系统有不同之处,且非常适合于复杂应用的部署.
Playbooks 可用于声明配置,更强大的地方在于,在 playbooks 中可以编排有序的执行过程,甚至于做到在多组机器间,来回有序的执行特别指定的步骤.并且可以同步或异步的发起任务.
我们使用 adhoc 时,主要是使用 /usr/bin/ansible 程序执行任务.而使用 playbooks 时,更多是将之放入源码控制之中,用之推送你的配置或是用于确认你的远程系统的配置是否符合配置规范.
在如右的连接中: ansible-examples repository ,有一些整套的playbooks,它们阐明了上述的这些技巧.我们建议你在另一个标签页中打开它看看,配合本章节一起看.
即便学完 playbooks 这个章节,仍有许多知识点只是入门的级别.
playbook语言示例
Playbooks 的格式是YAML(详见:YAML 语法:http://ansible-tran.readthedocs.io/en/latest/docs/YAMLSyntax.html),语法做到最小化,意在避免 playbooks 成为一种编程语言或是脚本,但它也并不是一个配置模型或过程的模型.
playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表.
在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible 模块的调用,这在前面章节学习过.
‘plays’ 好似音符,playbook 好似由 ‘plays’ 构成的曲谱,通过 playbook,可以编排步骤进行多机器的部署,比如在 webservers 组的所有机器上运行一定的步骤, 然后在 database server 组运行一些步骤,最后回到 webservers 组,再运行一些步骤,诸如此类.
“plays” 算是一个体育方面的类比,你可以通过多个 plays 告诉你的系统做不同的事情,不仅是定义一种特定的状态或模型.你可以在不同时间运行不同的 plays.
对初学者,这里有一个 playbook,其中仅包含一个 play:
1 |
|
(上述playbook在执行的时候出现一个warning:希望使用install而非latest)
在下面,我们将分别讲解 playbook 语言的多个特性.
plabook基础
主机与用户
你可以为 playbook 中的每一个 play,个别地选择操作的目标机器是哪些,以哪个用户身份去完成要执行的步骤(called tasks).
hosts 行的内容是一个或多个组或主机的 patterns,以逗号为分隔符,
remote_user就是账户名:
1 |
|
!!!note:参数 remote_user 以前写做 user,在 Ansible 1.4 以后才改为 remote_user.主要为了不跟 user 模块混淆(user 模块用于在远程系统上创建用户).
再者,在每一个 task 中,可以定义自己的远程用户:
1 |
|
!!!note:task 中的 remote_user 参数在 1.4 版本以后添加.
也支持从 sudo 执行命令:
1 |
|
同样的,你可以仅在一个 task 中,使用 sudo 执行命令,而不是在整个 play 中使用 sudo:
1 |
|
你也可以登陆后,sudo 到不同的用户身份,而不是使用 root:
1 |
|
如果你需要在使用 sudo 时指定密码,可在运行 ansible-playbook 命令时加上选项 --ask-sudo-pass (-K)
. 如果使用 sudo 时,playbook 疑似被挂起,可能是在 sudo prompt 处被卡住,这时可执行 Control-C 杀死卡住的任务,再重新运行一次.
1 | important: |
Tasks列表
每一个 play 包含了一个 task 列表(任务列表).一个 task 在其所对应的所有主机上(通过 host pattern 匹配的所有主机)执行完毕之后,下一个 task 才会执行.有一点需要明白的是(很重要),在一个 play 之中,所有 hosts 会获取相同的任务指令,这是 play 的一个目的所在,也就是将一组选出的 hosts 映射到 task.(注:此处翻译未必准确,暂时保留原文)
在运行 playbook 时(从上到下执行),如果一个 host 执行 task 失败,这个 host 将会从整个 playbook 的 rotation 中移除. 如果发生执行失败的情况,请修正 playbook 中的错误,然后重新执行即可.
每个 task 的目标在于执行一个 moudle, 通常是带有特定的参数来执行.在参数中可以使用变量(variables).
modules 具有”幂等”性,意思是如果你再一次地执行 moudle(译者注:比如遇到远端系统被意外改动,需要恢复原状),moudle 只会执行必要的改动,只会改变需要改变的地方.所以重复多次执行 playbook 也很安全.
对于 command module 和 shell module,重复执行 playbook,实际上是重复运行同样的命令.如果执行的命令类似于 ‘chmod’ 或者 ‘setsebool’ 这种命令,这没有任何问题.也可以使用一个叫做 ‘creates’ 的 flag 使得这两个 module 变得具有”幂等”特性 (不是必要的).
每一个 task 必须有一个名称 name,这样在运行 playbook 时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个 task 的. 如果没有定义 name,‘action’ 的值将会用作输出信息中标记特定的 task.
如果要声明一个 task,以前有一种格式: “action: module options” (可能在一些老的 playbooks 中还能见到).现在推荐使用更常见的格式:”module: options” ,本文档使用的就是这种格式.
下面是一种基本的 task 的定义,service moudle 使用 key=value 格式的参数,这也是大多数 module 使用的参数格式:
1 | tasks: |
比较特别的两个 modudle 是 command 和 shell ,它们不使用 key=value 格式的参数,而是这样:
1 | tasks: |
使用 command module 和 shell module 时,我们需要关心返回码信息,如果有一条命令,它的成功执行的返回码不是0, 你或许希望这样做:
1 | tasks: |
或者是这样:
1 | tasks: |
如果 action 行看起来太长,你可以使用 space(空格) 或者 indent(缩进) 隔开连续的一行:
1 | tasks: |
在 action 行中可以使用变量.假设在 ‘vars’ 那里定义了一个变量 ‘vhost’ ,可以这样使用它:
1 | tasks: |
这些变量在 tempates 中也是可用的,稍后会讲到.
在一个基础的 playbook 中,所有的 task 都是在一个 play 中列出,稍后将介绍一种更合理的安排 task 的方式:使用 ‘include:’
指令.
Acton shorthand
在 0.8 及以后的版本中,ansible 更喜欢使用如下的格式列出 modules:
1 | template: src=templates/foo.j2 dest=/etc/foo.conf |
在早期的版本中,使用以下的格式:
1 | action: template src=templates/foo.j2 dest=/etc/foo.conf |
早期的格式在新版本中仍然可用,并且没有计划将这种旧的格式弃用.
Handlers: 在发生改变时执行的操作
上面我们曾提到过,module 具有”幂等”性,所以当远端系统被人改动时,可以重放 playbooks 达到恢复的目的. playbooks 本身可以识别这种改动,并且有一个基本的 event system(事件系统),可以响应这种改动.
(当发生改动时)’notify’ actions 会在 playbook 的每一个 task 结束时被触发,而且即使有多个不同的 task 通知改动的发生, ‘notify’ actions 只会被触发一次.
举例来说,比如多个 resources 指出因为一个配置文件被改动,所以 apache 需要重新启动,但是重新启动的操作只会被执行一次.
这里有一个例子,当一个文件的内容被改动时,重启两个 services:
1 | - name: template configuration file |