Ansible Playbook中的變量與引用

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

前言

前面有說到使用playbook來搞一些複雜的功能,我們使用YAML來寫playbook,就像我們用其它語言寫代碼一樣,也是可以定義變量的,能定義變量,那這個功能就不得了了,就有必要好好的講講了。變量就好比playbook的翅膀,讓ansible playbook的使用場景大大增多。在Ansible中,變量的玩法有下面這幾種:

  • 通過inventory定義變量
  • 通過文件定義變量
  • 使用遠程主機的系統變量
  • 通過ansible-playbook命令行傳入變量
  • 通過vars定義變量
  • 通過vars_files定義變量
  • 通過register註冊變量
  • 使用vars_prompt傳入變量

玩法還挺多的,下面就對這些玩法進行一一的總結,爭取一次把Ansible中變量的玩法喫透。

通過inventory定義變量

我們可以在inventory文件中定義變量,然後在playbook中使用這些變量。到底怎麼玩,下面我通過一段代碼來舉例說明:

192.168.1.3 key=10086 

[server1]
192.168.1.3

[server1:vars]
key=10087
ansible_ssh_user='test1'

上面是我的inventory文件內容,我針對192.168.1.3這個主機定義了一個變量key,然後又針對server1這個主機組定義了變量key和ansible_ssh_user。然後我來寫一個測試playbook,看下在inventory文件中定義的變量怎麼用。

---

- hosts: server1
  tasks:
    - name: Display var from inventory file
      debug: msg="The {{ inventory_hostname }} value is {{ key }}"

輸出內容如下:

[jelly@localhost yaml]$ ansible-playbook inventoryVar.yaml 

PLAY [server1] *************************************

TASK [Gathering Facts] *****************************
ok: [192.168.1.3]

TASK [Display var from inventory file] *************
ok: [192.168.1.3] => {
    "msg": "The 192.168.1.3 value is 10086"
}

PLAY RECAP *****************************************
192.168.1.3                : ok=2    changed=0    unreachable=0    failed=0  

可以看到,我們通過{{}}來引用變量,同時也看到,主機定義的變量的優先級高於主機組定義的變量。

通過文件定義變量

通過文件定義變量這種玩法就用的更多了,在後面講到role的時候,還會專門用到這個知識點的。說白了就是我們在playbook的同級目錄建立兩個名分別爲host_varsgroup_vars的文件夾,分別用來定義主機和主機組的變量。下面是我的文件結構:

[jelly@localhost yaml]$ tree
.
├── fileVar.yaml
├── group_vars
│   └── server1
├── host_vars
│   └── 192.168.1.3

host_vars文件夾下的文件用被管理主機的IP爲文件名,比如此處的192.168.1.3,文件內容按照YAML的語法進行定義,比如此處192.168.1.3的內容如下:

key: 10086

group_vars文件夾下的文件用inventory下定義的組名來命名,比如此處的server1,文件內容也是按照YAML語法進行定義,比如此處server1的內容如下:

foo:
  field1: one
  field2: two

在來看我的測試playbook,它是這樣的:

---

- hosts: server1
  tasks:
    - name: Display var from file
      debug: msg="The {{ inventory_hostname }} value is {{ key }} and {{ foo.field1 }}"

重點是我們可以通過foo.field1這種方式來引用複雜的變量,運行結果如下:

[jelly@localhost yaml]$ ansible-playbook fileVar.yaml 

PLAY [server1] *************************************

TASK [Gathering Facts] *****************************
ok: [192.168.1.3]

TASK [Display var from file] ***********************
ok: [192.168.1.3] => {
    "msg": "The 192.168.1.3 value is 10086 and one"
}

PLAY RECAP *****************************************
192.168.1.3                : ok=2    changed=0    unreachable=0    failed=0  

使用遠程主機的系統變量

不知道大家有沒有看過上篇說過的Ansible Facts,我們通過setup模塊獲取的遠程主機的信息可以直接作爲變量在playbook中引用。是的,這樣就大大方便了我們的工作。下面牛通過一個簡單的playbook來看看怎麼玩。

---

- hosts: server1
  tasks: 
    - name: Echo System
      debug: msg="{{ ansible_os_family }}"

ansible_os_familyansible_facts節點下的一個值,我們可以直接在playbook中直接應用。就是這麼簡單!

通過ansible-playbook命令行傳入變量

上面的三種方式在我們日常工作中用的比較多,接下來說說怎麼通過ansible-playbook命令行傳參的方式定義變量。先來看下我們的測試YAML腳本:

---

- hosts: server1
  tasks: 
    - name: ansible-playbook command var
      debug: msg="var1 is {{ var1 }}; var2 is {{ var2 }}"

我們在命令行輸入以下命令進行執行:

ansible-playbook commandVar1.yaml -e "var1=1 var2=2"

除了這裏說的直接傳入變量,目前ansible-playbook還支持指定文件的方式傳入變量,變量文件的內容支持YAML和JSON兩種格式,來看下怎麼玩!!!

