ansible學習筆記二:playbook
繼續接上一章,上一章記錄了常用的模塊,這裏就開始把模塊應用到ansible-playbook內。
環境:
因爲自己筆記本性能問題,這裏只用兩臺虛擬機做測試:
服務器名 | IP |
---|---|
ansible-server | 192.168.31.53 |
ansible-client | 192.168.31.167 |
測試ansible-playbook
1. 測試一例:
ansible-playbook的文件是yml格式的,這裏先說下yml裏的格式:
格式 | 說明 |
---|---|
— | 默認開頭以3個-開頭 |
host | 指定劇本運行在什麼主機組 |
remote_user | 指定以什麼用戶去執行下面的動作 |
tasks | 動作開始 |
name | 說明當前動作是做什麼的 |
這裏需要注意的是,每一個name下,只能跟一個動作
寫yml,執行完之後檢查各項,用-C去檢查
示例:在/root/下創建newfile文件,增加test99用戶,指定爲系統用戶,shell類型爲:/sbin/nologin,安裝httpd服務,拷貝本機/var/www/html/index.html到指定機器/var/www/html目錄下,開啓httpd服務,並設爲開機自啓
[root@ansible ~]# cat file.yml
---
- hosts: all
remote_user: root
tasks:
- name: create new file
file: name=/root/newfile state=touch
- name: create new user
user: name=test99 system=yes shell=/sbin/nologin
- name: install package
yum: name=httpd
- name: copy html
copy: src=/var/www/html/index.html dest=/var/www/html/
- name: start service
service: name=httpd state=started enabled=yes
當運行完上面的之後,檢查
[root@ansible ~]# ansible all -m shell -a ‘ls /root/ -l’
192.168.31.167 | CHANGED | rc=0 >>
total 8
-rw-r–r-- 1 root root 21 Feb 8 22:19 123
-rw-r–r-- 1 root root 1190 Feb 5 22:57 ks.cfg
-rw-r–r-- 1 root root 0 Feb 9 04:13 newfile
[root@ansible ~]# ansible all -m shell -a ‘getent passwd test99’
192.168.31.167 | CHANGED | rc=0 >>
test99❌987:981::/home/test99:/sbin/nologin
[root@ansible ~]# ansible all -m shell -a ‘ss -tln| grep :80’
192.168.31.167 | CHANGED | rc=0 >>
LISTEN 0 128 :::80 ::😗
2. 在yml內增加tags及handlers
這裏增加tags,主要是可以通過在只是ansible-playbook的時候,可以通過-t 指定tags名,做指定動作。handlers需要配合notify,下面的文件內做了註釋了。
[root@ansible ~]# cat http.yml
---
- hosts: all
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd
# 這裏給動作打上標籤之後,可以在執行劇本的時候,通過 ansible-playbook -t installhttpd,starthttpd http.yml 命令只執行指定標籤的操作,同時tags可以寫成一樣的,
# 即,一個標籤指定多個動作的情況。
tags: installhttpd
- name: copy conf file
copy: src=/root/httpd.conf dest=/etc/httpd/conf/ backup=yes
# 當文件有變更的時候,會執行下面handlers裏的 restart service動作
notify: restart service
- name: start service
service: name=httpd state=started enabled=yes
tags: starthttpd
handlers:
- name: restart service
service: name=httpd state=restarted
3. 在yml內增加變量:
ansible-playbook在執行的時候,爲了更方便的運行,可以增加變量,以增加靈活性。下面測試了增加變量的方法。
3.1 方法1,外部通過-e去指定:
安裝指定的服務,變量的寫法: {{ }} 內部爲變量名,類似寫html裏的方式,下面的表達式的也是這樣的方式。
[root@ansible ~]# cat app.yml
---
- hosts: all
remote_user: root
tasks:
- name: install package
yum: name={{ pkname }}
- name: start service
service: name={{ pkname }} state=started
[root@ansible ~]# ansible-playbook app.yml -e pkname=httpd
PLAY [all] ******************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************************
ok: [192.168.31.167]
TASK [install package] *****************************************************************************************************************************************************************************************
changed: [192.168.31.167]
TASK [start service] ********************************************************************************************************************************************************************************************
changed: [192.168.31.167]
PLAY RECAP ******************************************************************************************************************************************************************************************************
192.168.31.167 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
檢查
[root@ansible ~]# ansible all -m shell -a ‘ss -ntl| grep 80’
192.168.31.167 | CHANGED | rc=0 >>
LISTEN 0 128 :::80 ::😗
3.2 方法2,內部指定:
通過vars指定變量。
[root@ansible ~]# cat app.yml
---
- hosts: all
remote_user: root
vars:
- pkname: nginx
tasks:
- name: install package
yum: name={{ pkname }}
- name: start service
service: name={{ pkname }} state=started
[root@ansible ~]# ansible-playbook app.yml
PLAY [all] ******************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************************
ok: [192.168.31.167]
TASK [install package] *****************************************************************************************************************************************************************************************
changed: [192.168.31.167]
TASK [start service] ********************************************************************************************************************************************************************************************
changed: [192.168.31.167]
PLAY RECAP ******************************************************************************************************************************************************************************************************
192.168.31.167 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
檢查
[root@ansible ~]# ansible all -m shell -a ‘ss -ntl| grep 80’
192.168.31.167 | CHANGED | rc=0 >>
LISTEN 0 128 :80 :
LISTEN 0 128 :::80 :::
3.3 方法3,用setup模塊裏的變量:
setup模塊,在上一章內已經說過了,其實這裏使用,相當於使用anisble自帶的變量。
[root@ansible ~]# cat var.yml
---
- hosts: all
remote_user: root
tasks:
- name: create log file
file: name=/root/{{ ansible_fqdn }}.log state=touch mode=600 owner=test
[root@ansible ~]# ansible-playbook var.yml
PLAY [all] ******************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************************
ok: [192.168.31.167]
TASK [create log file] ******************************************************************************************************************************************************************************************
changed: [192.168.31.167]
PLAY RECAP ******************************************************************************************************************************************************************************************************
192.168.31.167 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
檢查
[root@ansible ~]# ansible all -m shell -a ‘ls /root/*.log’
192.168.31.167 | CHANGED | rc=0 >>
/root/client.log
3.4 方法4,在其他文件內指定變量:
這裏類似於上面的在yml內直接指定,只是這樣把vars拿出來,方到單獨的文件內,類似於下一章要寫的roles,這裏提前寫下。寫法爲:key:vaule
[root@ansible ~]# cat vars.yml
var1: httpd
var2: nginx
[root@ansible ~]# cat testvar.yml
---
- hosts: all
remote_user: root
vars_files:
- vars.yml
tasks:
- name: install package
yum: name={{ var1 }}
- name: create file
file: name=/root/{{ var2 }} state=touch
[root@ansible ~]# ansible-playbook testvar.yml
PLAY [all] ****************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************
ok: [192.168.31.167]
TASK [install package] ****************************************************************************************************************
changed: [192.168.31.167]
TASK [create file] ********************************************************************************************************************
changed: [192.168.31.167]
PLAY RECAP ****************************************************************************************************************************
192.168.31.167 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
檢查
[root@ansible ~]# ansible all -m shell -a ‘rpm -q httpd ; ls /root/nginx’
192.168.31.167 | CHANGED | rc=0 >>
httpd-2.4.6-90.el7.centos.x86_64
/root/nginx
4. 通過template生成模板,在模板文件內修改成變量模式,以實現各機器的不一致:
在模板內添加變量,setup模塊的自帶變量ansible_processor_vcpus,和在/etc/ansible/hosts內定義的http_port變量
[root@ansible ansible]# egrep ‘worker_processes|listen’ templates/nginx.conf.j2 | grep -v ^#
worker_processes {{ ansible_processor_vcpus**2 }};
listen {{ http_port }} default_server;
listen [::]:{{ http_port }} default_server;
[root@ansible ansible]# grep 192.168.31.167 /etc/ansible/hosts
192.168.31.167 http_port=8080
把變量寫入yml內,以實現不通機器設置不通nginx監聽進程及開啓不同端口的效果
[root@ansible ansible]# cat tetempl.yml
---
- hosts: all
remote_user: root
tasks:
- name: install package
yum: name=nginx
- name: copy template
template: src=/root/ansible/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart service
- name: start service
service: name=nginx state=started
handlers:
- name: restart service
service: name=nginx state=restarted
[root@ansible ansible]# ansible-playbook tetempl.yml
PLAY [all] ****************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************
ok: [192.168.31.167]
TASK [install package] ****************************************************************************************************************
ok: [192.168.31.167]
TASK [copy template] ******************************************************************************************************************
changed: [192.168.31.167]
TASK [start service] ******************************************************************************************************************
changed: [192.168.31.167]
RUNNING HANDLER [restart service] *****************************************************************************************************
changed: [192.168.31.167]
PLAY RECAP ****************************************************************************************************************************
192.168.31.167 : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
檢查是否安裝nginx,是否複製過去新的nginx.conf文件,啓動的端口,啓動的worker監聽進程
[root@ansible ansible]# ansible all -m shell -a ‘rpm -q nginx;ls -l /etc/nginx/nginx.conf; ss -ntl| grep 80;ps aux | grep nginx | grep worker’
192.168.31.167 | CHANGED | rc=0 >>
nginx-1.16.1-1.el7.x86_64
-rw-r–r-- 1 root root 2473 Feb 10 13:30 /etc/nginx/nginx.conf
LISTEN 0 128 :8080 :
LISTEN 0 128 :::8080 :::
nginx 3444 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3445 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3446 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3447 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3448 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3449 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3450 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3451 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3452 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3453 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3454 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3455 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3456 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3457 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3458 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
nginx 3459 0.0 0.0 121236 3512 ? S 13:30 0:00 nginx: worker process
root 3571 2.0 0.0 113120 1360 pts/1 S+ 13:33 0:00 /bin/sh -c rpm -q nginx;ls -l /etc/nginx/nginx.conf; ss -ntl| grep 80;ps aux | grep nginx | grep worker
通過以上測試,發現ansible的變量優先級:
ansible-playbook變量的優先級: -e 指定變量 > 要執行的playbook內的變量 > 主機清單內的變量
5. playbook內添加when:
5.1 相當於if判斷
[root@ansible ansible]# cat tetempl.yml
---
- hosts: all
remote_user: root
tasks:
- name: install package
yum: name=nginx
- name: copy template
template: src=/root/ansible/templates/nginx7.conf.j2 dest=/etc/nginx/nginx.conf
# 當操作系統版本爲 7 的時候,執行當前操作,複製 nginx7.conf 到主機內
when: ansible_distribution_major_version == "7"
notify: restart service
- name: copy template
template: src=/root/ansible/templates/nginx6.conf.j2 dest=/etc/nginx/nginx.conf
# 當操作系統版本爲 6 的時候,執行當前操作,複製 nginx6.conf 到主機內
when: ansible_distribution_major_version == "6"
notify: restart service
- name: start service
service: name=nginx state=started
handlers:
- name: restart service
service: name=nginx state=restarted
[root@ansible ansible]# ansible-playbook tetempl.yml
PLAY [all] ******************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************************
ok: [192.168.31.167]
TASK [install package] ******************************************************************************************************************************************************************************************
ok: [192.168.31.167]
TASK [copy template] ********************************************************************************************************************************************************************************************
ok: [192.168.31.167]
TASK [copy template] ********************************************************************************************************************************************************************************************
skipping: [192.168.31.167]
TASK [start service] ********************************************************************************************************************************************************************************************
ok: [192.168.31.167]
PLAY RECAP ******************************************************************************************************************************************************************************************************
192.168.31.167 : ok=4 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
5.2 相當於shell裏的for循環:
5.2.1 測試1,迭代:
[root@ansible ansible]# cat testitem.yml
---
- hosts: web
remote_user: root
tasks:
- name: create some file
file: name=/root/{{ item }} state=touch
when: ansible_distribution_major_version == "7"
with_items:
- file1
- file2
- file3
- name: install some package
yum: name={{ item }}
with_items:
- htop
- sl
- hping3
[root@ansible ansible]# ansible-playbook testitem.yml
PLAY [web] ****************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************
ok: [192.168.31.167]
TASK [create some file] ***************************************************************************************************************
changed: [192.168.31.167] => (item=file1)
changed: [192.168.31.167] => (item=file2)
changed: [192.168.31.167] => (item=file3)
TASK [install some package] ***********************************************************************************************************
changed: [192.168.31.167] => (item=[u’htop’, u’sl’, u’hping3’])
PLAY RECAP ****************************************************************************************************************************
192.168.31.167 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@ansible ansible]# ansible web -m shell -a ‘ls /root/file* ; rpm -q sl hping3 htop’
192.168.31.167 | CHANGED | rc=0 >>
/root/file1
/root/file2
/root/file3
sl-5.02-1.el7.x86_64
hping3-0.0.20051105-24.el7.x86_64
htop-2.2.0-3.el7.x86_64
5.2.2 測試2,迭代嵌套子變量:
[root@ansible ansible]# cat testitem2.yml
---
- hosts: web
remote_user: root
tasks:
- name: create some groups
group: name={{ item }}
when: ansible_distribution_major_version == "7"
with_items:
- g1
- g2
- g3
- name: create some users
user: name={{ item.name }} group={{ item.group }}
with_items:
# 把創建好的用戶,添加到指定的用戶組內
- { name: 'user1', group: 'g1' }
- { name: 'user2', group: 'g2' }
- { name: 'user3', group: 'g3' }
[root@ansible ansible]# ansible-playbook testitem2.yml
PLAY [web] ****************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************
ok: [192.168.31.167]
TASK [create some groups] *************************************************************************************************************
ok: [192.168.31.167] => (item=g1)
ok: [192.168.31.167] => (item=g2)
ok: [192.168.31.167] => (item=g3)
TASK [create some users] **************************************************************************************************************
changed: [192.168.31.167] => (item={u’group’: u’g1’, u’name’: u’user1’})
changed: [192.168.31.167] => (item={u’group’: u’g2’, u’name’: u’user2’})
changed: [192.168.31.167] => (item={u’group’: u’g3’, u’name’: u’user3’})
PLAY RECAP ****************************************************************************************************************************
192.168.31.167 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@ansible ansible]# ansible web -m shell -a ‘getent passwd | grep ^user; getent group | grep ^g’
192.168.31.167 | CHANGED | rc=0 >>
user1❌1002:1002::/home/user1:/bin/bash
user2❌1003:1003::/home/user2:/bin/bash
user3❌1004:1004::/home/user3:/bin/bash
g1❌1002:
g2❌1003:
g3❌1004:
5.3.1 寫成表達式的方式:
[root@ansible ansible]# cat templates/for1.conf.j2
{% for port in ports %}
server{
listen {{ port }}
}
{% endfor%}
[root@ansible ansible]# cat testfor.yml
---
- hosts: web
remote_user: root
vars:
ports:
- 81
- 82
- 83
tasks:
- name: copy conf
template: src=for1.conf.j2 dest=/root/for1.conf
[root@ansible ansible]# ansible-playbook testfor.yml
PLAY [web] ****************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************
ok: [192.168.31.167]
TASK [copy conf] **********************************************************************************************************************
changed: [192.168.31.167]
PLAY RECAP ****************************************************************************************************************************
192.168.31.167 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@ansible ansible]# ansible web -m shell -a ‘cat /root/for1.conf’
192.168.31.167 | CHANGED | rc=0 >>
server{
listen 81
}
server{
listen 82
}
server{
listen 83
}
5.3.2 或者可以寫成下面的方式
[root@ansible ansible]# cat testfor2.yml
---
- hosts: web
remote_user: root
vars:
ports:
- listen_port: 81
- listen_port: 82
- listen_port: 83
tasks:
- name: copy conf
template: src=for2.conf.j2 dest=/root/for1.conf
[root@ansible ansible]# cat templates/for2.conf.j2
{% for port in ports %}
server{
listen {{ port.listen_port }}
}
{% endfor%}
5.4 比較複雜的
[root@ansible ansible]# cat testfor3.yml
---
- hosts: web
remote_user: root
vars:
ports:
- web1:
port: 81
name: web1.test.com
rootdir: /root/website1
- web2:
port: 82
name: web2.test.com
rootdir: /root/website2
- web3:
port: 83
name: web3.test.com
rootdir: /root/website3
tasks:
- name: copy conf
template: src=for3.conf.j2 dest=/root/for3.conf
[root@ansible ansible]# cat templates/for3.conf.j2
{% for p in ports %}
server{
listen {{ p.port }}
servername {{ p.name }}
documentroot {{ p.rootdir }}
}
{% endfor%}
[root@ansible ansible]# ansible-playbook testfor3.yml
PLAY [web] ****************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************
ok: [192.168.31.167]
TASK [copy conf] **********************************************************************************************************************
changed: [192.168.31.167]
PLAY RECAP ****************************************************************************************************************************
192.168.31.167 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@ansible ansible]# ansible web -m shell -a ‘cat /root/for3.conf’
192.168.31.167 | CHANGED | rc=0 >>
server{
listen 81
servername web1.test.com
documentroot /root/website1
}
server{
listen 82
servername web2.test.com
documentroot /root/website2
}
server{
listen 83
servername web3.test.com
documentroot /root/website3
}
5.5 在for循環內添加if判斷
[root@ansible ansible]# cat templates/for4.conf.j2
{% for p in ports %}
server{
listen {{ p.port }}
{% if p.name is defined %}
servername {{ p.name }}
{% endif %}
documentroot {{ p.rootdir }}
}
{% endfor%}
[root@ansible ansible]# cat testfor4.yml
---
- hosts: web
remote_user: root
vars:
ports:
- web1:
port: 81
#name: web1.test.com
rootdir: /root/website1
- web2:
port: 82
name: web2.test.com
rootdir: /root/website2
- web3:
port: 83
#name: web3.test.com
rootdir: /root/website3
tasks:
- name: copy conf
template: src=for4.conf.j2 dest=/root/for4.conf
[root@ansible ansible]# ansible-playbook testfor4.yml
PLAY [web] ******************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************************
ok: [192.168.31.167]
TASK [copy conf] ************************************************************************************************************************************************************************************************
changed: [192.168.31.167]
PLAY RECAP ******************************************************************************************************************************************************************************************************
192.168.31.167 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@ansible ansible]# ansible web -m shell -a ‘cat /root/for4.conf’
192.168.31.167 | CHANGED | rc=0 >>
server{
listen 81
documentroot /root/website1
}
server{
listen 82
servername web2.test.com
documentroot /root/website2
}
server{
listen 83
documentroot /root/website3
}