角色(roles):把playbook根據功能,如handler,tasks等分門別類的放在在各自的子目錄下,形成一個集合,就是角色。
Roles目錄可以是ansible.cfg中roles_path定義的路徑,也可以和入口Playbook文件存放在同級目錄。建議使用roles_path,方便統一管理。這篇的示例使用和入口Playbook文件存放在同級目錄。
Roles are ways of automatically loading certain vars_files, tasks, and handlers based on a known file structure. Grouping content by roles also allows easy sharing of roles with other users.
官方文檔的連接:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html
github上官方的簡單示例:
https://github.com/ansible/ansible-examples
最佳實踐的官方文檔:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html
Roles 目錄結構
Roles依賴目錄命名規則和目錄擺放。下面是官方的示例,定義了一個Roles的目錄結構:
site.yml
webservers.yml
fooservers.yml
roles/
common/
tasks/
handlers/
files/
templates/
vars/
defaults/
meta/
webservers/
tasks/
defaults/
meta/
- *.yml文件: 入口Playbook文件
- site.yml: 這個名字一般就是部署項目的Playbook文件名。如果還有其他任務在創建Playbook,名字隨意。
- roles目錄: 存放Roles的目錄。下面每一個子目錄就是一個角色,這裏有common和webservers
在每個角色下,根據功能按需創建目錄,目錄名有規範。每個目錄下都要有一個main.yml文件,ansible會調用這個文件。
目錄名稱的含義如下:
- tasks: 定義角色的任務列表,可以使用include包含其它的位於此目錄的task文件
- handlers: 定義角色中觸發條件時執行的動作
- defaults: 設定默認變量,優先級極低,基本就是該變量沒有值的時候纔會用到這個值
- vars: 定義角色使用的變量,優先級高
- files: 用來存放由copy模塊或script模塊調用的文件。不需要main.yml文件
- templates: 用來存放jinjia2模板,template模塊會自動在此目錄中尋找jinjia2模板文件。不需要main.yml文件
- meta: 定義角色的元數據,主要是用作依賴關係
多平臺支持
官方有一個在tasks裏區分的多平臺支持的示例。
另外還有一個從書上看到的不同平臺定義不同角色名的示例。
最後是一個在官方最佳實踐中的示例。
tasks 多平臺支持
tasks級別,對應tasks目錄。
定義好角色,角色下定義多個task文件。在main.yml中進行條件判斷,導入對應的task文件。
tasks/main.yml是必須有的,作爲tasks的入口文件,但是實際的代碼不用寫在這個文件裏,可以在這個文件裏包含其他yaml文件。官方有一個多平臺支持的示例:
# roles/example/tasks/main.yml
- import_tasks: redhat.yml
when: ansible_facts['os_family']|lower == 'redhat'
- import_tasks: debian.yml
when: ansible_facts['os_family']|lower == 'debian'
# roles/example/tasks/redhat.yml
- yum:
name: "httpd"
state: present
# roles/example/tasks/debian.yml
- apt:
name: "apache2"
state: present
roles 多平臺支持
角色級別,對應roles下的角色子目錄,比如common和webservers目錄。
直接定義好多個角色,有條件地將所有的角色導入。只有滿足要求的角色會被導入執行。
在roles層面來支持多平臺。預先爲不同平臺定義好不用的角色。比如兩個角色名分別爲 httpd_db 和 httpd_rh。那麼Playbook文件可以這麼寫:
# site.yml
- name: install httpd
hosts: webservers
roles:
- { role: httpd_db, when: ansible_os_family == 'Deian' }
- { role: httpd_rh, when: ansible_os_family == 'RedHat' }
這裏的判斷平臺的方式和上面的應該是一樣的,都是通過Ansible自動獲取的主機信息來進行自動判斷。這裏的寫法比上面的官網的寫法low。我沒有實際測試,就保留原來的寫法了。
group_by 模塊自動對主機分組
playbook級別,對應roles的同級目錄,比如site.yml文件。
先執行一個 group_by 模塊的task,對主機進行動態分組。之後再分別對組進行playbook的設置。
這部分內容和roles無關,用了roles可以套用,沒用roles也可以套用。是官方最佳實踐裏的做法。
group_by 模塊可以根據關鍵字對主機進行分組。關鍵字可以從主機信息中提取,提取到之後,可以先拼接上一段自定義的前綴或後綴。最終獲得的字符串會成爲一個主機組的組名,這樣Playbook中的hosts就可以直接填寫這個組名:
---
- name: talk to all hosts just so we can learn about them
hosts: all
tasks:
- name: Classify hosts depending on their OS distribution
group_by:
key: os_{{ ansible_facts['distribution'] }}
# now just on the CentOS hosts...
- hosts: os_CentOS
gather_facts: False
tasks:
- # tasks that only happen on CentOS go here
通過 group_by 模塊動態爲主機添加了分組,還可以事先創建好組變量文件,這些組變量也是會生效的。
Using Roles
官網有各種花式技巧:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html#using-roles
各種花式技巧:
- 把role寫在tasks中,這是一種新的語法格式。可以在引入role的前後執行別的task
- 使用絕對路徑引入role
- 引入role的同時,定義變量
- 有條件的導入role,上面roles的多平臺就是這麼用的
- 爲角色添加標籤。使用場景我還沒想明白
角色依賴關係
通過角色依賴,可以在使用角色時自動加入其它角色。角色依賴定義在 meta/main.yml 文件中的 dependencies 下,內容包含當前角色的依賴角色和依賴角色的參數列表。
配置文件示例:
---
dependencies:
- role: common
vars:
some_parameter: 3
- role: apache
vars:
apache_port: 80
- role: postgres
vars:
dbname: blarg
other_parameter: 12
角色的依賴關係,僅僅是meta文件中的一個key,也就是dependencies。別的key還有allow_duplicates,這個是定義角色可以重複執行任務的。其他key暫時在文檔中沒有出現。
角色中嵌入模塊和插件
在目錄結構中,列出了角色使用的基本目錄名稱。這裏的自定義模塊和插件也是放在roles目錄下的角色名子目錄中的。
新的目錄結構:
roles/
webservers/
tasks/
defaults/
meta/
library/
module1
module2
filter_plugins
filter1
filter2
在webservers角色下添加了自定義模塊,目錄名稱使用library。
ansible的插件有很多種,這裏是在webserver角色下,爲filter插件添加了兩個自定義功能的文件。
項目目錄結構
這裏是 Ansible 官方最佳實踐中推薦的一個工作目錄的結構:
production # 生產環境的 inventory 文件
stage # 試運行環境的 inventory 文件
group_vars/ # 定義組變量
group1
group2
host_vars/ # 定義主機變量
hostname1
hostname2
library/ # 如果有自定義的模塊,放在這裏(可選)
module_utils/ # 如果有自定義的模塊中要使用的工具,放在這裏(可選)
filter_plugins/ # 如果有自定義的過濾插件,放在這裏(可選)
site.yml # 主 playbook
webservers.yml # Web 服務器的 playbook
dbservers.yml # 數據庫服務器的 playbook
roles/ # role 文件存放目錄
common/ # common 角色目錄
tasks/ #
main.yml # task 入口
handlers/ #
main.yml # handler 入口
templates/ # 存放模板文件
ntp.conf.j2 #
files/ # 存放文件資源
bar.txt #
foo.sh #
vars/ #
main.yml # 定義角色使用的變量
defaults/ #
main.yml # 定義角色默認變量
meta/ #
main.yml # 定義角色依賴
webservers/ # webservers 角色目錄,不展開了
這裏的自定義模塊和插件是放在項目目錄下的,不會自動生效。
library的默認值: ~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
filter_plugins的默認值: ~/.ansible/plugins/filter:/usr/share/ansible/plugins/filter
官方文檔的這篇裏可以查到很多有關Ansible設置相關的信息,包括每個變量在配置文件中的名稱,在環境變量中的名稱,以及變量的默認值。
https://docs.ansible.com/ansible/latest/reference_appendices/config.html
可以去修改 ansible.cfg 配置文件,也可以利用默認的家目錄中的位置,創建軟連接。