티스토리 뷰

CloudNet@의 가시다님 Ansible 1기 스터디에 참여하게 되어 배운 내용과 책의 내용을 함께 정리합니다.

📚 앤서블로 시작하는 인프라 자동화

 

앤서블로 시작하는 인프라 자동화 | 장현정 - 교보문고

앤서블로 시작하는 인프라 자동화 | 효율적인 IT 자동화를 위한 도구, 앤서블 설계부터 응용까지 단계별로 배우는 인프라 관리클라우드 컴퓨팅을 논할 때 IaC(Infrastructure as Code)를 빼놓을 수 없는

product.kyobobook.co.kr

 

1. 반복문

반복문을 사용하면 동일한 모듈을 사용하는 작업을 여러 번 작성하지 않아도 됩니다. 작업을 여러 개 작성하는 대신 loop 반복문을 이용해 여러 개의 작업을 수행할 수 있습니다.

 

1.1. 단순 반복문

loop 키워드에 작업을 반복해야 하는 항목의 값을 작성하고 해당하는 값은 item 변수를 이용합니다.

 

loop 반복문을 playbook에 적용해봅니다.

~/my-ansible/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

playbook에는 serive의 name만 다른 task가 존재합니다. 이를 아래와 같이 반복문 적용을 통해 간소화할 수 있습니다.

~/my-ansible/check-services1.yml

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

반복문에 사용하는 item을 vars 변수로 저장하면 loop 키워드에서 변수명으로 사용할 수 있습니다. vars 변수는 별도 파일로도 저장하여 사용할 수 있습니다.

~/my-ansible/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 }}"

playbook을 실행한 결과는 모두 같습니다. 변수 값마다 inventory에 등록되어 있는 서버 모두(playbook에 hosts: all이라고 명시되어 있습니다)에서 실행해야 하기 때문에 task의 실행이 3번씩 일어납니다. 따라서 해당 플레이북 파일의 task는 총 6번 실행됩니다.

1.2. 사전 목록에 의한 반복문

여러 개의 item을 반복문에서 사전 목록(dictionary)으로 사용할 수 있습니다.

 

사전 목록을 사용하는 playbook을 작성해봅니다.

~/my-ansible/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'

playbook을 실행하면 추가된 변수를 item[’abc’] 형태로 참조하여 사용하여 아래와 같이 각 서버마다 파일이 해당하는 권한으로 잘 생성된 것을 확인할 수 있습니다.

 

이전 앤서블 스타일 반복문: 앤서블 2.5 버전 이하에서는 with_ 접두사 뒤에 여러 개의 반복문 키워드를 제공하는 서로 다른 구문의 반복문을 사용했었습니다. 이는 권장되지 않는 스타일이지만 아직 혼용의 시기이므로 알아둘 필요는 있습니다.

반복문 키워드 설명
with_items 문자열 목록 또는 사전 목록과 같은 단순한 목록의 경우 loop 키워드와 동일하게 작동합니다. loop와 달리 목록이 with_items에 제공되는 경우 단일 수준의 목록으로 병합되며, 반복문 변수 item에는 각 반복 작업 중 사용되는 목록 항목이 있습니다.
with_file 제어 노드의 파일 이름을 목록으로 사용할 경우 사용되며, 반복문 변수 item에는 각 반복 작업 중 파일 목록에 있는 해당 파일의 콘텐츠가 있습니다.
with_sequence 숫자로 된 순서에 따라 값 목록을 생성하는 매개 변수가 필요한 경우 사용되며, 반복문 변수 item에는 각 반복 작업 중 생성된 순서대로 생성된 항목 중 하나의 값이 있습니다.

 

1.3. Register 변수 사용

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

 

playbook을 생성해봅니다.

~/my-ansible/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

playbook을 실행하면 배열 형식으로 대괄호 ([]) 사이에 Key-Value 쌍으로 구성된 결과 값들이 모두 저장되어 보기 불편합니다. result 변수에 저장된 results의 결과를 item 변수로 사용하여 stdout 키의 값만 출력하는 playbook을 작성합니다.

~/my-ansible/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 }}"

