一文搞懂 ansible 變量配置


如何自定義變量

- hosts: webservers
  vars:
    http_port: 80

可以在temple 文件中使用 {{ }} 來使用變量

My amp goes to {{ max_amp_value }}

也可以在寫playbook的時候使用變量

template: src=foo.cfg.j2 dest={{ remote_install_path }}/foo.cfg

這里有個小技巧,使用變量時,要用雙引號引用。
錯誤寫法

- hosts: app_servers
  vars:
      app_path: {{ base_path }}/22

正確寫法

- hosts: app_servers
  vars:
       app_path: "{{ base_path }}/22"

facts: 系統的信息

從遠程節點搜集到的系統信息稱為facts。facts包括遠程主機的IP地址,和操作系統類型,磁盤相關信息等等。

執行下邊的命令來查看都有哪些信息:

- debug: var=ansible_facts
ansible test -m setup

返回內容類似下邊這樣:

ansible linux-node2 -m setup  |head
linux-node2 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "10.0.2.12",
            "192.168.56.12"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::250:56ff:fe3f:cc94",
            "fe80::250:56ff:fe30:8f96"
        ],
        ......省略若干行內容......

可以在temple模板中使用上邊返回的值:

{{ ansible_devices.sda.model }}
{{ ansible_facts['devices']['xvda']['model'] }}

要獲取系統的主機名:

{{ ansible_hostname }}

facts會經常在條件語句及模板中使用。如,根據不同的linux發行版,執行不同的包管理程序。

關閉facts

如果你確信不需要主機的任何facts信息,而且對遠程節點主機都了解的很清楚,那么可以將其關閉。遠程操作節點較多的時候,關閉facts會提升ansible的性能。

只需要在play中設置如下:

- hosts: whatever
  gather_facts: no

本地facts(facts.d)

如果遠程節點系統上存在etc/ansible/facts.d目錄,這個目錄下的以.fact為后綴的文件,里面的內容可以是JSON格式,或者ini格式書寫;或者是一個可以返回json格式數據的可執行文件,都可以用來提供本地facts信息。

在遠程節點創建一個/etc/ansible/facts.d/preferences.fact的文件,內容如下:

mkdir -p /etc/ansible/facts.d
cat >>/etc/ansible/facts.d/preferences.fact<<EOF
[general]
name=linux
test=True
EOF

在控制節點獲取自定義的信息:

ansible linux-node2 -m setup -a "filter=ansible_local"
linux-node2 | SUCCESS => {
    "ansible_facts": {
        "ansible_local": {
            "preferences": {
                "general": {
                    "name": "linux",
                    "test": "True"
                }
            }
        }
    },
    "changed": false
}

可以在playbooks或者模板中這樣使用獲取到的信息:

{{ ansible_local.preferences.general.name }}

linux-node2 服務器配置

mkdir /etc/ansible/facts.d -p

cat /etc/ansible/facts.d/ini.fact
[mytest]
niu=key

cat /etc/ansible/facts.d/niu.fact
{ "name":"shencan" , "list":["three","one","two"], "Dict": {"A":"B"} }

結果展示

ansible -i inventory/ linux-node2 -m setup -a "filter=ansible_local"
linux-node2 | SUCCESS => {
    "ansible_facts": {
        "ansible_local": {
            "ini": {
                "mytest": {
                    "niu": "key"
                }
            },
            "niu": {
                "Dict": {
                    "A": "B"
                },
                "list": [
                    "three",
                    "one",
                    "two"
                ],
                "name": "shencan"
            },
            "preferences": {
                "general": {
                    "name": "linux",
                    "test": "True"
                }
            }
        }
    },
    "changed": false
}

緩存 facts數據

編輯 ansible.cfg 添加如下內容,讓數據緩存到redis中。

[defaults]
gathering = smart
fact_caching = redis
fact_caching_timeout = 86400
# seconds

需要安裝相關的依賴程序

yum install redis
service redis start
pip install redis

使用facter擴展facts信息

使用過Puppet的讀者都熟悉facter是Puppet里面一個負責收集主機靜態信息的組件,Ansible的facts功能也一樣。Ansible的facts組件也會判斷被控制機器上是否安裝有facter和ruby-json包,如果存在的話,Ansible的facts也會采集facter信息。我們來查看以下機器信息:

ansible linux-node2 -m shell -a 'rpm -qa ruby-json facter'

ansible linux-node2 -m facter

當然,如果直接運行setup模塊也會采集facter信息
所有facter信息在ansible_facts下以facter_開頭,這些信息的引用方式跟Ansible自帶facts組件收集的信息引用方式一致。

使用ohai擴展facts信息

ohai是Chef配置管理工具中檢測節點屬性的工具,Ansible的facts也支持ohai信息的采集。當然需要被管機器上安裝ohai包。下面介紹ohai相關信息的采集:

ansible linux-node2 -m shell -a 'gem list|grep ohai'

如果主機上沒有安裝ohai包,可以使用gem方式進行安裝。如果存在ohai包,可以直接運行ohai模塊查看ohai屬性:

