初窺Ansible playbook

^_^果凍^_^發表於2020-06-02

Ansible是一個系列文章,我會盡量以通俗易懂、詼諧幽默的總結方式給大家呈現這些枯燥的知識點,讓學習變的有趣一些。
Ansible系列博文直達連結:Ansible入門系列

前言

在上一篇文章中說到Ansible有兩種玩法,一種是Ansible Ad-Hoc,另一種是就是這裡要說的playbook。playbook是Ansible進行配置管理的元件,雖然Ansible的日常Ad-Hoc命令功能很強大,能完成一些基本的配置管理工作,但是Ad-Hoc命令無法支撐複雜環境的配置管理工作。在我們實際使用Ansible的工作中,大部分時間都是在編寫playbook,接下來就重點說說如何玩轉這個playbook。

執行playbook命令

我們都是按照yaml語法規則來編寫playbook,至於yaml怎麼玩,後面的文章我會總結一下的。在我們按照要求編寫好了yaml檔案後,如何來執行這個yaml檔案呢?

Ansible提供了一個單獨的命令:ansible-playbook命令,我們可以通過這個命令來執行yaml指令碼。常見的ansible-playbook的使用方法如下:

最簡單的使用方法:

ansible-playbook copyDemo.yaml

我們還可以使用以下命令檢視輸出的細節:

ansible-playbook copyDemo.yaml --verbose

我們也可以使用以下命令檢視該yaml指令碼將影響的主機列表:

ansible-playbook copyDemo.yaml --list-hosts

還可以使用以下命令檢查yaml指令碼語法是否正確:

ansible-playbook copyDemo.yaml --syntax-check

上面的幾種使用方法基本就涵蓋了我們日常工作中80%的場景了,剩餘的20%場景,比如並行、非同步等,很少用到,等真正用到的時候再去查閱相關資料也來的及。而工作中,更多的時候,我們不是在編寫playbook,就是在編寫playbook的路上。所以,接下來我重點說說如何寫這個playbook,也就是playbook的基本語法。

playbook基本語法

最基本的playbook指令碼分為三個部分:

  1. 在哪些機器上以什麼身份執行
  2. 執行的任務有哪些
  3. 善後任務有哪些

我們在編寫playbook指令碼的時候,總是離不開上面的三個部分的。下面先來一個稍微有點複雜的playbook指令碼,讓大家先有一個整體的認識。

---
- hosts: server1
  user: root
  vars:
    http_port: 80
    max_clients: 200

  tasks:
    - name: Write apache config file
      template: src=/home/test1/httpd.j2 dest=/home/test2/httpd.conf
      notify:
        - restart apache
    - name: Ensure apache is running
      service: name=httpd state=started

  handlers:
    - name: restart apache
      service: name=httpd state=restarted

現在就對上述三部分稍作詳細總結。

主機和使用者

上面的yaml指令碼,我們一開始就會看到hostsuservars,其中vars在後面的文章進行專門總結。而這裡的hostsuser就是表示我們這個yaml將要在哪些主機上用哪個使用者身份去操作。而這裡的深一層次的關係如下表所示:

key 含義
hosts 為主機的IP,或者主機組名,或者關鍵字all
user 在遠端以哪個身份執行
become 切換成其他使用者身份執行,值為yes或者no
become_method 與become一起使用,值可以為sudo/su
become_user 與become一起使用,可以是root或者其它使用者名稱

在實際工作中,如果我們不指定user時,則預設使用連線遠端主機的使用者進行操作,如果指定了執行使用者而與ansible_ssh_user指定使用者不一致時,則需要開啟become操作,這裡的become配置與ansible.cfg中配置將相互配合完成工作,yaml中的become優先順序高於ansible.cfg中配置中的優先順序。

任務列表

任務列表是整個playbook的核心,對於任務列表,我們首先需要知道以下三點內容:

  • 任務是從上到下順序執行的,如果中間發生錯誤,那麼整個playbook會中止;
  • 每一個任務都是對模組的一次呼叫,只是使用不同的引數和變數而已;
  • 每一個任務最好有一個name屬性,這樣在執行yaml指令碼時,可以看到執行進度資訊。

對於任務的引數有兩種不同的寫法,我們在編寫yaml指令碼時,可以按照自己的喜好進行選擇。

寫法一:

- name: Write apache config file
  template: src=/home/test1/httpd.j2 dest=/home/test2/httpd.conf

寫法二:

- name: Write apache config file
  template: 
    src: /home/test1/httpd.j2
    dest: /home/test2/httpd.conf

這兩種寫法都是OK的,我一般喜歡第二種寫法。

最後,對於任務我們還需要特別一個點,那就是任務的執行狀態。我們在執行Ansible Ad-Hoc或者ansible-playbook的時候,在輸出中都會有一個changed欄位,比如:

192.168.1.3                : ok=2    changed=0    unreachable=0    failed=0  

或者

192.168.1.3                : ok=2    changed=1    unreachable=0    failed=0

這裡的這個changed就是人物的執行狀態,但是它為什麼一會是0,一會有是1呢?這就要說到Ansible中一個叫做“冪等性”的概念。

冪等性

冪等性是數學和電腦科學上一個常見的概念,多次執行產生的結果不會發生改變,這樣的特性就被成為冪等性。

大多數的Ansible模組在設計時保證了冪等性,冪等性保證了Ansible指令碼多次執行情況下的相同結果,儘可能的避免使用那些不能滿足冪等性的模組。比如我們經常使用的shell模組就是非冪等性的。

我們要明白Ansible是以“結果為導向的”,我們指定了一個“目標狀態”,Ansible會自動判斷“當前狀態”是否與“目標狀態”一致,如果一致,則不進行任何操作;如果不一致,那麼就將“當前狀態”變成“目標狀態”,這就是“冪等性”,“冪等性”可以保證我們重複的執行同一項操作時,得到的結果是一樣的。

那這個冪等性與上面的changed又有什麼關係呢?且聽我下面慢慢道來!

  • changed為false或者0時,表示Ansible沒有進行任何操作,沒有“改變什麼”;
  • changed為true或者大於0時,表示Ansible執行了操作,“當前狀態”已經被Ansible改變成了“目標狀態”。

copy這個模組來舉例子說明,當我們準備將一個檔案通過Ansible拷貝到遠端主機時,copy模組首先檢查遠端是否已經存在了該檔案,如果不存在,則把檔案拷貝過去,返回changed為大於0;如果存在時,則開始比對兩個檔案的md5值,如果md5值一致,則說明兩個檔案是一樣的,則不需要拷貝,此時copy模組則什麼都不幹,返回changed為0。

總結

通過三篇文章總結了Ansible中的常用模組、Ansible Ad-Hoc和ansible-playbook的一些慣用用法,從我的實際學習經驗來說,學到這裡,你可以將這三塊內容結合起來使用了,至少可以在你們生產環境鼓搗一下了。生來就是折騰,更何況我們這麼拼命、努力的學習呢!

果凍想,認真玩技術的地方。

2019年5月18日,於內蒙古呼和浩特。

相關文章