반복문과 조건문을 이용한 제어문 구현하기 - 반복문

728x90
반응형

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

 

 

  • 플레이북을 이용하여 자동화하려는 프로세스 개발을 하다 보면 애플리케이션 설치와 같이 동일한 작업을 여러 번 해야 하거나, 운영체제에 따라 다른 모듈을 써야 할 경우가 발생한다.
  • 이런 경우 앤서블에서는 loop 라는 반복문과 when 이라는 조건문을 사용할 수 있다.
  • 반복문과 조건문을 사용하면 적절한 조건에 따라 작업을 수행할 수 있도록 플레이북을 더 효율적으로 작성할 수 있다.

 

반복문

  • 반복문을 사용하면 동일한 모듈을 사용하는 작업을 여러 번 작성하지 않아도 된다.

 

단순 반복문

  • 단순 반복문은 특정 항목에 대한 작업을 반복한다.
  • loop 키워드를 작업에 추가하면 작업을 반복해야 하는 항목의 목록을 값으로 사용한다.
  • 해당하는 값을 사용하려면 item 변수를 이용할 수 있다.

 

vi check-services.yml

---

- hosts: all
  tasks:
    - name: Check sshd state
      ansible.builtin.service:
        name: sshd
        state: started

    - name: Check rsyslog state
      ansible.builtin.service:
        name: rsyslog
        state: started

 

vi 에디터를 사용해 sshd 서비스와 rsyslog 서비스의 상태를 체크하는 플레이북을 ansible.builtin.service 모듈을 이용해 작성한다.

 

ansible-playbook --syntax-check check-services.yml
ansible-playbook check-services.yml

 

ansible-playbook 명령어의 --syntax-check 옵션으로 에러 체크를 진행한 다음, 문제가 없으면 해당 플레이북을 실행한다.

sshd 서비스와 rsyslog 서비스를 확인하는 작업이 각각 진행된다.

 

cp check-services.yml check-services1.yml
vi check-services1.yml

---

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

      loop:
        - sshd
        - rsyslog

 

check-services.yml 파일을 check-services1.yml 파일로 복사한 다음 loop 반복문을 적용하기 위해  vi 에디터로 위 코드대로 수정한다.

ansible.builtin.service 모듈은 하나만 작성하고 하단에 loop 키워드를 추가한다. loop 키워드 아래에는 체크할 서비스인 sshd와 rsyslog를 나열하고, service 모듈 name에는 item 이라는 변수를 사용한다.

 

ansible-playbook --syntax-check check-services1.yml
ansible-playbook check-services1.yml

 

에러 체크를 진행하고 플레이북을 실행한다. 실행하면 노드별, 서비스별로 서비스 상태가 체크되는 것을 확인할 수 있다.

 

vi check-services2.yml

---

- hosts: all
  vars:
    services:
      - sshd
      - rsyslog

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

 

loop 문에 사용하는 아이템을 변수에 저장하면 loop 키워드에 해당 변수명을 사용할 수 있다.

체크한 sshd와 rsyslog를 services 라는 변수에 목록으로 저장하고, tasks의 loop 문에는 선언한 services 라는 변수를 사용한다.

 

ansible-playbook --syntax-check check-services2.yml
ansible-playbook check-services2.yml

 

에러 체크를 진행하고 플레이북을 실행한다. 실행하면 앞에서 진행한 플레이북과 동일한 결과가 출력되는 것을 확인할 수 있다.

 

 

사전 목록에 의한 반복문

  • 플레이북을 작성하다 보면 여러 개의 아이템이 필요한 경우가 발생한다.
  • 여러 항목을 loop 문에서 사전 목록으로 사용할 수 있다.

 

vi make-file.yml

---

- hosts: all

  tasks:
    - name: Create files
      ansible.builtin.file:
        path: "{{ item['log-path'] }}"
        mode: "{{ item['log-mode'] }}"
        state: touch
      loop:
        - log-path: /var/log/test1.log
          log-mode: '0644'
        - log-path: /var/log/test2.log
          log-mode: '0600'

 

make-file.yml 파일을 하나 생성하고 vi 에디터를 사용해 위 코드 대로 작성한다.

loop 키워드 아래에 log-path와 log-mode 라는 변수를 차례대로 여러 건 입력한다. 그리고 상단의 ansible.builtin.file 모듈에는 loop 문을 통해 추가한 변수를 item['log-path'], item['log-mode']로 참조하여 사용했다.

state는 touch 즉, 생성이다.

 

ansible.builtin.file은 ansible에서 파일 및 디렉토리를 관리하는데 사용되는 모듈이다.

path는 관리할 파일이나 디렉토리의 경로를 지정하고, mode는 파일이나 디렉토리의 접근 권한을 설정한다.

