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=10087ansible_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_vars和group_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_family是ansible_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: 10086var2: 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日,于內蒙古呼和浩特。