1. 程式人生 > >Ansible11:變量詳解

Ansible11:變量詳解

only rec key roles password end tle -h 輸入數據

目錄

  • 簡單說明
  • 一、在Inventory中定義變量
  • 二、在Playbook中定義變量
    • 1、通過vars關鍵字定義
    • 2、通過vars_files關鍵字引入變量文件
    • 3、通過vars_prompt來實現人機交互
    • 4、通過playbook的roles定義變量
  • 三、註冊變量
  • 四、通過fact獲取遠程主機變量
  • 五、使用set_fact模塊定義新的變量
  • 六、內置變量
    • 1、hostvars
    • 2、inventory_hostname與inventory_hostname_short
    • 3、group_names
    • 4、groups
    • 5、play_hosts
    • 6、ansible_version
    • 7、inventory_dir
    • 8、inventory_file
  • 七、通過命令行設置變量
  • 八、查看變量
  • 九、變量優先級

簡單說明

首先我需要特別強調的是,變量名不能包含"-"。其實官方文檔有詳細說明,我在沒仔細看官方文檔的時候踩到這個坑。拋出了如下異常:

{‘msg‘: "TypeError: unsupported operand type(s) for -: ‘StrictUndefined‘ and ‘unicode‘", ‘failed‘: True}

一、在Inventory中定義變量

詳見《Ansible2:主機清單》

二、在Playbook中定義變量

1、通過vars關鍵字定義

下面是一個簡單示例:

vars: 
  http_port: 80
  server_name: localhost
  cert_file: /etc/nginx/ssl/nginx.crt
  key_file: /etc/nginx/ssh/nginx.key
  conf_file: /etc/nginx/conf/default.conf

2、通過vars_files關鍵字引入變量文件

下面是一個簡單示例:

- hosts: all
  remote_user: root
  vars:
    favcolor: blue
  vars_files:
    - /vars/external_vars.yml
    - /vars/nginx_vars.yml

# /vars/nginx_vars.yml示例:
http_port: 80
server_name: localhost
cert_file: /etc/nginx/ssl/nginx.crt
key_file: /etc/nginx/ssh/nginx.key
conf_file: /etc/nginx/conf/default.conf

3、通過vars_prompt來實現人機交互

示例:

hosts: all
remote_user: root
vars_prompt:
  - name: ‘https_passphrase‘          #存儲數據的變量名
    prompt: ‘Key Passphrase‘          #手工輸入數據
    private: yes                      #當該值為yes,則用戶的輸入不會被打印

4、通過playbook的roles定義變量

詳見《ansible10:Playbook的角色與包含》

三、註冊變量

在有些時候,我們希望把某一條任務執行的結果保存下來,可以在接下的任務中調用或者做些判斷,可以通過register關鍵字來實現。

下面是個簡單的例子,如果/etc/motd文件中包含有‘hi‘字符串時,則輸出"mothd contains ther word hi":

- name: test play
  hosts: all
  tasks:
      - shell: cat /etc/motd
        register: motd_contents
      - shell: echo "motd contains the word hi"
        when: motd_contents.stdout.find(‘hi‘) != -1
        

下面是一個register的變量在循環中使用的例子:

- name: registered variable usage as a with_items list
  hosts: all
  tasks:
      - name: retrieve the list of home directories
        command: ls /home
        register: home_dirs
      - name: add home dirs to the backup spooler
        file: path=/mnt/bkspool/{{ item }} src=/home/{{ item }} state=link
        with_items: home_dirs.stdout_lines
        # same as with_items: home_dirs.stdout.split()

四、通過fact獲取遠程主機變量

我們在之前講ad-hoc常用模塊的時候提到setup模塊,用於獲取遠程主機的相關信息,並可以將這些信息作為變量在playbook裏進行調用。而setup模塊獲取這些信息的方法就是依賴於fact。在這裏,我們不再詳細說明獲取到的默認fact的內容。ansible除了能獲取到預定義的fact的內容,還支持手動為某個主機定制fact。稱之為本地fact。本地fact默認存放於目標主機的/etc/ansible/facts.d目錄下,如果文件為.ini格式或者json格式,ansible會自動識別。以這種形式加載的fact是key為ansible_local的特殊變量。

下面是一個簡單的示例,一個.ini格式的example.fact文件內容如下:

[book]
title=Ansible Book
author=Breeze Yan

將其復制到目標主機的/etc/ansible/facts.d/目錄,通過debug模塊打印輸出:

- name: print ansible_local
  debug: var=ansibl_local

會打印出如下內容:

ok: [localhost] => {
    "var": {
        "ansible_local": {
            "example": {
                "book": {
                    "author": "Breeze Yan", 
                    "title": "Ansible Book"
                }
            }
        }
    }
}

