playbook的使用
一、playbook介绍
1、playbook基础介绍
playbook 是 ansible 用于配置,部署,和管理被控节点的剧本。
通过 playbook 的详细描述,执行其中的一系列 tasks ,可以让远端主机达到预期的状态。playbook 就像 Ansible 控制器给被控节点列出的的一系列 to-do-list ,而被控节点必须要完成
play: 定义的是主机的角色
task: 定义的是具体执行的任务
playbook: 由一个或多个play组成,一个play可以包含多个task任务
1.1 playbook的优点
- 功能比ad-hoc更全
- 能很好的控制先后执行顺序, 以及依赖关系
- 语法展现更加的直观
- ad-hoc无法持久使用,playbook可以持久使用
1.2 playbook语法
采用的语法格式是YAML(Yet Another Markup Language)。YAML语法能够简单的表示散列表,字典等数据结构
1.3 YAML语法格式
- 缩进: YAML使用一个固定的缩进风格表示层级结构,每个缩进由两个空格组成, 不能使用tabs;
- 冒号:以冒号结尾的除外,其他所有冒号后面所有必须有空格;
- 短横线: 表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一列表;
Ansible-playbook采用YAML语法编写。连续的项目(即列表)用 -减号来表示,key/value(字典)用冒号:分隔。
1.4 playbook语法特性
- 以 - - -(三个减号)开始,必须顶行写;
- 次行开始写Playbook的内容,但是一般要求写明该playbook的功能;
- 严格缩进,并且不能用Tab键缩进;
- 缩进级别必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的;
- K/V的值可同行写,也可换行写。同行使用 : 分隔,换行写需要以 - 分隔;
1.5 playbook基础组件
Hosts:运行执行任务(task)的目标主机
remote_user:在远程主机上执行任务的用户
tasks:任务列表
handlers:任务,与tasks不同的是只有在接受到通知时才会被触发
templates:使用模板语言的文本文件,使用jinja2语法。
variables:变量,变量替换{{ variable_name }}
二、playbook的使用
请注意,在playbook运行时,屏幕中会显示每个play和任务的name键的值。(Gathering Facts任务是一项特别的任务,setup模块通常在play启动时自动运行这项任务。)对于含有多个play和任务的playbook,设置name属性后可以更加轻松地监控playbook执行的进展。
通常而言,Ansible Playbook中的任务是幂等的,而且能够安全地多次运行playbook。如果目标受管主机已处于正确的状态,则不应进行任何更改。如果再次运行这个playbook,所有任务都会以状态OK传递,且不报告任何更改。
1、实施一个play
1.1 编写一个单任务
[root@ansible ~]# cd /etc/ansible/
[root@ansible ansible]# mkdir playbook //创建目录
[root@ansible ansible]# cd playbook/
[root@ansible playbook]# vim user.yml
[root@ansible playbook]# cat user.yml
--- //分隔符
- name: task1 //任务的名字
gather_facts: no //
hosts: 192.168.47.129 //将要执行任务的主机
tasks: //任务
- name: create user for wangjingjing //任务名字
user: //用户模块
name: wangjingjing //用户名字
uid: 6000
state: present //用户状态
1.2 语法验证
[root@ansible playbook]# ansible-playbook --syntax-check playbook/user.yml
1.3 空运行
使用-C选项对playbook执行空运行。这会使ansible报告在执行该playbook时将会发生什么更改,但不会对受管主机进行任何实际的更改
[root@ansible playbook]# ansible-playbook -C playbook/user.yml
1.4运行playbook
ansible-playbook playbook/文件名
[root@ansible ansible]# ansible-playbook playbook/user.yml
PLAY [task1] **************************************************************************************************************
TASK [create user for wangjingjing] ***************************************************************************************
changed: [192.168.47.129]
PLAY RECAP ****************************************************************************************************************
192.168.47.129 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
//在apache主机上查询是否有wangjingjing这个用户
[root@apache ~]# id wangjingjing
uid=6000(wangjingjing) gid=6000(wangjingjing) 组=6000(wangjingjing)
1.5 配置Playbook执行的输出详细程序
ansible-playbook命令提供的默认输出不提供详细的任务执行信息。ansible-playbook -v命令提供了额外的信息,总共有四个级别
选项 | 描述 |
---|---|
-v | 显示任务结果 |
-vv | 任务结果和任务配置都会显示 |
-vvv | 包含关于与受管主机连接的信息 |
-vvvv | 增加了连接插件相关的额外详细程序选项,包括受管主机上用于执行脚本的用户以及所执行的脚本 |
[root@ansible ansible]# ansible-playbook playbook/user.yml -v
Using /etc/ansible/ansible.cfg as config file
PLAY [task1] **************************************************************************************************************
TASK [create user for wangjingjing] ***************************************************************************************
ok: [192.168.47.129] => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"}, "append": false, "changed": false, "comment": "", "group": 6000, "home": "/home/wangjingjing", "move_home": false, "name": "wangjingjing", "shell": "/bin/bash", "state": "present", "uid": 6000}
PLAY RECAP ****************************************************************************************************************
192.168.47.129 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@ansible ansible]# ansible-playbook playbook/user.yml -vv
ansible-playbook 2.9.23
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.6/site-packages/ansible
executable location = /usr/bin/ansible-playbook
python version = 3.6.8 (default, Dec 5 2019, 15:45:45) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
Using /etc/ansible/ansible.cfg as config file
Skipping callback 'actionable', as we already have a stdout callback.
Skipping callback 'counter_enabled', as we already have a stdout callback.
Skipping callback 'debug', as we already have a stdout callback.
Skipping callback 'dense', as we already have a stdout callback.
Skipping callback 'dense', as we already have a stdout callback.
Skipping callback 'full_skip', as we already have a stdout callback.
Skipping callback 'json', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'null', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.
Skipping callback 'selective', as we already have a stdout callback.
Skipping callback 'skippy', as we already have a stdout callback.
Skipping callback 'stderr', as we already have a stdout callback.
Skipping callback 'unixy', as we already have a stdout callback.
Skipping callback 'yaml', as we already have a stdout callback.
2、 实施多个play
Playbook是一个YAML文件,含有由一个或多个play组成的列表。记住一个play按顺序列出了要对清单中的选定主机执行的任务。因此,如果一个playbook中有多个play,每个play可以将其任务应用到单独的一组主机。
在编排可能涉及对不同主机执行不同任务的复杂部署时,这会大有帮助。我们可以这样进行编写:对一组主机运行一个play,完成后再对另一组主机运行另一个play。
2.1 编写并运行playbook
[root@ansible playbook]# cat vsftpd.yml
---
- hosts: apache
tasks:
- name: install vsftpd
yum:
name: vsftpd
state: latest
- name: start service for vsftpd
service:
name: vsftpd
state: started
enabled: yes
//验证
[root@ansible ansible]# ansible-playbook --syntax-check playbook/vsftpd.yml
playbook: playbook/vsftpd.yml
//空执行
[root@ansible ansible]# ansible-playbook -C playbook/vsftpd.yml
PLAY [apache] *************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************
ok: [192.168.47.129]
TASK [install vsftpd] *****************************************************************************************************
changed: [192.168.47.129]
TASK [start service for vsftpd] *******************************************************************************************
changed: [192.168.47.129]
PLAY RECAP ****************************************************************************************************************
192.168.47.129 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
//在apache主机上检查是否安装成功
[root@apache ~]# rpm -qa|grep vsftpd
vsftpd-3.0.3-31.el8.x86_64
2.2 用户属性+权限属性
远程连接普通用户
//先创建用户,设置密码
[root@apache ~]# id wangjingjing
uid=6000(wangjingjing) gid=6000(wangjingjing) 组=6000(wangjingjing)
[root@apache ~]# echo 1 | passwd --stdin wangjingjing
更改用户 wangjingjing 的密码 。
passwd:所有的身份验证令牌已经成功更新。
//生成密钥
[root@ansible playbook]# ssh-keygen
[root@ansible playbook]# ssh-copy-id wangjingjing@192.168.47.129
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
wangjingjing@192.168.47.129's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'wangjingjing@192.168.47.129'"
and check to make sure that only the key(s) you wanted were added.
//权限委派
[root@apache ~]# visudo
root ALL=(ALL) ALL
wangjingjing ALL=(ALL) NOPASSWD: ALL
//编写任务文件
[root@ansible playbook]# vim test.yml
[root@ansible playbook]# cat test.yml
---
- hosts: apache
remote_user: wangjingjing
become: yes
tasks:
- name: create user jing
user:
name: jing
state: present
//执行任务
[root@ansible ansible]# ansible-playbook playbook/test.yml
PLAY [apache] ******************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.47.129]
TASK [create user jing] ********************************************************
changed: [192.168.47.129]
PLAY RECAP *********************************************************************
192.168.47.129 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2.3 查找模块
模块文档
使用ansible-doc [module name]命令来显示模块的详细文档
ansible-doc user //显示user模块的帮助文档
应尽量避免在playbook中使用command、shell和raw模块,因为它们可以取胜任意命令,因此使用这些模块时很容易写出非幂等的playbook
非幂等的模块
copy模块可以测试来了解是否达到了需要的状态,如果已达到,则不进行任何更改。shell模块容许非常大的灵活性,但需要格外小心,从而确保它以幂等方式运行。
幂等的playbook可以重复运行,确保系统处于特定的状态,而不会破坏状态已经正确的系统。
//用copy模块,把配置文件从ansible主机copy到apache主机
[root@apache ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
[root@ansible playbook]# mkdir files
[root@ansible playbook]# ls
1 files test.yml user.yml vsfatpd.yml vsftpd.yml
[root@ansible playbook]# cd files/
[root@ansible files]# cp /etc/hosts .
[root@ansible files]# ls
hosts
[root@ansible files]# cat hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
[root@ansible files]# vim hosts
[root@ansible files]# cat hosts //把内容手动加进去
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.47.129 apache
192.168.47.130 mysql
192.168.47.131 php
[root@ansible files]# cd ..
[root@ansible playbook]# vim test.yml
[root@ansible playbook]# cat test.yml
---
- hosts: apache
remote_user: wangjingjing
become: yes
tasks:
- name: sync hosts file
copy:
src: files/hosts
dest: /etc/hosts
[root@ansible ansible]# ansible-playbook playbook/test.yml
PLAY [apache] ********************************************************
**********
TASK [Gathering Facts] ***********************************************
**********
ok: [192.168.47.129]
TASK [sync hosts file] ***********************************************
**********
changed: [192.168.47.129]
PLAY RECAP ***********************************************************
**********
192.168.47.129 : ok=2 changed=1 unreachable=0 fai
led=0 skipped=0 rescued=0 ignored=0
[root@apache ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.47.129 apache
192.168.47.130 mysql
192.168.47.131 php
2.4 Playbook特殊用法
语法 | 作用 |
---|---|
YAML注释 | 用于提高可读性 在YAML中,编号或井号字符(#)右侧的所有内容都是注释; 如果注释的左侧有内容,请在该编号符号的前面加一个空格 |
YAML字符串 | YAML中的字符串通常不需要放在引号里,即使字符串中包含空格。 字符串可以用双引号或单引号括起;编写多行字符串有两种方式。 可以使用管道符表示要保留字符串中的换行字符; 要编写多行字符串,还可以使用大于号字符来表示换行字符转换成空格并且行内的引导空白将被删除。 这种方法通常用于将很长的字符串在空格字符处断行,使它们跨占多行来提高可读性 |
YAML字典 | 字典也可以使用以大括号括起的内联块格式编写;大多数情况下应避免内联块格式,因为其可读性较低。 不过,至少有一种情形中会较常使用它。当playbook中包含角色列表时,较常使用这种语法,从而更加容易区分play中包含的角色和传递给角色的变量 |
YAML列表 | 列表也有以中括号括起的内联格式;我们应该避免使用此语法,因为它通常更难阅读 |