Ansible-變數----Jinja2模板--------------------亂雲低薄暮,急雪舞迴風
阿新 • • 發佈:2021-09-13
Ansible變數
一、變數介紹
1.1、概述
變數提供了便捷的方式來管理Ansible playbook的每一個專案中的動態之,比如nginx-1.6.3這個軟體包的版本,在其他地方或許會反覆使用,那麼如果將此值設定為變數,然後在其他的playbook中呼叫,會方便維護,減少維護成本。
1.2、定義變數的方式
1.通過命令列進行變數定義
2.在play檔案中進行變數定義
3.通過inventory主機清單中進行變數定義
4.通過vars_file定義變數
5.通過hosts_vars和group_vars定義定量
1.3、變數的優先順序
如果在定義變數時,變數衝突了,生效會有優先順序 如: 1.命令列中設定: age=11 2.paly檔案中: age=12 3.Inventory中:age=13 最終結果是:11 優先順序 # 命令列--> playbook --> Indentory檔案 #變數設定:命令時,應該由字母數字,下劃線組成,必須由字母開頭
二、變數的定義
2.1、在playbook檔案中進行變數定義
1)方式一:在模組下定義變數
- hosts: web_group
tasks:
- name: Install Http Nginx
yum:
name: "{{ packages }}"
state: installed
vars:
packages:
- httpd
- nginx
# 如果將變數設定到模組下,其他的 - name 是不識別的
2)方式二:在hosts下定義變數
- hosts: web vars: packages: - httpd - nginx tasks: - name: Install Http Nginx yum: name: "{{ packages }}" state: installed # 在 - hosts 下定義多個變數 - hosts: web vars: packages: - httpd - nginx web_vars: - mysql - redis tasks: - name: Install http yum: name: "{{ web_vars }}" # 設定到 - hosts 下,其他 hosts 不能識別
2.2、在vars_file 檔案中定義變數
在palybook中使用vars定義變數,只能在一個palybook中生效,其他playbook無法使用,第二種方式,在 'var_file檔案'中定義變數.
1)準備變數檔案
1. mkdir vars #建立單獨目錄,和playbook同級
2. cd vars/ #進入目錄
3. vim vars.yaml #建立變數檔案
packages:httpd #設定變數
web:
- nginx
- httpd
2)呼叫變數檔案
# vim playbook.yaml - hosts: web_group vars_files: /tmp/vars/vars.yaml tasks: - name: Install Http yum: name: "{{ packages }}" 呼叫多個變數檔案 # vim playbook22.yaml - hosts: lb_group vars_files: - /tmp/vars/vars.yaml - /tmp/vars/vars1.yaml tasks: - name: Install Mariadb yum: name: "{{ dbs }}" state: installed
2.3、通過Inventory主機清單進行變數定義
1)配置主機清單
[root@m01 ~]# vim /etc/ansible/hosts
... ...
[db_server]
db01 ansible_ssh_pass='1'
[db_server:vars]
web=nginx
2)呼叫變數
[root@m01 project]# vim yum.yml
- hosts: db_server
tasks:
- name: Touch File
file:
path: /tmp/{{ web }}
state: touch
#注意:
1.主機清單中定義變數,只要hosts配置的主機清單中設定變數的組,可以直接使用變數。
2.如果hosts配置的不是主機清單中設定變數的組,變數不可識別
3)主機清單定義變數優先順序
1.主機組定義的變數優先順序高於整合組定義的變數
2.主機定義的變數優先順序高於主機組定義的變數
# 主機 > 主機組 > 整合組
# vim /etc/ansible/hosts
[lb_server] #主機組
lb01 ansible_ssh_pass='1'
lb02 ansible_ssh_pass='1'
......
[nginx:children] #整合組
web_group
lb_server
[nginx:vars]
web=nginx_group
[web_group:vars]
web=nginx_host
2.4、通過hosts_vars和group_vars定義變數
比較好用的實在Ansible專案目錄下建立兩個變數目錄:
# 切記,目錄名字一定要一致,不能做任何修改。
'host_vars'
'group_vars'
1)主機組定義變數
1.建立主機組變數目錄,在ansible專案目錄下,不能改名字!和需要執行的ansible-playbook同級
[root@m01 project]# mkdir group_vars
2.目錄下建立變數檔案,檔案的名字要跟'主機清單中主機組名字一致'
[root@m01 project]# cd group_vars/
[root@m01 group_vars]# vim web_group
file:
- nginx
- mariadb
# 只要劇本中的hosts與設定變數的主機組名字相同,就可以直接使用變數
3.呼叫變數
- hosts: web_group
tasks:
- name: Touch File
path: /tmp/{{ file }}
state: touch
2)主機定義變數
1.建立主機變數的目錄,不能改名字!
[root@m01 project]# mkdir host_vars
2.目錄下建立變數檔案,檔案的名字要跟'主機清單中主機名字一致'
vim /tmp/host_vars/web01
file_name:
- httpd
- mysql
3.呼叫變數
- hosts: web_group
tasks:
- name: Touch File
file:
path: /tmp/{{ file_name }}
state: touch
2.5、命令列定義變數(命令列 -e 設定變數)
1)檢視劇本檔案
[root@m01 project]# cat test.yml
- hosts: web_group
tasks:
- name: Touch File
file:
path: /tmp/{{ file }}
state: touch
2)命令列指定變數執行
# 命令列指定變數
ansible-playbook test.yaml -e "file=papa"
# 命令列指定多個變數
ansible-playbook test.yaml -e "file=papa" -e "file2=papa2"
2.6、內建變數---可直接使用
部分內建變數
# 簡短主機名
ansible_fqdn
# 獲取當前play所操作的所有主機的主機名列表
play_hosts
# 獲取主機IP
ansible_eth1.ipv4.address
# 獲取時間
ansible_data_time.data
# 獲取系統
ansible_distribution
# 獲取系統版本號
ansible_distribution_major_version
....
#使用內建變數建立目錄,目錄格式為 主機名_IP_時間
[root@m01 project]# vim test.yml
- hosts: web_group
tasks:
- name: Touch File
file:
path: /backup/{{ ansible_fqdn }}_{{ ansible_eth1.ipv4.address }}_{{ ansible_date_time.date }}
state: directory
2.7、層級定義變數
#編輯變數檔案
[root@m01 ~]# vim vars_file.yml
lamp:
framework:
web_package: httpd
db_package: mariadb-server
php_package: php
lnmp:
framework:
web_package: nginx
db_package: mysql
php_package: php
lnmt:
framework:
web_package: nginx
db_package: mysql
java_package: tomcat
#編輯playbook檔案
[root@m01 ~]# vim test.yml
- hosts: web_group
vars_files: ./vars_file.yml
tasks:
- name: Install LAMP httpd
yum:
name: "{{ lamp.framework.web_package }}"
- name: Install LAMP mariadb-server
yum:
name: "{{ lamp.framework.db_package }}"
- name: Install LAMP php
yum:
name: "{{ lamp.framework.php_package }}"
#官方推薦寫法
[root@m01 ~]# vim test.yml
- hosts: web_group
vars_files: ./vars_file.yml
tasks:
- name: Install LAMP httpd
yum:
name: "{{ lamp['framework']['web_package'] }}"
- name: Install LAMP mariadb-server
yum:
name: "{{ lamp['framework']['db_package'] }}"
- name: Install LAMP php
yum:
name: "{{ lamp['framework']['php_package'] }}"
#執行playbook
[root@m01 ~]# ansible-playbook test.yml
三、變數註冊
當ansible的模組在執行之後,其實都會返回一些result結果,就像是執行指令碼,我們有的時候需要指令碼給我們一些return返回值,我們才知道,上一步是否執行成功,但是預設情況下,ansible的result是不會顯示出來的,所以,我們可以把這些返回值儲存到變數中,這樣我們就能通過呼叫對應的變數名,從而獲得這些result,這樣將模組的返回值,寫入到變數中的方法稱為變數註冊。
register 定義變數,可以使用debug輸出
debug模組
msg:可以輸出變數或者任何內容
when 判斷 rc
when: get_php_install.rc !=
ignore_errors: yes 忽略錯誤
3.1、使用ad-hoc回得到返回的結果
[root@m01 project]# ansible web01 -m shell -a 'ls -l /tmp'
web01 | CHANGED | rc=0 >>
total 0
drwx------. 2 root root 41 Dec 23 15:07 ansible_command_payload_Q9bnkr
-rw-r--r--. 1 root root 0 Dec 23 14:54 command
-rw-r--r--. 1 root root 0 Dec 23 14:57 host_vars
-rw-r--r--. 1 root root 0 Dec 23 14:56 playbook_vars
-rw-r--r--. 1 root root 0 Dec 23 14:55 vars_file
3.2、使用playbook執行同樣的命令得不到結果
[root@m01 project]# cat test.yml
- hosts: web_group
tasks:
- name: Touch File
shell: "ls -l /tmp"
[root@m01 project]# ansible-playbook test.yml
PLAY [web_group] *****************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************
ok: [web01]
ok: [web02]
TASK [Touch File] ****************************************************************************************************
changed: [web01]
changed: [web02]
PLAY RECAP ***********************************************************************************************************
web01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
3.3、使用註冊變數的方式
1)註冊一個變數並呼叫
# 註冊變數
- hosts:
tasks:
- name: Touch File
shell: ls -l /tmp
register: get_dir_list
# 呼叫變數
- hosts:
tasks:
- name: Touch File
shell: ls -l /tmp
register: get_dir_list
- name: Get get_dir_list #呼叫
debug:
msg: "{{ get_dir_list }}"
# 只輸出想要的部分
- hosts:
tasks:
- name: Touch File
shell: ls -l /tmp
register: get_dir_list
- name: Get get_dir_list
debug:
msg: "{{ get_dir_list.stdout_lines }}" # . 後面跟想要得到的資訊
2)變數註冊一般使用場景
- hosts:
...
- name: Check Install Status
shell: "rpm -qa | grep php | wc -l"
#shell: rpm -qa nginx
register: get_php_is_install
- name: Install Php Server
shell: "yum localinstall -y /tmp/*.rpm"
when: get_php_is_install.stdout_lines == 0
...
四、facts快取
Ansible facts 是在被管理主機上通過Ansible 自動採集發現的變數,facts包含每臺特定的主機資訊,比如:被控端的主機名、IP地址、系統版本、cpu數量、記憶體狀態、磁碟狀態等等
4.1、使用場景
1.通過facts快取檢查cpu,來生成對應的nginx配置檔案
2.通過facts快取檢查主機名,生成不同的redis配置檔案
3.通過facts快取檢索物理機的記憶體大小來生成不同的mysql配置檔案
# ansible facts類似於saltstack中的grains對於做自動化的小夥伴是非常有用滴。
4.2、關閉facts快取
- hosts:
gather_facts: no # 關閉快取資訊採集
tasks:
...
# 如果不適用內建變數,可以關閉會提高劇本的執行速度,如果使用內建變數,那麼不能關閉facts快取
4.3、一般使用
# template 用法和copy類似,支援ansible——facts的內建變數
用於推送配置檔案時,使用內建變數,主機名和IP地址會根據主機的資訊做出更改,適合不同的主機使用配置檔案
1.配置redis配置檔案
vim /etc/redis.conf
# bind {{ ansible_eth1.ipv4.address }}
2.編寫劇本
- hosts: web_group
tasks:
- name: Install Redis
yum:
name: redis
- name: Send Config File
tmplate:
src: /tmp/redis.conf
dest: /etc/
3.檢視受控端配置
[root@web01 ~] # bind 172.16.1.7
[root@web02 ~] # bind 172.16.1.8
五、Ansible流程控制
不管是shell還是各大程式語言中,流程控制,條件判斷這些都是必不可少的,在我們使用Ansible的過程中,條件判斷的使用頻率極其高。
#例如:
1.我們使用不同的系統的時候,可以通過判斷系統來對軟體包進行安裝
2.在nfs和rsync安裝過程中,客戶端伺服器不需要推送配置檔案,之前我們都是寫多個play,會影響效率。
3.我們在原始碼安裝nginx的時候,執行第二遍就無法執行了,此時我們就可以進行判斷是否安裝過。
5.1、playbook條件語句
# when 判斷語句,符合條件後執行,變數不需要加{{}}和""
1)判斷系統
- hosts: web_group
tasks:
- name: Install CentOS httpd
shell: yum install -y https
when: ansible_distribution == "CentOS"
- name: Install Ubuntu Httpd
shell: "apt-get apache2"
when: ansible_distribution == "Ubuntu"
2)判斷主機
- name: Creater www Group
group:
name: www
gid: 666
state: present
when: ansible_fqdn != 'db01'
- name: Create www User
user:
name: www
uid: 666
group: www
shell: /sbin/nologin
create_home: false
state: present
when: ansible_fqdn != 'db01'
3)判斷服務是否安裝
- hosts:
tasks:
# 使用shell模組檢查nginx是否安裝,複製給變數註冊
- name: Check Nginx Status
shell: rpm -qa nginx
register: is_install_nginx
# 呼叫註冊變數,當stdout_lines為0的時候,才會安裝
- name: Install Nginx
yum:
name: nginx
when: is_install_nginx.stdout.lines == 0
4)判斷系統版本啟動服務
兩種方式:1.列表的形式 2.多條件and連線
# 使用列表的形式
- name: Start CentOS 6 Server
shell: "/etc/init.d/htttpd start"
when:
- ansible_distribution == CentOS
- ansible_distribution_major_version == 6
- name: Start CentOS 7 Server
shell: "systemctl start httpd"
when:
- ansible_distribution == CentOS
- ansible_distribution_major_version == 7
# 使用多條件and連線
- name: Start CentOS 7 Server
shell: "systemctl start httpd"
when: (ansible_distribution == 'CentOS') and (ansible_distribution_major_version == '7')
### 5)判斷是否啟動
- hosts: web01
tasks:
- name: Check Nginx
shell: ps -ef | grep [n]ginx # 判斷是否啟動
ignore_errors: yes #忽略錯誤,如果沒有啟動就報錯,ansible就會停止,所以要忽略錯誤
register: check_nginx #變數註冊
- name: Stop Nginx
service:
name: nginx
state: stopped
when: check_nginx.rc == 0 # 返回值為0是啟動,非0就是沒有啟動
5.2、playbook迴圈語句
ansible操作多臺主機,需要傳送檔案,建立目錄之類的,建立兩個目錄需要兩個file模組來建立,100個需要100個file模組,為了提高工作效率,可以使用迴圈,減少重複性程式碼。
1)定義迴圈安裝服務
- hosts: web_group
tasks:
- name: Install Nginx and Nfs
yum:
name: "{{ nginx_nfs }}"
vars:
nginx_nfs:
- nginx
- nfs-server
2)定義迴圈啟動服務
# 錯誤寫法
- hosts: web01
tasks:
- name: Start Server
service:
name: "{{ packages }}"
state: started
vars:
packages:
- nginx
- httpd
# 正確寫法
- hosts: web01
tasks:
- name: Start Server
service:
name: "{{ item }}"
state: started
with_items:
- nginx
- httpd
3)字典定義變數
- hosts: web_group
tasks:
- name: Create Some Group
group:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
state: present
with_items:
- { name: "haopapa", gid: "666" }
- { name: "papahao", gid: "777" }
- { name: "pahaopa", gid: "888" }
- hosts: web_group
tasks:
- name: Create Some User
user:
name: "{{ item.user }}"
uid: "{{ item.uid }}"
group: "{{ item.group }}"
shell: "{{ item.shell }}"
create_home: "{{ item.create_home }}"
with_items:
- { name: "a", uid: "111", group: "www", shell: "/sbin/nologin", create_home: "false" }
- { name: "b", uid: "222", group: "www", shell: "/sbin/nologin", create_home: "false" }
- { name: "c", uid: "333", group: "www", shell: "/sbin/nologin", create_home: "false" }
- { name: "d", uid: "444", group: "www", shell: "/sbin/nologin", create_home: "false" }
六、playbook handlers觸發器
6.1、什麼是handlers?
handlers用來執行某些條件下的任務,比如當配置檔案發生變化的時候,通過notify觸發handler去重啟服務
在saltstack中也有類似的觸發器,寫法相對ansible簡單,只需要watch,配置檔案即可。
6.2、配置觸發器
- hosts: web01
tasks:
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx #配置notify
- name: Start Nginx Server
service:
name: nginx
state: started
handlers: #handlers放在最後,所以tasks執行完之後,執行handlers
- name: restart_nginx
service:
name: nginx
state: restarted
6.3、觸發器使用注意事項
1.無論'多少個task'通知了相同的handlers, handlers僅會在tasks結束後'執行一次'。
2.handlers只有在'其所在'的任務'被執行時',才會被'執行';如果一個任務中定義了notify呼叫handlers,但是由於條件判斷等原因,該任務未被執行,那麼handlers同樣不會執行。
3.handlers只會在每一個play的'末尾執行'一次;如果想在一個playbook'中間執行'handelers,則需要'meta模組'來實現,例如:flush_handlers。
4.如果一個play在執行到呼叫handlers的語句之前失敗了,那麼這個handlers將不會被執行,我們可以使用meta模組的-'-force-handlers'選項來'強制執行handlers',即使handlers所在的play中途執行失敗也能執行。
6.4、示例:
[root@m01 project]# cat php.yml
- hosts: web_group
tasks:
- name: Tar php Package
unarchive:
src: /project/package/php.tar.gz
dest: /tmp/
- name: Check php Install Status
shell: "rpm -qa | grep php | wc -l"
register: get_php_instll_status
- name: Install php Server
shell: "yum localinstall -y /tmp/*.rpm"
when: get_php_instll_status.stdout_lines == 0
- name: Config php Server
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
with_items:
- { src: "/project/conf/php.ini", dest: "/etc" }
- { src: "/project/conf/www.conf", dest: "/etc/php-fpm.d/" }
notify: restart_php
- name: Start php Server
systemd:
name: php-fpm
state: started
handlers:
- name: restart_php
systemd:
name: php-fpm
state: restarted
七、playbook任務標籤
7.1、標籤的作用
預設情況下,Ansible在執行一個playbook時,會執行playbook中定義的所有任務,Ansible的標籤(tag)功能可以給單獨任務設定整個playbook打賞標籤,然後利用這些標籤來指定要執行playbook中個別任務,或不執行執行任務。
7.2、打標籤的方式
1.對一個task打一個標籤
2.對一個task打多個標籤
3.對多個task打一個標籤
7.3、對一個task打一個標籤
- hosts: web01
task:
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx
tags: reconf_nginx # 在某一個任務上打上標籤
7.3、對多個task打一個標籤
- hosts: nginx
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx
tags: reconf_nginx # 在某一個任務上打上標籤
- name: Config Nginx wordpress
copy:
src: /project/conf/linux.wp.com.conf
dest: /etc/nginx/conf.d/
notify: reload_nginx
when: (ansible_fqdn == "web01") or (ansible_fqdn == "web02")
tags: reconf_nginx #同一個標籤
7.4、對一個task打多個標籤
- hosts: nginx
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx
tags:
- reconf_nginx
- reconfig_nginx #在同一個任務上打多個標籤
7.5、標籤使用方式
1)檢視標籤
# ansible-playbook ceshi.yaml --list-tags
playbook: ceshi.yaml
play #1 (web01): web01 TAGS: []
TASK TAGS: [httpd_start, nginx_start]
2)執行指定標籤的內容
# 執行指定標籤代表的內容
ansible-playbook ceshi.yaml -t nginx_start
# 執行指定多個標籤代表的內容
ansible-playbook ceshi.yaml -t nginx_start,httpd_start
3)不執行指定標籤的內容
ansible-playbook ceshi.yaml --skip-tags nginx_start
# 八、palybook的複用
playbok提供了include功能,可以呼叫多個yaml檔案內的task任務列表統一執行,可以實現將功能拆分模組化,'可以理解為鬆耦合',然後根據需求呼叫各個模組去執行任務
8.1、playbook複用的配置
1)編輯兩個劇本
# cat play1.yaml
- name: Install Nginx
yum:
name: nginx
# cat play2.yaml
- name: Config Nginx
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
2)編寫複用劇本的檔案
- hosts: web_group
tasks:
- include_tasks: /tmp/play1.yaml
- include_tasks: /tmp/play2.yaml
3)直接複用playbook檔案
[root@m01 project]# cat main.yml
- import_playbook: ./base.yml
- import_playbook: ./nginx.yml
- import_playbook: ./php.yml
- import_playbook: ./wordpress.yml
- import_playbook: ./mariadb.yml
九、playbook其他功能
9.1、playbook忽略錯誤
預設playbook會檢測task執行的返回狀態,如果遇到錯誤則會立即終止playbook的後續task執行,然而有些playbook即使執行錯誤了也要讓其繼續執行
# ignore_errors:yes 忽略錯誤
- hosts: web_group
tasks:
- name: Ignore False
shell: /bin/false # 出現錯誤,playbook停止
ignore_errors: yes # 忽略錯誤,ansible繼續執行
當task執行失敗是,playbook將不再執行,如果在task設定了handlers也不會被執行,所以可以使用強制呼叫handler
9.2、強制呼叫handler
# force_handlers: yes 強制呼叫handlers
- hosts: web_group
force_handlers: yes # 在hosts層寫上強制呼叫
tasks:
- name: Send Nginx Config
template:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify:
- restart_nginx
- restart_php-fpm
- name: Make False
shell: /bin/false # 人為製造錯誤
handlers:
- name: restart_nginx
systemd:
name: nginx
state: restarted
- name: restart_php-fpm
systemd:
name: php-fpm
state: restarted
# 正常情況下,playbook會在發生錯誤時停止執行playbook,handlers不會被執行,因為在最前面開啟了強制呼叫handlers,所以handlers還是會執行。
9.3、抑制changed
被管理主機沒有發生變化,可以使用引數將change狀態改為ok
# changed_when 被管理主機沒有變化,將change狀態改為ok
- hosts: web_group
tasks:
- name: shell
shell: netstat -tupln | grep nginx
register: grep_port
changed_when: false # 沒有改變時,狀態改為ok
9.4、max_fail_percentage
一般來講,當task失敗時,ansible會停止執行失敗的那臺主機上的任務,但是繼續對其他 主機執行。在負載均衡的場景中,我們會更希望ansible在所有主機執行失敗之前就讓play停止,否則很可能會面臨所有主機都從負載均衡器上摘除並且都執行失敗導致服務不可用的場景。這個時候,我們可以使用'serial'語句'配合'---'max_fail_percentage語句使用'。'max_fail_percentage'表示當最大失敗主機的比例達到多少時,ansible就讓整個play'失敗'
假如負載均衡後面有4臺主機,並且有一臺主機執行失敗,這時ansible還會繼續執行,要讓Play停止執行,則必須超過25%,所以如果想一臺失敗就停止執行,我們可以將max_fail_percentage的值設為24。如果我們希望只要有執行失敗,就放棄執行,我們可以將max_fail_percentage的值設為0。
9.5、serial每次在指定數量的主機上執行playbook
serial的值為1,即表示在某一個時間段內,play只在一臺主機上執行。如果為2,則同時有2臺主機執行play
9.6、ignore_errors
在執行playbook時,不可避免會遇到一些錯誤。ansible預設處理錯誤的機制是遇到錯誤就停止執行。但有些時候,有些錯誤是計劃之中的。我們希望忽略這些錯誤,以讓playbook繼續往下執行。這個時候就需要用到ignore_erros了
ignore_errors: yes
9.7、when用法
1. when: ansible_fqdn == "lb01" 匹配一臺主機
2. when: ansible_fqdn != "lb01" 取反
3. when: ansible_fqdn is match "web*" 匹配多臺主機
when 的 in 和 and 及 or 用法
when:
ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux'] and
(ansible_distribution_version|version_compare('7', '<') or
ansible_distribution_version|version_compare('8', '>='))
or
ansible_distribution == 'Fedora'
or
ansible_distribution == 'Ubuntu' and
ansible_distribution_version|version_compare('15.04', '>=')
# 更加簡潔的用法
when:
- ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux']
- ansible_distribution_version|version_compare('15.04', '>=')
十、Ansible Jinja2模板概述
10.1、Jinja2模板概述
# 什麼是Jinja2模板
Jinja2是python的全功能模板引擎,是Flask作者開發的一個模板系統,起初是模仿django模板的一個模板引擎,為flask提供模板支援。Jinja2能識別所有的pythone資料型別字典、物件等等。
# 優點:
1.相對於 template , Jinja2更加靈活,提供了控制結構,表示式和繼承等。
2.相對於Mako,Jinja2僅有控制結構,不允許在模板中編寫太多的業務邏輯
3.相對於Django模板,Jinja2效能更好
4.Jinjs2模板的可讀性很好。
# Jinja2與Ansible關係
Ansible通常會使用Jinja2模板來修改被管理主機的配置檔案等,在saltstack中同樣會使用到Jinja2
# Ansible如何使用Jinja2
使用Ansible的Jinja2模板也就是使用template模組,該模組和copy模組一樣,都是將'檔案複製'到遠端主機上去,但是區別在於, template模組可以獲取到檔案中的變數,而copy則是原封不動的把檔案內容複製過去。'template能識別變數','copy不能'.
# Ansible使用Jinja2注意事項
Ansible允許Jinja2模板中使用條件判斷和迴圈,但是不允許在playbook中使用。
# 不是每個管理員都需要這個特性,但是有些時候Jinja2模板能大大提高效率
10.2、Ansible Jinja2模板使用
1)變數使用語法
{{ EXPR }} 輸出變數值,會輸出自定義的變數值或facts
Jinja2模板中使用 {{ }} 語法表發一個變數,它是一種特殊的佔位符,當利用jinja2進行渲染的時候,他會把這些特殊的佔位符進行填充/替換。
搭配 template 模組進行使用
2)邏輯判斷語法
# 條件判斷
{% if EXPR %}
{% elif EXPR %}
{% else EXPR %}
{% endif EXPR %}
3)迴圈語法
# 迴圈表示式 支援python中的變數語句
range就是python中經常使用的取值範圍,和shell中`seq 20`一樣
{% for i in range(7,20) %}
{% endfor %}
4)註釋
Jinja2註釋語法
{# COMMENT #}
shell中只是在內容最前面加上#
10.3、Jinja2模板測試
1)配置登陸檔案的Jinja2模板
# vim motd.j2
Welcome to {{ ansible_fqdn }}
This system total mem is : {{ ansible_memtotal_mb }} MB
This system free mem is : {{ ansible_memfree_mb }} MB
# 編寫劇本
- hosts: all # all代表主機清單中所有主機
tasks:
- name: Send Motd
template:
src: /root/motd.j2
dest: /etc/motd
# 執行檢視結果
[root@m01 project]# ansible-playbook motd.yml
#檢視結果 以下結果只是推過來時候檢視一次,不是動態表示,做測試用檢視
Last login: Thu Dec 24 15:29:37 2020 from 10.0.0.61
Welcome to db01
This system total mem is : 972 MB
This system free mem is: 267 MB
2)配置負載均衡nginx
vim upstream.j2
upstream {{ server_name }} {
{{ for i in range(7,20) }}
server {{ net_ip }}.{{ i }};
{{ endfor }}
}
server {
server_name {{ server_name }};
listen {{ nginx_port }};
location / {
proxy_pass http://{{server_name}};
include proxy_params;
}
}
# 準備變數檔案
vim upstream_vars.yml
server_name: www.papacnb.com
nginx_port: 80
net_ip: 172.16.1
# 編寫劇本
- hosts: lb
tasks:
- name: Send Nginx Conf File
template:
src: /root/upstream.j2
dest: /etc/nginx/conf.d/upstream.conf
notify: restart_upstream
- name: start nginx
service:
name: nginx
state: started
handlers:
- name: restart_upstream
service:
name: nginx
state: restarted
# 執行並測試
### 3)keepalived配置檔案
# 編輯配置檔案--使用變數+判斷語句
[root@m01 project]# vim keepalived.conf
global_defs {
router_id {{ ansible_fqdn }} # 變數
}
vrrp_instance VI_1 {
{% if ansible_fqdn == lb01 %} # 判斷
state MASTER
{% else %} # 判斷
state BACKUP
{% endif %} # 結束判斷
interface eth0
virtual_router_id 50
{% if ansible_fqdn == lb01 %} # 判斷
priority 100
{% else %} # 判斷
priority 90
{% endif %} # 結束判斷
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.3
}
}
# 編輯劇本
- hosts: lb_group
tasks:
- name: Send Keepalived.conf
template:
src: keepalived.conf
dest: /etc/keepalived/
notify: restart_keepalived
handlers:
- name: restart_keepalived
service:
name: keepalived
state: restarted