Contents

Ansible - 變數管理及應用

透過 Playbook 可以很方便執行大量機器部署,在大量環境下可以透過變數方式,如同寫程式一般可以更靈活且彈性的進行部署及維護。

練習環境
可以使用 HowHow 的創建 Lab 練習環境,來操作多台機器練習 Ansible,使用方式請參閱 HowHow 網站

1.Ansible 變數介紹

Ansible 可以使用變數使得執行起來更佳彈性且靈活,像是角色創立、套件安裝、服務啟動等等,另外 Ansible 變數取名方式與 Python 一致,使用蛇形命名法(snake case),例如: web_server_01 。


2. Playbook 定義變數

2.1. 定義變數於 PlayBook 內

使用 vars 關鍵字並定義變數 , Playbook 範例:

1
2
3
4
5
6
- name: var example
  hosts: all
  vars:
      user: joe
      home: /home/joe
...

2.2. 定義變數檔案於 PlayBook 內

使用 vars_files 關鍵字定義變數的檔案路徑 , Playbook 範例:

1
2
3
4
5
- name: var example
  hosts: all
  vars_files:
      - users.yml
...

user.yml 變數檔案內容範例 :

1
2
user: joe
home: /home/joe

3. PlayBook 中使用變數

使用兩個大刮號包住變數名稱,即可使用定義好的變數,Playbook 範例:

1
2
3
4
5
6
7
8
9
- name: var example
  hosts: all
  vars:
    user : joe
    
  tasks:
    - name: Create the User  {{ user }}
      user:
        name: "{{ user }}"
IMPORTANT
變數如果為 Value 第一個開頭需要加註雙引號,如上 PlayBook 內容 , 兩個不同的樣式。

4. 主機變數及群組變數

在 inventory 中也可以定義變數,不過此作法比較少用,影響 inventory 可讀性及維護性。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
[servera]
demo1.example.com
demo2.example.com

[web]
demo2.example.com
demo3.exmaple.com

[servera:vars]
user=joe

[pd:children]
web
servera

[pd:vars]
user=administrator

5. 使用資料夾管理主機變數及群組變數

透過 group_vars 及 host_vars 兩個資料夾管理群組及主機變數,此方式最常使用管理較為直覺也容易,其專案架構如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[student@workstation example-project]$ tree -F
.
├── ansible.cfg
├── group_vars/
│   ├── datacenter1
│   ├── datacenter2
│   └── datacenters
├── host_vars/
│   ├── demo1.example.com
│   └── demo2.example.com
├── inventory
└── playbook.yml

inventory 內容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[student@workstation example-project]$ cat inventory 
[datacenter1]
demo1.example.com
demo2.example.com

[datacenter2]
demo3.example.com
demo4.example.com

[datecenters:children]
datacenter1
datacenter2

5.1. group_vars 資料夾管理群組變數

在 group_vars 資料夾內建立對應群組的檔案名稱,並在該檔案內定義變數。

1
2
3
4
5
6
[student@workstation example-project]$ cat group_vars/datacenter1
service: httpd
[student@workstation example-project]$ cat group_vars/datacenter2
service: php
[student@workstation example-project]$ cat group_vars/datacenters
package: httpd

5.2. host_vars 資料夾管理主機變數

在 host_vars 資料夾內建立對應主機的檔案名稱,並在該檔案內定義變數。

1
2
3
4
[student@workstation example-project]$ cat host_vars/demo1.example.com 
packege: mysql-server
[student@workstation example-project]$ cat host_vars/demo2.example.com 
package: firewalld

6. 指令定義變數

透過 ansible-playbook 定義執行變數。

1
ansible-playbook example.yml -e "package=httpd"

7. Ansible 變數使用建議

Ansible 可以設定變數的地方還有十分的多,可至 Ansible 官方手冊 查閱 ,建議在同一個公司內共同商議,要在哪個地方使用變數,方便管理及維護。


8. Ansible Fact 變數

在 Ansible 執行時,第一個 task 任務總是會出現 Gathering Facts ,這個任務就是搜尋所有主機的相關訊息並存為 Fact 變數,這任務預設會自動採集,除非手動設置不採集。 Fact 會採集下列相關訊息( 僅列出部分 ):

  1. 主機名稱
  2. 核心版本
  3. 網路介面卡
  4. IP 地址
  5. 作業系統版本
  6. 環境變數
  7. CPU
  8. 記憶體
  9. 硬碟空間

透過 Fact 可以藉由不同機器做出不同條件篩選,例如大於多少空間硬碟才部署 MySQL 或是哪些 IP 執行特定操作等。

印出 Fact Playbook 範例:

1
2
3
4
5
6
7
[student@workstation example]$ cat fact.yml 
- name: Fact dump
  hosts: serverb
  tasks:
    - name: Print all facts
      debug:
        var: ansible_facts