mode에서 0644는 소유자에게 읽기, 쓰기 권한을 부여하고, 그룹과 기타 사용자에게는 읽기 권한 만 부여

0600은 소유자에게만 읽기, 쓰기 권한을 부여하고, 그룹과 기타 사용자는 어떤 권한도 갖지 못한다는  것을 의미한다.

 

정리하자면 해당 호스트들의 해당 경로에 test.log 라는 파일을 2개 생성하는 것이다.

 

ansible-playbook --syntax-check make-file.yml
ansible-playbook make-file.yml

 

에러 체크를 진행하고 플레이북을 실행한다.

실행하면 각 노드에 test1.log 와 test2.log 파일이 생성된다.

 

ssh -p 22 tnode1-centos
ll /var/log/test*
exit

ssh -p 22 tnode2-ubuntu
ll /var/log/test*
exit

ssh -p 22 tnode3-ubuntu
ll /var/log/test*
exit

 

실제로 해당 노드에 접속하면 test1.log, test2.log 파일이 생성된 것을 확인할 수 있다.

 

 

반복문과 Register 변수 사용

  • Register 변수는 반복 실행되는 작업의 출력을 캡처할 수 있다.
  • 반복 실행되는 작업들이 모두 잘 수행되었는지 확인할 수 있으며, 이 값을 이용해 여러 작업을 수행할 수 있다.

 

vi loop_register.yml

---

- hosts: localhost
  tasks:
    - name: loop echo test
      ansible.builtin.shell: "echo 'I can speak {{ item }}'"
      loop:
        - Korean
        - English
      register: result

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

 

loop_register.yml 파일을 생성하고 vi 에디터로 위 코드 내용을 작성한다.

ansible.builtin.shell 모듈은 원격지의 쉘 명령어를 실행하는 모듈이다. 이 모듈을 이용해 "I can speak ~" 라는 메시지를 출력하게 된다.(echo는 리눅스에서 주어진 문자열을 출력하는 명령어다)

이때 loop를 이용해 Korean과 English를 할 수 있다고 아이템을 나열한다.

하단의 register 키워드를 사용해 실행 결과를 result 변수로 저장한다.

저장된 result 변수는 ansible.builtin.debug 모듈을 통해 해당 내용을 확인할 수 있다.

 

ansible-playbook --syntax-check loop_register.yml
ansible-playbook loop_register.yml

 

에러 체크를 진행하고 loop_register.yml 플레이북을 실행한다.

실행하면 echo 문이 잘 실행되는 것을 확인할 수 있다.

register 키워드에 의해 저장된 result 내용에는 대괄호 사이에 Key - Value 쌍으로 구성된 결과 값들이 모두 저장되어 있다.

 

vi loop_register1.yml

---

- hosts: localhost
  tasks:
    - name: loop echo test
      ansible.builtin.shell: "echo 'I can speak {{ item }}'"
      loop:
        - Korean
        - English
      register: result

    - name: Show result
      ansible.builtin.debug:
        msg: "Stdout: {{ item.stdout }}"
      loop: "{{ result.results }}"

 

앞에서 실행한 플레이북 결과를 확인하면 result 내의 results의 실행 결과는 배열 형식으로 저장되어 있다.

이때 results의 특정 값을 플레이북에서 사용할 경우 loop 문을 이용할 수 있다.

이번에는 loop 키워드를 사용하여 result.results를 아이템 변수로 사용해 본다. 그리고 해당 아이템의 stdout 의 값을 출력할 때는 item.stdout 이라는 변수로 결과를 출력한다.

 

해당 코드를 정리하자면 loop 매개 변수에서 Korean, English라는 두 개의 값을 지정하였다. 그리고 ansible.builtin.shell 모듈은 이 두 값에 대해 각각 echo 'I can speak Korean'과 echo 'I can speak English'라는 명령어를 실행하게 된다.

실행 결과는 register 매개 변수를 통해 result 변수에 저장된다. 

result.results는 result 변수에 저장된 값 중 results 라는 키에 해당하는 값이다.

ansible.builtin.debug 모듈로 result.results의 각 항목(item)에 대해 "Stdout: {{ item.stdout }}" 라는 메시지를 출력한다. 여기서 item.stdout은 각 명령어의 실행 결과 중 표준 출력(stdout)을 나타낸다.

 

즉, item = result.results의 각 항목을 나타내고, result.results는 I can speak Korean, I can speak English 라는 두 개의 값을 포함하고 있다.

 

ansible-playbook --syntax-check loop_register1.yml
ansible-playbook loop_register1.yml

 

에러 체크를 진행하고 플레이북을 실행한다.

실행하면 loop로 사용된 item에 저장된 값(I can speak Korean, I can speak English)가 ansible.builtin.debug 모듈을 이용해 출력한 메시지를 확인할 수 있다.

 

 

 

728x90
반응형