핸들러 및 작업 실패 처리

728x90
반응형

출처 : 앤서블로 시작하는 인프라 자동화

 

 

  • 앤서블 모듈은 멱등(Idempotent)가 가능하도록 설계되어 있다. 즉, 플레이북을 여러 번 실행해도 결과는 항상 동일하다.
  • 플레이 및 해당 작업은 여러 번 실행할 수 있지만, 해당 호스트는 원하는 상태로 만드는 데 필요한 경우에만 변경된다.
  • 한 작업에서 시스템을 변경해야 하는 경우 추가 작업을 실행해야 할 수 있다.
  • 핸들러는 다른 작업에서 트리거한 알림에 응답하는 작업이며, 해당 호스트에서 작업이 변경될 때만 핸들러에 통지한다.

 

앤서블 핸들러

  • 앤서블에서 핸들러를 사용하려면 notify 문을 사용하여 명시적으로 호출된 경웅에만 사용할 수 있다.
  • 핸들러를 정의할 때는 같은 이름으로 여러 개의 핸들러를 정의하기보다는 각각의 고유한 이름을 사용하여 정의하는 것이 좋다.

 

vi handler-sample.yml

---

- hosts: tnode2-ubuntu

  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"

 

해당 플레이북에 선언된 태스크는 rsyslog 라는 서비스를 재시작하는 서비스이다.

해당 태스크가 실행되면 notify 키워드를 통해 print msg 라는 핸들러를 호출한다.

핸들러는 handlers라는 키워드로 시작하며, 태스크와 동일하게 작성한다.

 

ansible-playbook handler-sample.yml

 

플레이북을 실행하면 tnode2-ubuntu 노드의 rsyslog 서비스를 재시작하고 print msg 라는 핸들러를 호출해 rsyslog is restarted 라는 메시지를 출력한다.

 

 

작업 실패 무시

  • 앤서블은 플레이 시 각 작업의 반환 코드를 평가하여 작업의 성공 여부를 판단한다.
  • 보통 작업이 실패하면 앤서블은 이후의 모든 작업을 건너뛰지만, ignore_errors 키워드를 통해 플레이를 계속 실행할 수 있다.

 

vi ignore-example.yml

---

- hosts: tnode1-centos

  tasks:
    - name: Install apache2
      ansible.builtin.dnf:
        name: apache2
        state: latest
      ignore_errors: yes

    - name: Print msg
      ansible.builtin.debug:
        msg: "Before task is ignored"

 

대상 호스트는 tnode1-centos 이고. 에러를 발생시키기 위해 CentOS에는 없는 apache2 패키지를 설치하는 작업을 추가하고, 해당 작업 하단의 ignore_errors: yes 라는 구문을 추가한다.

 

즉, CentOS에는 없는 apache2 를 설치를 시도하고, 에러가 발생해도 멈추지 않고 플레이를 진행하도록 설정하였다.

 

ansible-playbook ignore-example.yml

 

해당 플레이북을 실행하면 Install apache2 태스크에서 에러가 발생하지만, ignoring 이라는 메시지와 함께 에러가 무시되고 다음 태스크인 Pring msg 가 실행되는 것을 확인할 수 있다.

 

 

작업 실패 후 핸들러 실행

  • 앤서블은 일반적으로 작업이 실패하고 해당 호스트에서 플레이가 중단되면 이전 작업에서 알림을 받은 모든 핸들러가 실행되지 않는다.
  • 플레이북에 force_handlers: yes 키워드를 설정하면 이후 작업이 실패하여 플레이가 중단되어도 알림을 받은 핸들러가 호출된다.

 

vi force-handler.yml

---

- hosts: tnode2-ubuntu
  force_handlers: yes

  tasks:
    - name: restart rsyslog
      ansible.builtin.service:
        name: "rsyslog"
        state: restarted

      notify:
        - print msg

    - name: install apache2
      ansible.builtin.dnf:
        name: "apache2"
        state: lastest

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

 

host 아래에 force_handlers: yes 구문을 추가하고, restart rsyslog 태스크와 hanlders 사이에 install apache2 태스크를 추가한다.

 

ansible-playbook force-handler.yml

 

플레이북을 실행하면 install apache2에서 에러가 발생해도 restart rsyslog 태스크의 handler는 수행되는 것을 확인할 수 있다.

 

 

앤서블 블록 및 오류 처리

  • 앤서블은 블록이라는 오류를 제어하는 문법을 제공한다.
  • 블록은 작업을 논리적으로 그룹화하는 절이며, 작업 실행 방법을 제어하는 데 사용할 수 있다.
  • 블록을 통해 rescue 문과 always 문을 함께 사용함으로써 오류를 처리할 수 있다.
    • block : 실행할 기본 작업을 정의
    • rescue : block 절에 정의된 작업이 실패하는 경우 실행할 작업을 정의
    • always : block 및 rescue 절에 정의된 작업의 성공 또는 실패 여부와 관계없이 항상 실행되는 작업을 정의

 

vi block-example.yml

---

- hosts: tnode2-ubuntu
  vars:
    logdir: /var/log/daily_log
    logfile: todays.log

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

      rescue:
        - name: Make Directory when Not found Directory
          ansible.builtin.file:
            path: "{{ logdir }}"
            state: directory
            mode: '0755'

      always:
        - name: Create File
          ansible.builtin.file:
            path: "{{ logdir }}/{{ logfile }}"
            state: file
            mode: '0644'

 

block 구문에서 ansible.builtin.find 모듈을 이용하여 /var/log/daily_log 라는 디렉토리를 찾고, 만약 없으면 Warning을 발생시킨 후 다음 태스크로 넘어가지만, failed_when 구문을 사용하여 result.msg 변수에 Not all paths 라는 메시지가 발견되면 실패 처리하도록 한다.

 

rescue 구문에는 디렉토리가 없으면 해당 디렉토리를 생성하며, always 구문에는 로그 파일을 생성한다.

 

ansible-playbook block.example.yml

 

플레이북을 실행하면 Find Directory 태스크에서 디렉토리를 찾지 못해 오류가 발생하고, Make Directory when Not found Directory 태스크에서 해당 디렉토리를 생성한다. 그리고 Create File 태스크가 실행된다.

 

본 블로그 주인장이 실수를 하여 Create Fild 태스크에서 에러가 발생했는데 정상적으로 플레이북을 실행하면 해당 태스크가 실행된다.

 

ssh -p 22 tnode2-ubuntu

ll /var/log/daily_log

exit

 

tnode2-ubuntu 노드로 접속해 /var/log/daily_log 디렉토리 안을 확인하면 todays.log 파일이 생성된 것을 확인할 수 있다.

 

ansible-playbook block-example.yml

 

다시 block-example.yml 플레이북을 실행하면 이번에는 Find Directory 태스크에서 해당 디렉토리가 존재하므로 rescue 구문의 태스크가 실행하지 않고 always 구문에 있던 Create File 태스크가 실행된다.

 

 

728x90
반응형