playbook을 실행해보면 사용자가 실행한 쉘 명령어의 결과값만을 별도로 출력하여 실행 결과를 보기 한결 편해졌습니다.

 

2. 조건문

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

 

2.1. 조건 작업 구문

when 문은 조건부로 작업을 실행할 때 테스트할 조건을 값으로 사용합니다. 테스트할 수 있는 가장 간단한 조건 중 하나는 Boolean 변수가 true인지 false인지 여부입니다.

 

playbook에 조건을 설정하여 봅니다. run_my_task 변수에 true로 값을 설정하고, when 문에서 run_my_task를 사용하면 true인 경우에만 작업이 실행됩니다.

~/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

run_my_task 변수의 값을 false로 바꾸고 playbook을 실행하면, 해당 task를 무시합니다.

---
- 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

playbook 실행 결과에서 echo message라는 task를 skipping한 것을 확인할 수 있습니다.

 

2.2. 조건 연산자

when 문에 bool 변수(true, false) 외에도 조건 연산자를 사용할 수 있습니다.

  • != : 값이 같지 않을 때 true
  • >, >=, <=, < : ‘초과, ‘ 이상’, ‘이하’, ‘미만’ 일 때에 true
  • not : 조건의 부정
  • and, or : ‘그리고’, ‘또는’의 의미로 여러 조건의 조합 가능
  • in : 값이 포함된 경우에 true. 예를 들어 2 in “1, 2, 3” 은 true
  • is defined : 변수가 정의된 경우 true

OS 종류에 따라 task를 수행하는 playbook을 생성해봅니다.vars 키워드로 supported_distros 라는 변수를 사전 타입의 값으로 저장하며, when 구문에서 ansible_facts[’distribution’] in supported_distros 라는 조건문을 추가합니다.

~/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

ansible_facts['distribution'] 값이 ‘Ubuntu’ 나 ‘CentOS’ 면 task가 실행될텐데, 서버들은 모두 Ubuntu이므로 Ubuntu에 대한 내용만 출력되는 것을 확인할 수 있습니다.

when 구문에는 or이나 and 연사자를 사용할 수 있어 다중의 조건을 모두 만족하는 상황에만 task가 실행되도록 지정할 수 있습니다.

~/my-ansible/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'] == "Ubuntu" and ansible_facts['distribution_version'] == "22.04"

 

and 연산자는 아래의 playbook처럼 사전 형태의 목록으로도 표현할 수 있습니다.

~/my-ansible/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'] == "Ubuntu" 
        - ansible_facts['distribution_version'] == "22.04"

또한, and 연산자와 or 연산자를 함께 사용할 수도 있습니다.

~/my-ansible/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_version'] == "22.04" )

 

2.3. 반복문과 조건문 사용

when 문의 item[’mount’]은 loop문에서 선언한 ansible_facts의 mounts 중 mount 값과 size_available 값을 사용해 반복문고 조건문을 함께 사용하는 playbook을 생성해봅니다. item 변수의 키값들은 myfacts에 수집된 캐시 내용에서 쉽게 확인할 수 있습니다.

~/my-ansible/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

playbook을 실행할 때 옵션으로 --flush-cache를 사용하여 그동안 수집된 캐시들을 제거하고 새로 수집할 수 있으며 playbook의 조건에 해당하는 경로만 msg로 출력되는 것을 확인할 수 있습니다.

조건문을 사용할 때는 반복문뿐만 아니라 register 키워드로 작업 변수도 사용할 수 있습니다. systemctl 명령어로 rsyslog가 active인지를 체크하여 해당 결과를 result 변수에 저장하고, Print rsyslog status 태스크에서 result.stdout 값이 active 일 경우에만 해당 값을 출력하는 playbook을 작성해봅니다.

~/my-ansible/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"

ansible.builtin.command 모듈에 사용된 명령어의 결과값은 실제 활성화되어있다면 아래와 같이 active라는 결과값이 출력됩니다.

 

이전에 playbook을 실행할 때 --flush-cache 옵션을 주어 제거되었던 tnode1과 tnode2의 팩트들이 다시 수집되는 것과 register 키워드로 등록된 결과값이 when 조건과 일치하여 출력되는 결과까지 확인할 수 있습니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함