Cloud Engineering/Ansible

[Ansible] Playbook 변수 사용하기 / vars_prompt / filter (필터) / lookup (조회)

minjiwoo 2023. 2. 28. 16:56
728x90

변수 정의하기 

Ansible에서 변수를 정의할 수 있는 곳은 다음과 같다. 

  • 플레이북
  • 외부 참조 파일
  • 인벤토리 파일 
  • 명령의 -e 옵션

Ansible 에서는 변수를 key, value 형태로 정의한다. 

 

Playbook 에서 변수의 우선 순위

동일한 변수명을 가진 경우 플레이북에서 변수가 참조되는 우선순위는 다음과 같다. (우선 순위 높은 순으로 정렬되었다.)

-e옵션으로 변수 지정 > 플레이북 vars_files 변수 > 플레이북에 정의된 변수 > host_vars 디렉토리의 호스트 변수 > Inventory 의 호스트 변수 > group_vars directory의 그룹 변수 > Inventory 의 그룹변수

 

1. 인벤토리 파일에 변수 정의하기 

인벤토리 파일에서 host 변수 및 group 변수를 작성할 수 있다. 

ansi-master1     
ansi-node1 temp=aaa
[AA]    
ansi-node1       
ansi-node2 
        
[AA:vars] 
username1=vagrant  
temp=bbb
[BB]    
ansi-node2
ansi-node3
        
[CC]    
ansi-node3
ansi-node1
        
[DD:children]    
AA      
BB

예를 들어서 다음과 같이 변수를 출력하는 간단한 playbook 을 생성한다. 

- name: print var
  hosts: AA
  tasks:
  - name: task1
    debug:
      msg: "{{ temp }}"

출력 결과는 다음과 같다. 

변수의 우선순위가 inventory 파일 내에서 정의된 경우 host 변수가 group 변수 보다 높다. 따라서 host 변수가 정의된 ansi-node1에서는 temp 변수 값이 aaa 로 출력된다. 

 

2. 플레이북 내에서 변수 정의 

vars: 필드 하위에 키 - 값 쌍으로 변수를 정의할 수 있다. 

- name: print var
  hosts: AA
  vars: 
    temp: ccc
  tasks:
  - name: task1
    debug:
      msg: "{{ temp }}"

결과

3. group_vars/ 내의 파일 

인벤토리 파일이 있는 경로의 group_vars 디렉토리보다 플레이북 파일이 있는 경로의 group_vars 우선순위가 높다. 

mkdir group_vars

플레이북이 파일이 있는 경로에 group_vars 디렉토리를 생성하고, 하위에 파일을 작성한다. 

vi group_vars/example

temp: group_variable_file

vars_files 필드에서 사용할 변수 파일을 지정한다. vars_files 필드는 리스트 항목으로, 여러개의 파일을 지정할 수 있다. 

- name: print var
  hosts: AA
#  vars: 
#    temp: ccc
  vars_files:
  - group_vars/example
  tasks:
  - name: task1
    debug:
      msg: "{{ temp }}"

 playbook 실행 결과 

group_vars/example 파일에서 temp 변수를 참조하고 있다. 

 

4. host_vars/ 내부 파일 

위의 group_vars 에 설정한 변수 파일을 참조하는 것과 동일하게 작업할 수 있다.

/host_vars/example 파일 내용

temp: host_variable_file

 

play book file 내용

- name: print var
  hosts: AA
  vars_files:
  - host_vars/example
  tasks:
  - name: task1
    debug:
      msg: "{{ temp }}"

 

플레이북 실행 결과

5. -e 옵션으로 extra vars 지정하기 

$ ansible-playbook vars1.yaml -e 'temp=hello'

extra vars 가 가장 우선순위가 높다. 

 

vars_prompt

사용자에게 변수의 값을 입력하도록 지정한다.

vars_prompt가 쓰이는 경우는 패스워드 같이 저장하기에 민감한 정보를 다루거나 변동사항이 많은 경우 버전 명을 직접 사용자가 지정할 수 있도록 할 때 쓰인다.

 

vars_prompt 사용 예시 (1) - 새로운 유저의 id 와 password 를 입력받을 때 

- hosts: ansi-node2        
  vars_prompt:             
  - name: user_id          
    prompt: "Enter user id"
    private: no            
    default: admin         
  - name: user_pw          
    prompt: "Enter password"
    private: yes           
    encrypt: sha512_crypt  
    confirm: yes           
    salt_size: 8           
  tasks:                   
  - name: enroll new user  
    user:                  
      name: "{{ user_id }}"
      password: "{{ user_pw }}"

user_id 프롬프트 변수는 private 설정에 no 라고 했기 때문에 화면에 출력되지만, user_pw의 경우 private 설정이 yes 이므로 화면에 표시되지 않는다. 또한 confirm 옵션을 yes 라고 했기 때문에 두번 입력하게 된다. 

 

