文章目錄
- 一、Playbook簡介
- 三種常見的數據格式
- Playbook特點
- YAML語言介紹
- 二、Playbook核心組件
- host組件
- remote_user組件
- task列表和action組件
- gather_facts
- Handlers notify
- ignore_errors
- 三、playbook命令
- playbook命令
- tags 標簽
- 四、Playbook中的變量
- setup模塊中的變量
- Playbook命令行中定義變量
- 定義變量文件
- 直接在playbook文件中建立變量
- 使用獨立的變量文件
- 針對主機和主機組的變量
- 四、template模版技術
- Jinja2簡介
- template
- template中使用流程控制for和 if
- 五、循環迭代
- 迭代with_items(loop)
- 迭代嵌套子變量
- playbook中使用when
- 六、角色
- 建立role
一、Playbook簡介
在Ansible中,playbook就是一個包含了要在遠程主機上執行的一系列任務的文件。通過playbook,可以實現自動化配置、部署和管理遠程主機的操作。它可以定義任務的順序、條件、并發執行等,是Ansible自動化工具中的核心組件之一。通過編寫和執行playbook,可以實現系統管理的自動化和規范化。
三種常見的數據格式
- XML:Extensible Markup Language,可擴展標記語言,可用于數據交換和配置
- JSON:JavaScript Object Notation, JavaScript 對象表記法,主要用來數據交換或配置,不支持注釋
- YAML:YAML Ain’t Markup Language YAML 不是一種標記語言, 主要用來配置,大小寫敏感,不支持tab。
注意:ansible使用的YAML語言。
由于YAML語言不支持tab所以我們設置一些vim編輯器的選項
set ai 開啟自動縮進
set ts=2 設置Tab鍵的寬度為2個空格
Playbook特點
- playbook 劇本是由一個或多個"play"組成的列表。
- play的主要功能在于將預定義的一組主機,裝扮成事先通過ansible中的task定義好的角色。Task實際是調用ansible的一個module,將多個play組織在一個playbook中,即可以讓它們聯合起來,按事先編排的機制執行預定義的動作。
- Playbook 文件是采用YAML語言編寫的。
YAML語言介紹
YAML:YAML Ain’t Markup Language,即YAML不是標記語言。不過,在開發的這種語言時,YAML的意思其實是:“Yet Another Markup Language”(仍是一種標記語言)
YAML是一個可讀性高的用來表達資料序列的格式。YAML參考了其他多種語言,包括:XML、C語言、Python、Perl以及電子郵件格式RFC2822等。Clark Evans在2001年在首次發表了這種語言,另外Ingy d?t Net與Oren Ben-Kiki也是這語言的共同設計者,目前很多最新的軟件比較流行采用此格式的文件存放配置信息,如:ubuntu,anisble,docker,kubernetes等。
YAML官方網站:http://www.yaml.organsible 官網: https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
YAML語言特性
- YAML的可讀性好
- YAML和腳本語言的交互性好
- YAML使用實現語言的數據類型
- YAML有一個一致的信息模型
- YAML易于實現
- YAML可以基于流來處理
- YAML表達能力強,擴展性好
YAML語法簡介
- 在單一文件第一行,用連續三個連字號"-" 開始,還有選擇性的連續三個點號( … )用來表示文件的結尾
- 次行開始正常寫Playbook的內容,一般建議寫明該Playbook的功能
- 使用#號注釋代碼
- 縮進必須是統一的,不能空格和tab混用
- 縮進的級別也必須是一致的,同樣的縮進代表同樣的級別,程序判別配置的級別是通過縮進結合換行來實現的
- YAML文件內容是區別大小寫的,key/value的值均需大小寫敏感
- 多個key/value可同行寫也可換行寫,同行使用,分隔
- key后面冒號要加一個空格 比如: key: value
- value可是個字符串,也可是另一個列表
- YAML文件擴展名通常為yml或yaml
支持的數據類型
- YAML 支持以下常用幾種數據類型:
- 標量:單個的、不可再分的值
- 對象:鍵值對的集合,又稱為映射(mapping)/ 哈希(hashes) / 字典(dictionary)
- 數組:一組按次序排列的值,又稱為序列(sequence) / 列表(list)
二、Playbook核心組件
一個playbook 中由多個組件組成,其中所用到的常見組件類型如下:
- Hosts 執行的遠程主機列表
- Tasks 任務集,由多個task的元素組成的列表實現,每個task是一個字典,一個完整的代碼塊功能需最少元素需包括 name 和 task,一個name只能包括一個task。
- Variables 內置變量或自定義變量在playbook中調用。
- Templates 模板,可替換模板文件中的變量并實現一些簡單邏輯的文件。
- Handlers 和 notify 結合使用,由特定條件觸發的操作,滿足條件方才執行,否則不執行。
- tags 標簽 指定某條任務執行,用于選擇運行playbook中的部分代碼。ansible具有冪等性,因此會自動跳過沒有變化的部分,即便如此,有些代碼為測試其確實沒有發生變化的時間依然會非常地長。此時,如果確信其沒有變化,就可以通過tags跳過此些代碼片斷。
注意:查看模塊用法 用ansible-doc 加上 模塊名 可以查看模塊的使用方法和例子
host組件
Hosts:playbook中每一個play的目的都是為了讓特定主機以某個指定的用戶身份執行任務。hosts用于指定要執行指定任務的主機,需要事先定義在主機清單中。
host文件的例子
Websrvs:dbsrvs #或者,兩個組的并集W
ebsrvs:&dbsrvs #與,兩個組的交集
webservers:!dbsrvs #在websrvs組,但不在dbsrvs組
- hosts: websrvs:appsrvs
remote_user組件
remote_user: 可用于Host和task中。也可以通過指定其通過sudo的方式在遠程主機上執行任務,其可用于play全局或某任務;此外,甚至可以在sudo時使用sudo_user指定sudo時切換的用戶。
- hosts: websrvs remote_user: zhangsan tasks:- name: test connection ping:remote_user: wangsudo: yes#默認sudo為rootsudo_user:wang#sudo為wang
task列表和action組件
play的主體部分是task list,task list中有一個或多個task,各個task 按次序逐個在hosts中指定的所有主機上執行,即在所有主機上完成第一個task后,再開始第二個task。
task的目的是使用指定的參數執行模塊,而在模塊參數中可以使用變量。模塊執行是冪等的,這意味著多次執行是安全的,因為其結果均一致每個task都應該有其name,用于playbook的執行結果輸出,建議其內容能清晰地描述任務執行步驟。如果未提供name,則action的結果將用于輸出。
寫yml時,一定要注意對齊!
set ai 開啟自動縮進
set ts=2 設置Tab鍵的寬度為2個空格
gather_facts
作用:收集信息
表示不收集信息,但是使用變量是需要收集。
默認是收集信息的。
---
- hosts: webremote_user: rootgather_facts: notasks:-name: install httpd yum: name=httpd-name: start httpdservice: name=httpd state=started enabled=yes
Handlers notify
Handlers本質是task list ,類似于MySQL中的觸發器觸發的行為,其中的task與前述的task并沒有本質上的不同,主要用于當關注的資源發生變化時,才會采取一定的操作。而Notify對應的action可用于在每個play的最后被觸發,這樣可避免多次有改變發生時每次都執行指定的操作,僅在所有的變化發生完成后一次性地執行指定操作。在notify中列出的操作稱為handler,也即notify中調用handler中定義的操作。
注意:
- 如果多個task通知了相同的handlers, 此handlers僅會在所有tasks結束后運行一 次。
- 只有notify對應的task發生改變了才會通知handlers,沒有改變則不會觸發handlers 。
- handlers 是在所有前面的tasks都成功執行才會執行,如果前面任何一個task失敗,會導致handler跳過執行,可以使用force_handlers: yes 強制執行handler。
---- hosts: webgather_facts: notasks:- name: add groupgroup: name=nginx state=present- name: add useruser: name=nginx state=present group=nginx- name: install epelyum: name=epel-release.noarch state=present- name: install nginxyum: name=nginx state=present- name: config filecopy: src=/data/nginx.conf dest=/etc/nginxnotify:- restart nginxhandlers:- name: restart nginxservice: name=nginx state=restarted
~
當配置文件發生改動時,才會觸發handlers,并重新啟動nginx。注意notify和handlers是成對出現的。notify下面的名字和handlers的名字要一致。
ignore_errors
如果一個task出錯,默認將不會繼續執行后續的其他task。利用ignore_errors:yes可以忽略此task的錯誤,繼續向下執行playbook其它的task。
playbook是默認順序執行的,當一個出錯之后,便不會執行下一個,所以對于那些不重要的命令,如果執行不成功,即可忽略。
---
- hosts: websrvstasks:- name: errorcommand: /bin/falseignore_errors: yes- name: continuecommand: wall continue
三、playbook命令
playbook命令
命令 | 含義 |
---|---|
–syntax-check | 語法檢查,可縮寫成–syntax, 相當于bash -n |
-C --check | 模擬執行,只檢測可能會發生的改變,但不真正執行操作,dry run |
–list-hosts | 列出tag |
–list-tasks | 列出task |
–limit | 只針對主機列表中的特定主機執行 --limit 主機地址 |
-i INVENTORY | 指定主機清單文件,通常一個項對應一個主機清單文件 |
–start-at-task START_AT_TASK | 從指定task開始執行,而非從頭開始,START_AT_TASK為任務的name |
-v -vv -vvv | 顯示過程 |
tags 標簽
在playbook文件中,可以利用tags組件,為特定 task 指定標簽,當在執行playbook時,可以只執行特定tags的task,而非整個playbook文件。
tag就相當于標簽。
vim httpd.yml
---
# tags example
- hosts: websrvsremote_user: rootgather_facts: notasks:- name: Install httpdyum: name=httpd state=present- name: Install configure filecopy: src=files/httpd.conf dest=/etc/httpd/conf/tags: conf- name: start httpd servicetags: serviceservice: name=httpd state=started enabled=yes
ansible-playbook –t conf,service httpd.yml
四、Playbook中的變量
變量名:僅僅能由字母、數字和下劃線組成,且只能以字母開頭。
變量調用方式:
通過{{ variable_name }} 調用變量,且變量名前后建議加空格,有時用"{{ variable_name }}"才生效。
變量來源:
-
ansible 的 setup facts 遠程主機的所有變量都可直接調用
-
通過命令行指定變量,優先級最高
setup模塊中的變量
本模塊自動在playbook調用,不要用ansible命令調用,生成的系統狀態信息, 并存放在facts變量中。詳情可以用ansible-doc setup查詢。facts 包括的信息很多,如: 主機名,IP,CPU,內存,網卡等。
facts 變量的實際使用場景案例:
- 通過facts變量獲取被控端CPU的個數信息,從而生成不同的Nginx配置文件。
- 通過facts變量獲取被控端內存大小信息,從而生成不同的memcached的配置文件。
- 通過facts變量獲取被控端主機名稱信息,從而生成不同的Zabbix配置文件。
利用setup 模塊中的變量生成日志文件
---
- hosts: webremote_user: rootgather_facts: yestasks:- name: create log filefile: name=/data/{{ ansible_nodename }}.log state=touch owner=zhangsan mode=600
Playbook命令行中定義變量
"{ { 變量名 } } "
使用ansible-playbook -e 選項,在使用命令時定義變量。
- hosts: webgather_facts: notasks:- name: create useruser: name={{ myname }} system=yes create_home=noansible-playbook -e myname=cxk -e myname1=wyf playbook
定義變量文件
- hosts: webgather_facts: notasks:- name: install {{pkname1}}yum: name={{pkname1}} state=present- name: install {{pkname2}}yum: name={{pkname2}} state=presentansible-playbook -e "@var" test1.yml
# @代表文件 var 即是文件名
注意:
1.var文件要在同一文件夾中
2.定義變量時
tasks:- name: install "{{pkname1}}"
或者
tasks:- name: "install {{pkname1}}"
直接在playbook文件中建立變量
方法是:使用vars組件。
---
- hosts: webvars:username: test1groupname: group1tasks:- name: create groupgroup: name={{ groupname }} state=present- name: create useruser: name={{ username }} state=present
變量之間相互調用
---
- hosts: websvars: suffix: "txt"file: "{{ ansible_nodename }}.{{suffix}}"tasks:- name: test varfile: path="/data/{{file}}" state=touch
使用獨立的變量文件
可以在一個獨立的playbook文件中定義變量,在另一個playbook文件中引用變量文件中的變量,比playbook中定義的變量優化級高。
先寫一個變量文件
vim vars.yml
---
# variables file
package_name: mariadb-server
service_name: mariadb
然后調用這個文件
vim var5.yml
---
#install package and start service
- hosts: dbsrvsremote_user: rootvars_files:- vars.ymltasks:- name: install packageyum: name={{ package_name }}tags: install- name: start serviceservice: name={{ service_name }} state=started enabled=yes
針對主機和主機組的變量
在inventory主機清單文件中指定的主機定義變量以便于在playbook中使用。
在hosts文件中修改,并且只針對單個主機。
[websrvs]
www1.cxk.com http_port=80 maxRequestsPerChild=808
www2.cxk.com http_port=8080 maxRequestsPerChild=909
#只是針對單個主機
例子:
vim /etc/ansible/hosts
[web]
192.168.232.20 hname=www1 domain=accp.com
192.168.232.30 hname=www2 domain=cxk.com[web:vars]
mark='-'ansible web -m hostname -a 'name={{ hname }}{{ mark }}{{ domain }}'
這些變量只針對單個主機有效。
四、template模版技術
Ansible模板技術是Ansible自動化工具中的一個重要特性,它使用Jinja2模板引擎來生成動態配置文件。
Jinja2簡介
Jinja2 是一個現代的,設計者友好的,仿照 Django 模板的 Python 模板語言。 它速度快,被廣泛使用,并且提供了可選的沙箱模板執行環境保證安全:
特性:
- 沙箱中執行
- 強大的 HTML 自動轉義系統保護系統免受 XSS
- 模板繼承
- 及時編譯最優的 python 代碼
- 可選提前編譯模板的時間
- 易于調試。異常的行數直接指向模板中的對應行。
- 可配置的語法
http://docs.jinkan.org/docs/jinja2/
https://www.w3cschool.cn/yshfid/
官方中文文檔
template
template功能:可以根據和參考模塊文件,動態生成相類似的配置文件 template文件必須存放于templates目錄下,且命名為 .j2 結尾 yaml/yml 文件需和templates目錄平級。
是這樣一個目錄:
但是用template模塊式,它會用模版生成的內容完全替換目標文件。 請特別注意。
template中使用流程控制for和 if
for循環
例子生成虛擬主機。
準備j2文件,注意for循環有其固定的寫法。
vim templates/for1.j2
# 準備 j2 文件{% for vhost in nginx_vhosts %}
server {listen {{ vhost }}
}
{% endfor %}
這邊定義了一個變量vhost。
準備yml文件
---
- hosts: webvars:nginx_vhosts:- 81- 82- 83tasks:- name: template configtemplate: src=for1.j2 dest=/data/test.conf
這樣即可完成。
五、循環迭代
需要執行重復性的任務時,需要用迭代機制。
迭代with_items(loop)
對迭代項的引用,固定內置變量名為"item";要在task中使用with_items給定要迭代的元素列表;注意: ansible2.5版本后,可以用loop代替with_items。
---
- hosts: webgather_facts: notasks:- name: create useruser: name={{ item }} state=present groups=wheelwith_items:- testuser1- testuser2- testuser3
**注意= 號后不要空格**上面語句的功能等同于下面的語句- name: add several users user: name=testuser1 state=present groups=wheel- name: add several usersuser: name=testuser2 state=present groups=wheel- name: add several usersuser: name=testuser3 state=present groups=wheel
迭代嵌套子變量
在迭代中,可以嵌套自變量,用來提高工作效率。
例子:
批量建立用戶
---
- hosts: webgather_facts: notasks:- name: create groupgroup: name={{ item }} state=presentwith_items:- nginx- mysql- tomcat- name: create useruser: name={{ item.user }} group={{ item.group }} uid={{ item.uid }} state=presentwith_items:- { user: 'nginx', group: 'nginx' , uid: '80' }- { user: 'mysql', group: 'mysql' , uid: '3306' }- { user: 'tomcat', group: 'tomcat' , uid: '8080' }
playbook中使用when
when語句可以實現條件測試。如果需要根據變量、facts或此前任務的執行結果來做為某task執行與否的前提時要用到條件測試,通過在task后添加when子句即可使用條件測試,jinja2的語法格式。
---
- hosts: webtasks:- name: install sl "{{ ansible_os_family }}"yum: name=slwhen: ansible_os_family == "RedHat"- name: install sl "{{ ansible_os_family }}"apt: name=slwhen: ansible_os_family == "Debian"#ansible_os_family
根據不同的系統,使用不同的安裝命令。
六、角色
角色是ansible自1.2版本引入的新特性,用于層次性、結構化地組織playbook。roles能夠根據層次型結構自動裝載變量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。簡單來講,roles就是通過分別將變量、文件、任務、模板及處理器放置于單獨的目錄中,并可以便捷地include它們的一種機制。 角色一般用于基于主機構建服務的場景中,但也可以是用于構建守護進程等場景中。
運維復雜的場景:建議使用 roles,代碼復用度高。
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html
官方文檔
在此文件夾中
role目錄結構
roles/project1/tasks/files/vars/ templates/handlers/default/ meta/ project2/tasks/files/vars/ templates/handlers/default/ meta/
Role各目錄作用
- roles/project/ :項目名稱,有以下子目錄。
- files/ :存放由copy或script模塊等調用的文件。
- templates/:template模塊查找所需要模板文件的目錄
- tasks/:定義task,role的基本元素,至少應該包含一個名為main.yml的文件;其它的文件需要在此文件中通過include進行包含。
- handlers/:至少應該包含一個名為main.yml的文件;此目錄下的其它的文件需要在此文件中通過include進行包含。
- vars/:定義變量,至少應該包含一個名為main.yml的文件;此目錄下的其它的變量文件需要在此文件中通過include進行包含。
- meta/:定義當前角色的特殊設定及其依賴關系,至少應該包含一個名為main.yml的文件,其它文件需在此文件中通過include進行包含。
- default/:設定默認變量時使用此目錄中的main.yml文件,比vars的優先級低。
建立role
- 創建role的目錄結構.在以roles命名的目錄下分別創建以各角色名稱命名的目錄,如mysql等,在每個角色命名的目錄中分別創建相關的目錄和文件,比如tasks、files、handlers、templates和vars等目錄;用不到的目錄可以創建為空目錄,也可以不創建。
- 編寫和準備role的功能文件。
- 編寫playbook文件調用需要的角色應用于指定的主機
創建相應的文件夾。
建立各個文件,其中main文件中規定了所有文件執行的順序。
注意:使用role需要再其同級別的目錄建立yml文件。