Ansible的脚本---playbook剧本

通过task调用ansible的模板将多个play组织在一个playbook中运行。

playbooks本身由以下各部分组成

(1)Tasks:任务,即调用模块完成的某操作;

(2)Variables:变量

(3)Templates:模板

(4)Handlers:处理器,当某条件满足时,触发执行的操作;

(5)Roles:角色。

下面是一个playbook的示例

- hosts: webserver              //定义的主机组,即应用的主机

  vars:                        //定义变量

    http_port: 80

    max_clients: 200

  user: root

  tasks:                               //执行的任务

  - name: ensure apache is at the latest version

    yum: pkg=httpd state=latest

  - name: write the apache config file

    template: src=/srv/httpd.j2 dest=/etc/httpd.conf

    notify:

    - restart apache

  - name: ensure apache is running

    service: name=httpd state=started

  handlers:                       //处理器

    - name: restart apache

      service: name=httpd state=restarted

执行一个playbook

ansible-playbook [yaml文件名]

例如:ansible-playbook ping.yml

参数:-k(–ask-pass) 用来交互输入ssh密码

        -K(-ask-become-pass) 用来交互输入sudo密码

        -u   指定用户

补充命令:

ansible-playbook nginx.yaml --syntax-check    #检查yaml文件的语法是否正确

ansible-playbook nginx.yaml --list-task       #检查tasks任务

ansible-playbook nginx.yaml --list-hosts      #检查生效的主机

ansible-playbook nginx.yaml --start-at-task='Copy Nginx.conf'     #指定从某个task开始运行

hosts和users介绍

Playbook的设计目的是为了让某个或某些主机以某个用户的身份去执行相应的任务。其中用于指定要执行指定任务的主机用hosts定义,可以是一个主机也可以是由冒号分割的多个主机组;用于指定被管理主机上执行任务的用户用remote_user来定义

---

- hosts: webserver               #指定主机组,可以是一个或多个组。

  remote_user: root                #指定远程主机执行的用户名

还可以为每个任务定义远程执行用户:

---

- hosts: mysql

  remote_user: root             

  tasks:

    - name: test connection

      ping:

      remote_user: mysql          #指定远程主机执行tasks的运行用户为mysql

执行playbook时:ansible-playbook ping.yml -k

remote_user也可以定义指定用户通过sudo的方法在被管理主机上运行指令

指定远程主机sudo切换用户:

---

- hosts: mysql

  remote_user: root            

  become: yes                #2.6版本以后的参数,之前是sudo,意思为切换用户运行

  become_user: mysql          #指定sudo用户为mysql

执行playbook时:ansible-playbook ping.yml -K

tasks列表和action介绍

1.Play的主体部分是task列表,task列表中的各任务按次序逐个在hosts中指定的主机上执行,即在所有主机上完成第一个任务后再开始第二个任务。

在运行playbook时(从上到下执行),如果一个host执行task失败,整个tasks都会回滚,请修正playbook 中的错误,然后重新执行即可。

Task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量,模块执行时幂等的,这意味着多次执行是安全的,因为其结果一致。

2.每一个task必须有一个名称name,这样在运行playbook时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个task的。如果没有定义name,‘action’的值将会用作输出信息中标记特定的task。

3.定义一个task,常见的格式:”module: options” 例如:yum: name=httpd

4.ansible的自带模块中,command模块和shell模块无需使用key=value格式

小示例:

---

- hosts: webserver

  remote_user: root

  tasks:

   - name: disable selinux

     command: '/sbin/setenforce 0'

   - name: make sure apache is running

     service: name=httpd state=started

Ansible之playbook(剧本)介绍与案例分析_自动化运维Ansible之playbook(剧本)介绍与案例分析_ansible_02

play中只要执行命令的返回值不为0,就会报错,tasks停止

:q

可以使用ignore_errors: True 来忽略错误信息,继续执行task

修改如下

---

- hosts: webserver

  remote_user: root

  tasks:

   - name: command

     command: '/sbin/command'

     ignore_errors: True             #忽略错误,强制返回成功

   - name: make sure apache is running

     service: name=httpd state=started

Ansible之playbook(剧本)介绍与案例分析_自动化运维_03

Ansible之playbook(剧本)介绍与案例分析_playbook_04

以下是另外一个示例,

表示可以在一个playbook文件中针对不同的主机同时设置各自的tasks

---

- hosts: webserver

  remote_user: root

  tasks:

   - name: create nginx group

     group: name=nginx system=yes gid=208

   - name: create nginx user

     user: name=nginx uid=208 group=nginx system=yes

- hosts: mysql

  remote_user: root

  tasks:

   - name: copy file to mysql

     copy: src=/etc/inittab dest=/opt/inittab.back

Ansible之playbook(剧本)介绍与案例分析_剧本_05Ansible之playbook(剧本)介绍与案例分析_playbook_06Ansible之playbook(剧本)介绍与案例分析_剧本_07

Handlers介绍

