Ansible之Playbook

Playbook介绍

playbook参考文档

Playbookad-hoc相比,是一种完全不同的运用ansible的方式,类似与saltstackstate状态文件。ad-hoc无法持久使用,playbook可以持久使用。 playbook是由一个或多个play组成的列表,play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓的task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联合起来按事先编排的机制完成某一任务

Playbook核心元素

Playbook语法

playbook使用yaml语法格式,后缀可以是yaml,也可以是yml

一个简单的示例

 

 

Playbook的运行方式

通过ansible-playbook命令运行 格式:ansible-playbook <filename.yml> ... [options]

 

 

Playbook中元素属性

主机与用户

在一个playbook开始时,最先定义的是要操作的主机和用户

除了上面的定义外,还可以在某一个tasks中定义要执行该任务的远程用户

还可以定义使用sudo授权用户执行该任务

 

 

tasks任务列表

每一个task必须有一个名称name,这样在运行playbook时,从其输出的任务执行信息中可以很清楚的辨别是属于哪一个task的,如果没有定义 nameaction的值将会用作输出信息中标记特定的task 每一个playbook中可以包含一个或者多个tasks任务列表,每一个tasks完成具体的一件事,(任务模块)比如创建一个用户或者安装一个软件等,在hosts中定义的主机或者主机组都将会执行这个被定义的tasks

 

 

Handlers与Notify

很多时候当我们某一个配置发生改变,我们需要重启服务,(比如httpd配置文件文件发生改变了)这时候就可以用到handlersnotify了; (当发生改动时)notify actions会在playbook的每一个task结束时被触发,而且即使有多个不同task通知改动的发生,notify actions知会被触发一次;比如多个resources指出因为一个配置文件被改动,所以apache需要重启,但是重新启动的操作知会被执行一次。

 

 

Playbook中变量的使用

环境说明:这里配置了两个组,一个apache组和一个nginx组

 

 

命令行指定变量

执行playbook时候通过参数-e传入变量,这样传入的变量在整个playbook中都可以被调用,属于全局变量

 

 

hosts文件中定义变量

/etc/ansible/hosts文件中定义变量,可以针对每个主机定义不同的变量,也可以定义一个组的变量,然后直接在playbook中直接调用。注意,组中定义的变量没有单个主机中的优先级高。

 

 

playbook文件中定义变量

编写playbook时,直接在里面定义变量,然后直接引用,可以定义多个变量;注意:如果在执行playbook时,又通过-e参数指定变量的值,那么会以-e参数指定的为准。

 

 

调用setup模块获取变量

setup模块默认是获取主机信息的,有时候在playbook中需要用到,所以可以直接调用。常用的参数参考

 

 

独立的变量YAML文件中定义

为了方便管理将所有的变量统一放在一个独立的变量YAML文件中,laybook文件直接引用文件调用变量即可。

 

 

Playbook中标签的使用

一个playbook文件中,执行时如果想执行某一个任务,那么可以给每个任务集进行打标签,这样在执行的时候可以通过-t选择指定标签执行,还可以通过--skip-tags选择除了某个标签外全部执行等。

 

 

1)通过-t选项指定tags进行执行

 

 

2)通过--skip-tags选项排除不执行的tags

 

 

Playbook中模板的使用

template模板为我们提供了动态配置服务,使用jinja2语言,里面支持多种条件判断、循环、逻辑运算、比较操作等。其实说白了也就是一个文件,和之前配置文件使用copy一样,只是使用copy,不能根据服务器配置不一样进行不同动态的配置。这样就不利于管理。 说明: 1、多数情况下都将template文件放在和playbook文件同级的templates目录下(手动创建),这样playbook文件中可以直接引用,会自动去找这个文件。如果放在别的地方,也可以通过绝对路径去指定。 2、模板文件后缀名为.j2

循环参考

示例:通过template安装httpd

1)playbook文件编写

 

 

2)模板文件准备,httpd配置文件准备,这里配置文件端口使用了变量

3)查看目录结构

 

 

4)执行playbook,由于192.168.1.36那台机器是6的系统,模板文件里面的配置文件是7上面默认的httpd配置文件,httpd版本不一样(6默认版本为2.2.15,7默认版本为2.4.6),所以拷贝过去后启动报错。下面使用playbook中的判断语句进行处理;此处先略过

 

 

template之when

when语句参考

条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句执行,在task中使用jinja2的语法格式、 when语句: task后添加when子句即可使用条件测试;when语句支持jinja2表达式语法。

