1. 程式人生 > 其它 >Ansible-變數----Jinja2模板--------------------亂雲低薄暮,急雪舞迴風

Ansible-變數----Jinja2模板--------------------亂雲低薄暮,急雪舞迴風

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