Ansible playbook的使用

playbooks概念

task:

     任务:使用各模块所执行的特性操作任务,比如:-m user -a 'name= password='

Variables:

     变量:

Templates:

     模板

在定义模板后可以实现各节点对应的变量来取代,表达式自身会根据当前节点所赋值做运算,之后生成的值则赋予这个参数,用于生产不同配置的配置文件,所以模板主要实现配置不同场景文本文件

 

而且这种使用模板语言来定义

模板语言中可以根据定义替换成特定主机的某些值

 

handlers:

处理器:

如果某一次操作配置文件发生改变的话,远程和本地配置文件不一致,那么肯定是将其配置文件需要进行覆盖,这样需要在配置文件发送改变的话需要触动某些机制进行操作

      说白了就是事先可以在某些条件下,比如配置发生改变)被触发的操作

Rolse:

    角色:层次型组织playbooks以及其所依赖的各种资源的一种机制;其角色可以单独被调用

彼此之间的server服务器的配置肯定是完全不一样的,如果对于这些节点同时配置并提供同样的playbooks 是不可能的,所以将其每个server分成组

之间有些角色或者功能是相同的,那么比如web server 之间可能有同步时间等,某些服务是通用的,因此有了这些机制之后能够实现按需要将某个类特定服务器相同操作定义基础配置,将特定功能定义成一类操作


playbook
是基于YAML语言所定义的声明试配置文件

数据结构包括:

每个横线所表示引导一个列表中的一向,通过缩进所表示具有相同缩进的元素是同一个列表的元素

如下所示,定义playbook的结构化部分:

 

- name : deploy web server     #定义一个任务模块,跟上这个名称

  user : foouser               #使用user模块定义其使用的用户是foouer

  sodu : True                  #是否允许sudo权限

  hosts : all                  #对所有的主机模块生效

 

tasks:                     #将一个任务定义应用某一个具体操作

- name : install apache         #定义名称为install apache

  apt : pkg=apache2-mpm-prefork state=latest       #使用apt模块进行安装 状态为latest

 

首先来定义一个httpd服务,并让其能够开机自动启动服务

[root@testA test]# pwd

/opt/test

首先定义头部信息

- name: install httpd service

  user: root

  hosts: a

 

#再定义任务信息

tasks:

  - name: install                       #定义第一个任务名称并调用yum模块,与命令一致

    yum: name=httpd state=present

 

  - name: service on                    #定义第二个任务

    service: name=httpd enabled=yes state=started

 

执行

[root@testA test]# ansible-playbook web.yaml

 

PLAY [install httpd service] **************************************************

 

GATHERING FACTS ***************************************************************

ok: [192.168.101.243]

ok: [192.168.101.242]

 

TASK: [install] ***************************************************************

changed: [192.168.101.243]

changed: [192.168.101.242]

 

TASK: [service on] ************************************************************

changed: [192.168.101.243]

changed: [192.168.101.242]

 

PLAY RECAP ********************************************************************

192.168.101.242            : ok=3    changed=2    unreachable=0    failed=0  

192.168.101.243            : ok=3    changed=2    unreachable=0    failed=0  

ok = 3 有3个设定执行成功,分别是1.安装 2.修改服务启动状态 3.开启服务

以上为playbook的最简单的使用

 

 

YAML语法

YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用"-"来代表,Map里的键值对用":"分隔。下面是一个示例。

name: John Smith
age: 41
gender: Male
spouse:
    name: Jane Smith
    age: 37
    gender: Female
children:
    -   name: Jimmy Smith
        age: 17
        gender: Male
    -   name: Jenny Smith
        age 13
        gender: Female

 

YAML最关键的部分为列表 字段 和映射

列表的所有元素均使用“-”打头,例如:
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango

一定要做好缩进,通过空格进行排序,排列整齐的认为是同一级别的

 

Ansible基础元素

facts

在套用某个主机之前先获取其各种相关数据的一种机制

 

获取某个节点的变量信息:

[root@testA wangchao]# ansible 192.168.101.242 -m setup

直接返回了许多数据,这里所描述的功能表示基于setup所获取指定主机各种变量

 

在跟对方节点通信之前可以先将对方节点返回一些可用信息,而这些信息都是通过facts所获取的

而这些信息都是变量 都是可以被调用的,

有些变量很有用,比如:

        "ansible_os_family": "RedHat",
       "ansible_pkg_mgr": "yum", 

根据反馈的结果再来决定使用哪些组件来管理

 

可以通过这些东西来判断来应用哪些任务

获得对方的线程,无非是cpu个数x2,那么在变量中也有体现,如下所示:

        "ansible_processor_cores": 1, 

 

变量的种类

1.自定义变量

2.facts

3.主机/invertory变量  host variables

4.组变量,将多个主机定义为一个组,如下所示:

[a]

hostip

[a:vars]

ntp_server=ntp.xxx.com

 

组中可以嵌套一个组

[apache]

host_1

host_2

 

[nginx]

ngx1.xx.com

 

[webservers:children]

nginx

apache

 

[webserver:vars]

ntp_server=ntp.xxx.com

因此常见变量有以上4类

 

根据之前的反馈来判断任务是否执行成功

获取到某一指定的结果状态才会运行,比如:

tasks:

  -command: /bin/false

   register: result          

   ingnore_errors: True

第二种方式:

  - command:/bin/something

    when: result|failed          #可以根据此前执行结果做出执行

 

when中可以判断此前某个结果是否是所期望的,进而根据其做出判断的

 

迭代:

还可以实现遍历循环操作,如下所示:

在主机组a中,添加3个用户

- name: add user

  remote_user: root

  hosts: a

 

  tasks:

  - name: add serveral users

    user: name={{items}} state=present

    with_items:

    - test4

    - test5

    - test6

这里变量必须是以{{item}}进行标记,而调用变量必须是with_items:进行赋值

 

让各自执行安装,但是要使用yum安装,并且只有对方包管理器是yum

需要用到变量判断的功能

涉及到:when

首先需要使用setup获取对方变量,如果使用的匹配yum,那么再进行操作

[root@testA ~]# ansible 192.168.101.242 -m setup

涉及变量:

"ansible_pkg_mgr": "yum",

 

涉及参数:

  when: ansible_pkg_mgr == "yum"

当变量为yum的时候才执行操作

- name: install zsh

  remote_user: root

  hosts: a

  tasks:

  - name: install zsh

    yum: name=zsh state=present

    when: ansible_pkg_mgr == "yum"


执行:

[root@testA wangchao]# ansible-playbook zsh.yaml

PLAY [install zsh] ************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.101.243]     #
手机各个节点的facts信息
ok: [192.168.101.242]

TASK: [install zsh] *********************************************************** 

#开始执行任务

changed: [192.168.101.243]

changed: [192.168.101.242]

PLAY RECAP ******************************************************************** 

#返回的执行结果
192.168.101.242            : ok=2    changed=1    unreachable=0    failed=0  
192.168.101.243            : ok=2    changed=1    unreachable=0    failed=0   

 

补充:在使用with_items的时候还可以使用hashes

user:name={{item,name}} state=present groups=`item`.`group`

with_items:

  -{name:'test1',gourp: 'wheel'}

  -{name:'test2',gourp: 'root'}

 

通过以上的操作,简单来说就是由多个列表,其主要功能就是将事先归并的主机,先通过tasks定义好的角色

联合起来共同完成一个任务

 

关于状态码

如果命令或脚本的退出状态码不为0,那么可以使用一下方式代替

tasks:

  - name: run this xxx

    shell: /usr/bin/somecommand || /bin/true

#或:

    ignore_errors: True

 

playbook基础组建

handlers      触发操作

handlers用于当关注的资源发生变化时采取一定的操作

就是说只有触发的时候才会操作

 

使用notify这个action可以用于每个play的最后被触发,这样可以避免多次发生改变每次都执行指定的操作

所以可以指定每次什么时候出发handlers 

 

官方给出的例子:

- name: template config file

  template: src=template.j2 dest=/etc/foo.conf   #万一这个配置文件发生了改变,那么执行下面操作

  notify:

    - restart service                        #这里的restart是需要定义handlers的,所以要保持一致

    - restart service(httpd)

 

handlers:

    - name restart memcache

      service: name=memcache state=restarted

    - name: restart httpd

      service: name=httpd  state=restarted

以上意思为,如果src的配置文件发生了改变,那么则触发这个handlers定义的操作

 

接下来我们定义一个httpd的配置文件,当文件发生改变的时候,则推送这个配置文件到各个节点并重启httpd服务

[root@testA test]# mkdir httpd

[root@testA test]# cd httpd/

[root@testA httpd]# pwd

/opt/test/httpd

[root@testA httpd]# cp /etc/httpd/conf/httpd.conf .

[root@testA httpd]# ls

httpd.conf

 

为了演示效果将端口监听在8080端口

