앤서블 모듈은 멱등(idempotent)이 가능하도록 설계되어 있습니다.
즉, 플레이북을 여러 번 실행해도 결과는 항상 동일합니다.
또한 플레이 및 해당 작업은 여러 번 실행할 수 있지만,
해당 호스트는 원하는 상태로 만드는 데 필요한 경우에만 변경됩니다.
하지만 한 작업에서 시스템을 변경해야 하는 경우 추가 작업을 실행해야 할 수도 있습니다.
예를 들어 서비스의 구성 파일을 변경하려면 변경 내용이 적용되도록 서비스를 다시 로드해야 합니다.
이때 핸들러는 다른 작업에서 트리거한 알림에 응답하는 작업이며, 해당 호스트에서 작업이 변경될 때만 핸들러에 통지합니다.
1. 핸들러
#1. Handlers
참조 링크 : https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html
앤서블에서 핸들러를 사용하려면 notify 문을 사용하여 명시적으로 호출된 경우에만 사용할 수 있습니다.
또한 핸들러를 정의할 때는 같은 이름으로 여러 개의 핸드러를 정의하기보다는 각각의 고유한 이름을 사용하여 정의하는 것이 좋습니다.
1) 플레이북 생성
rsyslog 재시작 태스크가 실행되면 notify 키워드를 통해 print msg라는 핸들러를 호출합니다.
* 핸들러는 handlers 키워드로 시작합니다.
~/my-ansible/handler-sample.yml
---
- hosts: tnode2
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"
2) 실행
마찬가지로, 한번 더 실행하더라도 동일한 결과를 얻습니다.
앞서 설명드린 듯이, 앤서블은 멱등성을 띄고 있기 때문입니다.
#2. 작업 실패 무시
- 앤서블은 플레이 시 각 작업의 반환 코드를 평가하여 작업의 성공 여부를 판단합니다.
일반적으로는 작업이 실패하면 앤서블은 이후의 모든 작업을 건너뜁니다. - 하지만 작업이 실패해도 플레이를 계속 실행할 수 있습니다. 이는 ignore_errors라는 키워드로 구현할 수 있습니다.
1) 플레이북 생성
다음의 내용은 강제로 apache3 패키지를 설치하는 내용입니다.
어떻게 되는지 한번 보겠습니다.
우선 두개의 플레이북을 생성해 주겠습니다.
~/my-ansible/ignore-example-1.yml
---
- hosts : tnode1
tasks:
- name: Install apache3
ansible.builtin.apt:
name: apache3
state: latest
- name: Print msg
ansible.builtin.debug:
msg: "Before task is ignored"
~/my-ansible/ignore-example-2.yml
---
- hosts : tnode1
tasks:
- name: Install apache3
ansible.builtin.apt:
name: apache3
state: latest
ignore_errors: yes
- name: Print msg
ansible.builtin.debug:
msg: "Before task is ignored"
위 두 개의 플레이북은 ignore_errors: yes 구문의 유무가 다릅니다.
플레이북 1 실행 후,
플레이북 2 실행 후,
ignore-example-2.yml을 실행했을 때는 ignore_errors를 거쳐서 플레이북이 실행되는 것을 확인하실 수 있습니다.
#3. 작업 실패 후 핸들러
- 앤서블은 일반적으로 작업이 실패하고 해당 호스트에서 플레이가 중단되면 이전 작업에서 알림을 받은 모든 핸들러가 실행되지 않습니다.
- 하지만 플레이북에 force_handlers: yes 키워드를 설정하면 이후 작업이 실패하여 플레이가 중단되어도 알림을 받은 핸들러가 호출됩니다.
이번 세션에 사용할 모듈은 다음의 세 가지입니다.
ansible.builtin.apt 모듈
- 참조 링크 : https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_module.html
ansible.builtin.dnf 모듈
- 참조 링크 : https://docs.ansible.com/ansible/latest/collections/ansible/builtin/dnf_module.html
Error handling in playbooks
- 참조 링크 : https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_error_handling.html
1) 플레이북 생성
hosts 아래 force_handlers: yes 를 추가하고, install apache2 태스크를 추가합니다.
~/my-ansible/force-handler-1.yml
---
- hosts: tnode2
tasks:
- name: restart rsyslog
ansible.builtin.service:
name: "rsyslog"
state: restarted
notify:
- print msg
- name: install apache3
ansible.builtin.apt:
name: "apache3"
state: latest
handlers:
- name: print msg
ansible.builtin.debug:
msg: "rsyslog is restarted"
~/my-ansible/force-handler-2.yml
---
- hosts: tnode2
force_handlers: yes
tasks:
- name: restart rsyslog
ansible.builtin.service:
name: "rsyslog"
state: restarted
notify:
- print msg
- name: install apache3
ansible.builtin.apt:
name: "apache3"
state: latest
handlers:
- name: print msg
ansible.builtin.debug:
msg: "rsyslog is restarted"
2) 실행
플레이북을 실행하면, 두 번째 플레이북에서 install apache3 태스크가 실패했음에도 불구하고 print msg 핸들러가 실행된 것은 앞서 말씀드린 force_handlers: yes 옵션 때문입니다.
이 옵션은 실패한 태스크가 있더라도 등록된 핸들러를 강제로 실행하게 만듭니다.
이러한 동작은 특히 어떤 태스크가 실패했을 때도 중요한 정리 작업이나 알림을 보내야 할 경우 유용합니다.
예를 들어, 특정 서비스를 재시작해야 하거나 실패 알림을 보내야 하는 경우 등에 사용됩니다.
#4. 작업 실패 조건 지정 (shell script 보다는 module을 사용하자)
- 앤서블에서 셸 스크립트를 실행한 뒤 결과로 실패 또는 에러 메시지를 출력해도, 앤서블에서는 작업이 성공했다고 간주합니다.
- 어떤 명령이라도 실행된 경우에는 태스크 실행 상태를 항상 changed 로 합니다.
- 이런 경우 failed_when 키워드를 사용하여 작업이 실패했음을 나타내는 조건을 지정할 수 있습니다.
1) 스크립트 생성
~/my-ansible/adduser-script.sh
# 사용자 추가하는 스크립트 파일 내용 확인
cat ~/my-ansible/Easy-Ansible/chapter_07.3/adduser-script.sh
cp ~/my-ansible/Easy-Ansible/chapter_07.3/adduser-script.sh adduser-script.sh
chmod +x adduser-script.sh
ls -l adduser-script.sh
# 해당 스크립트로 user1 생성해보기
## "passwd: unrecognized option '--stdin'" 에러는 암호 적용 부분에서 발생
sudo ./adduser-script.sh
sudo ./adduser-script.sh "user1" "qwe123"
tail -n 3 /etc/passwd
sudo userdel -rf user1
2) tnode1에 스크립트를 복사 후 확인
# 사용자 추가하는 스크립트 파일을 tnode1에 복사
ansible -m copy -a 'src=/home/ubuntu/my-ansible/adduser-script.sh dest=/home/ubuntu/adduser-script.sh' tnode1
# 복사 확인
ssh tnode1 ls -l /home/ubuntu/
-rw-r--r-- 1 root root 846 Jan 13 22:09 adduser-script.sh
# 스크립트 실행 확인
ssh tnode1
---------------
sudo chmod +x adduser-script.sh
sudo ./adduser-script.sh
exit
---------------
3) 플레이북 생성
~/my-ansible/failed-when-1.yml
---
- hosts: tnode1
tasks:
- name: Run user add script
ansible.builtin.shell: /home/ubuntu/adduser-script.sh
register: command_result
- name: Print msg
ansible.builtin.debug:
msg: "{{ command_result.stdout }}"
~/my-ansible/failed-when-2.yml
failed_when 조건식 :
command_result.stdout 변수에 “Please…”라는 문자열이 있으면 작업을 실패(fail)로 처리하겠다는 의미입니다.
---
- hosts: tnode1
tasks:
- name: Run user add script
ansible.builtin.shell: /home/ubuntu/adduser-script.sh
register: command_result
failed_when: "'Please input user id and password' in command_result.stdout"
- name: Print msg
ansible.builtin.debug:
msg: "{{ command_result.stdout }}"
4) 실행
실행하면 첫 번째 플레이북은 정상 동작하는 것으로 보입니다.
스크립트가 0이 아닌 종료 코드를 반환하지 않았기 때문에, Ansible은 이 태스크를 성공적으로 완료한 것으로 간주합니다.
그 결과, 두 번째 태스크인 Print msg가 실행되어 스크립트의 출력 내용을 표시합니다.
ansible -m shell -a "tail -n 3 /etc/passwd" tnode1
위의 커맨드를 통해서 유저가 추가 됐는지 확인합니다.
두 번째 플레이북을 실행하면, 다음과 같이 나옵니다.
조건 "'Please input user id and password' in command_result.stdout"는 스크립트의 출력 "Please input user id and password"라는 문자열이 포함되어 있으면 태스크가 실패한 것으로 간주하도록 설정합니다.
스크립트의 실행 결과에서 해당 문자열이 발견되었기 때문에, Ansible은 이 태스크를 실패한 것으로 간주합니다.
따라서 Print msg 태스크는 실행되지 않고, 플레이북의 실행이 중단됩니다.
감사합니다.
'DevOps > Ansible' 카테고리의 다른 글
[Ansible 101] 2주차 도전과제 (0) | 2024.01.21 |
---|---|
[Ansible 101] 앤서블 블록 및 오류처리 (0) | 2024.01.21 |
[Ansible 101] 조건문 (0) | 2024.01.21 |
[Ansible 101] 반복문 (2) | 2024.01.21 |
[Ansible 101 스터디] 앤서블 1주차 기본 실습 (변수) (6) | 2024.01.14 |