如果不想從fact中獲取變量,可以通過如下方法關閉fact:

- hosts: whatever
  gather_facts: no

五、使用set_fact模塊定義新的變量

在《ansible7:Playbook常用模塊》中有對set_fact模塊用法的詳細說明

六、內置變量

1、hostvars

獲取某臺指定的主機的相關變量。如果有一臺web服務器的配置文件中需要指定db服務器的ip地址,我們假定這臺db服務器的hostname為db.exmaple.com,ip地址綁定在eth0網卡上,我們可以通過如下方法在web服務器上調用db服務器的ip地址:

{{ hostvars[‘db.example.com‘].ansible_eth0.ipv4.address }}

需要註意的是db.example.com不能使用ip地址來取代,只能使用主機名或別名。

2、inventory_hostname與inventory_hostname_short

inventory_hostname是Ansible所識別的當前正在運行task的主機的主機名。如果在inventory裏定義過別名,那麽這裏就是那個別名,如果inventory包含如下一行:

server1 ansible_ssh_host=192.168.1.1

inventory_hostname即為server1
利用hostvarsinventory_hostname變量,可以輸出與當前主機相關聯的所有變量:

- debug: var=hostvars[inventory_hostname]

與inventory_hostname相近的還有一個inventory_hostname_short,如果一臺主機的inventory_hostname為server1.exmaple.com,則inventory_hostname_short的值為server1

3、group_names

用於標識當前正在執行task的目標主機位於的主機組。假如我們有三臺主機,用來配置成一主二從的mysql服務器。inventory配置如下:

[mdb]
db1
[sdb]
db2
db3

mysql配置文件my.conf.j2示例如下:

#我們知道db1在mdb組,當db1與當前正在執行任務的主機位於同一組時,我們認為當前主機即在mdb組,所以對當前主機應用mysql master的配置
{% if ‘db1‘ in group_names %}
[mysqld]
server-id=1
log-bin=mysql-bin
log-bin-index=mysql-bin.index
sync-binlog=1
innodb_flush_log_at_trx_commit=1
#當db1與當前主機不在同一組時,則認為當前主機不在mdb組,即應用my slave的配置
{% else %}
[mysqld]
server-id=2
relay-log=relay-log
relay-log-index=relay-log.index
read-only = yes
sync_master_info = 1
sync_relay_log = 1
sync_relay_log_info = 1
relay_log_recovery = 1
skip_slave_start    
{% endif %}

我們執行如下task:

- name: copy config file to mysql master
  template: src=my.conf.j2 dest=/etc/my.cnf

4、groups

當你想要訪問一組主機的變量時,groups變量會很有用。假如我們有一個inventory文件定義如下:

[web]
server1
server2

在配置一臺HAproxy的負載均衡器時,我們的配置文件肯定需要web群組的所有服務器的IP,配置文件包含如下片段:

backend web-backend
{% for host in groups.web%}
    server {{host.inventory_hostname}} {{ host.ansible_default_ipv4.address }}:80
{% endfor %}

最終生成的文件如下:

backend web-backend
    server server1 192.168.1.1:80
    server server2 192.168.1.2:80

再給一個例子,在所有的dbservers組的服務器上創建一個數據庫用戶kate:

- name: Create a user for all db servers
  mysql_user: name=kate password=test host={{ hostvars.[item].ansible_eth0.ipv4.address }} state=present
  with_items: groups[‘dbservers‘] 

5、play_hosts

當前playbook會在哪些hosts上運行

6、ansible_version

當前ansible的版本

7、inventory_dir

主機清單所在目錄

8、inventory_file

主機清單文件

七、通過命令行設置變量

示例如下:

---
- hosts: ‘{{ hosts }}‘
  remote_user: ‘{{ user }}‘
  tasks:
     - ...
     
ansible-playbook release.yml --extra-vars "hosts=vipers user=starbuck"

也可以寫成類似如下方式:

--extra-vars ‘{"pacman":"mrs","ghosts":["inky","pinky","clyde","sue"]}‘

八、查看變量

為了方便調試,ansible提供了debug模塊來很方便的查看模塊。用法可以參考通過fact獲取主機變量中的打印本地fact的示例

九、變量優先級

  1. extra vars(命令中-e)最優先
  2. inventory 主機清單中連接變量(ansible_ssh_user 等)
  3. play 中 vars、vars_files 等
  4. 剩余的在 inventory 中定義的變量
  5. 系統的 facts 變量
  6. 角色定義的默認變量(roles/rolesname/defaults/main.yml)

    子組會覆蓋父組,主機總是覆蓋組定義的變量

Ansible11:變量詳解