类似这样:

 

 

示例:通过when语句完善上面的httpd配置

1)准备两个配置文件,一个centos6系统httpd配置文件,一个centos7系统httpd配置文件。

 

 

2)修改playbook文件,通过setup模块获取系统版本去判断。setup常用模块

 

 

3)执行playbook

 

 

template之with_items

with_items迭代,当有需要重复性执行的任务时,可以使用迭代机制。 对迭代项的引用,固定变量名为“item”,要在task中使用with_items给定要迭代的元素列表。 列表格式:   字符串   字典

示例1:通过with_items安装多个不同软件

编写playbook

 

 

上面tasks写法等同于:

 

 

示例2:通过嵌套子变量创建用户并加入不同的组

1)编写playbook

 

 

2)执行playbook并验证

 

 

template之for if

通过使用forif可以更加灵活的生成配置文件等需求,还可以在里面根据各种条件进行判断,然后生成不同的配置文件、或者服务器配置相关等。

示例1

1)编写playbook

 

 

2)模板文件编写

 

 

3)执行playbook并查看生成结果

 

 

示例2

1)编写playbook

 

 

2)模板文件编写

 

 

3)执行playbook并查看生成结果

 

 

示例3

在for循环中再嵌套if判断,让生成的配置文件更加灵活

1)编写playbook

 

 

2)模板文件编写

 

 

3)执行playbook并查看生成结果

 

Ansible之Roles

Roles介绍

ansible1.2版本引入的新特性,用于层次性、结构化地组织playbookroles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令引入即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷的include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。主要使用场景代码复用度较高的情况下。

Roles目录结构

Roles目录结构

各目录含义解释

 

 

Roles示例

通过ansible roles安装配置httpd服务,此处的roles使用默认的路径/etc/ansible/roles

1)创建目录

 

 

2)变量文件准备vars/main.yml

3)配置文件模板准备templates/httpd.conf.j2

 

 

4)任务剧本编写,创建用户、创建组、安装软件、配置、启动等

 

 

5)编写重启httpd的handlershandlers/main.yml

6)编写主的httpd_roles.yml文件调用httpd角色

 

 

7)整体的一个目录结构查看

 

 

8)测试playbook语法是否正确

 

 

9)上面的测试没有问题,正式执行playbook

 

 

这里有看到报错,其原因是因为192.168.1.36这台机器是centos6系统,别的都是centos7系统,两个系统安装的httpd默认版本是不一样的,所以报错。如果需要优化。参考这里

ansible roles总结

1、编写任务(task)的时候,里面不需要写需要执行的主机,单纯的写某个任务是干什么的即可,装软件的就是装软件的,启动的就是启动的。单独做某一件事即可,最后通过main.yml将这些单独的任务安装执行顺序include进来即可,这样方便维护且一目了然。 2、定义变量时候直接安装k:v格式将变量写在vars/main.yml文件即可,然后task或者template直接调用即可,会自动去vars/main.yml文件里面去找。 3、定义handlers时候,直接在handlers/main.yml文件中写需要做什么事情即可,多可的话可以全部写在该文件里面,也可以像task那样分开来写,通过include引入一样的可以。在task调用notify时直接写与handlers名字对应即可(二者必须高度一直)。 4、模板文件一样放在templates目录下即可,task调用的时后直接写文件名字即可,会自动去到templates里面找。注意:如果是一个角色调用另外一个角色的单个task时后,那么task中如果有些模板或者文件,就得写绝对路径了。

 

ansible之template模块的用法

趁着最近在搞ansible,现在学习了一波template模块的用法:

1、目录结构

使用template模块在jinja2中引用变量,先来目录结构树

打开定义好的变量:

打开hosts文件查看节点信息:

现在通过定义好的变量在templates目录下创建j2文件:

查看tasks主任务定义:

查看工作目录下面的执行yaml:

在tasks目录下面的main.yaml定义使用了template模块,调用templates目录下面的test.j2文件

执行:

然后在两个节点查看:

可以看见在各个节点的tem目录下面的文件都用变量替换了

2、if控制

使用template模块调用的j2文件使用{% if %} {% endif %}进行控制:

在上面中使用if进行了判断,如果ansible_hostname变量与定义的master_hostname变量值相等,那么将此文件copy到节点上就使用条件1,而过不满足条件1那么执行条件2

