본문 바로가기

DevOps/Ansible

[A101] 4. Ansible 반복문, 조건문

cloudNet@ 팀의 가시다 님이 진행하는 앤서블 스터디 2주차 정리입니다.

 

지난번 포스팅 까지 앤서블의 플레이북, 모듈, 변수등에 대해서 학습했습니다.

이번 포스팅에서는 조건문과 반복문에 대해서 배워보겠습니다.

 

  반복문

 

Loops — Ansible Documentation

As of Ansible 2.8, you can get extended loop information using the extended option to loop control. This option will expose the following information. Note When using loop_control.extended more memory will be utilized on the control node. This is a result

docs.ansible.com

  • 반복문은 IAC의 꽃이라고 할수 있습니다. 동일한 모듈을 재사용 할수 있기 때문에 동일한 작업을 여러번 불필요하게 수고하는 것을 피할 수 있습니다.
  • 단순 반복문 : 특정 항목에 대한 작업을 반복 - item 변수, 변수 목록 지정
    • loop 키워드를 작업에 추가하면 작업을 반복해야 하는 항목의 목록을 지정하여 사용합니다. 그리고 해당하는 값을 변수처럼 사용하려면 item 변수를 이용할 수 있습니다.

  반복문 예제 

1. 플레이북 작성

~/my-ansible/check-services1.yml

---
- hosts: all
  tasks:
  - name: Check sshd and rsyslog state
    ansible.builtin.service:
      name: "{{ item }}"
      state: started
    loop:
      - sshd
      - rsyslog

2. 플레이북 작성 후 동작확인

 

#
ansible-playbook check-services1.yml
...
TASK [Check sshd and rsyslog state] ****************************************************
ok: [tnode2] => (item=sshd)
ok: [tnode1] => (item=sshd)
ok: [tnode3] => (item=sshd)
ok: [tnode2] => (item=rsyslog)
ok: [tnode1] => (item=rsyslog)
ok: [tnode3] => (item=rsyslog)
...

 

 

  도전과제 1.

linux user1~10(10명) 를 반복문을 통해서 생성 후 확인 후 삭제를 해보자

 

1. 플레이북 작성

---

- hosts: all
  tasks:
  - name: Create User {{ item }}
    ansible.builtin.user:
      name: "{{ 'testuser%01x' | format(item) }}"
      state: present
    loop: "{{ range(1, 10 + 1, 1)|list }}"

2. 플레이북 실행 후 확인

# 생성된 user을 확인함.
ubuntu@server:~/my-ansible$ for i in {1..3}; do echo ">> tnode$i <<"; ssh tnode$i tail -n 3 /etc/passwd; echo; done
>> tnode1 <<
user8:x:1008:1008::/home/user8:/bin/sh
user9:x:1009:1009::/home/user9:/bin/sh
user10:x:1010:1010::/home/user10:/bin/sh

>> tnode2 <<
user8:x:1008:1008::/home/user8:/bin/sh
user9:x:1009:1009::/home/user9:/bin/sh
user10:x:1010:1010::/home/user10:/bin/sh

>> tnode3 <<
user8:x:1008:1008::/home/user8:/bin/sh
user9:x:1009:1009::/home/user9:/bin/sh
user10:x:1010:1010::/home/user10:/bin/sh

3. 플레이북 삭제 

---

- hosts: all
  tasks:
  - name: Remove the user {{ item }}
    ansible.builtin.user:
      name: "{{ 'testuser%01x' | format(item) }}"
      state: absent
      remove: yes
    loop: "{{ range(1, 10 + 1, 1)|list }}"

 

4. 플레이북 삭제 후 확인

# user 확인
ubuntu@server:~/my-ansible$ for i in {1..3}; do echo ">> tnode$i <<"; ssh tnode$i tail -n 3 /etc/passwd; echo; done
>> tnode1 <<
_chrony:x:114:121:Chrony daemon,,,:/var/lib/chrony:/usr/sbin/nologin
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false

>> tnode2 <<
_chrony:x:114:121:Chrony daemon,,,:/var/lib/chrony:/usr/sbin/nologin
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false

>> tnode3 <<
_chrony:x:114:121:Chrony daemon,,,:/var/lib/chrony:/usr/sbin/nologin
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false

 

 

  도전과제 2.

루프 반복문 중 sequence 를 이용하여 /var/log/test1 ~ /var/log/test100 100개 파일(file 모듈)을 생성 확인 후 삭제를 해보자 

 

 

Variables, Conditionals, Loops - Ansible Handbook

Just like any other Scripting or programming language we can use variable in ansible playbooks. Variables could store different values for different items. Variables help us to have shorter and more readable playbooks. Imagine we want to apply patches on h

borosan.gitbook.io

1. 플레이북 실행

---
- hosts: all

  tasks:
    - name: Create files
      ansible.builtin.file:
        path: /var/log/test{{ item }}
        state: touch
      with_sequence: start=1 end=100

2. 확인

$ ansible -m shell -a "ls -l /var/log/test100" all


tnode2 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 0 Jan 17 22:44 /var/log/test100
tnode1 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 0 Jan 17 22:44 /var/log/test100
tnode3 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 0 Jan 17 22:44 /var/log/test100

3. 삭제 플레이북 실행

---
- hosts: all

  tasks:
    - name: Remove files
      ansible.builtin.file:
        path: /var/log/test{{ item }}
        state: absent
      with_sequence: start=1 end=100

 

  조건문

  • 앤서블은 조건문을 사용하여 특정 조건이 충족될 때 작업 또는 플레이를 실행할 수 있습니다.
  • 예를 들면 호스트의 운영체제 버전에 해당하는 서비스를 설치
  • 앤서블에서 조건문을 사용할 때는 플레이 변수, 작업 변수, 앤서블 팩트 등을 사용할 수 있습니다.

 

