Playbook 可以用来管理远程主机的配置与部署, 方便对远程主机执行一些策略和步骤。
https://docs.ansible.com/ansible/latest/user_guide/playbooks.html
一、基础
Playbook 使用YAML语法,每个Playbook文件由一个或多个plays组成。每个play就是对一组远程主机的操作,多组远程主机就是多个play。
1、基本语法
- hosts: webserver
remote_user: root
gather_facts: False
tasks:
- name: install nginx
yum:
name: nginx
state: present
- name: install php
yum: name=nginx state=present
- hosts: dbserver
gather_facts: False
tasks:
- name: install mariadb
yum:
name: mariadb
state: present
hosts
: 指定主机或者主机组
remote_user
: 连接远程主机的用户, 默认就是root, ansible 配置文件定义的。 在测试的时候,发现换用户不管用,还不如直接修改ansible_user
变量来的直接。
gather_facts
: 是否获取远程主机的fact信息,如果不需要使用fact变量,可以关闭,节省执行时间。默认是开启的,可以用False或no关闭。
tasks
: 任务列表,下面定义任务。
name
: 任务名称,在执行的时候会显示,所以最好是加上。yum
: 这个位置是模块名称,后面是模块的定义参数。有两种使用方式, 意思都一样, 推荐使用换行那种。
yum: name=nginx state=present
yum:
name: mariadb
state: present
2、提权
- hosts: dbserver
remote_user: op
gather_facts: False
vars:
ansible_user: op
tasks:
- name: print ansible_user
debug: msg={{ ansible_user }}
- name: install mariadb
yum:
name: mariadb-server
state: present
上面添加ansible_user
变量是因为remote_user切换不动用户,使用变量硬性修改。
[root@lvs playbook]# ansible-playbook test.yml -u op
PLAY [dbserver] *********************************************************************************************************************
TASK [print ansible_user] ***********************************************************************************************************
ok: [172.100.102.90] => {
"msg": "op"
}
TASK [install mariadb] **************************************************************************************************************
fatal: [172.100.102.90]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "changes": {"installed": ["mariadb-server"]}, "msg": "You need to be root to perform this command.\n", "rc": 1, "results": ["Loaded plugins: fastestmirror\n"]}
PLAY RECAP **************************************************************************************************************************
172.100.102.90 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
提示普通用户不能yum安装软件。 有的公司不会直接用root
登录,都是普通用户连接,然后sudo执行管理命令。
- hosts: dbserver
remote_user: op
gather_facts: False
become: yes
become_method: sudo
become_user: root
vars:
ansible_user: op
tasks:
- name: print ansible_user
debug: msg={{ ansible_user }}
- name: install mariadb
yum:
name: mariadb-server
state: present
几个提权关键字跟ansible命令是一样的。
become
: 是否提权
become_method
: 提权方法,比如:sudo, su。 默认sudo。
become_user
: 提权到哪个用户,一般都是root,默认也是root。
上面的become_method
与become_user
都可以省略。
执行的时候如果sudo需要输入密码,ansible-playbook 命令需要添加参数, --ask-become-pass
或-K
, 交互式输入密码。
[root@lvs playbook]# ansible-playbook test.yml -K
BECOME password:
PLAY [dbserver] *********************************************************************************************************************
TASK [print ansible_user] ***********************************************************************************************************
ok: [172.100.102.90] => {
"msg": "op"
}
TASK [install mariadb] **************************************************************************************************************
changed: [172.100.102.90]
PLAY RECAP **************************************************************************************************************************
172.100.102.90 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
提权也可以只添加在某个任务里。
- name: install mariadb
become: yes
become_method: sudo
become_user: root
yum:
name: mariadb-server
state: present
3、主机执行顺序
在2.4版以后添加的
可以控制主机的执行顺序, 默认是inventory中主机列表的顺序。
关键字: order
。
有以下参数:
inventory
: 默认值,以inventory文件里的主机顺序。
reverse_inventory
: inventory文件里的相反顺序。
sorted
: 按主机名称的字母顺序排序
reverse_sorted
: 按主机名称的字母顺序反向排序
shuffle
: 随机排序。
例子:默认情况
- hosts: webserver
remote_user: root
gather_facts: False
tasks:
- name: print hello
shell: echo 'hello'
相当于
- hosts: webserver
remote_user: root
order: inventory
gather_facts: False
tasks:
- name: print hello
shell: echo 'hello'
为了方便测试,需要修改并发。下面修改并发为1,-f参数指定。
ansible-playbook test.yml -f 1
执行顺序:
TASK [print hello] ******************************************************************************************************************
changed: [172.100.102.90]
changed: [172.100.102.92]
changed: [172.100.102.93]
改为reverse_inventory。
- hosts: webserver
remote_user: root
order: reverse_inventory
gather_facts: False
tasks:
- name: print hello
shell: echo 'hello'
[root@lvs playbook]# ansible-playbook test.yml -f 1
PLAY [webserver] ********************************************************************************************************************
TASK [print hello] ******************************************************************************************************************
changed: [172.100.102.93]
changed: [172.100.102.92]
changed: [172.100.102.90]
4、可以换行
行太长了,可以换行,换行以后保持缩进或更多缩进。
tasks:
- name: Copy ansible inventory file to client
copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
owner=root group=root mode=0644
5、忽略错误
多个任务,在前面的任务发生错误以后, 后面的任务就不在执行了。
如:
tasks:
- name: install httpd
yum: name=httpd state=present
- name: print hello
shell: echo 'hello'
TASK [install httpd] ****************************************************************************************************************
fatal: [172.100.102.90]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "changes": {"installed": ["httpd"]}, "msg": "You need to be root to perform this command.\n", "rc": 1, "results": ["Loaded plugins: fastestmirror\n"]}
fatal: [172.100.102.93]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "changes": {"installed": ["httpd"]}, "msg": "You need to be root to perform this command.\n", "rc": 1, "results": ["Loaded plugins: fastestmirror\n"]}
fatal: [172.100.102.92]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "changes": {"installed": ["httpd"]}, "msg": "You need to be root to perform this command.\n", "rc": 1, "results": ["Loaded plugins: fastestmirror\n"]}
如果在install httpd那里安装失败, 下面的print hello就不会执行了。可以添加忽略错误的关键字ignore_errors
:
tasks:
- name: install httpd
yum: name=httpd state=present
ignore_errors: True
- name: print hello
shell: echo 'hello'
TASK [install httpd] ****************************************************************************************************************
fatal: [172.100.102.93]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "changes": {"installed": ["httpd"]}, "msg": "You need to be root to perform this command.\n", "rc": 1, "results": ["Loaded plugins: fastestmirror\n"]}
...ignoring
fatal: [172.100.102.92]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "changes": {"installed": ["httpd"]}, "msg": "You need to be root to perform this command.\n", "rc": 1, "results": ["Loaded plugins: fastestmirror\n"]}
...ignoring
fatal: [172.100.102.90]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "changes": {"installed": ["httpd"]}, "msg": "You need to be root to perform this command.\n", "rc": 1, "results": ["Loaded plugins: fastestmirror\n"]}
...ignoring
TASK [print hello] ******************************************************************************************************************
changed: [172.100.102.93]
changed: [172.100.102.92]
changed: [172.100.102.90]
注意, 这个忽略错误,只是忽略返回码不为0的错误,也就是命令执行错误。 而连接或登录远程主机失败的错误无法忽略。
6、任务控制
--tags, --skip-tags
只执行某个或某几个任务,而不是全部执行。
- hosts: webserver
gather_facts: False
tasks:
- name: install httpd
yum: name=httpd state=present
tags: install_nginx
- name: push nginx conf
copy: src=/etc/nginx/nginx.conf
dest=/etc/nginx/nginx.conf
tags: config
- name: restart nginx
service: name=nginx state=restarted
tags: restart_nginx
比如只执行install_nginx与config。
ansible-playbook --tags "install_nginx, config" test.yml
跳过restart_nginx。
ansible-playbook --skip_tags "restart_nginx" test.yml
--start-at-task
指定从某个任务开始,而不是从头开始执行。这个跟tags
没关系。
比如从push nginx conf开始:
ansible-playbook --start-at-task "push nginx conf" test.yml
6、语法检查
--syntax-check
ansible-playbook --syntax-check test.yml
二、handlers
添加只有在某些任务执行发生变化的时候才会触发执行的任务。
比如: 第一次发布配置文件,需要触发重载配置的操作。然后后来又再一次发布,但是配置都没有做过修改,ansible对比文件发现都一样,实际也不会推送配置, 这样也就没有必要重载配置。
1、基本格式
- hosts: webserver
gather_facts: False
tasks:
- name: push nginx conf
copy: src=/etc/nginx/nginx.conf
dest=/etc/nginx/nginx.conf
notify: reload nginx
handlers:
- name: reload nginx
service: name=nginx state=reloaded
handlers
也是配置任务列表, 与 tasks
没有什么不同。
notify
后面的就是 handlers
里的任务名称。
执行结果:
[root@lvs playbook]# ansible-playbook test1.yml
PLAY [webserver] ********************************************************************************************************************
TASK [push nginx conf] **************************************************************************************************************
changed: [172.100.102.93]
changed: [172.100.102.92]
RUNNING HANDLER [restart nginx] *****************************************************************************************************
changed: [172.100.102.93]
changed: [172.100.102.92]
PLAY RECAP **************************************************************************************************************************
172.100.102.92 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.100.102.93 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
可以看到触发了HANDLER。
再执行一下:
[root@lvs playbook]# ansible-playbook test1.yml
PLAY [webserver] ********************************************************************************************************************
TASK [push nginx conf] **************************************************************************************************************
ok: [172.100.102.92]
ok: [172.100.102.93]
PLAY RECAP **************************************************************************************************************************
172.100.102.92 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.100.102.93 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2、notify
触发多个
notify
后面可以写成列表,用来触发多个handler的任务。
如:
- hosts: webserver
gather_facts: False
tasks:
- name: push nginx conf
copy: src=/etc/nginx/nginx.conf
dest=/etc/nginx/nginx.conf
notify:
- reload nginx
- echo hello
handlers:
- name: reload nginx
service: name=nginx state=reloaded
- name: echo hello
debug: msg='hello'
这里的nginx.conf配置文件又修改了一下,不然也不会触发。
TASK [push nginx conf] **************************************************************************************************************
changed: [172.100.102.93]
changed: [172.100.102.92]
RUNNING HANDLER [reload nginx] ******************************************************************************************************
changed: [172.100.102.93]
changed: [172.100.102.92]
RUNNING HANDLER [echo hello] ********************************************************************************************************
ok: [172.100.102.93] => {
"msg": "hello"
}
ok: [172.100.102.92] => {
"msg": "hello"
}
3、同一个play中相同handler任务多次触发也只会执行一次
tasks中的任务多次触发同一个handler任务,对应的handler任务也只会执行一次。
handler的执行会在tasks执行完以后再执行。
4、listen
侦听任务通知
虽然所notify可以通知多个handler。 但是量很大的情况下,可能会遇到多个任务都需要触发一大堆handler。
这种情况就可以使用listen
,应该更加的灵活。
handlers的任务添加listen
, 然后notify
后面是listen
的字符串,不再是handler任务的名称。
- hosts: webserver
gather_facts: False
tasks:
- name: push nginx conf
copy: src=/etc/nginx/nginx.conf
dest=/etc/nginx/nginx.conf
notify: restart web server
handlers:
- name: restart nginx
service: name=nginx state=restarted
listen: restart web server
- name: restart php-fpm
service: name=php-fpm state=restarted
listen: restart web server
- name: test
shell: echo 'hello world'
listen: restart web server
TASK [push nginx conf] **************************************************************************************************************
changed: [172.100.102.93]
changed: [172.100.102.92]
RUNNING HANDLER [restart nginx] *****************************************************************************************************
changed: [172.100.102.93]
changed: [172.100.102.92]
RUNNING HANDLER [restart php-fpm] ***************************************************************************************************
changed: [172.100.102.93]
changed: [172.100.102.92]
RUNNING HANDLER [test] **************************************************************************************************************
changed: [172.100.102.93]
changed: [172.100.102.92]