본문 바로가기

리눅스

[draft] Ansible 팩트 변수와 매직 변수

Ansible 팩트 변수(Facts Variables)와 매직 변수(Magic Variables)

Ansible은 실행 시점에 시스템 정보와 실행 환경 정보를 자동으로 변수로 수집합니다.

팩트 변수(Facts Variables)란?

팩트 변수란 Ansible이 setup 모듈을 통해 자동으로 수집한 시스템 정보를 의미합니다.

  • OS 종류, 버전
  • 커널 정보
  • 네트워크 인터페이스
  • CPU / 메모리
  • 디스크 정보 등
플레이북 실행 시 기본적으로 Gathering Facts 단계에서 자동 수집됩니다.

1. 팩트 변수 수동 확인하기 (setup 모듈)

특정 팩트 필터링

ansible localhost -m setup -a "filter=*내용*"
ansible -i ./inventory kube-node1 -m setup -a "filter=ansible_distribution"
kube-node1 | SUCCESS => {
    "ansible_facts": {
        "ansible_distribution": "Ubuntu",
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false
}

와일드카드 필터 사용

ansible -i ./inventory kube-node1 -m setup -a "filter=*ansible_distribution*"
kube-node1 | SUCCESS => {
    "ansible_facts": {
        "ansible_distribution": "Ubuntu",
        "ansible_distribution_file_parsed": true,
        "ansible_distribution_file_path": "/etc/os-release",
        "ansible_distribution_file_variety": "Debian",
        "ansible_distribution_major_version": "22",
        "ansible_distribution_release": "jammy",
        "ansible_distribution_version": "22.04",
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false
}

CLI에서 grep으로 확인

ansible -i ./inventory kube-node1 -m setup | egrep ansible_distribution
        "ansible_distribution": "Ubuntu",
        "ansible_distribution_file_parsed": true,
        "ansible_distribution_file_path": "/etc/os-release",
        "ansible_distribution_file_variety": "Debian",
        "ansible_distribution_major_version": "22",
        "ansible_distribution_release": "jammy",
        "ansible_distribution_version": "22.04",
팩트 변수는 모두 ansible_ 접두사로 시작

2. 사용자 정의 팩트(Custom Facts)

Ansible은 사용자가 직접 정의한 팩트도 자동으로 수집할 수 있습니다.

 

Control Node 설정 (ansible.cfg)

vim ansible.cfg
fact_path=/etc/ansible/facts.d/
$ cat ansible.cfg | grep -C4 fact_path

# (string) This option allows you to globally configure a custom path for 'local_facts' for the implied M(ansible.builtin.setup) task when using fact gathering.
# If not set, it will fallback to the default from the M(ansible.builtin.setup) module: ``/etc/ansible/facts.d``.
# This does **not** affect  user defined tasks that use the M(ansible.builtin.setup) module.
fact_path=/etc/ansible/facts.d/

# (pathspec) Colon separated paths in which Ansible will search for Jinja2 Filter Plugins.
;filter_plugins=~/.ansible/plugins/filter:/usr/share/ansible/plugins/filter
fact_path는 로컬 팩트가 저장되는 경로입니다.

Managed Node 설정

sudo mkdir /etc/ansible/facts.d/

스크립트 기반 팩트 작성

  • date_time.fact
vim date_time.fact
#!/usr/bin/bash

DATE=`date`
echo "{\"date\" : \"${DATE}\"}"
chmod +x /etc/ansible/facts.d/date_time.fact
  • JSON 기반 팩트 생성
vim test.fact
{"fact_key": "fact_value"}

사용자 정의 팩트 확인

ansible -i ./inventory kube-node1 -m setup -a "filter=ansible_local"
kube-node1 | SUCCESS => {
    "ansible_facts": {
        "ansible_local": {
            "date_time": {
                "date": "Mon Nov  7 02:39:25 PM KST 2022"
            },
            "test": {
                "fact_key": "fact_value"
            }
        },
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false
}
사용자 정의 팩트는 ansible_local 네임스페이스 아래에 저장됩니다.

3. 플레이북에서 사용자 정의 팩트 사용

check_date.yml

vim check_date.yml
---

- hosts: all

  tasks:
   - name: Get custom facts
     debug:
      msg: The custom fact is {{ansible_local.date_time}}

   - name: get key:value
     debug:
       msg: "{{ansible_local.test}}"

ansible-playbook 실행

ansible-playbook -i ./inventory --limit kube-node1 check_date.yml

PLAY [all] *********************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [kube-node1]

TASK [Get custom facts] ********************************************************************************************
ok: [kube-node1] => {
    "msg": "The custom fact is {'date': 'Mon Nov  7 02:44:41 PM KST 2022'}"
}

TASK [get key:value] ***********************************************************************************************
ok: [kube-node1] => {
    "msg": {
        "fact_key": "fact_value"
    }
}

PLAY RECAP *********************************************************************************************************
kube-node1                 : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

4. 매직 변수(Magic Variables)란?

매직 변수는 Ansible이 실행 컨텍스트 자체에서 자동으로 제공하는 내부 변수입니다.

팩트 변수와 달리 시스템 정보가 아니라 실행 환경 정보입니다.

5. 주요 매직 변수 정리

변수 설명
hostvars 인벤토리의 모든 호스트와 호스트에 할당된 변수가 포함된 사전/맵
group_names 현재 호스트가 속한 그룹 목록은 항상 Inventory_hostname을 반영하고 위임을 무시합니다.
groups 인벤토리의 모든 그룹이 포함된 사전/맵 및 각 그룹에는 해당 그룹에 속한 호스트 목록이 있습니다.
inventory_hostname 플레이에서 반복되는 '현재' 호스트의 인벤토리 이름입니다. 이는 위임의 영향을 받지 않으며 항상 작업의 원래 호스트를 반영합니다.

6. 매직 변수 확인

gatherMagic.yaml 작성

vim gatherMagic.yaml
---
- name: gather magic 
  hosts: all
  gather_facts: false

  tasks:
  - name: magic variable
    debug:
      var: "{{ item }}"
    loop:
      - ansible_config_file
      - playbook_dir
      - inventory_dir
      - inventory_file
      - ansible_check_mode
      - ansible_diff_mode
      - ansible_forks
      - ansible_verbosity
      - inventory_hostname
      - ansible_play_hosts
      - ansible_version

ansible-playbook 실행

ansible-playbook -i ./inventory --limit kube-node1 gatherMagic.yaml

PLAY [gather magic] ************************************************************************************************

TASK [magic variable] **********************************************************************************************
ok: [kube-node1] => (item=ansible_config_file) => {
    "ansible_config_file": "/home/vagrant/ansible-spec/ansible.cfg",
    "ansible_loop_var": "item",
    "item": "ansible_config_file"
}
ok: [kube-node1] => (item=playbook_dir) => {
    "ansible_loop_var": "item",
    "item": "playbook_dir",
    "playbook_dir": "/home/vagrant/ansible-spec"
}
ok: [kube-node1] => (item=inventory_dir) => {
    "ansible_loop_var": "item",
    "inventory_dir": "/home/vagrant/ansible-spec/inventory",
    "item": "inventory_dir"
}
ok: [kube-node1] => (item=inventory_file) => {
    "ansible_loop_var": "item",
    "inventory_file": "/home/vagrant/ansible-spec/inventory/inventory.yaml",
    "item": "inventory_file"
}
ok: [kube-node1] => (item=ansible_check_mode) => {
    "ansible_check_mode": false,
    "ansible_loop_var": "item",
    "item": "ansible_check_mode"
}
ok: [kube-node1] => (item=ansible_diff_mode) => {
    "ansible_diff_mode": false,
    "ansible_loop_var": "item",
    "item": "ansible_diff_mode"
}
ok: [kube-node1] => (item=ansible_forks) => {
    "ansible_forks": 5,
    "ansible_loop_var": "item",
    "item": "ansible_forks"
}
ok: [kube-node1] => (item=ansible_verbosity) => {
    "ansible_loop_var": "item",
    "ansible_verbosity": 0,
    "item": "ansible_verbosity"
}
ok: [kube-node1] => (item=inventory_hostname) => {
    "ansible_loop_var": "item",
    "inventory_hostname": "kube-node1",
    "item": "inventory_hostname"
}
ok: [kube-node1] => (item=ansible_play_hosts) => {
    "ansible_loop_var": "item",
    "ansible_play_hosts": [
        "kube-node1"
    ],
    "item": "ansible_play_hosts"
}
ok: [kube-node1] => (item=ansible_version) => {
    "ansible_loop_var": "item",
    "ansible_version": {
        "full": "2.12.5",
        "major": 2,
        "minor": 12,
        "revision": 5,
        "string": "2.12.5"
    },
    "item": "ansible_version"
}

PLAY RECAP *********************************************************************************************************
kube-node1                 : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

7. hostvars 확인 예제

ansible localhost -m debug -a "var=hostvars['localhost']"
MAGIC_VARIABLE_MAPPING = dict(
   connection       = ('ansible_connection',),
   remote_addr      = ('ansible_ssh_host', 'ansible_host'),
   remote_user      = ('ansible_ssh_user', 'ansible_user'),
   port             = ('ansible_ssh_port', 'ansible_port'),
   accelerate_port  = ('ansible_accelerate_port',),
   password         = ('ansible_ssh_pass', 'ansible_password'),
   private_key_file = ('ansible_ssh_private_key_file', 'ansible_private_key_file'),
   pipelining       = ('ansible_ssh_pipelining', 'ansible_pipelining'),
   shell            = ('ansible_shell_type',),
   become           = ('ansible_become',),
   become_method    = ('ansible_become_method',),
   become_user      = ('ansible_become_user',),
   become_pass      = ('ansible_become_password','ansible_become_pass'),
   become_exe       = ('ansible_become_exe',),
   become_flags     = ('ansible_become_flags',),
   ssh_common_args  = ('ansible_ssh_common_args',),
   docker_extra_args= ('ansible_docker_extra_args',),
   sftp_extra_args  = ('ansible_sftp_extra_args',),
   scp_extra_args   = ('ansible_scp_extra_args',),
   ssh_extra_args   = ('ansible_ssh_extra_args',),
   sudo             = ('ansible_sudo',),
   sudo_user        = ('ansible_sudo_user',),
   sudo_pass        = ('ansible_sudo_password', 'ansible_sudo_pass'),
   sudo_exe         = ('ansible_sudo_exe',),
   sudo_flags       = ('ansible_sudo_flags',),
   su               = ('ansible_su',),
   su_user          = ('ansible_su_user',),
   su_pass          = ('ansible_su_password', 'ansible_su_pass'),
   su_exe           = ('ansible_su_exe',),
   su_flags         = ('ansible_su_flags',),
   executable       = ('ansible_shell_executable',),
   module_compression = ('ansible_module_compression',),
)
ansible localhost -m debug -a "var=hostvars['localhost']"

 

참고URL

- 변군이글루 블로그 : facts 모듈(facts module)

- Ansible Documentation : Special Variables - Magic variables