ansible linux-node2 -m ohai

如果直接運行setup模塊,也會采集ohai信息

Registered 獲取執行命令的輸出

register方式用於在task之間傳遞變量。

在剛開始使用 ansible-playbook 做應用程序部署的時候,因為在部署的過程中有使用到 command 或 shell 模塊執行一些自定義的腳本,而且這些腳本都會有輸出,用來表示是否執行正常或失敗。如果像之前自己寫腳本做應用程序部署的,這很好實現。但現在是用 Ansible 做,那么要怎么樣做可以獲取到 ansible playbook 中 command 模塊的輸出呢? Ansible 也提供的解決辦法,這時我們就可以通過使用 register 關鍵字來實現,register 關鍵字可以存儲指定命令的輸出結果到一個自定義的變量中,我們通過訪問這個自定義變量就可以獲取到命令的輸出結果。Register 的使用很方便,只需要在 task 聲明 register 關鍵字,並自定義一個變量名就可以。如下:

- hosts: web_servers

  tasks:

     - shell: /usr/bin/foo
       register: foo_result
       ignore_errors: True

     - shell: /usr/bin/bar
       when: foo_result.rc == 5

register 中存放的的數據其實是ansible stdout返回的json數據,拿到json數椐后就可以做相關使用和處理了。可以使用-v 查看上一個task的stdout 數據。

- name: echo date
 command: date
 register: date_output

- name: echo date_output
 command: echo "30"
 when: date_output.stdout.split(' ')[2] == "30"

這里第 1 個 task 是執行了一個 date 命令,register 關鍵字將 date 命令的輸出存儲到 date_output 變量名。第 2 個 task 對輸出進行分析,並使用 when 對關鍵字對分析后的進行判斷,如果匹配,則執行這個 task,不匹配就不執行。這里要重點說下的,因為 register 獲取到的輸出內容都是字符串,而 ansible 又是 python 寫的,你可以使用 python 字符串的方法對其做處理,比如本文中使用的 split,還可以使用 find 方法。個人覺得,真是非常靈活方便。

注冊變量

register: xxx
  • xxx.stdout.find(sdf)
  • xxx.stdout_lines

使用debug模塊查看register中的數據

---
  - hosts: all
      gather_facts: False
      tasks:
          - name: register variable
              shell: hostname
              register: info
          - name: display variable
              debug: msg="The varibale is  {{ info  }}"

內置變量

ansible 默認內置了一下變量,可以直接使用。hostvars, groups, group_names, and inventory_hostname

hostvars

hostvars 是用來調用指定主機變量,需要傳入主機信息,返回結果也是一個 JSON 字符串,同樣,也可以直接引用 JSON 字符串內的指定信息。如果主機執行獲取了 facts 數據,則hosts中將會包含 facts 中的數據。

- name: Get the masters IP
  set_fact: dns_master="{{ hostvars.ns1.ansible_default_ipv4.address }}"

- name: Configure BIND
  template: dest=/etc/named.conf src=templates/named.conf.j2

hostvars 例子

{
	'linux-node1': {
		'inventory_file': '/data/db/playbooks/inventory/open_falcon',
		'ansible_playbook_python': '/usr/bin/python2',
		'falcon_mysql_port': 3306,
		'ansible_check_mode': True,
		'falcon_mysql_passwd': 123456,
		'ansible_diff_mode': True,
		'open_falcon_path': '/data/app/open-falcon',
		'groups': {
			'ungrouped': [],
			'judge': ['linux-node2_judge1', 'linux-node2_judge2'],
			'all': ['linux-node1', 'linux-node2_judge1', 'linux-node2_judge2'],
			'open_falcon': ['linux-node2_judge1', 'linux-node2_judge2', 'linux-node1'],
			'api': ['linux-node1']
		},
		'ansible_forks': 5,
		'ansible_facts': {},
		'inventory_hostname': 'linux-node1',
		'ansible_inventory_sources': ['/data/db/playbooks/inventory/open_falcon'],
		'target': 'judge',
		'inventory_hostname_short': 'linux-node1',
		'playbook_dir': '/data/db/playbooks/playbooks',
		'omit': '__omit_place_holder__38ba14590a3d51c234a21046ca130054f96cc570',
		'ansible_skip_tags': [],
		'inventory_dir': '/data/db/playbooks/inventory',
		'ansible_verbosity': 0,
		'role': 'test',
		'group_names': ['api', 'open_falcon'],
		'falcon_mysql_host': '192.168.56.12',
		'ansible_run_tags': ['test_vars'],
		'ansible_version': {
			'major': 2,
			'full': '2.7.1',
			'string': '2.7.1',
			'minor': 7,
			'revision': 1
		},
		'falcon_mysql_name': 'falcon'
	},
  ’linux-node2_judge2‘: {
    'ansible_hostname': 'linux-node2',
		'ansible_ssh_port': 52113,
    'ansible_ssh_host': 'linux-node2',
    'ansible_system': 'Linux',
		'playbook_dir': '/data/db/playbooks/playbooks',
		'ansible_run_tags': ['test_vars'],
		'judge_http_port': 6081,
		'ansible_python_version': '2.7.5'
  }
}