1. 플레이북 작성

 ~/my-ansible/when_task.yml

---
- hosts: localhost
  vars:
    run_my_task: true

  tasks:
  - name: echo message
    ansible.builtin.shell: "echo test"
    when: run_my_task
    register: result

  - name: Show result
    ansible.builtin.debug:
      var: result

 

2. 실행

#
ansible-playbook when_task.yml
...
TASK [echo message] ***************************************************************************************************************************************************************************
changed: [localhost]
...

 

3. 플레이북 변경

  • run_my_task: false
---
- hosts: localhost
  vars:
    run_my_task: false

  tasks:
  - name: echo message
    ansible.builtin.shell: "echo test"
    when: run_my_task
    register: result

  - name: Show result
    ansible.builtin.debug:
      var: result

 

4. 실행

(건너뜀)

#
ansible-playbook when_task.yml
...
TASK [echo message] ***************************************************************************************************************************************************************************
skipping: [localhost]
...

 

  조건문 연산자

  • 조건 연산자 : when 문에 bool 변수(true, false) 외에도 조건 연산자를 사용할 수 있습니다.
    • != : 값이 같지 않을 때 true
    • >, >=, <=, < : ‘초과, ‘ 이상’, ‘이하’, ‘미만’ 일 때에 true
    • not : 조건의 부정
    • and, or : ‘그리고’, ‘또는’의 의미로 여러 조건의 조합 가능
    • in : 값이 포함된 경우에 true. 예를 들어 2 in “1, 2, 3” 은 true
    • is defined : 변수가 정의된 경우 true

 

  조건문 연산자 예제 (Example)

1. 플레이북 작성

~/my-ansible/check-os.yml

---
- hosts: all
  vars:
    supported_distros:
      - Ubuntu
      - CentOS

  tasks:
    - name: Print supported os
      ansible.builtin.debug:
        msg: "This {{ ansible_facts['distribution'] }} need to use apt"
      when: ansible_facts['distribution'] in supported_distros

 

2. 플레이북 실행

 if 문 :  ansible_facts['distribution' 값이 ‘Ubuntu’ 나 ‘CentOS’ 면 출력(테 스 트  수행)

 

#
ansible-playbook check-os.yml
...
TASK [Print supported os] *********************************************************************************************************************************************************************
ok: [tnode1-ubuntu.local] => {
    "msg": "This Ubuntu need to use apt"
}
ok: [tnode2-ubuntu.local] => {
    "msg": "This Ubuntu need to use apt"
}
ok: [tnode3-ubuntu.local] => {
    "msg": "This Ubuntu need to use apt"
}

 

  조건문 도전과제 3 

 

Ubuntu OS이면서 fqdn으로 tnode1 인 경우, debug 모듈을 사용하여 OS 정보fqdn 정보를 출력해보자

 

 

ansible_facts[' ' ] 안에는 굉장히 많은 Key.Value 값이 존재한다. 

앤서블 서버와 tnode1,2,3에 대한 OS 정보 부터,커널 버전까지 굉장히 많은 정보들이 담겨 있다.

 

  • 호스트 이름
  • 커널 버전
  • 네트워크 인터페이스 이름
  • 운영체제 버전
  • CPU 개수
  • 사용 가능한 메모리
  • 스토리지 장치의 크기 및 여유 공간
  • 등등…

이중에서 fqdn과 distribution이라는 키값을 이용해서 조건문을 작성한다.

 

 

1. 플레이북 작성

---
- hosts: all

  tasks:
    - name: Print os type
      ansible.builtin.debug:
        msg: >-
             fqdn: {{ ansible_facts['fqdn'] }}
             OS: {{ ansible_facts['distribution'] }}
      when: 
        - ansible_facts['fqdn'] == "ip-10-10-1-11.ap-northeast-2.compute.internal" 
        - ansible_facts['distribution'] == "Ubuntu"

 

2. 플레이북 실행

ansible-playbook check_os.yml 

PLAY [all] *********************************************************************

TASK [Print os type] ***********************************************************
ok: [tnode1] => {
    "msg": "fqdn: ip-10-10-1-11.ap-northeast-2.compute.internal OS: Ubuntu"
}
skipping: [tnode2]
skipping: [tnode3]

PLAY RECAP *********************************************************************
tnode1                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
tnode3                     : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

 

  핸들러

  • 일부 작업에서 시스템을 변경 한 후에 추가 작업을 실행해야 할 수도 있습니다.
  • 예를 들어 서비스의 구성 파일을 변경하려면 변경 내용이 적용되도록 서비스를 다시 로드해야 합니다.
  • 이때 핸들러는 다른 작업에서 트리거한 알림에 응답하는 작업이며, 해당 호스트에서 작업이 변경될 때만 핸들러에 통지합니다.

✅  핸들러 예제 Example

1. 플레이북 작성

~/my-ansible/handler-sample.ym 

---
- 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. 플레이북 실행 
 
 
✔️ tnode2 노드에 rsyslog 서비스를 재시작하고, print msg라는 핸들러를 호출해 “rsyslog..” 메시지를 출력
 
#
ansible-playbook handler-sample.yml
...
TASK [restart rsyslog] **********************************************************************************************************************************************************************
changed: [tnode2-ubuntu.local]

RUNNING HANDLER [print msg] *****************************************************************************************************************************************************************
ok: [tnode2-ubuntu.local] => {
    "msg": "rsyslog is restarted"
}

# 한번 더 실행 해보기
ansible-playbook handler-sample.yml