我這裏準備了兩個文件,分別是YAML和JSON格式的。內容如下:

[jelly@localhost yaml]$ cat var.json 
{"var1":"10086", "var2":"10087"}
[jelly@localhost yaml]$ cat var.yaml 
---
var1: 10086
var2: 10087

接下來,我在命令行指定var.json或者var.yaml文件傳入變量:

ansible-playbook commandVar1.yaml -e "@var.json"

玩起來還是蠻簡單的!

注意:ansible-playbook命令行傳進去的變量都是全局變量

通過vars定義變量

通過vars定義變量,這個就簡單了,在之前的文章中也有說過,這裏就通過一個簡單的YAML腳本來演示。

---

- hosts: server1
  vars:
    var1: 10086
    var2: 10087
  
  tasks: 
    - name: Display vars
      debug: msg="var1 is {{var1}}, var2 is {{var2}}"

這個就是這麼簡單,自己理解去吧!!!

通過vars_files定義變量

這種玩法就有點意思了,怎麼說呢。我們可以把所有的變量定義到某個文件內,然後在playbook文件內使用vars_files參數引用這個變量文件。比如這樣子:

---

- hosts: server1
  vars_files:
    - var.yaml
  
  tasks: 
    - name: Display vars
      debug: msg="var1 is {{var1}}, var2 is {{var2}}"

通過register註冊變量

如果我們有需要在兩個task之間傳遞數據的場景,就可以考慮使用這裏的register註冊變量了,比如我們在一個playbook中有兩個task,分別是TaskA和TaskB,如果TaskB需要根據TaskA的執行結果做一些判斷,這個時候就需要在兩個task之間傳遞數據,把TaskA的執行結果傳遞給TaskB。怎麼搞?看下面的代碼。

---

- hosts: server1
  tasks:
    - name: TaskA
      shell: hostname
      register: info

    - name: TaskB
      debug: msg="TaskA's output is {{info}}"

執行上面的YAML腳本,輸出結果如下:

[jelly@localhost yaml]$ ansible-playbook registerVar.yaml 

PLAY [server1] ******************************************

TASK [Gathering Facts] **********************************
ok: [192.168.1.3]

TASK [TaskA] ********************************************
changed: [192.168.1.3]

TASK [TaskB] ********************************************
ok: [192.168.1.3] => {
    "msg": "TaskA's output is {'changed': True, 'end': '2019-10-08 08:34:11.129667', 'stdout': 'localhost.localdomain', 'cmd': 'hostname', 'rc': 0, 'start': '2019-10-08 08:34:11.123739', 'stderr': '', 'delta': '0:00:00.005928', 'stdout_lines': ['localhost.localdomain'], 'stderr_lines': [], 'failed': False}"
}

PLAY RECAP **********************************************
192.168.1.3                : ok=3    changed=1    unreachable=0    failed=0  

從上面的YAML腳本,我們可以看到TaskA中執行的hostname命令,它的輸出結果註冊到了info中,這樣一來,在TaskB中就可以引用info了,完成數據在task之間的傳遞。

同時也可以看到,info的結果是一段Python字段數據,裏面存儲着很多信息包含執行時間、狀態變化等信息。register的輸出數據結果都是Python字典,我們可以很容易地挑選出我們想要的信息,比如這樣:

---

- hosts: server1
  tasks:
    - name: TaskA
      shell: hostname
      register: info

    - name: TaskB
      debug: msg="TaskA's output is {{info.stdout}}"

使用vars_prompt傳入變量

Ansible還支持在運行playbook的時候通過交互式的方式給定義好的參數傳入變量值,只需要在playbook中定義vars_prompt的變量名和交互式提示內容即可!就像下面這樣:

---

- hosts: server1
  vars_prompt:
    - name: "var1"
      prompt: "Please input var1"
      private: no

    - name: "var2"
      prompt: "Please input var2"
      default: '10086'
      private: yes

  tasks: 
    - name: echo var1
      debug: msg="var1 is {{var1}}"

    - name: echo var2
      debug: msg="var2 is {{var2}}"

在運行上面的YAML腳本的時候,會提示進行變量輸入,其中我們定義的var1爲非私有變量,var2爲私有變量還有一個默認值。當定義爲私有變量時,在終端輸入變量時,則不會顯示對應的值,就像我們ssh登陸主機,輸入密碼看不見一樣。

總結

哦,我的天哪!總結完一看,這麼長,這麼多內容;但是還好,內容雖多,但是蠻簡單的。在上班路上,或者下班路上,看看這麼一篇總結,也還是不錯的。希望你看完這篇文章後,能感嘆一下,Ansible的變量玩法還有這麼多啊。玩了Ansible這麼久,就是感覺這貨一直都在給我帶來驚喜,越來越好玩,越來越耐玩!還等什麼,搞個測試環境,也玩一玩!

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

2019年10月8日,於內蒙古呼和浩特。

關注果凍想公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章