ansible_hostname这个变量是setup模块中的值,是节点的固定值

现在查看tasks下面的文件:

将上面的test.j2改为了if条件的j2,然后执行:

查看各节点生成的文件内容:

可以看见生成的文件内容不一样,于是这样就可以将节点的不同内容进行分离开了

当然还可以使用另外的方式隔离节点的不同:

因为各个节点的ansible_hostname和ip都是固定的所以也可以根据上面进行区分不同(不过这种方式限制了一定的范围)

3、for循环

使用template模块调用j2文件使用for循环:

 创建jinja关于for的文件:

执行该角色:

验证两节点的文件内容:

4、default默认值

使用default()默认值

当我们定义了变量的值时,采用变量的值,当我们没有定义变量的值时,那么使用默认给定的值:

首先查看定义的变量:

然后查看jinja2的文件:

可以看见并没有定义server_port这个变量

查看tasks文件:

执行完成后,查看文件内容:

现在向vars/main.yaml中定义server_port变量,并给定值:

再次执行,然后查看文件内容:

可以看见使用了定义的值

控制playbook执行:策略等

设置并发数量 forks

如果您有可用的处理能力并希望使用更多并发,您可以在 中设置数量ansible.cfg:

或者在命令行上传递它:ansible-playbook -f 30 my_playbook.yml

使用关键字控制执行 除了策略之外,还有几个关键字也会影响游戏执行。您可以使用 设置一次要管理的主机数量、百分比或数量列表serial。在开始下一批主机之前,Ansible 在指定数量或百分比的主机上完成播放。您可以使用 限制分配给块或任务的工人数量throttle。您可以控制 Ansible 如何选择组中的下一个主机来执行order。您可以使用run_once. 这些关键字不是策略。它们是应用于游戏、块或任务的指令或选项。

设置批量大小 serial

默认情况下,Ansible 针对您在每次播放的字段中设置的模式中的所有主机并行运行hosts:。如果您只想一次管理几台机器,例如在滚动更新期间,您可以使用serial关键字定义 Ansible 一次应管理多少台主机:

在上面的例子中,如果我们在 'webservers' 组中有 6 台主机,Ansible 将在移动到接下来的 3 台主机之前在其中 3 台主机上完全执行播放(两个任务):

Note 使用 serial 设置批大小会将 Ansible 故障的范围更改为批大小,而不是整个主机列表。可以使用ignore_unreachable或max_fail_percentage来修改此行为。

您还可以使用serial关键字指定百分比。Ansible 将百分比应用于一次播放中的主机总数以确定每次传递的主机数:

如果主机数不等分为传递数,则最终传递包含余数。在此示例中,如果 webservers 组中有 20 台主机,则第一批将包含 6 个主机,第二批将包含 6 个主机,第三批将包含 6 个主机,最后一批将包含 2 个主机。

您还可以将批量大小指定为列表。例如:

在上面的示例中,第一批将包含单个主机,下一个将包含 5 个主机,并且(如果还有剩余的主机),接下来的每个批次将包含 10 个主机或所有剩余的主机,如果少于 10 个主机留下了。

您可以按百分比列出多个批次大小:

您还可以混合和匹配这些值:

Note 无论百分比有多小,每次通过的主机数将始终为 1 或更多。

限制执行 throttle

该throttle关键字限制了工人的特定任务的数量。它可以在块和任务级别进行设置。使用throttle限制,可能是CPU密集型或相互作用与限速API任务:

如果您已经限制了分叉的数量或并行执行的机器数量,您可以使用 减少工作线程的数量throttle,但不能增加它。换句话说,要产生效果,如果您将它们一起使用,您的throttle设置必须低于您的forks或serial设置。

基于 inventory 的订单执行

order 关键字控制主机的运行顺序。order 的可能值为:

inventory: (默认)inventory为所请求的选择提供的订单(请参阅下面的注释)

reverse_inventory: 与上面相同,但反转返回的列表

sorted: 按名称的字母顺序排序

reverse_sorted: 按名称反向字母顺序排序

shuffle: 每次运行随机排序

Note “inventory”顺序不等于在清单源文件中定义主机/组的顺序,而是“从编译的清单返回选择的顺序”。这是一个向后兼容的选项,虽然可重现,但通常不可预测。由于库存的性质、主机模式、限制、库存插件以及允许多个来源的能力,几乎不可能返回这样的订单。对于简单情况,这可能恰好与文件定义顺序匹配,但不能保证。