이전 블로그에서는 작업제어의 조건문까지 다루었다.
이번에는 조건문 이후에 템플릿부터 다룰 예정이다.
Asible에서 파일을 관리하는 가장 강력한 방법은 템플릿을 만드는 것
템플릿을 사용하면 가능한 변수와 팩트를 사용하여 파일이 배포될 때 관리 호스트에 대해 자동으로 사용자 정의되는 템플릿 구성 파일을 작성할 수 있음
Jinja2
Jinja2 의 특징
Jinja2 기호
Jinja2 템플릿
1 . 템플릿 생성 예제
vi template1.yml # 템플릿 작성
- name: template test
hosts: AA
vars:
site_name: groom_world
tasks:
- name: create template
template: # 템플릿 모듈
src: test1.j2
dest: /tmp/test
vi test1.j2 # j2(jinja2) 파일 작성
Welcome {{ site_name }}
This node is {{ ansible_facts.hostname }}
-> 해당 노드 해당 디렉터리에 test파일이 만들어진 것을 확인
-> test파일에 입력한 정보가 작성된것을 확인
2 . 템플릿 생성 예제 (j2를 이용한 fact 접근)
vi template2.yml # 템플릿 작성
- name: template test
hosts: AA
tasks:
- name: create directory
file:
state: directory
dest: /etc/ansible/facts.d
recurse: yes
- name: create fact file
template:
src: factfile.j2
dest: /etc/ansible/facts.d/test.fact
- setup:
- name: print lacal facts
debug:
msg: "{{ ansible_local }}"
vi factfile.j2 # j2파일 작성
{# local_fact.config #}
[test1]
hostname= {{ ansible_facts.hostname }}
ipaddr={{ ansible_facts.enp0s8.ipv4.address }}
-> j2파일이 템플릿으로 대상 노드들에게 팩트파일로 전달되고 팩트파일의 정보가 출력되는 것을 볼 수 있다
3 . 템플릿 생성 예제 (j2를 이용한 반복문)
vi template3.yml # 템플릿 생성
- name: template test
hosts: ABC
tasks:
- template:
src: host_test.j2
dest: /etc/hosts1
vi host_test.j2 # j2파일 생성
{% for i in [1,2,3] %}
ansi-node{{ i }} 192.168.56.2{{ i }}
{% endfor %}
-> 대상 노드들에게 호스트와 ip가 적힌 새로운 호스트파일이 생성되어있는 것을 확인
1 . 핸들러 생성 예시
- name: handler test
hosts: ansi-node1
tasks:
- copy:
content: "{{ ansible_facts.hostname }} handler test"
dest: /var/www/html/index.html
notify:
- Restart web service # 알림이름
handlers:
- name: Restart web service # handler가 인지할 알림이름
service:
name: apache2
state: restarted
-> 첫번째 실행에서 notify를 통해 핸들러가 작동된것을 볼 수 있다. 이때 다시 실행해보면 멱등성에 의해 결과에 변함이 없는 것을 확인할 수 있다. 즉, 아무 작업도 하지 않는다.
-> 최종적으로 curl해봤을 때 index.html의 문구가 나오는 것을 확인
-> 알림이름과 handler가 인지할 알림이름은 반드시 같아야 한다
2 . 다중알림 핸들러 생성 예시
vi html1.j2 # j2파일 생성
{{ ansible_facts.hostanme }} is handlers test1
vi handler2.yml # 플레이북 생성
- name: handlers test
hosts: ansi-node3
tasks:
- name: Install package
apt:
name:
- apache2
- firewalld
state: present
update_cahce: yes
- name: Config index.html
template:
src: html1.j2
dest: /var/www/html/index.html
notify:
- Restart web service
- Restart firewalld service
handlers:
- name: Restart web service
service:
name: apache2
state: restarted
- name: Restart firewalld service
service:
name: firewalld
state: restarted
-> 여러 알림을 만들고 알림이 울리면 핸들러가 알림에 해당하는 작업 실행
📗 만약 핸들러에 어떤 작업을 추가하고 다시 실행해도 위의 알림을 포함한 작업에서는 변화가 없기 때문에 알림은 핸들러에게 가지 않고 따라서 핸들러에 추가된 작업은 무시된다
2-1 . 다중알림 핸들러의 다른 형태
cp handler2.yml handler3.yml
- name: handlers test
hosts: ansi-node3
tasks:
- name: Install package
apt:
name:
- apache2
- firewalld
state: present
update_cache: yes
- name: Config index.html
template:
src: html1.j2
dest: /var/www/html/index.html
notify:
- Restart service # 여러 알림이 아닌 하나의 알림 설정
handlers:
- name: Restart web service
service:
name: apache2
state: restarted
listen: Restart service # listen모듈로 알림 선택
- name: Restart firewalld service
service:
name: firewalld
state: restarted
listen: Restart service
-> 알림을 여러개 설정할 필요없이 listen모듈로 간편하게 알림을 선택할 수 있다
📗 firewalld를 설치한 상황에서 curl명령을 보냈을 때 응답이 오려면 firewalld가 http를 열어줘야한다
<핸들러 사용시 주의 사항>
1 . 위임 생성 예시
- name: delegate test
hosts: ansi-node1
tasks:
- command: hostname
register: hostname_result1
- debug:
msg: "{{ hostname_result1.stdout }}"
- command: hostname
register: hostname_result2
delegate_to: ansi-node2 # 위임
- debug:
msg: "{{ hostname_result2.stdout }}"
-> 명령어 실행 후 node2에게 위임했기 때문에 node1의 플레이에서 작업 도중에 node2의 hostname을 등록변수에 담아 출력할 수 있었다.
2 . 팩트 수집 위임 생성 예시
- name: delegate facts test
hosts: ansi-node1
gather_facts: 0 # 수집x
tasks:
- setup:
delegate_to: ansi-node2 # 위임
delegate_facts: true # 수집 o
- name: delegate ansi-node2
hosts: ansi-node2
gather_facts: no # 수집 x
tasks:
- debug:
msg: "{{ ansible_facts.hostname }}"
-> node2에게 위임 후 팩트 수집 한다. 이후 node2를 대상으로 팩트 수집을 하지않아도 팩트 정보가 출력되는 것을 알 수 있다.
<작업의 그룹화>
1 . 블록 사용 예시 (작업의 그룹화)
- name: block test
hosts: AA
tasks:
- name: block test1
block:
- name: command hostname
command: hostname
register: result1
- name: print hostname
debug:
msg: "{{ result1.stdout }}"
when: ansible_hostname == 'ansi-node1'
- name: block test2
block:
- name: command grep
command: grep 'ansi-node2' /etc/hosts
register: result2
- name: print result2
debug:
msg: "{{ result2.stdout }}"
when: ansible_hostname == 'ansi-node2'
-> 작업을 그룹화 시켜서 조건문에 의해 node1에 대해서 hostname, node2에 대해서 grep의 결과가 나온 것을 확인
2 . 블록 사용 예시 (오류 처리)
- name: block test
hosts: ansi-node1
tasks:
- name: block session
block:
- name: print1
debug:
msg: "block message 1"
- name: command
command: failed
- name: print2
debug:
msg: "block messages 2"
rescue:
- name: print3
debug:
msg: "rescue block messages 1"
always:
- name: print4
debug:
msg: "always block messages 1"
-> print1 출력 후 command 실패에 의해 print2는 출력되지않는다. 하지만 중지되는것이 아니라 rescue문에 의해 print3가 출력된다. always는 성공여부와 관계없이 항상 출력
📕 rescue & always
1 . 작업에 태그 추가
- name: tag test
hosts: ansi-node1
tags: play1
tasks:
- block:
- name: task 1-1
debug:
msg: task 1-1
tags: task1
- name: task 1-2
debug:
msg: task 1-2
tags: task1
- name: task 2-1
debug:
msg: task 2-1
tags: task2
- name: task 2-2
debug:
msg: task 2-1
tags: task2
tags: block1
- name: task 3
debug:
msg: task 3
tags: task3
- name: tag test2
hosts: ansi-node2
tags: play2
tasks:
- name: task 4
debug:
msg: task4
-> 플레이 단위, 블록 단위, 작업 단위 등에 tag를 붙일 수 있다
-> 태그를 통해 원하는 작업만 실행시킬 수 있다
<태그의 실행>
재사용 가능한 아티팩트
플레이북에서 변수 재사용
1 . include를 이용한 핸들러
2 . import를 이용한 핸들러
3 . import를 이용한 핸들러