Handlers用于当关注的资源发生变化时所采取的操作。在notify中列出的操作便称为handler,也就是在notify中需要调用handler中定义的操作。而notify这个动作在每个play的最后被触发,仅在所有的变化发生完成后一次性的执行指定操作。

Handlers也是一些task的列表,和一般的task并没有什么区别。

是由通知者进行的notify,如果没有被notify,则Handlers不会执行,假如被notify了,则Handlers被执行

不管有多少个通知者进行了notify,等到play中的所有task执行完成之后,handlers也只会被执行一次

示例

---

- hosts: webserver

  remote_user: root

  tasks:

   - name: install httpd package

     yum: name=httpd state=latest

   - name: install configuration file for httpd

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

     notify:                         //引用下面handlers的操作

      -restart httpd

   - name: start httpd service

     service: enabled=true name=httpd state=started

  handlers:          //定义操作,如果被notify,则执行定义的操作,否则不执行

   - name: restart httpd

     service: name=httpd state=restarted

也可以引入变量

变量的介绍

在Ansible中变量名仅能由字母,数字和下划线组成,并且只能以字母开头。

使用参数vars:    定义变量

变量引用格式:{{变量名}}  

---

- hosts: webserver

  remote_user: root

  vars:            //定义变量

  - package: httpd

  - service: httpd

  tasks:

   - name: install httpd package

     yum: name={{package}} state=latest         //引用第一个变量

   - name: install configuration file for httpd

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

     notify:

      -restart httpd

   - name: start httpd service

     service: enabled=true name={{service}} state=started        //引用第二个变量

  handlers:

   - name: restart httpd

     service: name={{service}} state=restarted                //引用第二个变量

playbook使用变量的方法:

1.通过ansible命令传递

例如:编辑如下yaml

vi a.yml

---

- hosts: mysql

  remote_user: root

  vars:

  - user: 

  tasks:

  - name: add new user

    user: name={{user}}

然后执行命令: ansible-playbook a.yml -e "user=testvar"

可以执行命令查看:ansible mysql  -a 'id testvar'

Ansible之playbook(剧本)介绍与案例分析_playbook_08Ansible之playbook(剧本)介绍与案例分析_playbook_09

2.直接在yaml中定义变量---如上handlers示例

3.直接引用一些变量

如:引用ansible的固定变量

ansible_all_ipv4_addresses:此变量是查看主机网卡ipv4地址的固定变量

vi test.yml

---

- hosts: mysql

  remote_user: root

  tasks:

   - name: copy file

     copy: content="{{ansible_all_ipv4_addresses}}," dest=/opt/vars.txt

执行命令:ansible-playbook test.yml

查看mysql主机上vars.txt文件内容

Ansible之playbook(剧本)介绍与案例分析_自动化运维_10Ansible之playbook(剧本)介绍与案例分析_自动化运维_11

再如:引用主机变量

vi /etc/ansible/hosts

在mysql组的主机后面添加如下

[mysql]

192.168.195.163 testvar="195.163"          #定义testvar变量的值为195.163

vi test.yml      #添加{{testvar}}主机变量

---

- hosts: mysql

  remote_user: root

  tasks:

   - name: copy file

     copy: content="{{ansible_all_ipv4_addresses}},{{testvar}}" dest=/opt/vars.txt

执行命令:ansible-playbook test.yml

查看mysql主机上vars.txt文件内容

Ansible之playbook(剧本)介绍与案例分析_剧本_12Ansible之playbook(剧本)介绍与案例分析_ansible_13Ansible之playbook(剧本)介绍与案例分析_自动化运维_14Ansible之playbook(剧本)介绍与案例分析_ansible_15

--------条件测试--------

如果需要根据变量、facts(setup)或此前任务的执行结果来作为某task执行与否的前提时要用到条件测试,在Playbook中条件测试使用when子句。

在task后添加when子句即可使用条件测试:when子句支持jinjia2表达式或语法,例如:

vi b.yml

---

- hosts: webserver

  remote_user: root

  tasks:

    - name: reboot CentOS

      command:  '/usr/sbin/init 6'

      when: ansible_distribution == "CentOS"

Ansible之playbook(剧本)介绍与案例分析_playbook_16

Ansible之playbook(剧本)介绍与案例分析_ansible_17

多条件判断

vi b.yml

---

- hosts: webserver

  remote_user: root

  tasks:

    - name: reboot CentOS

      command:  '/usr/sbin/init 6'

      when:

        - ansible_distribution == "CentOS"

        - ansible_distribution_major_version == "7"

Ansible之playbook(剧本)介绍与案例分析_playbook_18

组条件判断

vi when.yml

---

- hosts: mysql

  remote_user: root

  tasks:

    - name: "shut down CentOS 6 and Debian 7 systems"

      command: /sbin/shutdown -t now

      when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6") or

            (ansible_distribution == "Debian" and ansible_distribution_major_version == "7")

自定义变量进行条件测试

vi when.yml

---

