文章目錄
- 一、變量 variables
-
- 1.1 什麼是變量
- 1.2 定義變量的幾種方式
- 二、變量實戰
-
- 2.1 在playbook中定義變量
- 2.2 在 vars_files 檔案中定義變量
- 2.3 在Inventory中定義變量
-
- 2.3.1 在Inventory檔案中定義變量
- 2.3.2 使用host_vars定義變量
- 2.3.3 使用group_vars定義變量
- 2.4 通過執行Playbook傳遞變量
- 2.5 變量的優先級
- 2.6 nfs 服務端和用戶端實作變量方式寫法
- 三、 Ansible Register
-
- 3.1 什麼是Register
- 3.2 register批量修改主機名稱
- 3.3 使用register 完成jumpserver key 的建立
- 五、Ansible Facts Variables
-
- 5.1 什麼是facts Ansible
- 5.2 facts 應用場景
- 5.3 示例
- 5.4 根據不同的ip位址生成不同的Redis配置檔案
- 5.5 根據不同的主機cup數生成不同的nginx配置檔案
- 5.6 根據主機記憶體生成Memcached配置
- 5.6 批量修改主機名稱
- 5.7 facts變量優化
- 六、 Ansible task control
-
- 6.1 when
-
- 6.1.1 根據不同作業系統安裝相同的軟體
- 6.1.2 為特定的主機添加Nginx倉庫
- 6.1.3 判斷服務是否正常運作
- 6.1.4 判斷是否安裝nginx 未按裝可以執行不同的操作,例如安裝nginx
- 6.2 loop循環
-
- 6.2.1 使用循環批量啟動服務與安裝軟體
- 6.2.2 使用loop循環批量建立使用者
- 6.2.3 使用loop循環copy檔案
- 6.3.Handlers與Notify
- 6.4 tags 任務标簽
- 6.5 include任務複用
-
- 6.5.1 多個項目同時需要重新開機nginx
- 6.5.2 Inlcude結合tags應用 安裝tomcat
- 6.7 Playbook異常處理
- 6.8 change狀态
- 6.9 changed_when檢查任務結果
一、變量 variables
1.1 什麼是變量
變量提供了便捷的方式來管理 ansible 項目中的動态值。 比如 nginx-1.12,可能後期會反複的使用到這個版本的值,那麼如果将此值設定為變量,後續使用和修改都将變得非常友善。
1.2 定義變量的幾種方式
- 通過指令行傳遞變量參數定義
-
在play檔案中定義變量
2.1 通過vars定義變量
2.2 通過vars_files定義變量
-
通過inventory在主機組或單個主機中設定變量
3.1 通過host_vars對主機進行定義
3.2 通過group_vars對主機組進行定義
二、變量實戰
2.1 在playbook中定義變量
在 playbook 的檔案中開頭通過 vars 關鍵字進行變量定義
[[email protected] playbook_vars]# cat playbook_vars1.yml
- hosts: localhost
vars:
- web_server: httpd
- nfs_server: nfs
tasks:
- name: Output vaiables
debug:
msg:
- "{{ web_server }}"
- "{{ nfs_server }}"
[[email protected] playbook_vars]# ansible-playbook playbook_vars1.yml
PLAY [localhost] *****************************************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************************************
ok: [localhost]
TASK [Output vaiables] ***********************************************************************************************************************
ok: [localhost] => {
"msg": [
"httpd",
"nfs"
]
}
PLAY RECAP ***********************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2.2 在 vars_files 檔案中定義變量
在 playbook 中使用 vars_files 指定檔案作為變量檔案,好處就是其他的 playbook 也可以調用;
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI2EzX4xSZz91ZsAzNfRHLGZkRGZkRfJ3bs92YsAjMfVmepNHL9cGWkVHbHRVUtxUNy1iY1IVavVzZtxUNtJTY1IVavVTQClGVF5UMR9Fd4VGdsATNfd3bkFGazxycykFaKdkYzZUbapXNXlleSdVY2pESa9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2YDNmFTOwIjZ3UWMjRGOiFjY2QjY1YTY2kjNjhTNlBzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
1.準備vars_file檔案
[[email protected] playbook_vars]# cat vars_file.yml
web_server: httpd
nfs_serve: nfs
2.在playbook中play階段調用
[[email protected] playbook_vars]# cat playbook_vars2.yml
- hosts: localhost
vars_files: ./vars_file.yml
tasks:
- name: Output vaiables
debug:
msg:
- "{{ web_server }}"
- "{{ nfs_server }}"
2.3 在Inventory中定義變量
2.3.1 在Inventory檔案中定義變量
1.定義
[[email protected] playbook_vars]# cat hosts
[webservers]
172.16.1.7 state=MASTER
172.16.1.8 state=BACKUP
[webservers:vars]
port=80
2.調用
[[email protected] playbook_vars]# cat playbook_vars3.yml
- hosts: webservers
tasks:
- name: Output variables
debug:
msg:
- " {{ state }} {{ port }}"
3.輸出
[[email protected] playbook_vars]# ansible-playbook playbook_vars3.yml
TASK [Output variables]
*****************************************************
ok: [172.16.1.7] => {
"msg": [
" MASTER 80"
]
}
ok: [172.16.1.8] => {
"msg": [
" BACKUP 80"
]
}
2.3.2 使用host_vars定義變量
1.在項目目錄中建立 host_vars目錄,然後在建立一個檔案,檔案的檔案名稱要與 inventory 清單中的主機名稱要保持完全一緻,如果是ip位址,則建立相同ip位址的檔案即可
1.建立host_vars目錄
[[email protected] playbook_vars]# mkdir host_vars
2.編寫相同主機名的檔案
[[email protected] playbook_vars]# touch host_vars/172.16.1
name: bertwu
age: 18
3.調用
[[email protected] playbook_vars]# cat playbook_vars4.yml
- hosts: 172.16.1.7
tasks:
- name: Output variables
debug:
msg: "{{ name }} {{ age }}"
4.執行測試
[[email protected] playbook_vars]# ansible-playbook playbook_vars4.yml
*******************************************************************
ok: [172.16.1.7] => {
"msg": "bertwu 18"
}
如果主機清單中的其他主機區調用,會報錯
2.3.3 使用group_vars定義變量
1.在項目目錄中建立 group_vars目錄,然後在建立一個檔案,檔案的檔案名稱要與 inventory 清單中的組名稱保持完全一緻;
2.在 group_vars 目錄中建立 webservers檔案,為 webservers主機組設定變量;
[[email protected] group_vars]# cat webservers
name: Jay
age:30
3.編寫 playbook,隻需在 playbook 檔案中使用變量即可
[[email protected] playbook_vars]# cat playbook_vars5.yml
- hosts: webservers
tasks:
- name: Output varibles
debug:
msg:
- "{{ name }} {{ age }}"
4.調用
[[email protected] playbook_vars]# ansible-playbook playbook_vars5.yml
TASK [Output varibles] *************************************************
ok: [172.16.1.7] => {
"msg": [
"bertwu 18"
]
}
ok: [172.16.1.8] => {
"msg": [
"Jay 30"
]
}
5.測試其他組能否使用 webservers 組中定義的變量;測試後會發現無法調用;
6.系統提供了特殊的 all 組,也就說在 group_vars 目錄下建立一個 all 檔案,定義變量對所有的主機組都生效;
2.4 通過執行Playbook傳遞變量
在執行Playbook時,可以通過指令行
--extra-vars
或
-e
外置傳參設定變量;
[[email protected] playbook_vars]# cat vars6.yml
- hosts: localhost
tasks:
- name: Output variables
debug:
msg:
- "{{ user }} {{ uid }}"
執行,并且傳遞多個參數
[[email protected] playbook_vars]# ansible-playbook vars6.yml -e "user=tom" -e "uid=666"
TASK [Output variables] ***********************************************************
ok: [localhost] => {
"msg": [
"tom 666"
]
}
2.5 變量的優先級
1)在plabook中定義vars變量
2)在playbook中定義vars_files變量
3)在host_vars中定義變量
4)在group_vars中定義變量
5)通過執行指令傳遞變量
結果:
1.指令行傳參
2.play中的vars_files
3.play中的vars
4.invetory主機清單中的vars
5.host_vars
6.group_vars
7.group_vars/all
8.inventory 組變量
2.6 nfs 服務端和用戶端實作變量方式寫法
[[email protected] playbook_vars]# tree -L 1
.
├── ansible.cfg
├── exports.j2
├── hosts
├── nfs_varibles.yml
└── vars_file.yml
1.vars_flle變量檔案
[[email protected] playbook_vars]# cat vars_file.yml
## nfs
webservers: test
group_name: xxx
user_name: xxx
nfs_gid: 555
nfs_uid: 555
nfs_share_directory: /nfs_data
local_mount_directory: /opt
nfs_ip_range: 172.16.1.0/24
2.nfs配置檔案
[[email protected] playbook_vars]# cat exports.j2
{{ nfs_share_directory }} {{ nfs_ip_range }}(rw,sync,all_squash,anonuid={{nfs_uid }},anongid={{ nfs_gid }})
3.nfs用戶端和服務端:
[[email protected] playbook_vars]# cat nfs_varibles.yml
- hosts: "{{ webservers }}"
vars_files: ./vars_file.yml
tasks:
- name: Installed nfs servers
yum:
name: nfs-utils
state: present
- name: Configure nfs
template:
src: ./exports.j2
dest: /etc/exports
backup: yes
notify: Restart nfs server
- name: Create group
group:
name: "{{ group_name }}"
gid: "{{ nfs_gid }}"
system: yes
state: present
- name: Create user
user:
name: "{{ user_name }}"
uid: "{{ nfs_uid }}"
group: "{{ group_name }}"
system: yes
- name: Create share directory
file:
path: "{{ nfs_share_directory }}"
owner: "{{ user_name }}"
group: "{{ group_name }}"
mode: 0755
state: directory
recurse: yes
- name: start nfs
systemd:
name: nfs
state: started
enabled: yes
handlers:
- name: Restart nfs server
systemd:
name: nfs
state: restarted
- hosts: localhost
vars_files: ./vars_file.yml
tasks:
- name: Remote Mount
mount:
src: "172.16.1.99:{{ nfs_share_directory }}"
path: "{{ local_mount_directory }}"
state: mounted
fstype: nfs
opts: defaults
三、 Ansible Register
3.1 什麼是Register
register 可以将 task 執行的任務結果存儲至某個變量中,便于後續的引用;
[[email protected] playbook_vars]# cat register1.yml
- hosts: webservers
tasks:
- name: check netstat
shell: netstat -lntp
register: system_status
- name: print state
debug:
msg:
- "{{ system_status.cmd }}"
- "{{ system_status.stdout_lines }}"
[[email protected] playbook_vars]# ansible-playbook register1.yml
TASK [print state] ***************************************************************************************************************************
ok: [172.16.1.7] => {
"msg": [
"netstat -lntp",
[
"Active Internet connections (only servers)",
"Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name ",
"tcp 0 0 0.0.0.0:2049 0.0.0.0:* LISTEN - ",
"tcp 0 0 0.0.0.0:50565 0.0.0.0:* LISTEN 911/rpc.statd ",
"tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 3553/php-fpm: maste ",
"tcp 0 0 0.0.0.0:873 0.0.0.0:* LISTEN 555/rsync ",
"tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 551/rpcbind ",
"tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 3591/nginx: master ",
"tcp 0 0 0.0.0.0:20048 0.0.0.0:* LISTEN 924/rpc.mountd ",
"tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 905/sshd ",
"tcp 0 0 0.0.0.0:36696 0.0.0.0:* LISTEN - ",
"tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1100/master ",
"tcp6 0 0 :::36673 :::* LISTEN - ",
"tcp6 0 0 :::2049 :::* LISTEN - ",
"tcp6 0 0 127.0.0.1:8005 :::* LISTEN 1238/java ",
"tcp6 0 0 :::873 :::* LISTEN 555/rsync ",
"tcp6 0 0 :::56394 :::* LISTEN 911/rpc.statd ",
"tcp6 0 0 :::111 :::* LISTEN 551/rpcbind ",
"tcp6 0 0 :::8080 :::* LISTEN 1238/java ",
"tcp6 0 0 :::20048 :::* LISTEN 924/rpc.mountd ",
"tcp6 0 0 :::22 :::* LISTEN 905/sshd ",
"tcp6 0 0 ::1:25 :::* LISTEN 1100/master "
]
]
}
3.2 register批量修改主機名稱
[[email protected] playbook_vars]# cat register2.yml
- hosts: test
tasks:
- name: check netstat
shell: echo echo $RANDOM | md5sum | cut -c 1-8 # 生成8位随機數
register: random_name
- name: print state
debug:
msg:
- "{{ random_name.stdout }}"
- name: Change hostname
hostname:
name: "{{ random_name.stdout}}"
3.3 使用register 完成jumpserver key 的建立
[[email protected] playbook_vars]# cat key.yml
- hosts: localhost
tasks:
- name: Create jumpserver key
shell: 'if grep "BOOTSTRAP_TOKEN" ~/.bashrc;then
echo $BOOTSTRAP_TOKEN;
else
BOOTSTRAP_TOKEN=`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 24`;
echo "BOOTSTRAP_TOKEN=$BOOTSTRAP_TOKEN" >> ~/.bashrc ;
echo $BOOTSTRAP_TOKEN
fi'
register: JMS_BOOTSTRAP_TOKEN
- name: Create jumpserver key
shell: 'if grep "SECRET_KEY" ~/.bashrc;then
echo $SECRET_KEY;
else
SECRET_KEY=`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 49`;
echo "SECRET_KEY=$SECRET_KEY" >> ~/.bashrc ;
echo $SECRET_KEY
fi'
register: JMS_SECRET_KEY
- name: Output test
debug:
msg:
- "{{ JMS_BOOTSTRAP_TOKEN.stdout.split('=')[-1] }}"
- "{{ JMS_SECRET_KEY.stdout.split('=')[-1] }}"
[email protected] playbook_vars]# ansible-playbook key.yml
TASK [Output test] ****************************************************
ok: [localhost] => {
"msg": [
"ecUjA0BytELzk2zAOBJfni86dguxhWGEnV4ZLPVZklhwWheXA",
"QTZwLs7uG1TO0jVCBSM6XeTU7uxY1XFiDdxFPAOhUNfvr10KZ"
]
}
五、Ansible Facts Variables
5.1 什麼是facts Ansible
裝置管理控制與時間排程程式:Facilities Administration Control and Time Schedule
facts 變量主要用來自動采集”被控端主機“ 自身的狀态資訊。比如:被控端的,主機名、IP位址、系統版本、CPU數量、記憶體狀态、磁盤狀态等等。
5.2 facts 應用場景
1.通過facts變量檢查被控端硬體CPU資訊,進而生成不同的Nginx配置檔案。
2.通過facts變量檢查被控端記憶體狀态資訊,進而生成不同的memcached的配置檔案。
3.通過facts變量檢查被控端主機名稱資訊,進而生成不同的Zabbix配置檔案。
4.通過facts變量檢查被控端主機IP位址資訊,進而生成不同的redis配置檔案。
5.3 示例
檢視本機狀态資訊
[[email protected] playbook_vars]# ansible localhost -m setup
[[email protected] playbook_vars]# cat facts_print_information.yml
- hosts: localhost
tasks:
- name: Print the basic information of centos
debug:
msg:
- "{{ ansible_eth0.ipv4.address }}"
- "{{ ansible_eth1.ipv4.address }}"
- "{{ ansible_distribution }}" # 平台資訊 centos 或ubuntu
- "{{ ansible_fqdn}}" # 主機名稱
- "{{ ansible_processor_count }}"
- "{{ansible_hostname}}" # 主機名
[[email protected] playbook_vars]# ansible-playbook facts_print_information.yml
TASK [Print the basic information of centos] *******************************************************
ok: [localhost] => {
"msg": [
"10.0.0.62",
"172.16.1.62",
"CentOS",
"manager",
1
]
}
如果沒有使用facts變量需求,可以關閉其功能,加速ansible執行性能;
在play階段定義
gather_facts: no
,因為擷取後端的facts 變量是非常慢的。
[[email protected] playbook_vars]# cat facts_print_information.yml
- hosts: localhost
gather_facts: no
tasks:
- name: Print the basic information of centos
debug:
5.4 根據不同的ip位址生成不同的Redis配置檔案
[[email protected] playbook_vars]# cat redis.yml
- hosts: webservers
tasks:
- name: install redis server
yum:
name: redis
state: present
- name: configure redis server
template:
src: ./redis.conf.j2
dest: /etc/redis.conf
notify: restart redis server
- name: start redis server
systemd:
name: redis
state: started
enabled: yes
handlers:
- name: restart redis server
systemd:
name: redis
state: restarted
配置檔案寫成動态的
[[email protected] playbook_vars]# cat redis.conf.j2
bind 127.0.0.0 {{ ansible_eth1.ipv4.address }}
5.5 根據不同的主機cup數生成不同的nginx配置檔案
"ansible_processor_cores": 3, # 每個處理器的核心數
"ansible_processor_count": 2, # 處理器cpu總數
"ansible_processor_threads_per_core": 1, # 每個線程需要的核心數
"ansible_processor_vcpus": 6, # 總核心數
worker_processes {{ ansible_processor_vcpus * 2 }};
5.6 根據主機記憶體生成Memcached配置
# memcached配置檔案如下
[[email protected] project1]# cat memcached.j2 PORT="11211"
USER="memcached"
MAXCONN="1024"#根據記憶體狀态生成不同的配置(支援+-*/運算)
CACHESIZE="{{ ansible_memtotal_mb //2 }}" # 總記憶體/2#
CACHESIZE="{{ ansible_memtotal_mb * 0.8 }}" # 使用記憶體80%
OPTIONS=""
5.6 批量修改主機名稱
[[email protected] playbook_vars]# cat change_hostname.yml
- hosts: localhost
tasks:
- name: Change hostname
hostname:
name: "web_{{ ansible_eth1.ipv4.address.split(".")[-1] }}"
5.7 facts變量優化
當我們使用 gather_facts: no 關閉 facts,确實能加速 Ansible 執行,但是有時候又需要使用 facts 中的内容,還希望執行的速度快一點,這時候可以設定 facts 的緩存存入redis中;
修改ansibl.cfg配置檔案
# smart 表示預設收集 facts,但 facts 已有的情況下不會收集,即使用緩存 facts
# implicit 表示預設收集 facts,要禁止收集,必須使用 gather_facts: False;
# explicit 則表示預設不收集,要顯式收集,必須使用 gather_facts: Ture。
host_key_checking = False
gathering = smart
fact_caching_timeout = 86400
fact_caching = redis
fact_caching_connection = 172.16.1.41:6379:1
# 若 redis 設定了密碼# fact_caching_connection = 172.16.1.41:6379:1:passwd
[[email protected] playbook_vars]# yum install python-pip
[[email protected] playbook_vars]# pip install redis # 安裝redis子產品
# 檢視redis伺服器庫,看是否緩存成功。
127.0.0.1:6379[1]> select 1 #選擇1号庫
OK
127.0.0.1:6379[1]> keys *
1) "ansible_cache_keys"
2) "ansible_factslocalhost"
127.0.0.1:6379[1]>
六、 Ansible task control
6.1 when
when 關鍵字主要針對 TASK 任務進行判斷,對于此前我們使用過的 yum 子產品是可以自動檢測軟體包是否已被安裝,無需人為幹涉;但對于有些任務則是需要進行判斷才可以實作的。
- 比如:web 節點都需要配置 nginx 倉庫,但其他節點并不需要,此時就會用到 when 判斷。
- 比如: Centos 與 Ubuntu 都需要安裝 Apache,而 Centos 系統軟體包為 httpd,而 Ubuntu系統軟體包為httpd2,那麼此時就需要判斷主機系統,然後為不同的主機系統安裝不同的軟體包。
6.1.1 根據不同作業系統安裝相同的軟體
[[email protected] playbook_vars]# cat when_system.yml
- hosts: webservers
tasks:
- name: centos Install httpd
yum:
name: httpd
state: present
when: (ansible_distribution == "CentOS")
- name: ubuntu install apache2
yum:
name: httpd2
state: present
when: (ansible_distribution == "Ubuntu")
6.1.2 為特定的主機添加Nginx倉庫
為主機名為web或lb開頭的主機添加nginx yum倉庫
[[email protected] playbook_vars]# cat when_nginx.yml
- hosts: all
tasks:
- name: add ningx yum repository
yum_repository:
name: nginx
description: add nginx yum repository
baseurl: http://nginx.org/packages/centos/7/$basearch/
gpgcheck: no
when: (ansible_hostname is match("web*")) or (ansible_hostname is match("lb*"))
6.1.3 判斷服務是否正常運作
判斷httpd 是否啟動, 啟動則重新開機,否則不做處理
[[email protected] playbook_vars]# cat when_isactive.yml
- hosts: webservers
tasks:
- name: Check service is active
shell: systemctl is-active httpd
ignore_errors: yes
register: check_service
- name: Output debug
debug:
msg:
- "{{check_service}}"
- name: httpd restarted
systemd:
name: httpd
state: restarted
when: (check_service.rc == 0)
6.1.4 判斷是否安裝nginx 未按裝可以執行不同的操作,例如安裝nginx
[[email protected] playbook_vars]# cat when_is_install_nginx.yml
#- hosts: webservers
- hosts: localhost
tasks:
- name: Check is_install nginx
shell: yum list installed | grep nginx
ignore_errors: yes
register: check_service
- name: Output debug
debug:
msg:
- "{{check_service}}"
- name: install nginx
yum:
name: nginx
state: present
enablerepo: nginx
when: (check_service.rc == 1)
6.2 loop循環
在寫 playbook 的時候發現了很多 task 都要重複引用某個相同的子產品,比如一次啟動10個服務,或者一次拷貝10個檔案,如果按照傳統的寫法最少要寫10次,這樣會顯得 playbook 很臃腫。如果使用循環的方式來編寫 playbook,這樣可以減少重複編寫 task 帶來的臃腫;
6.2.1 使用循環批量啟動服務與安裝軟體
[[email protected] loop]# cat loop_service.yml
- hosts: test
tasks:
- name: install mariadb maraidb-server httpd
yum:
name: "{{ item }}"
state: present
loop:
- mariadb
- mariadb-server
- httpd
- name : start all
systemd:
name: "{{ item }}"
state: started
loop:
- httpd
- mariadb
6.2.2 使用loop循環批量建立使用者
[[email protected] ~]# cat loop-user.yml
- hosts: webservers
tasks:
- name: Add Users
user:
name: {{ item.name }}
groups: {{ item.groups }}
loop:
- { name: 'testuser1', groups: 'bin' }
- { name: 'testuser2', groups: 'root' }
6.2.3 使用loop循環copy檔案
[[email protected] loop]# cat loop_copy.yml
- hosts: test
tasks:
- name: Copy rsync file
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode}}"
owner: root
group: root
loop:
- { src: ./rsync.conf,dest: /etc/rsync.conf,mode: "0644" }
- { src: ./rsync.pass,dest: /etc/rsypc.pass, mode: "0600" }
6.3.Handlers與Notify
Handlers 是一個觸發器,同時是一個特殊的 tasks,它無法直接運作,它需要被 tasks 通知後才會運作。比如:httpd 服務配置檔案發生變更,我們則可通過 Notify 通知給指定的 handlers 觸發器,然後執行相應重新開機服務的操作,如果配置檔案不發生變更操作,則不會觸發 Handlers 任務的執行。
handlers 注意事項
- 無論多少個 task 通知了相同的 handlers, handlers 僅會在所有 tasks 結束後運作一次。
- 隻有 task 發生改變了才會通知 handlers ,沒有改變則不會觸發handlers
- 不能使用 handlers 替代 tasks、因為 handlers 是一個特殊的tasks
6.4 tags 任務标簽
預設情況下,Ansible 在執行一個 playbook 時,會執行 playbook 中所有的任務。而标簽功能是用來指定要運作 playbook 中的某個特定的任務;
-
為 playbook 添加标簽的方式有如下幾種:
對一個 task 打一個标簽
對一個 task 打多個标簽
對多個 task 打一個标簽
-
task打完标簽使用的幾種方式
-t 執行指定tag标簽對應的任務
–skip-tags 執行除 --skip-tags 标簽之外的所有任務
例:
[[email protected] loop]# cat loop_service.yml
- hosts: test
tasks:
- name: install mariadb maraidb-server httpd
yum:
name: "{{ item }}"
state: present
loop:
- mariadb
- mariadb-server
- httpd
tags: # 為一個任務打多個标簽
- install_mariadb
- install_httpd
- name : start all
systemd:
name: "{{ item }}"
state: started
loop:
- httpd
- mariadb
tags: # 為一個任務打多個标簽
- start_httpd
- start_mariadb
使用
-t
指定 tags 标簽對應的任務, 多個 tags 使用逗号隔開即可
使用
--skip-tags
指定要排除的 tags 标簽對應的任務, 多個 tags 使用逗号隔開即可
[[email protected] loop]# ansible-playbook -t install_mariadb,start_httpd loop_service.yml
[[email protected] loop]# ansible-playbook --skip-tags install_mariadb, loop_service.yml
6.5 include任務複用
有時,我們發現大量的 Playbook 内容需要重複編寫,各 Tasks 之間功能需互相調用才能完成各自功能,Playbook 龐大到維護困難,這時我們需要使用include比如:A項目需要用到重新開機 httpd,B項目需要重新開機 httpd,那麼我們可以使用 Include來減少重複編寫。
6.5.1 多個項目同時需要重新開機nginx
1.編寫 restart_nginx.yml 檔案
不包含任何play階段資訊
[[email protected] loop]# cat restart_nginx.yml
- name: Restart nginx server
systemd:
name: nginx
state: restarted
2.project_1 如下
[[email protected] loop]# cat restart_nginx.yml
- name: Restart nginx server
systemd:
name: nginx
state: restarted
[[email protected] loop]# cat project_1.yml
- hosts: webservers
tasks:
- name: echo a
shell: echo 'a project'
- name: Restart nginx server
include: ./restart_nginx.yml
3.project_2 如下
[[email protected] loop]# cat project_2.yml
- hosts: webservers
tasks:
- name: echo b
shell: echo 'b project'
- name: Restart nginx server
include: ./restart_nginx.yml
[[email protected] loop]# cat project_2.yml
- hosts: webservers
tasks:
- name: echo b
shell: echo 'b project'
- name: Restart nginx server
include: ./restart_nginx.yml
6.5.2 Inlcude結合tags應用 安裝tomcat
1.下載下傳jdk解壓到remote
2.yum本地安裝jdk
3.遠端建立/soft 目錄
4.遠端解壓tomcat到/soft目錄
5.制作軟連接配接
6.推送tomcat啟停檔案
7.推送配置檔案 權限0600
8.啟動tomcat
方式1
1.總入口檔案
[[email protected]_62 loop]# cat main.yml
- hosts: test
vars :
- src_jdk_path: /root/jdk-8u281-linux-x64.rpm
- dest_jdk: /root
- tomcat_dir: /soft
- tomcat_version: 8.5.71
- tomcat_service: ./tomcat.service
- tomcat_name: tomcat8
tasks:
- name: install tomcat8
include: ./install_tomcat8.yml
tags: install_tomcat8
- name: install tomcat9
include: ./install_tomcat9.yml
tags: install_tomcat9
handlers:
- name: reload tomcat
systemd:
name: tomcat
state: restarted
2.install_tomcat8.yml
[[email protected]_62 loop]# cat install_tomcat8.yml
- name: copy jdk_rpm to remote
copy:
src: "{{ src_jdk_path }}"
dest: "{{ dest_jdk }}"
- name: install_jdk_rpm
yum:
name: "{{ src_jdk_path }}"
state: present
- name: create /soft to remote host
file:
path: "{{ tomcat_dir }}"
state: directory
- name: unarchive tomcat package to remote /soft
unarchive:
src: "{{ dest_jdk }}/apache-tomcat-{{ tomcat_version }}.tar.gz"
dest: "{{ tomcat_dir}}"
- name: make tomcat link
file:
src: "{{ tomcat_dir }}/apache-tomcat-{{ tomcat_version }}"
dest: "{{ tomcat_dir }}/{{tomcat_name}}"
state: link
- name: copy systemd start file
template:
src: "{{ tomcat_service }}"
dest: /usr/lib/systemd/system/tomcat.service
- name: copy tomcat configure file
copy:
src: ./server.xml.j2
dest: "{{tomcat_dir}}/{{tomcat_name}}/conf/server.xml"
notify: reload tomcat
- name: start tomcat
systemd:
name: tomcat
state: restarted
3.install_tomcat9.yml 檔案與8一模一樣
預設會裝8 ,如果裝tomcat9 隻需要指定參數即可
方式2
直接在main.yml寫一個tasks , 隻需一個install_tomcat.yml檔案,預設安裝的是tomcat8 ,安裝tomcat需要指定版本号及目錄。
[[email protected]_62 loop]# cat main.yml
- hosts: localhost
vars :
- src_jdk_path: /root/jdk-8u281-linux-x64.rpm
- dest_jdk: /root
- tomcat_dir: /soft
- tomcat_version: 8.5.71
- tomcat_service: ./tomcat.service
- tomcat_name: tomcat8
tasks:
- name: install tomcat
include: ./install_tomcat.yml
tags: install_tomcat
handlers:
- name: reload tomcat
systemd:
name: tomcat
state: restarted
[[email protected]_62 loop]# cat install_tomcat.yml
#- hosts: test
# vars:
# - src_jdk_path: /root/jdk-8u281-linux-x64.rpm
# - dest_jdk: /root
# - tomcat_dir: /soft
# - tomcat_version: 8.5.71
# - tomcat_service: ./tomcat.service
# - tomcat_name: tomcat8
#
# tasks:
- name: copy jdk_rpm to remote
copy:
src: "{{ src_jdk_path }}"
dest: "{{ dest_jdk }}"
- name: install_jdk_rpm
yum:
name: "{{ src_jdk_path }}"
state: present
- name: create /soft to remote host
file:
path: "{{ tomcat_dir }}"
state: directory
- name: unarchive tomcat package to remote /soft
unarchive:
src: "{{ dest_jdk }}/apache-tomcat-{{ tomcat_version }}.tar.gz"
dest: "{{ tomcat_dir}}"
- name: make tomcat link
file:
src: "{{ tomcat_dir }}/apache-tomcat-{{ tomcat_version }}"
dest: "{{ tomcat_dir }}/{{tomcat_name}}"
state: link
- name: copy systemd start file
template:
src: "{{ tomcat_service }}"
dest: /usr/lib/systemd/system/tomcat.service
- name: copy tomcat configure file
copy:
src: ./server.xml.j2
dest: "{{tomcat_dir}}/{{tomcat_name}}/conf/server.xml"
notify: reload tomcat
- name: start tomcat
systemd:
name: tomcat
state: restarted
預設安裝tomcat8:
[[email protected]_62 loop]# ansible-playbook -t install_tomcat main.yml
安裝tomcat9:
tomcat.service配置檔案如下:
[[email protected]_62 loop]# cat tomcat.service
[Unit]
Description=tomcat - high performance web server
Documentation=https://tomcat.apache.org/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
#Environment=JAVA_HOME=/usr/local/jdk
Environment=CATALINA_HOME=/soft/{{ tomcat_name }}
Environment=CATALINA_BASE=/soft/{{ tomcat_name }}
ExecStart=/soft/{{ tomcat_name }}/bin/startup.sh
ExecStop=/soft/{{ tomcat_name }}/bin/shutdown.sh
[Install]
WantedBy=multi-user.target
6.7 Playbook異常處理
在 playbook 執行的過程中,難免會遇到一些錯誤。由于 playbook 遇到錯誤後,不會執行之後的任務,不便于調試,此時,可以在tasks中使用
ignore_errors: yes
來暫時忽略錯誤,使得 playbook 繼續執行。
[[email protected] ~]# cat ignore.yml
- hosts: all
tasks:
- name: Ignore False
command: /bin/false
ignore_errors: yes
通常情況下,當 task 失敗後,play将會終止,任何在前面已經被 tasks notify 的 handlers 都不會被執行。如果你在 play 中設定了
force_handlers: yes
參數,被通知的 handlers 就會被強制執行。(有些特殊場景可能會使用到)
- hosts: web
force_handlers: yes #強制調用handlers
tasks:
- name: Touch File
file:
path=/tmp/bgx_handlers
state=touch
notify: Restart Httpd Server
....
6.8 change狀态
[[email protected]_62 loop]# cat change.yml
- hosts: webservers
tasks:
- name: get nginx port
shell: netstat -lntp | grep nginx
register: nginx_port
- name: output nginx port
debug:
msg:
- "{{ nginx_port.stdout_lines }}"
執行 playbook 會發現第一個 task 運作 shell 子產品報告的改變,即使它沒有真正的在遠端系統做出改變,如果你一直運作,它會一直處在改變狀态。
shell 任務不應該每次都報告 changed 狀态,因為它沒有在被管理主機執行後發生變化。添加
changed_when: false
來抑制這個改變
[[email protected]_62 loop]# cat change.yml
- hosts: webservers
tasks:
- name: get nginx port
shell: netstat -lntp | grep nginx
register: nginx_port
changed_when: false
- name: output nginx port
debug:
msg:
- "{{ nginx_port.stdout_lines }}"
6.9 changed_when檢查任務結果
如果結果正确,則正常往下執行,否則退出執行。
[[email protected]_62 loop]# cat change_when.yml
- hosts: webservers
tasks:
- name: check ningx server
shell: /usr/sbin/nginx -t
register: check_nginx
changed_when:
- check_nginx.stdout.find('successful')
- false
- name: start nginx server
systemd:
name: nginx
state: restarted