Listen 8080

 

效果如下:

[root@testA httpd]# cat httpd.yaml

- name: conf

  remote_user: root

  hosts: a

  tasks:

  - name: install httpd

    yum: name=httpd state=present

    when: ansible_pkg_mgr == "yum"

 

  - name: conf file

    copy: src=/opt/test/httpd/httpd.conf dest=/etc/httpd/conf/httpd.conf

    notify: restart httpd

 

  - name: start httpd

    service: name=httpd enabled=yes state=started

 

  handlers:

  - name: restart httpd

    service: name=httpd state=restarted

以上为从检测对端是否为yum包管理器 如果是yum则安装httpd 再cp配置文件到指定目录最后将服务加到开机启动项并启动,最后重启服务

但是以上有几个步骤重复了

 

改进:

如果第二次执行的时候就没有必要去重新yum安装

在playbook中 其中一个选项 -t

-t表示可以执行某些特定标签对应的tasks

接下来为每个步骤都添加一个标签,如下所示:

  - name: conf file

    copy: src=/opt/test/httpd/httpd.conf dest=/etc/httpd/conf/httpd.conf

    tags: conf

    notify: restart httpd

 

执行:

[root@testA httpd]# ansible-playbook httpd.yaml -t conf

 

PLAY [conf] *******************************************************************

 

GATHERING FACTS ***************************************************************

ok: [192.168.101.243]

ok: [192.168.101.242]

 

TASK: [conf file] *************************************************************

ok: [192.168.101.243]

ok: [192.168.101.242]

 

PLAY RECAP ********************************************************************

192.168.101.242            : ok=2    changed=0    unreachable=0    failed=0  

192.168.101.243            : ok=2    changed=0    unreachable=0    failed=0  

 

如果是多个任务,也可以同时使用一个tags

都在每个tasks 指定tags: conf 即可

 

通过目录结构的方式也将其一组资源再次切分

如下所示:

直接使用inculde进行调用其他的yaml文件

[root@testA httpd]# mkdir tasks

将以下部分保留

[root@testA httpd]# vim tasks/main.yaml

  - name: install httpd

    yum: name=httpd state=present

    when: ansible_pkg_mgr == "yum"

 

  - name: conf file

    copy: src=/opt/test/httpd/httpd.conf dest=/etc/httpd/conf/httpd.conf

    tags: conf

    notify: restart httpd       #用来调用handlers

 

  - name: start httpd

    service: name=httpd enabled=yes state=started

 

 

编辑httpd.yaml

[root@testA httpd]# cat httpd.yaml

- name: conf

  remote_user: root

  hosts: a

  tasks:

    include: tasks/main.yaml

 

定义handlers

[root@testA httpd]# mkdir handlers

[root@testA httpd]# cd handlers/

[root@testA handlers]# vim main.yaml

内容如下:

  - name: restart httpd

    service: name=httpd state=restarted

通过以上的定义,再修改主配置文件:

[root@testA httpd]# pwd

/opt/test/httpd

[root@testA httpd]# cat httpd.yaml

- name: conf

  remote_user: root

  hosts: a

  tasks:

    include: tasks/main.yaml

  handlers:

    include: handlers/main.yaml

执行操作并查看

 

如果没有问题则改一下httpd.conf配置文件并指定标签

[root@testA httpd]# ansible-playbook httpd.yaml -t conf

 

一个roles的案例如下所示:
          site.yml
          webservers.yml
          fooservers.yml
          roles/
             common/
               files/
               templates/
               tasks/
               handlers/
               vars/  
               meta/
             webservers/
               files/
               templates/
               tasks/
               handlers/
               vars/
               meta/

创建role的步骤

(1) 创建以roles命名的目录;
(2) 在roles目录中分别创建以各角色名称命名的目录,如webservers等;
(3) 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建;
(4) 在playbook文件中,调用各角色;

 

rolse

再定义一个目录rolse

[root@testA httpd]# mkdir roles

将目录的文件都挪到roles里

[root@testA httpd]# mv files/ handlers/ httpd.yaml tasks/ roles/web/

[root@testA httpd]# ls roles/
web

 

这里的roles 表示角色目录,而这个角色名就叫做web

而在这个角色当中,通常命名为site.yaml

[root@testA web]# mv httpd.yaml site.yaml

 

定义一个yaml 用于调用site.yaml

[root@testA httpd]# cat webserver.yaml

- name: web service

  remote_user: root

  hosts: a

  roles:

  - web