vars_prompt 설정 필드

  • name 변수 이름
  • prompt 화면에 출력할 문자열
  • private 사용자가 키보드로 입력을 할 때, 화면에 입력값이 보이는지 여부 (true/false) 로 설정
  • default 기본값
  • encrypt 암호 알고리즘
  • salt_size : salt 길이 기본 8 (sha256으로 버무린다)
  • confirm 입력값을 한 번 더 치도록 검증

 

vars_prompt 사용 예시 (2) - 파일 이름을 입력값으로 받기

- hosts: ansi-node1
  vars_prompt:
  - name: f_name
    prompt: "Ener the new file name"
    private: no
  tasks:
  - name: create a new file
    file: 
      state: touch
      path: /home/vagrant/{{ f_name }}
      owner: vagrant
      group: vagrant
  - name: copy the content
    copy:
      content: "This is a new file! \n"
      dest: "/home/vagrant/{{ f_name }}"
$ ansible-playbook test_prompt.yaml

실행 결과를 확인한다. ssh 로 ansi-node1 에 파일이 생성되었는지 확인한다. 

 ansi-node1 에 copy 모듈을 통해 내용이 잘 들어갔는지 확인한다. 

 

필터 (Filter)

변수를 정의할 때 | 뒤에 어떠한 값을 설정하여 필터를 지정할 수 있다.

필터의 역할

1. 현재 변수가 없는 경우에 기본 값 제공을 할 수 있다. 

{{ temp | default('DEFAULT_VALUE')}}

플레이북 예시

- name: print var
  hosts: AA
  tasks:
  - name: task1
    debug:
      msg: "{{ temp2 | default('hello') }}"

현재 temp2 라는 변수가 없어서 지정한 디폴트 값 hello 가 출력된다. 

2. 변수가 반드시 있어야 하는 경우 변수가 확인할 수 있다.

{{ temp | mandatory }}
- name: print var               
  hosts: AA                     
  tasks:                        
  - name: task1                 
    debug:                      
      msg: "{{ temp2 | mandatory }}"

temp2 값이 있는지 필터 mandatory 로 확인한다. temp2가 없어서 오류가 발생한다. 

 

3. list -> dictionary  로 변환

{{ temp_list | dict2items }}

list 타입 변수를 dictionary 로 바꾸는 예시

- name: print var
  hosts: AA   
  vars:       
    temp_list:
    - key: "apple"
      value: 3
    - key: "banana"
      value: 10
    - key: "orange"
      value: 5
  tasks:      
  - name: task1
    debug:    
      msg: "{{ temp_list | items2dict }}"

단, 리스트를 구성할 때 key, value 형식에 맞춰주어야 items2dict 기능을 사용할 수 있다. 아래와 같이 딕셔너리 형태로 출력되었다.

4. dictionary -> list 변환 

{{ temp_dict | dict2items }}

 

- name: print var                    
  hosts: AA                          
  vars:                              
    temp_dict:                       
      "apple": 10                    
      "banana": 100                  
      "pineapple": 50                
  tasks:                             
  - name: task1                      
    debug:                           
      msg: "{{ temp_dict | dict2items }}"

플레이북 실행 결과이다. 리스트 형태로 출력된다. 

이외에도 ip를 검사하거나 json 형식을 검사하는 등의 목적으로 , 말그대로 한번 필터를 거쳐서 확인하는 작업에 사용할 수 있다. 

5. Hash 함수 사용하기 

filter 와 함께 password_hash 함수를 사용하면 encryption 알고리즘, salt 값을 argument로 넣어서 해시 값을 얻을 수 있다.다음의 예시는 비밀번호 1111 를 1234 salt 값과 함께 sha256 해시함수를 이용하여 해시값을 출력하는 예시이다.

- name: hash playbook
  hosts: ansi-node1
  gather_facts: no
  tasks:
  - debug:
      msg: "{{ '1111' | password_hash('sha256', '1234') }}"

 

  • password_hash() 함수 이외에도  단순히 해시값을 얻는 hash('sha256') 함수도 있다. 

lookup 플러그인 

lookup 플러그인으로 대상에 대해 데이터를 검색해서 그 값을 변수로 가져올 수 있다. 다음은 lookup 을 이용하여 hostname을 가져와서 hname 이라는 변수에 저장하는 예시이다. 

- name: lookup hostname
  hosts: ansi-node1 
  vars:             
    hname: "{{ lookup('file', '/etc/hostname') }}"
  tasks:            
  - debug:          
      msg: "{{ hname }}"

플레이북으로 실행시키게 되면, 호스트이름이 출력된다. 

728x90