반복문과 조건문을 이용한 제어문 구현하기 - 조건문
출처 : 앤서블로 시작하는 인프라 자동화
조건문
- 앤서블은 조건문을 사용하여 특정 조건이 충족될 때 작업 또는 플레이를 실행할 수 있다.
- ex) 조건문을 사용하여 호스트의 운영체제 버전에 해당하는 서비스 설치
- 앤서블에서 조건문을 사용할 때는 플레이 변수, 작업 변수, 앤서블 팩트 등을 사용할 수 있다.
조건 작업 구문
- when 문은 조건부로 작업을 실행할 때 테스트할 조건을 값으로 사용한다.
- 조건이 충족되면 작업이 실행되고, 조건이 충족되지 않으면 작업을 건너 뛴다.
- when 문을 테스트하는 가장 간단한 조건 중 하나는 Boolean 변수가 true인지 false 인지의 여부이다.
vi when_task.yml
---
- hosts: localhost
vars:
run_my_task: true
tasks:
- name: echo message
ansible.builtin.shell: "echo test"
when: run_my_task
run_my_task 라는 변수에 true라는 값을 저장한다.
when 문에서 run_my_task를 사용하면 run_my_task가 true 인 경우에만 tasks가 실행된다.
ansible-playbook --syntax-check when_task.yml
ansible-playbook when_task.yml
vi when_task.yml
---
- hosts: localhost
vars:
run_my_task: false
tasks:
- name: echo message
ansible.builtin.shell: "echo test"
when: run_my_task
이번에는 run_my_task 변수를 false로 수정한다.
ansible-playbook when_task.yml
다시 플레이북을 실행해보면 이번에는 echo massage 태스크가 수행되지 않고 건너 뛴 것을 확인할 수 있다. 왜냐하면 when 문에서 run_my_task가 false 이기 때문이다.
조건 연산자
- when 문을 사용할 때는 true 또는 false 값을 갖는 Bool 변수 외에도 조건 연산자를 사용할 수 있다.
- ex) when 문에 ansible_facts['machine'] == "x86_64" 라는 구문을 사용했다면 ansible_facts['machine'] 값이 x86_64 일 때만 해당 태스크를 수행한다.
- 운영체제 종류에 따라 태스크를 수행하는 예제를 통해 조건 연산자 사용법을 알아보자.
vi check-os.yml
---
- hosts: all
vars:
supported_distros:
- CentOS
- RedHat
tasks:
- name: Print supported os
ansible.builtin.debug:
msg: "This {{ ansible_facts['distribution'] }} need to use dnf"
when: ansible_facts['distribution'] in supported_distros
vi 에디터로 check-os.yml 파일을 생성하고 위 코드를 작성한다.
vars 키워드로 supported_distros 라는 변수를 사전 타입의 값으로 저장한다. 그리고 태스크의 when 구문에서 ansible_facts['distribution'] in supported_distros 라는 조건문을 추가한다.
ansible-playbook check-os.yml
check-os.yml 플레이북을 실행한다.
실행하면 변수 supported_distros에 있는 centos인 tnode1-centos는 출력되지만, 변수에 없는 tnode2-ubuntu와 tnode2-ubuntu는 해당 태스크를 실행하지 않는다.
복수 조건문
- 앤서블의 when 문은 단일 조건문 뿐만 아니라 복수 조건문도 사용할 수 있다.
- ex) 운영체제가 CentOS이고 서버 타입이 x86_64일 경우에만 작업이 실행되게 구성 가능
- 운영체제가 CentOS이거나 우분투일 경우 작업이 수행되는 예제를 통해 복수 조건문을 사용해 본다.
vi check_os1.yml
---
- hosts: all
tasks:
- name: Print os type
ansible.builtin.debug:
msg: "OS Type: {{ ansible_facts['distribution'] }}"
when: ansible_facts['distribution'] == "CentOS" or ansible_facts['distribution'] == "Ubuntu"
check_os1.yml 파일을 생성하고 vi 에디터로 위 코드를 작성한다.
when 문에서는 ansible_facts['distribution'] 의 값이 CentOS 거나 Ubuntu일 경우에만 수행되도록 or 구문을 사용했다.
ansible-playbook check_os1.yml
플레이북을 실행하면 운영체제가 CentOS 거나 Ubuntu 일 경우 작업을 수행한다. 우리의 호스트들은 모두 CentOS거나 Ubuntu 이므로 모두 작업을 수행하게 된다.
vi check_os2.yml
---
- hosts: all
tasks:
- name: Print os type
ansible.builtin.debug:
msg: >
OS Type: {{ ansible_facts['distribution'] }}
OS Version: {{ ansible_facts['distribution_version'] }}
when: ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_version'] == "8"
이번에는 when 문을 수정한다. ansible_facts['distribution']의 값이 CentOS고, ansible_fact['distribution_version'] 이 8인 경우에만 작업이 수행되도록 and 연산자를 사용한다.
즉, 현재 시스템의 운영체제가 CentOS 8 인 경우에만 작업을 수행한다.
ansible-playbook check_os2.yml
플레이북을 실행하면 CentOS 8 인 tnode1-centos 만 작업을 수행하고 나머지 호스트들은 작업을 건너 뛰게 된다.
vi check_os3.yml
---
- hosts: all
tasks:
- name: Print os type
ansible.builtin.debug:
msg: >
OS Type: {{ ansible_facts['distribution'] }}
OS Version: {{ ansible_facts['distribution_version'] }}
when:
- ansible_facts['distribution'] == "CentOS"
- ansible_facts['distribution_version'] == "8"
and 연산자는 조건문에서 바로 사용하거나 사전 형태의 목록으로 표현하는 방법 2가지가 있다.
ansible-playbook check_os3.yml
플레이북을 실행해보면 위의 플레이북과 동일한 결과를 출력하는 것을 확인할 수 있다.
vi check_os4.yml
---
- hosts: all
tasks:
- name: Print os type
ansible.builtin.debug:
msg: >
OS Type: {{ ansible_facts['distribution'] }}
OS Version: {{ ansible_facts['distribution_version'] }}
when: >
( ansible_facts['distribution'] == "CentOS" and
ansible_facts['distribution_version'] == "8")
or
( ansible_facts['distribution'] == "Ubuntu" and
ansible_facts['distribution'] == "20.04" )
when 문에서는 and 연산자와 or 연산자를 함께 사용할 수 있다.
운영체제가 CentOS 8 이거나 Ubuntu 20.04 인 경우에만 작업을 수행하도록 만들어보자.
ansible-playbook check_os4.yml
플레이북을 실행하면 tnode1-centos 만 작업을 수행한다.
tnode2-ubuntu와 tnode3-ubuntu의 버전은 22.04 이기 때문에 skip 된다.
반복문과 조건문 사용
- 반복문과 조건문을 함께 사용할 수 있다.
vi check_mount.yml
---
- hosts: db
tasks:
- name: Print Root Directory Size
ansible.builtin.debug:
msg: "Directory {{ item.mount }} size is {{ item.size_available }}"
loop: "{{ ansible_facts['mounts'] }}"
when: item['mount'] == "/" and item['size_available'] > 300000000
vi 에디터로 check_mount.yml 파일을 생성하고 위 코드를 작성한다.
when 문의 item['mount'] 는 loop 문에서 선언한 ansible_facts의 mounts 중 mount 라는 값과 size_available 이라는 값을 사용해 구현한 것이다.
즉, db 호스트(tnode3-ubuntu)에서 mount의 속성이 '/' 이고, size_available 속성이 300000000 보다 큰 경우에만 해당 작업을 수행한다.
ansible-playbook check_mount.yml
플레이북을 실행하면 앤서블 팩트에서 mounts 라는 사전 타입의 변수값을 반복하면서 mount가 '/' 이고 size_available 값이 300000000 보다 큰 경우에만 메시지를 출력하고, 그렇지 않으면 건너 뛴다.
vi register-when.yml
---
- hosts: all
tasks:
- name: Get rsyslog service status
ansible.builtin.command: systemctl is-active rsyslog
register: result
- name: Print rsyslog status
ansible.builtin.debug:
msg: "Rsyslog status is {{ result.stdout }}"
when: result.stdout == "active"
조건문을 사용할 때는 반복문 뿐만 아니라 register 키워드로 작업 변수도 사용할 수 있다.
systemctl 명령어로 rsyslog가 active 인지 체크하여 해당 결과를 result에 저장하고, Print rsyslog status 태스크에서 result.stdout 값이 active 일 경우 해당 값을 출력하는 코드이다.
ansible-playbook register-when.yml
해당 플레이북을 실행하면 각 호스트의 rsyslog 상태를 확인하고 해당 결과를 출력한다.