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'}