본문 바로가기

Engineering/Ansible

[Ansible] 9. 핸들러 및 작업 실패 처리

 

 

 

어떠한 작업이 이루어진 이후에 실행되어야만 하는 작업들이 있다. 예를 들어 서비스의 config를 변경 후에 변경사항을 적용하려면 서비스를 재시작 해야 하는데, 이때 핸들러를 사용하여 작업 할 수 있다. 핸들러는 대상 노드가 변경 될 때(play 결과가 changed일 때) 수행하게 된다.


 

앤서블 핸들러

앤서블에서 핸들러를 사용하려면 notify 문을 이용하여 명시적으로 호출된 경우에 사용할 수 있다

.

[root@Ansible-Controller ch09_handler]# cat handler-ex.yml 
---
- hosts: node1

  tasks:
  - name: restart rsyslog
    ansible.builtin.service:
      name: rsyslog
      state: restarted
    notify:
    - print msg

  handlers:
   - name: print msg
     ansible.builtin.debug:
       msg: 'rsyslog is restarted'

ansible.builtin.service 모듈을 이용하여 rsyslog 서비스를 재시작한다. 해당 태스크를 수행하고 변화를 감지하면 notify 문을 통해 print msg라는 핸들러를 호출하고, handlers 키워드로 전달받아 다음 동작을 수행한다.

 

 

핸들러는 notify로 인해 알림을 받은 경우에 실행된다. 선언된 핸들러라도 알림을 받지 못하면 실행되지 않는다.

다중 핸들러가 선언된 경우, 알림을 받은 순서가 아닌 선언 순서로 실행된다.


작업 실패 무시

일반적으로 앤서블은 작업이 실패하면 이후 모든 작업을 건너뛴다. 하지만 ignore_errors 옵션을 사용하여 작업 실패가 발생해도 이어서 작업을 진행 할 수 있다.

---
- hosts: localhost

  tasks:
  - name: make an error
    ansible.builtin.yum:
      name: qwer1234
      state: latest
    ignore_errors: yes

  - name: Prt msg
    ansible.builtin.debug:
      msg: "IDC ab error"

태스크 내에 에러가 발생하여도 무시하고, 다음 작업을 진행 후에 play를 끝 마친 결과를 확인할 수 있다.

 

작업 실패 후 핸들러 실행

앤서블에서는 위에서 언급한 것과 같이 작업이 실패하면 이후 작업을 모두 건너뛰고, 핸들러 역시 실행되지 않는다. 이와 같은 경우, 플레이북에서 force_handlers 옵션을 추가하여 작업 실패가 발생하더라도 알림을 받은 핸들러를 호출 할 수 있다.

---
- hosts: localhost
  force_handlers: yes

  tasks:
  - name: restart rsyslog
    ansible.builtin.service:
      name: rsyslog
      state: restarted
    notify:
    - print msg

  - name: make an error
    ansible.builtin.yum:
      name: qwer1234
      state: latest

  handlers:
   - name: print msg
     ansible.builtin.debug:
       msg: 'rsyslog is restarted'

원래라면 'make an error' 단계에서 오류를 반환하고 playbook 실행이 종료되었겠지만, force_handlers: yes 옵션을 추가해주어서 notify 받은 핸들러 작업까지 수행한 것을 확인할 수 있다. 


block 및 오류 처리

앤서블에서는 block이라는 오류를 제어하는 문법을 제공한다. block은 작업을 논리적으로 그룹화하여 작업 실행 방식을 정한다. block은 rescue와 always 문을 함께 사용하여 작업 제어를 가능케 한다.

  • block: 실행할 기본 작업
  • rescue: block에서 작업을 실패한 경우 실행됨
  • always: block과 rescue에서 정의한 작업과 관계 없이 실행됨
---
- hosts: all
  vars:
    log_dir: /var/log/ansible_block
    log_file: block_test.log

  tasks:
  - name: Configure Log Env
    block:
      - name: Find Dir
        ansible.builtin.find:
          paths: "{{ log_dir }}"
        register: result
        failed_when: "'Not all paths' in result.msg"

    rescue:
      - name: Mk Dir When it doesn't exist
        ansible.builtin.file:
          path: "{{ log_dir }}"
          state: directory
          mode: 0755

    always:
      - name: Create File
        ansible.builtin.file:
          path: "{{ log_dir }}/{{ log_file }}"
          state: touch
          mode: 0644

 

block 문에서 제어 노드의 {{ log_dir }} 경로에 디렉토리 존재 여부를 확인하고, 실패 시 rescue 문에서 정의한대로 해당 경로에 디렉토리를 생성한다. 마지막으로 존재여부와 관계 없이 always 문을 실행하여 {{ log_dir }} 아래 {{ log_file }}을 생성한다.

$ ls -al /var/log/ansible_block/
total 4
drwxr-xr-x   2 root root   28 Sep 12 05:32 .
drwxr-xr-x. 12 root root 4096 Oct  1 03:21 ..
-rw-r--r--   1 root root    0 Sep 12 05:32 block_test.log

'Engineering > Ansible' 카테고리의 다른 글

[Ansible]10. Ansible Role  (2) 2024.10.16
[Ansible] 8. 반복문과 조건문을 이용한 제어문 구현  (0) 2024.09.04
[Ansible] 7. Ansible Facts 활용  (0) 2024.09.02
[Ansible] 6. Ansible Vault  (0) 2024.08.29
[Ansible] 5. 변수  (1) 2024.08.28