groups

groups 變量是一個全局變量,引用了inventory文件里所有的主機以及主機組信息 它返回的是一個json字符串。

{
	'ungrouped': [],
	u 'judge': [u 'linux-node2_judge1', u 'linux-node2_judge2'],
	'all': [u 'linux-node1', u 'linux-node2_judge1', u 'linux-node2_judge2'],
	u 'open_falcon': [u 'linux-node2_judge1', u 'linux-node2_judge2', u 'linux-node1'],
	u 'api': [u 'linux-node1']
}

playbook中通過{{ groups }}或是{{ groups.屬性}}的方式來引用

  - name: Create a user for all app servers
  with_items: groups.appservers
  mysql_user: name=kate password=test host={{ hostvars.[item].ansible_eth0.ipv4.address }} state=present
{% for host in groups['app_servers'] %}
   {{ hostvars[host]['ansible_facts']['eth0']['ipv4']['address'] }}
{% endfor %}
etcd_initial_cluster: |-
      {% for item in groups['etcd'] -%}
        {{ hostvars[item]['node_name'] }}=http://{{ hostvars[item]['ansible_default_ipv4']['address'] }}:2380{% if not loop.last %},{% endif %}
      {%- endfor %}
etcd_initial_cluster_state: "new"

group_names

group_names引用當前主機所在的group的名稱

{% if 'webserver' in group_names %}
   # some part of a configuration file that only applies to webservers
{% endif %}
- name: For secure machines
  set_fact: sshconfig=files/ssh/sshd_config_secure
  when: "'secure' in group_names"

- name: For non-secure machines
  set_fact: sshconfig=files/ssh/sshd_config_default
  when: "'secure' not in group_names"
  • inventory_hostname 變量保存了在設備配置清單中服務器的主機名
  • inventory_hostname_short 變量跟inventory_hostname一樣,只是去掉域名,比如inventory_hostname 是host.example 那么inventory_hostname_short就是host
  • inventory_dir 是設備清單文件的路徑
  • inventory_file 是設備清單文件的文件名

通過 vars_files 指定變量文件

---

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

  tasks:

  - name: this is just a placeholder
    command: /bin/echo foo

/vars/external_vars.yml 文件內容

---
# in the above example, this would be vars/external_vars.yml
somevar: somevalue
password: magic

使用 --extra-vars (or -e ) 命令行傳入 變量

ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"
ansible-playbook release.yml --extra-vars "@some_file.json"
ansible-playbook release.yml --extra-vars '{"version":"1.23.45","other_variable":"foo"}'
ansible-playbook arcade.yml --extra-vars '{"pacman":"mrs","ghosts":["inky","pinky","clyde","sue"]}'

變量讀取的優先級

讀取順序倒敘實現,最后一行是優先級最高的

  • command line values (eg “-u user”)
  • role defaults [1]
  • inventory file or script group vars [2]
  • inventory group_vars/all [3]
  • playbook group_vars/all [3]
  • inventory group_vars/* [3]
  • playbook group_vars/* [3]
  • inventory file or script host vars [2]
  • inventory host_vars/* [3]
  • playbook host_vars/* [3]
  • host facts / cached set_facts [4]
  • play vars
  • play vars_prompt
  • play vars_files
  • role vars (defined in role/vars/main.yml)
  • block vars (only for tasks in block)
  • task vars (only for the task)
  • include_vars
  • set_facts / registered vars
  • role (and include_role) params
  • include params
  • extra vars (always win precedence)

定義一個roles 來測試執行順序 vim roles/test/main.yaml

- debug:
    msg: test_vars {{ test_vars }}

playbook 中定義 vars vim playbooks/role.yaml

- hosts: "{{ target }}"
  roles:
    - "{{ role }}"
  vars:
    - test_vars: playbook

執行roles ansible-playbook -i inventory/ -e target=localhost -e role=test playbooks/role.yaml -t test_vars -CD

TASK [test : debug] **************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "test_vars playbook"
}

第二步 在roles/vars中定義變量

vim test/vars/main.yaml
test_vars: test_vars

執行roles ansible-playbook -i inventory/ -e target=localhost -e role=test playbooks/role.yaml -t test_vars -CD

TASK [test : debug] **************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "test_vars test_vars"
}

第三步 在roles文件中定義 vim roles/test/main.yaml

- debug:
    msg: test_vars {{ test_vars }}
  vars:
    - test_vars: block

執行roles ansible-playbook -i inventory/ -e target=localhost -e role=test playbooks/role.yaml -t test_vars -CD

TASK [test : debug] **************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "test_vars block"
}

第四步 命令行中使用 -e 傳入變量

ansible-playbook -i inventory/ -e target=localhost -e role=test playbooks/role.yaml  -t test_vars -CD  -e "test_vars=cmdline"
TASK [test : debug] **************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "test_vars cmdline"
}

參考文檔

Using Variables


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM