ansible核心工具:playbook剧本

playbook剧本

playbook概述

ansbile-playbook是一系统ansible命令的集合,其利用yaml 语言编写,运行过程,ansbile-playbook命令根据自上而下的顺序依次执行。
同时,playbook开创了很多特性,它可以允许你传输某个命令的状态到后面的指令,如你可以从一台机器的文件中抓取内容并附为变量,然后在另一台机器中使用,这使得你可以实现一些复杂的部署机制,这是ansible命令无法实现的。

playbook的核心组件

用场景化的方式对比,来记忆核心组件

剧本 playbook
场地 主机组:hosts
演员 授权执行的用户:remote_user
故事情节 执行的任务:tasks(调用的是各种ansible模块)

playbook的语言:YAML

yaml概述

YAML:是一种非标记语言。是用来写配置文件的语言,非常简洁和强大。YAML语法和其他语言类似,也可以表达散列表、标量等数据结构。
结构通过空格来展示;
序列里配置项通过-来代表;
Map里键值用:来分隔;
YAML的扩展名为yaml。

基本语法规则

1.大小写敏感
2.使用缩进表示层级关系
3.缩进时不允许使用Tab键,只允许使用空格。
4.缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

playbook的组成

通过task调用ansible的模板将多个play组织在一个playbook中运行。playbooks本身由以下各部分组成

(1) Tasks:任务,即调用模块完成的某操作;
(2) Variables:变量
(3) Templates:模板
(4) Handlers:处理器,当某条件满足时,触发执行的操作;
(5) Roles:角色。

play示例

一、看一个综合脚本(认知)

vim play.yaml                                        #写一个脚本

- hosts: webserver                                   #hosts定义应用的主机对象
  vars:                                              #vars定义变量
    http_port: 80
    max_client: 200
  users: root                                        #users定义用户
  tasks:                                             #tasks定义执行的任务
  - name: ensure apache is at the latest version     #任务名1
    yum: pkg=httpd state=latest                      #调用yum模块
  - name: write the apache config file               #任务名2
    template: src=/srv/http.j2 dest=/etc/httpd.conf  #使用template模板
    notify:                                          #调用notify:为handlers服务
    - restart apache                                 #定义notify的任务名
  - name: ensure apache is running                   #任务名3
    service: name=httpd state=started                #调用service模块
  handlers:                                          #handlers:任务2的条件满足,则触发执行
    - name: restart apache                           #匹配notify的任务名
      service: name=httpd state=restarted            #调用service模块

ansible-play play.yaml --syntax-check                #检查语法
ansible-play play.yaml --list-task                   #检查task任务
ansible-play play.yaml --list-hosts                  #检查生效的主机
ansible-play play-yaml --start-at-task='ensure is runnning' #从某个任务开始执行

二、写一个简单脚本(上手)

新手易错点:

‘-’ 不加
‘-’和‘:’后的空格不加
格式一定要对齐,不能随便缩进,缩进表示层级关系
tab键不要用,不识别
[root@master ~]# vim web.yaml                              #写一个脚本

- hosts: webserver
  remote_user: root
  tasks:
   - name: firewalld                                        #关防火墙
     service: name=firewalld state=stopped
   - name: httpd                                            #安装apache
     yum: name=httpd
   - name: start                                            #开启apache
     service: name=httpd state=started
   - name: html                                             #写一个网页内容
     copy: content="hello" dest=/var/www/html/index.html

[root@master ~]# ansible-playbook web.yaml --syntax-check   #检查语法

playbook: web.yaml
[root@master ~]# ansible-playbook web.yaml                  #执行剧本

PLAY [webserver] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [20.0.0.12]

TASK [firewalld] ***************************************************************
changed: [20.0.0.12]

TASK [httpd] *******************************************************************
changed: [20.0.0.12]

TASK [start] *******************************************************************
changed: [20.0.0.12]

TASK [text] ********************************************************************
changed: [20.0.0.12]

PLAY RECAP *********************************************************************
20.0.0.12                  : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

三、在简单脚本上进行一系列操作(深化学习)

1、模拟某个服务名写错

[root@master ~]# vim web.yaml                              #修改脚本内容
#将脚本中任务中的服务“firewalld”改成“firewall”

[root@master ~]# ansible-playbook web.yaml --syntax-check

playbook: web.yaml                                         #语法检查未出错
[root@master ~]# ansible-playbook web.yaml 

PLAY [webserver] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [20.0.0.12]

TASK [firewalld] *************************************************************** 
fatal: [20.0.0.12]: FAILED! => {"changed": false, "msg": "Could not find the requested service firewall: host"}                
                                                          #检测出问题,下面任务也无法执行
PLAY RECAP *********************************************************************
20.0.0.12                  : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

2、跳过写错的任务

[root@master ~]# vim web.yaml                             #修改脚本内容
#在出错的任务下加上忽略错误语句:ignore_errors: true
- hosts: webserver
  user: root
  tasks:
   - name: firewalld
     service: name=firewall state=stopped                  #此为出错的任务
     ignore_errors: true                                   #忽略错误
   - name: httpd
     yum: name=httpd
   - name: start
     service: name=httpd state=started
   - name: text
     copy: content="hello" dest=/var/www/html/index.html
     
[root@master ~]# ansible-playbook web.yaml --syntax-check   #检查语法

playbook: web.yaml
                                       
[root@master ~]# ansible-playbook web.yaml 

PLAY [webserver] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [20.0.0.12]

TASK [firewalld] ***************************************************************
fatal: [20.0.0.12]: FAILED! => {"changed": false, "msg": "Could not find the requested service firewall: host"}
...ignoring                                                 #检测出问题,执行忽略!下面的任务照常执行

TASK [httpd] *******************************************************************
ok: [20.0.0.12]

TASK [start] *******************************************************************
ok: [20.0.0.12]

TASK [text] ********************************************************************
ok: [20.0.0.12]

PLAY RECAP *********************************************************************
20.0.0.12                  : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1   

3、引入变量(三种方式)
(1)方式一:剧本里写入变量(用var定义,用双括号调用)

[root@master ~]# vim a.yaml                  #新写一个脚本

- hosts: mysql
  remote_user: root
  vars:                            
    - aaa: nike                               #定义变量:aaa
  tasks:
    - name: create user
      user: name={{aaa}}                      #使用变量:{{  }}
                     
[root@master ~]# ansible-playbook a.yaml --syntax-check

playbook: a.yaml

[root@master ~]# ansible-playbook a.yaml      #执行剧本

PLAY [mysql] *******************************************************************

TASK [Gathering Facts] *********************************************************
ok: [20.0.0.13]

TASK [create user] *************************************************************
changed: [20.0.0.13]

PLAY RECAP *********************************************************************
20.0.0.13                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


#来到mysql的主机上验证:
[root@node2 ~]# id nike                       #看下nike是否被创建
uid=1002(nike) gid=1002(nike) 组=1002(nike)

(2)方式二:hosts里配置

[root@master ~]# vi /etc/ansible/hosts
.......

[webserver]
20.0.0.12
[mysql]                                       #找到需要操作的主机
20.0.0.13   aaa=nike                          #在ip地址后加入变量

(3)方式三:命令里指定(用“-e”)

[root@master ~]# ansible-playbook a.yaml -e aaa="nike"

(4)ansible的固定变量可以直接用“{{ }}”引用,不需要定义。

[root@master ~]# vim a.yaml                        #修改脚本内容

- hosts: mysql
  remote_user: root
  tasks:
    - name: create file                            #未使用vars定义变量,直接使用{{ }}调用固定变量
      copy: content={{ansible_all_ipv4_address}} dest=/opt/b.txt
[root@master ~]# ansible-playbook a.yaml     

#去到mysql节点验证:
[root@node2 opt]# ls                               #有了创建的b.txt
111.txt  b.txt  inittab.bak  rh
[root@node2 opt]# cat b.txt
["192.168.122.1", "20.0.0.13"]

四、添加条件判断(when)

单条件判断
多条件判断
组条件判断:when (“条件1”)or("条件2")
自定义条件判断:先定义变量,在when里面引用变量

多条件判断案例:

[root@master ~]# vim c.yml

- hosts: mysql
  remote_user: root
  tasks:
  - name: "guanji"
    command: /sbin/shutdown -r now                               #满足“when”条件成立,则执行重启
    when:
      - ansible_distribution == "CentOS"                         #条件1:是centos系统
      - ansible_distribution_major_version == "7"                #条件2:版本是7

[root@master ~]# ansible-playbook c.yml 

PLAY [mysql] *******************************************************************

TASK [Gathering Facts] *********************************************************
ok: [20.0.0.13]

TASK [guanji] ******************************************************************
fatal: [20.0.0.13]: FAILED! => {"msg": "Failed to connect to the host via ssh: ssh: connect to host 20.0.0.13 port 22: Connection refused"}                                                          
                                    #此处出现报错的问题是因为节点重启无法连接,不影响剧本正常操作
PLAY RECAP *********************************************************************
20.0.0.13                  : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

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

例子1:

- hosts: mysql
  remote_user: root
  tasks:
  - name: "install packages"
    yum: name={{ item }} state=latest
    with_items:                 #依次安装以下三个服务
      - httpd                
      - mysql
      - php
      
例子2:

- hosts: mysql
  remote_user: root
  tasks:
  - name: "users"
    yum: name={{ item.name }} state=present groups={{ item.groups }}
    with_items:                 #依次把用户加入组内
      - { name:'aaa', groups:'root'}
      - { name:'bbb', groups:'wheel'}

上一篇:playbook自动化安装lamp


下一篇:ansible管理变量和加解密