今日課程推薦:https://edu.51cto.com/course/23377.html ,Ansible與Ansible-playbook應用實戰視訊課程
playbook字面意思,即劇本,現實中由演員按照劇本表演,在Ansible中,這次由計算機進行表演,由計算機安裝、部署應用,提供對外服務,以及組織計算機處理各種各樣的事情。
playbook檔案由YMAL語言編寫。YMAL格式是類似于JSON的檔案格式,便于人了解和閱讀,同時便于書寫。首先學習了解一下YMAL的格式,對後面書寫playbook很有幫助。以下為playbook常用到的YMAL格式規則。
檔案的第一行應該以“---” (三個連字元)開始,表明YMAL檔案的開始。
在同一行中,#之後的内容表示注釋,類似于shell,python和ruby。
YMAL中的清單元素以“-”開頭然後緊跟着一個空格,後面為元素内容。
同一個清單中的元素應該保持相同的縮進。否則會被當作錯誤處理。
play中hosts,variables,roles,tasks等對象的表示方法都是鍵值中間以“:”分隔表示,“:”後面還要增加一個空格。
首先看下面這個例子:
等價于JSON的下面這個格式:
playbook檔案是通過ansible-playbook指令進行解析的,ansbile-playbook指令會根據自上而下的順序依次執行playbook檔案中的内容。
playbook是由一個或多個“play”組成的清單。play的主要功能在于,将事先合并為一組的主機組合成事先通過Ansible定義好的角色。将多個play組織在一個playbook中就可以讓它們聯同起來按事先編排好的機制完成一系列複雜的任務。
playbooks主要有以下四部分構成,分别如下。
Target部分: 定義将要執行 playbook 的遠端主機組。
Variable部分: 定義playbook運作時需要使用的變量。
Task部分: 定義将要在遠端主機上執行的任務清單。
Handler部分: 定義task 執行完成以後需要調用的任務。
下面介紹下構成playbook的四個組成部分。
playbook中的每一個play的目的都是為了讓某個或某些遠端主機以某個指定的使用者身份執行任務。
hosts:用于指定要執行任務的遠端主機,每個playbook都必須指定hosts,hosts也可以使用通配符格式。主機或主機組在inventory清單(hosts檔案)中指定,可以使用系統預設的/etc/ansible/hosts,也可以自己編輯,在運作的時候加上-i選項,可指定自定義主機清單的位置。
remote_user:用于指定在遠端主機上執行任務的使用者。可以指定任意使用者,也可以使用sudo,但是使用者必須要有執行相應任務的權限。
play的主體部分是task list。
task list中的各任務按次序逐個在hosts中指定的所有遠端主機上執行,即在所有遠端主機上完成第一個任務後再開始第二個。在運作自上而下某playbook時,如果中途發生錯誤,則所有已執行任務都将復原,是以在更正playbook後需要重新執行一次。
task的目的是使用指定的參數執行子產品,而在子產品參數中可以使用變量。子產品執行一個指令,即使執行一次或多次, 其結果是一樣的,這意味着playbook多次執行是安全的,因為其結果均一緻。tasks包含name和要執行的子產品,name是可選的,隻是為了便于使用者閱讀,建議加上去,子產品是必需的,同時也要給予子產品相應的參數。
定義tasks推薦使用module: options”的格式,例如:
用于當關注的資源發生變化時采取一定的操作。handlers是和“notify”配合使用的。
“notify”這個動作可用于在每個play的最後被觸發,這樣可以避免多次有改變發生時,每次都執行指定的操作,通過“notify”,僅在所有的變化發生完成後一次性地執行指定操作。
在notify中列出的操作稱為handler,也就是說notify用來調用handler中定義的操作。
注意:在notify中定義的内容一定要和handlers中定義的“ - name”内容一樣,這樣才能達到觸發的效果,否則會不生效。
(4)tags
tags用于讓使用者選擇運作或略過playbook中的部分代碼。Ansible具有幂等性,是以會自動跳過沒有變化的部分;但是當一個playbook任務比較多時,一個一個的判斷每個部分是否發生了變化,也需要很長時間。是以,如果确定某些部分沒有發生變化,就可以通過tags跳過這些代碼片斷。
使用ansible-playbook運作playbook檔案,輸出的内容為JSON格式。并且由不同顔色組成,便于識别。一般而言,輸出内容中,每個顔色表示的含義如下。
綠色代表執行成功,但系統保持原樣。
黃色代表系統狀态發生改變,也就是執行的操作生效。
紅色代表執行失敗,會顯示錯誤資訊。
下面是一個簡單的playbook檔案:
上面的playbook 實作的功能是新增一個使用者,每個參數含義如下。
name參數對該playbook實作的功能做一個概述,後面執行過程中,會輸出name的值。
hosts參數指定了對哪些主機進行操作。
user參數指定了使用什麼使用者登入到遠端主機進行操作。
gather_facts參數指定了在執行task任務前,是否先執行setup子產品擷取主機相關資訊,此參數預設值為true,表示開啟,如果我們在task中要使用facts資訊時,就需要開啟此功能。否則可以設定為false。設定為false可以加快playbook的執行速度。
vars參數,指定了變量,這裡指字一個user1變量,其值為testuser,需要注意的是,變量值一定要用引号括起來。
tasks指定了一個任務,其下面的name參數同樣是對任務的描述,在執行過程中會列印出來。user是一個子產品,user後面的name是user子產品裡的一個參數,而增加的使用者名調用了上面user1變量的值。
在playbook中,task部分是整個任務的核心,我們前面介紹的ansible的常用子產品,例如commands子產品、shell子產品、file子產品、cron子產品、user子產品等,在playbook中仍然可用,每個子產品所使用的參數以及含義跟指令行模式下也完全一樣,隻不過寫法不同而已,下面通過幾個例子來看看playbook中常見功能子產品的寫法。
下面是一個playbook示例,test.yml檔案内容如下:
這個playbook檔案中,使用了user、file、synchronize和shell子產品,檔案開始定義了一個主機組hadoophosts,然後設定root使用者在遠端主機上執行操作,接着,就是task任務的開始,“- name”是描述性資訊,用來辨別任務執行内容和進度,第一個task用來建立一個hadoop使用者,使用了user子產品,注意,上面的user表示ansible的user子產品,而user後面的name、state是user子產品的參數,這些參數含義上面已經做過介紹,這裡就不在重複了
。
下面還有file子產品、synchronize子產品以及shell子產品,它們的寫法跟user子產品類似,也不再過多介紹。
從此檔案可以看出,通過playbook模式編寫的檔案更加簡潔、易懂,隻要設定好了任務的運作政策、順序,每次需要用到這個操作的話,直接執行就可以了。執行的方式如下:
unarchive子產品用來實作解壓縮,也就是将壓縮檔案解壓分發到遠端不同節點上。隻需記住如下幾個參數即可:
src: 源檔案路徑,這個源檔案在管理機上。
dest: 指定遠端主機的檔案路徑。
mode:設定遠端主機上檔案權限。
看下面這個例子:
這個操作是将管理機上的/src/spark.tar.gz檔案傳輸到遠端主機上後進行解壓縮,并将解壓縮後的檔案放到遠端主機的/opt目錄下。注意,這個例子中我們設定了gather_facts選項為false,這是因為下面的操作中,沒有用到facts資訊。
在自動化運維中,對檔案進行内容替換是一個非常常見的場景,比如修改、删除、添加作業系統的某些參數等,Ansible中雖然提供了shell子產品結合sed指令來達到替換的效果,但經常會遇到需要轉義的問題,并且考慮到可讀性性和可維護性等多方面因素,使用Ansible自帶的替換子產品是一個不錯的選擇。Ansible常用的替換子產品為replace和lineinfile。
replace子產品可以根據指定的正規表達式替換遠端主機下某個檔案中的内容,常用的參數有如下幾個:
path:要操作的遠端主機上檔案的路徑。
regexp:正規表達式,指定替換規則。
replace:指定最終要替換的字元串。
backup:是否在修改檔案之前對檔案進行備份,yes是進行備份。
這個操作是對遠端主機上/etc/selinux/config檔案中的enforcing字元串進行替換,替換為disabled,替換前進行備份。其實就是關閉遠端主機上selinux服務。
最後,再介紹一下lineinfile,此子產品也可以實作replace的功能,但lineinfile功能更加強大,支援的參數也比較多,常用參數含義如下:
path:操作的遠端主機上的檔案路徑
regexp:正規表達式,要替換的内容規則
line:指定替換後的文本内容
state:當設定為absent代表删除比對的行
insertafter:insertafter參數可以将文本插入到“指定的行”之後
insertbefore:insertbefore參數可以将文本插入到“指定的行”之前
backup:進行替換操作前是否進行備份
下面來看一個基于lineinfile的playbook任務:
這個playbook任務中,調用了四次lineinfile替換操作,第一次是在/etc/profile檔案中找到以ulimit開頭的行,并在後面添加一行内容"ulimit -c unlimited",第二次是在/etc/profile檔案的最後添加一個JAVA_HOME路徑,第三次是修改/etc/selinux/config檔案中以“SELINUX=”開頭的行,将其替換為“SELINUX=disabled”,其實就是關閉selinux,最後一個操作是在/etc/resolv.conf檔案找查找以search開頭的行,然後将其删除掉。
ansible中定義變量的方式有很多種,可以将子產品的執行結果注冊為變量,也可以在roles中的檔案内定義變量,還可以使用内置變量等,而register、set_fact都可用來注冊一個變量。
使用register選項,可以将目前task的輸出結果指派給一個變量,看下面這個例子:
此例子是将在遠端主機上執行的shell指令“hostname”的輸出結果指派給變量host_result,然後再将變量引用并使用debug子產品輸出。輸出結果是json格式的。注意,此例子最後還使用了debug子產品,此子產品用于在調試中輸出資訊.
下面是上面playbook的debug輸出結果:
可以看出,此輸出是一段json格式的資料,最頂端的key為host_result,大括号内還有多個二級key,我們想要的結果是輸出遠端主機的主機名即可,不需要這些額外的二級key資訊,如何實作這個要求呢,如果想要輸出json資料的某二級key項,可以使用"key.dict"或"key['dict']"的方式引用即可。從上面輸出可以看到,我們需要的二級key是stdout項,是以要僅僅輸出此項内容,可以将變量引用改為host_result.stdout即可,也就是将上面的playbook任務改成如下内容:
在這個playbook中,我們又增加了一個debug參數,debug子產品常用的參數有兩個,分别是msg和var,它們都可以引用變量輸出資訊,但有一點小差別,msg可以輸出自定義資訊,并且變量需要雙大括号包含起來,而var參數隻能輸出變量,并且不需要雙大括号。
修改後的playbook執行debug輸出結果如下:
從輸出可知,這個才是我們想要的結果。
set_fact和register的功能很類似,它也可以将task輸出指派給變量。set_fact更像shell中變量的指派方式,可以将某個變量的值指派給另一個變量,也可以将字元串指派給變量。看下面這個例子:
這個例子是将hostname的輸出結果指派給host_result變量,然後通過set_fact将host_result變量指派給var1變量,接着又将一個字元串指派給var2變量,最後,通過debug子產品輸出這些變量資訊。注意這些子產品的使用方式和書寫格式。
這個playbook的輸出結果為:
ansible預設隻會對遠端主機執行操作,但有時候如果需要在管理機本機上執行一些操作,該如何實作呢,這個實作的方法有很多,可以通過delegate_to(任務委派)來實作,也可以通過connection:local方法,還可以通過local_action關鍵字來實作。
下面來看一個例子,說明它們的用法。
這個例子中,依次使用了connection、delegate_to和local_action三種方式,還使用了一個變量{{inventory_hostname}},這是ansible的一個内置變量,它用來擷取遠端主機的主機名,說到主機名,其實就是用到了facts資訊,是以,需要設定gather_facts選項為true,另外,$(hostname)是shell裡面的變量,也是用來擷取主機名,此例子實作的功能是将遠端主機的主機名依次輸出到管理機的/tmp/local.log檔案中。