範例執行結果 ( ansible_facts 為 fact 的關鍵字) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[student@workstation example]$ ansible-playbook fact.yml 

PLAY [Fact dump] ***********************************************************************************************

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

TASK [Print all facts] *****************************************************************************************
ok: [serverb] => {
    "ansible_facts": {
        "all_ipv4_addresses": [
            "172.25.250.11"
        ],
        "all_ipv6_addresses": [],
        "ansible_local": {},
        "apparmor": {
            "status": "disabled"
        },
        "architecture": "x86_64",
        "bios_date": "04/01/2014",
        "bios_version": "1.13.0-2.module+el8.4.0+534+4680a14e",
        "cmdline": {
            "BOOT_IMAGE": "(hd0,msdos1)/vmlinuz-4.18.0-348.el8.0.2.x86_64",
            "rd.lvm.lv": "rl_workstation/swap",
            "resume": "/dev/mapper/rl_workstation-swap",
            "ro": true,
            "root": "/dev/mapper/rl_workstation-root"
        },
...

8.1. Fact 變數取值

透過上述範例,可以知道 ansible_facts 變數內存放不同的內容,可以使用於 Python Dict 字典方式將 Value 取出。

Fact 變數
Short host name ansible_facts['hostname']
FQDN ansible_facts['fqdn']
IPv4 ansible_facts['ansible_default_ipv4']['address']
顯示 DNS 列表 ansible_facts['dns']['nameservers']
顯示 /dev/vda1 分區大小 ansible_facts['devices']['vda']['partitions']['vda1']['size']
NOTE

除了使用中刮號取值之外也可以使用物件屬性方式取值~

ansible_facts['ansible_default_ipv4']['address'] ,此方是可以取得 IPv4 。 ansible_facts.ansible_default_ipv4.address , 此方式也可以取得 IPv4 。

8.2. Fact 變數取值應用

印出受控主機 IPv4 地址, Playbook 範例:

1
2
3
4
5
6
- name: Example
  hosts: all
  tasks:
    - name: Print various Ansible facts
      debug:
        msg: The default IPv4 address of {{ ansible_facts.fqdn }} is {{ ansible_facts.default_ipv4.address  }}

Playbook 執行結果 :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[student@workstation example]$ ansible-playbook example.yml 

PLAY [Example] ************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************
ok: [serverb]
ok: [servera]
ok: [serverc]

TASK [Print various Ansible facts] ****************************************************************************
ok: [servera] => {
    "msg": "The default IPv4 address of servera.lab.example.com is 172.25.250.10"
}
ok: [serverb] => {
    "msg": "The default IPv4 address of serverb.lab.example.com is 172.25.250.11"
}
ok: [serverc] => {
    "msg": "The default IPv4 address of serverc.lab.example.com is 172.25.250.12"
}

PLAY RECAP ****************************************************************************************************
servera                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverb                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverc                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

8.3. 儲存 Fact 變數內容小技巧

使用 ansible 的 setup 模組,可以採集 fact 再藉由 Linux 輸出導向至檔案內,就可以慢慢查看並找到所要的變數內容來應用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[student@workstation example]$ ansible serverc -m setup > /tmp/serverc.facts
[student@workstation example]$ head /tmp/serverc.facts 
serverc | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "172.25.250.12"
        ],
        "ansible_all_ipv6_addresses": [],
        "ansible_apparmor": {
            "status": "disabled"
        },
        "ansible_architecture": "x86_64",

8.4. 停止自動採集 Fact

每一次採集 Fact 大約耗上 1 - 2 秒時間,少量機器執行不會有感覺,如果今天要部署上千台機器,且又不會使用到 Fact 變數,就可以手動關閉採集 ( gather_facts : no ) ,加速 Playbook 執行效率。

停用 facts 自動採集 Playbook 範例 :

1
2
3
4
5
- name: example
  hosts: all
  gather_facts: no
  tasks:
    ...

9. Ansible 魔法變數

有些變數無法透過 setup 模組 ( Fact ) 採集,而是藉由 ansible 自動產生的變數稱做魔法變數,例如:

  1. group_names : 在 Inventory 主機清單內的群組名稱。
  2. groups :在 Inventory 主機清單內群組的主機清單。
  3. playbook_dir : 執行 playbook 路徑

更多魔法變數請至 Ansible 官方手冊查閱 。


10. 小結

Ansible 變數運用千變萬化, 能有效掌握變數更能寫出可讀性且彈性較高的 PlayBook 。



如果你還沒有註冊 Like Coin,你可以在文章最下方看到 Like 的按鈕,點下去後即可申請帳號,透過申請帳號後可以幫我的文章按下 Like,而 Like 最多可以點五次,而你不用付出任何一塊錢,就能給我寫這篇文章的最大的回饋!