主机规划
主机名称 | 操作系统版本 | 内网IP | 外网IP(模拟) | 安装软件 |
---|---|---|---|---|
ansi-manager | CentOS7.5 | 172.16.1.180 | 10.0.0.180 | ansible |
ansi-haproxy01 | CentOS7.5 | 172.16.1.181 | 10.0.0.181 | |
ansi-haproxy02 | CentOS7.5 | 172.16.1.182 | 10.0.0.182 | |
ansi-web01 | CentOS7.5 | 172.16.1.183 | 10.0.0.183 | |
ansi-web02 | CentOS7.5 | 172.16.1.184 | 10.0.0.184 | |
ansi-web03 | CentOS7.5 | 172.16.1.185 | 10.0.0.185 |
添加用户账号
说明:
1、 运维人员使用的登录账号;
2、 所有的业务都放在 /app/ 下「yun用户的家目录」,避免业务数据乱放;
3、 该用户也被 ansible 使用,因为几乎所有的生产环境都是禁止 root 远程登录的(因此该 yun 用户也进行了 sudo 提权)。
1 | # 使用一个专门的用户,避免直接使用root用户 |
Ansible 配置清单Inventory
之后文章都是如下主机配置清单
1 | [yun@ansi-manager ansible_info]$ pwd |
条件判断-when
when 判断在 ansible 任务中的使用频率非常高。
例如判断主机是否已经安装指定的软件包;对机器的操作系统进行判断然后再根据不同的方法「yum或apt等」进行软件包安装;根据操作系统的版本判断进行软件包的安装「是安装MySQL还是Mariadb」等。
示例:根据主机名的不同,下载不同的文件
1 | [yun@ansi-manager object04]$ pwd |
标准循环
注意:
1、循环语法有两种:loop 和 with_
2、loop 是在ansible 2.5 添加的,with_
简单列表循环
如果我们需要在 playbook 中启动多个服务,或者下载多个文件;按照之前所学的,那么我们需要写多个 task。但这样会使得 playbook 变得臃肿,因此这时我们就需要引进循环了。
示例:一次启动多个服务,下载多个文件
使用 loop 方式【推荐】
1 | [yun@ansi-manager object04]$ pwd |
备注:以上方法可用在 yum 模块中。
使用 with_items 方式
其中 playbook 文件中仅把 loop 变为了 with_items。
1 | [yun@ansi-manager object04]$ pwd |
如果用在 yum 模块中则会报如下弃用告警,因此该方法不适用于 yum 模块。
遍历哈希列表
如果我们需要创建多个用户并且每个用户都有指定的附加组;或者要创建多个文件,每个文件属主、属组、权限不一样;或者需要拷贝文件,但是每个文件的位置不一样,且属主、属组、权限不一样等等;那之前所学的简单循环就不能满足我们的需求了。这时「哈希列表循环」就闪亮登场了。
示例:
使用 loop 方式【推荐】
1 | [yun@ansi-manager object04]$ pwd |
使用 with_items 方式
其中 playbook 文件中仅把 loop 变为了 with_items。
1 | [yun@ansi-manager object04]$ pwd |
遍历字典
示例:
使用 loop 方式【推荐】
1 | [yun@ansi-manager object04]$ pwd |
使用 with_items 方式
1 | [yun@ansi-manager object04]$ pwd |
变量循环-vars
针对yum 安装多个包很有用,其他则会报出警告。
1 | [yun@ansi-manager object04]$ pwd |
该方法不一定适用于其他模块
触发器-handlers
当我们修改了服务的配置文件时,这时我们需要去重启服务,那么 handlers 就可以派上用场了。
注意事项:
1、无论多少个 task 通知了相同的 handlers,handlers 仅会在所有 tasks 结束后运行一次。
2、只有 task 发生改变了才会通知 handlers,没有改变则不会通知和触发 handlers。
3、不能用 handlers 替代 task 。
1 | [yun@ansi-manager object05]$ pwd |
任务标签-tags
默认情况下,当我们执行一个 playbook 时,会执行该 playbook 中所有的任务。如果只想执行一个 task 或者部分 task 用于调试或者需求就是执行部分 task。那么可以使用 ansible 的标签(tags)功能给单独 task 或者全部 task 打上标签。之后利用这些标签来指定要运行哪些 playbook 任务,或不运行哪些 playbook 任务。
打标签方式
对一个 task 打一个标签;
对一个 task 打多个标签;
对多个 task 打一个标签
标签如何运用
-t TAGS, --tags=TAGS:执行指定的 tag 标签任务;多个标签使用逗号分开
--skip-tags=SKIP_TAGS:跳过指定标签不执行,执行指定外的 task「标签作用于 task 上,即使该task还有其他标签,这个 task 也不会被执行」;多个标签使用逗号分开
1 | [yun@ansi-manager object05]$ pwd |
playbook 标签查看
1 | [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key --syntax-check test_tags.yml # 语法检测 |
playbook 执行
1 | ## 单个标签执行 |
文件引用/复用-include与import
在实际应用中,是不可能将所有 task 写在一个 playbook 中的,需要进行拆分,方便后期重复使用。这样后面写其他 playbook 的时候,如果有重复的,那么直接引用之前写的即可。
Includes 与 Imports
1、include 和 import 虽然功能相近,但是 ansible 执行引擎对他们的处理却截然不同。
2、所有 import* 语句都会在解析 playbook 时进行预处理。「提前准备好工具」
3、所有 include* 语句都是在执行 playbook 时遇到再处理。「需要什么工具,再拿什么工具」
PS:include 模块:这个模块还将支持一段时间,但在不久的将来可能会弃用「最好不要使用这个模块」。
示例
1 | [yun@ansi-manager object05]$ pwd |
忽略错误-ignore_errors
在 playbook 执行过程中,默认情况下如果有错误发生,那么后面的 task 就不执行,并且退出当前的 playbook。
如果我们对某些 task 执行结果不关心,不管执行是否成功,后面的 task 也要继续执行。那就需要通过 ignore_errors 来忽略当前 task 的错误结果,让后面的 task 继续往下执行。
1 | [yun@ansi-manager object05]$ pwd |
默认情况
使用了 ignore_errors 的情况
自定义错误判定条件-failed_when
命令不依赖返回状态码来判定是否执行失败,而是要查看命令返回内容来决定,比如返回内容中包括 command not found 字符串,则判定为失败。
1 | [yun@ansi-manager object05]$ pwd |
强制调用触发器-force_handlers
通常情况下,当 task 执行失败后,playbook 会终止。任何在此之前已经被 task notify 的 handlers 都不会被执行。
此时,如果你在 playbook 中设置了 force_handlers: yes 参数,则被通知的 handlers 就会被强制执行(有些特殊场景可能会使用到)。
如示例,在一个 playbook 中,如果配置文件的 task 已经被执行成功,并且 notify 了 handlers,之后必须重启服务。那么我们会强制要求:即使后续的 task 执行失败,之前被通知的 handlers 也必须执行。
如果不强制执行就变成了,第一次执行时:配置文件修改成功,但由于之后有 task 执行失败,导致 playbook 终止,后续 handlers 没有被调用,对应服务没有重启;第二次执行时:配置文件没发生改变「因此第一次已经更新了配置文件」,因此不会通知 handlers。最终结果就是配置改变了,但是就是没有重启服务。显然不符合我们的初衷。
1 | [yun@ansi-manager object05]$ pwd |
抑制changed状态-changed_when
ansible 会自动判断模块执行状态,command、shell 及其它模块如果修改了远程主机状态则被判定为 changed 状态,不过也可以自己决定达到 changed 状态的条件。
当我们在 playbook 中使用 shell 或者 command 模块时,每次 task 执行状态都是 changed。原因是因为每次我们都去执行获取当前数据,而不是一个固化的状态。
但在实际应用中,我们可能不需要 shell 或者 command 模块执行后的 changed 状态,这时我们就需要通过 changed_when: false 来抑制这个改变。
当然上述的 changed_when: false 可以在任何模块中使用,不局限于 shell 和 command 模块,只是我们常用于这两个模块而已。
1 | [yun@ansi-manager object05]$ pwd |