
이전 블로그에서는 작업제어의 조건문까지 다루었다.
이번에는 조건문 이후에 템플릿부터 다룰 예정이다.
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를 이용한 핸들러