- hosts: all

  vars:

    exist: "True"

  tasks:

  - name: creaet file

    command:  touch /tmp/test.txt

    when: exist | match("True")

  - name: delete file

    command:  rm -rf /tmp/test.txt

    when: exist | match("False")

Ansible之playbook(剧本)介绍与案例分析_自动化运维_19Ansible之playbook(剧本)介绍与案例分析_自动化运维_20Ansible之playbook(剧本)介绍与案例分析_自动化运维_21

将变量exist的值改为“False”,再执行一遍playbook,结果如何?

Ansible之playbook(剧本)介绍与案例分析_自动化运维_22Ansible之playbook(剧本)介绍与案例分析_自动化运维_23Ansible之playbook(剧本)介绍与案例分析_playbook_24

----------迭代-------------

当有需要重复性执行的任务时,可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句指明迭代的元素列表即可。例如:

---

- hosts: webserver

  remote_user: root

  tasks:

    - name: "Install Packages"

      yum: name={{ item }} state=latest

      with_items:

        - httpd

        - mysql-server

        - php

Ansible之playbook(剧本)介绍与案例分析_ansible_25

也可以自己定义

---

- hosts: webserver

  remote_user: root

  tasks:

    - name: "Add users"

      user: name={{ item.name }} state=present groups={{ item.groups }}

      with_items:

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

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

Ansible之playbook(剧本)介绍与案例分析_playbook_26Ansible之playbook(剧本)介绍与案例分析_自动化运维_27Ansible之playbook(剧本)介绍与案例分析_ansible_28


Templates模块

Jinja是基于Python的模板引擎。template类是Jinja的另一个重要组件,可以看作一个编译过的模块文件,用来生产目标文本,传递Python的变量给模板去替换模板中的标记。

在ansible管理端上yum安装httpd服务并复制httpd配置文件作为模板进行修改配置

yum -y install httpd

cp  /etc/httpd/conf/httpd.conf ./

vi httpd.conf                            //放在管理端

Listen {{http_port}}

ServerName {{server_name}}

MaxClients {{access_num}}

mv httpd.conf httpd.conf.j2

Ansible之playbook(剧本)介绍与案例分析_playbook_29Ansible之playbook(剧本)介绍与案例分析_剧本_30

vi /etc/ansible/hosts

[webserver]

192.168.195.162 http_port=192.168.195.162:80 access_num=100 server_name="www.yun.com:80"

Ansible之playbook(剧本)介绍与案例分析_剧本_31

vi apache.yml

---

- hosts: webserver

  remote_user: root

  vars:

    - package: httpd

    - service: httpd

  tasks:

    - name: install httpd package

      yum: name={{package}} state=latest

    - name: install configure file

      template: src=/opt/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf

      notify:

        - restart httpd

    - name: start httpd server

      service: name={{service}} enabled=true state=started

  handlers:

    - name: restart httpd

      service: name={{service}} state=restarted

//注意格式对齐

ansible-playbook apache.yml    #执行脚本

Ansible之playbook(剧本)介绍与案例分析_ansible_32

Ansible之playbook(剧本)介绍与案例分析_剧本_33

安装好httpd后,直接通过浏览器进行访问apache网页,可以看到默认首页

Ansible之playbook(剧本)介绍与案例分析_自动化运维_34

去远程主机上查看,配置文件修改内容

grep -i listen /etc/httpd/conf/httpd.conf

grep -i maxClient /etc/httpd/conf/httpd.conf

grep -i servername /etc/httpd/conf/httpd.conf

Ansible之playbook(剧本)介绍与案例分析_自动化运维_35

tags模块

在一个playbook中,我们一般会定义很多个task,如果我们只想执行其中的某一个task或多个task时就可以使用tags标签功能了,格式如下:

vi hosts.yml

---

- hosts: webserver

  remote_user: root

  tasks:

    - name: Copy hosts file

      copy: src=/etc/hosts dest=/opt/hosts

      tags:

      - only

    - name: touch file

      file: path=/opt/hosts-1 state=touch

执行命令:ansible-playbook hosts.yml --tags="only"

查看被管理服务器上的文件创建情况

Ansible之playbook(剧本)介绍与案例分析_playbook_36Ansible之playbook(剧本)介绍与案例分析_ansible_37Ansible之playbook(剧本)介绍与案例分析_ansible_38

事实上,不光可以为单个或多个task指定同一个tags。playbook还提供了一个特殊的tags为always。作用就是当使用always当tags的task时,无论执行哪一个tags时,定义有always的tags都会执行。

vi hosts.yml

---

- hosts: webserver

  remote_user: root

  tasks:

    - name: Copy hosts file

      copy: src=/etc/hosts dest=/opt/hosts-2

      tags:

      - only

    - name: touch file

      file: path=/opt/hosts-3 state=touch

  tags:

  - always

执行命令:ansible-playbook hosts.yml --tags="only"

查看被管理服务器上的文件创建情况

Ansible之playbook(剧本)介绍与案例分析_剧本_39Ansible之playbook(剧本)介绍与案例分析_ansible_40