playbook 是 Ansible 进行配置管理的组件, 虽然 Ansible 的日常 Ad-Hoc 命令功能很强大, 能完成一
些基本配置管理工作, 但是 Ad-Hoc 命令无法支撑复杂环境的配置管理工作。 在我们实际使用 Ansible
的工作中, 大部分时间都是在编写 playbook 。
提示:本篇文章所使用的环境为centos-8.2基于ansible-2.8.0 搭建
具体环境搭建,请参考:ansible-2.8.0 搭建链接
Tasks:任务,由模板定义的操作列表
Variables:变量
Templates:模板,即使用模板语法的文件
Handlers:处理器 ,当某条件满足时,触发执行的操作
Roles:角色
Ansible 的 playbook 文 件 格 式 为 YAML 语 法 。
首先先了解一下YAML,默认的SLS文件的renderer是YAML renderer。YAML是一个有很多强大特性的标记性语言。Salt使用了一个YAML的小型子集,映射非常常用的数据结构,像列表和字典。
YAML renderer的工作是将YAML数据格式的结构编译成为Python数据结构给Salt使用。
YAML语法有三个注意事项,具体如下
1、使用空白字符为文件缩排表示结构,不过不能使用TAB
2、注释用#号
3、字符串平常不使用引号,如果有需要,可以使用单引号或双引号。使用双引号表示字符串时,特殊字符可以通过倒斜线(\)来进行定义
YAML编写技巧
1 、缩进
YAML使用一个固定的缩进风格表示数据层结构关系。建议使用2个空格。
不要使用table键。
2 、冒号
冒号两边表示key和value。
3 、短横线
想要表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一列表的一部分。
1 ) 需要以 “----”( 3 个减号) 开始, 且需顶行首写。
2 ) 次行开始正常写 Playbook 的内容, 但笔者建议写明该 Playbook 的功能。
3 ) 使用 # 号注释代码。
4 ) 缩进必须是统一的, 建议使用两个空格,不能将空格和 Tab 混用。
5 ) 缩进的级别必须是一致的, 同样的缩进代表同样的级别, 程序判别配置的级别是通过缩进结合换行来
实现的。
6 ) YAML 文件内容和 Linux 系统大小写判断方式保持一致, 是区别大小写的, k/v 的值均需大小写敏
感。
7 ) k/v 的值可同行写也可换行写。 同行使用“:” 分隔, 换行写需要以分隔。
8 ) 一个完整的代码块功能需最少元素, 需包括 name: task。
9 ) 一个 name 只能包括一个 task。
#编辑yaml文件
[root@Ansible-Server ansible]# vim install_nginx.yaml
---
- hosts: all
tasks:
- name: Insatll nginx
yum:
name: nginx
state: present
#语法检查
[root@Ansible-Server ansible]# ansible-playbook install_nginx.yaml --syntax-check
playbook: install_nginx.yaml
#查看Playbook 文件中所有的task名称
[root@Ansible-Server ansible]# ansible-playbook install_nginx.yaml --list-task
playbook: install_nginx.yaml
play #1 (all): all TAGS: []
tasks:
Insatll nginx TAGS: []
#查看Playbook 文件中针对的主机
[root@Ansible-Server ansible]# ansible-playbook install_nginx.yaml --list-hosts
playbook: install_nginx.yaml
play #1 (all): all TAGS: []
pattern: ['all']
hosts (4):
node01
node3
node02
node04
#空运行,但是存在依赖关系,检查结果会报错
[root@Ansible-Server ansible]# ansible-playbook install_nginx.yaml --check
PLAY [all] ***********************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************
ok: [node04]
ok: [node01]
ok: [node02]
ok: [node03]
TASK [Insatll nginx] *************************************************************************************************
changed: [node04]
changed: [node02]
changed: [node03]
changed: [node01]
PLAY RECAP ***********************************************************************************************************
node01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#限定Playbook 执行范围,即使Playbook中设置了hosts的值为all
[root@Ansible-Server ansible]# ansible-playbook install_nginx.yaml --limit node01
PLAY [all] ***********************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************
ok: [node01]
TASK [Insatll nginx] *************************************************************************************************
changed: [node01]
PLAY RECAP ***********************************************************************************************************
node01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@Ansible-Server ansible]# ansible-playbook install_nginx.yaml
PLAY [all] ***********************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************
ok: [node02]
ok: [node04]
ok: [node03]
ok: [node01]
TASK [Insatll nginx] *************************************************************************************************
ok: [node01]
changed: [node03]
changed: [node02]
changed: [node04]
PLAY RECAP ***********************************************************************************************************
node01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#查看nginx是否成功安装
[root@Ansible-Server ansible]# ansible all -m shell -a 'yum list installed nginx'
[WARNING]: Consider using the yum module rather than running 'yum'. If you need to use command because yum is
insufficient you can add 'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to
get rid of this message.
node01 | CHANGED | rc=0 >>
Installed Packages
nginx.x86_64 1:1.14.1-9.module_el8.0.0+184+e34fea82 @AppStream
node02 | CHANGED | rc=0 >>
Installed Packages
nginx.x86_64 1:1.14.1-9.module_el8.0.0+184+e34fea82 @AppStream
node04 | CHANGED | rc=0 >>
Installed Packages
nginx.x86_64 1:1.14.1-9.module_el8.0.0+184+e34fea82 @AppStream
node03 | CHANGED | rc=0 >>
Installed Packages
nginx.x86_64 1:1.14.1-9.module_el8.0.0+184+e34fea82 @AppStream
#检查worker_processes 设置
[root@Ansible-Server ansible]# ansible all -m shell -a 'grep worker_processes /etc/nginx/nginx.conf'
node04 | CHANGED | rc=0 >>
worker_processes auto;
node02 | CHANGED | rc=0 >>
worker_processes auto;
node01 | CHANGED | rc=0 >>
worker_processes auto;
node03 | CHANGED | rc=0 >>
worker_processes auto;
##修改Playbook文件
---
- hosts: all
tasks:
- name: Insatll nginx
yum:
name: nginx
state: present
- name: Start nginx
service:
name: nginx
state: started
enabled: yes
#执行指定name对应的任务
[root@Ansible-Server ansible]# ansible-playbook install_nginx.yaml --start-at-task='Start nginx'
PLAY [all] ***********************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************
ok: [node03]
ok: [node02]
ok: [node01]
ok: [node04]
TASK [Start nginx] ***************************************************************************************************
changed: [node03]
changed: [node02]
changed: [node04]
changed: [node01]
PLAY RECAP ***********************************************************************************************************
node01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#查看http服务是否启动成功
[root@Ansible-Server ansible]# ansible all -m shell -a 'systemctl is-active nginx'
node03 | CHANGED | rc=0 >>
active
node01 | CHANGED | rc=0 >>
active
node02 | CHANGED | rc=0 >>
active
node04 | CHANGED | rc=0 >>
active
#查看http服务是否开机自启
[root@Ansible-Server ansible]# ansible all -m shell -a 'systemctl is-enabled nginx'
node03 | CHANGED | rc=0 >>
enabled
node04 | CHANGED | rc=0 >>
enabled
node01 | CHANGED | rc=0 >>
enabled
node02 | CHANGED | rc=0 >>
enabled
ansible 支持幂等性–绝大多数ansible模块支持,命令已经执行成功了,再次执行返回结果不会报错
#编辑Playbook文件
[root@Ansible-Server ansible]# vim install_nginx.yaml
---
- hosts: all
tasks:
- name: 1.Insatll nginx
yum:
name: nginx
state: present
- name: 2.Copy index.html
copy:
src: file/index.html
dest: /usr/share/nginx/html
- name: 3.Configure nginx.conf
lineinfile:
path: /etc/nginx/nginx.conf
regexp: ' listen 80 default_server;'
line: ' listen 8080 default_server;'
state: present
notify:
- restart nginx
- name: 4.Start nginx
service:
name: nginx
state: started
enabled: yes
- name: 5.Config firewalld
firewalld:
port: 8080/tcp
permanent: yes
state: enabled
immediate: yes
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
#检查语法
[root@Ansible-Server ansible]# ansible-playbook install_nginx.yaml --syntax-check
playbook: install_nginx.yaml
#执行Playbook
[root@Ansible-Server ansible]# ansible-playbook install_nginx.yaml
PLAY [all] ***********************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************
ok: [node04]
ok: [node02]
ok: [node01]
ok: [node03]
TASK [1.Insatll nginx] ***********************************************************************************************
ok: [node02]
ok: [node04]
ok: [node03]
ok: [node01]
TASK [2.Copy index.html] *********************************************************************************************
ok: [node04]
ok: [node03]
ok: [node02]
ok: [node01]
TASK [3.Configure nginx.conf] ****************************************************************************************
ok: [node03]
ok: [node01]
ok: [node04]
ok: [node02]
TASK [4.Start nginx] *************************************************************************************************
ok: [node03]
ok: [node01]
ok: [node02]
ok: [node04]
TASK [5.Config firewalld] ********************************************************************************************
ok: [node04]
ok: [node03]
ok: [node02]
ok: [node01]
PLAY RECAP ***********************************************************************************************************
node01 : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#测试
[root@Ansible-Server ansible]# for i in {4..7}; do curl http://192.168.5.$i:8080; done
hello ansible
hello ansible
hello ansible
hello ansible
--->nfs_server node02:192.168.5.5
--->nfs-client node03:192.168.5.6
#配置nfs_server
[root@Ansible-Server ansible]# vim nfs_server.yaml
---
- hosts: dev
tasks:
- name: 1.Install nfs-utils
yum:
name: nfs-utils
state: present
- name: 2.Configure nfs server
copy:
src: ./file/exports
dest: /etc/exports
backup: yes
- name: 3.Create group www
group:
name: www
gid: 666
system: yes
state: present
- name: 4.Create user www
user:
name: www
group: www
uid: 666
system: yes
state: present
create_home: no
shell: /bin/nologin
- name: 5.Create nfs share directory
file:
path: /ansible_data
owner: www
group: www
mode: '0755'
recurse: yes
state: directory
- name: 6.Start nfs server
systemd:
name: nfs-server
state: started
enabled: yes
- name: 7.Modify firewall rule
firewalld:
service: '{{ item }}'
permanent: yes
state: enabled
immediate: yes
with_items:
- nfs
- rpc-bind
- mountd
#语法检查
[root@Ansible-Server ansible]# ansible-playbook nfs_server.yaml --syntax-check
playbook: nfs_server.yaml
#配置nfs_client
[root@Ansible-Server ansible]# vim nfs_client.yaml
---
- hosts: test
tasks:
- name: 1.Install nfs-utils
yum:
name: nfs-utils
state: present
- name: 2.Create mount point directory
file:
path: /mnt/nfs
state: directory
- name: 3.Mount nfs
mount:
src: node02:/ansible_data
path: /mnt/nfs
fstype: nfs
state: mounted
#语法检查
[root@Ansible-Server ansible]# ansible-playbook nfs_client.yaml --syntax-check
playbook: nfs_client.yaml
#查看nfs 挂载情况
[root@Ansible-node03 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 379M 0 379M 0% /dev
tmpfs 396M 0 396M 0% /dev/shm
tmpfs 396M 5.7M 391M 2% /run
tmpfs 396M 0 396M 0% /sys/fs/cgroup
/dev/mapper/cl-root 17G 1.9G 16G 11% /
/dev/sda1 976M 130M 780M 15% /boot
tmpfs 80M 0 80M 0% /run/user/0
node02:/ansible_data 17G 1.9G 16G 11% /mnt/nfs
-->node01 192.168.5.4 安装httpd
-->node02 192.168.5.5 安装mariadb
#编辑Playbook 文件
---
- name: Install and Start httpd
hosts: node01
tasks:
- name: 1.install httpd
yum:
name: httpd
state: present
- name: 2.Start httpd
service:
name: httpd
state: started
enabled: yes
- name: 3.Configure firewall
firewalld:
service: http
state: enabled
immediate: yes
permanent: yes
- name: Install and start mariadb
hosts: node02
tasks:
- name: 1.Install mariadb
yum:
name: mariadb-server
state: latest
- name: 2.Start service
service:
name: mariadb
enabled: yes
state: started
- name: 3.Configure firewall
firewalld:
service: mysql
state: enabled
immediate: yes
permanent: yes
#检查语法
[root@Ansible-Server ansible]# ansible-playbook muti_playbook.yml --syntax-check
playbook: muti_playbook.yml
#执行Playbook
[root@Ansible-Server ansible]# ansible-playbook muti_playbook.yml
PLAY [Install and Start httpd] *************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
ok: [node01]
TASK [1.install httpd] *********************************************************************************************
changed: [node01]
TASK [2.Start httpd] ***********************************************************************************************
changed: [node01]
TASK [3.Configure firewall] ****************************************************************************************
changed: [node01]
PLAY [Install and start mariadb] ***********************************************************************************
TASK [Gathering Facts] *********************************************************************************************
ok: [node02]
TASK [1.Install mariadb] *******************************************************************************************
changed: [node02]
TASK [2.Start service] *********************************************************************************************
changed: [node02]
TASK [3.Configure firewall] ****************************************************************************************
changed: [node02]
PLAY RECAP *********************************************************************************************************
node01 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#检测结果
--node01
[root@Ansible-node01 ~]# systemctl is-active httpd
active
[root@Ansible-node01 ~]# systemctl is-enabled httpd
enabled
[root@Ansible-node01 ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens33
sources:
services: cockpit dhcpv6-client http ssh
ports: 8080/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
--node02
[root@Ansible-node02 ~]# systemctl is-active mysql
active
[root@Ansible-node02 ~]# systemctl is-enabled mysql
enabled
[root@Ansible-node02 ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens33
sources:
services: cockpit dhcpv6-client mountd mysql nfs rpc-bind ssh
ports: 8080/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules: