Ansible 조건문 및 반복문

AnsibleBeginner
지금 연습하기

소개

이번 실습에서는 Ansible의 강력한 두 가지 기능인 조건문(conditionals)과 반복문(loops)을 살펴봅니다. 이러한 개념을 활용하면 특정 조건에 따라 작업을 실행하도록 제어하고 여러 항목에 대한 작업을 반복하여 더욱 동적이고 효율적인 플레이북을 작성할 수 있습니다. 이번 실습을 마치면 플레이북에서 조건문을 사용하여 의사결정을 내리고, 반복문을 구현하여 반복적인 작업을 효율적으로 수행하는 방법을 이해하게 됩니다. 이 지식은 인프라 관리를 위한 더욱 유연하고 강력한 Ansible 플레이북을 만드는 데 도움이 될 것입니다.

환경 설정

이번 단계에서는 Ansible 조건문 및 반복문 연습을 위한 작업 환경을 설정합니다. 이 준비 과정을 통해 이후의 모든 작업에서 사용되는 파일과 디렉터리가 생성됩니다.

먼저 프로젝트 디렉터리로 이동합니다. 터미널에 다음 명령어를 입력하세요.

cd ~/project

이 명령어는 현재 디렉터리를 이번 실습을 위한 지정된 작업 공간인 ~/project로 변경합니다.

이제 인벤토리(inventory) 파일을 생성하겠습니다. Ansible에서 인벤토리 파일은 플레이북 내의 명령어, 모듈, 그리고 작업이 실행될 호스트 및 호스트 그룹을 정의합니다. 이번 실습에서는 로컬호스트(localhost)만 포함하는 간단한 인벤토리를 사용합니다.

inventory.ini라는 새 파일을 생성합니다.

nano inventory.ini

이 명령어는 nano 텍스트 에디터를 엽니다. nano 사용법에 익숙하지 않더라도 걱정하지 마세요. 간단하고 사용자 친화적인 텍스트 에디터입니다. 커서가 파일 내부에 위치하게 되며 입력을 시작할 수 있습니다.

이제 파일에 다음 내용을 추가합니다.

[local]
localhost ansible_connection=local

각 항목의 의미는 다음과 같습니다.

  • [local]은 "local"이라는 이름의 그룹을 정의합니다.
  • localhost는 호스트의 이름입니다.
  • ansible_connection=local은 Ansible에게 SSH를 사용하는 대신 로컬에서 명령어를 실행하도록 지시합니다.

파일을 저장하고 nano를 종료하려면 Ctrl+X를 누르고, 수정한 버퍼를 저장하기 위해 Y를 누른 다음, Enter를 눌러 파일 이름을 확인합니다.

다음으로 플레이북을 위한 디렉터리를 생성합니다.

mkdir playbooks
cd playbooks

mkdir 명령어는 "playbooks"라는 이름의 새 디렉터리를 생성하며, 그 후 cd를 사용하여 이 새 디렉터리로 이동합니다.

왜 이렇게 하는 걸까요? Ansible 파일을 디렉터리별로 정리하는 것은 모범 사례입니다. 프로젝트가 커지고 복잡해질수록 프로젝트를 정돈된 상태로 유지해 줍니다.

이 단계를 거쳐 기본적인 Ansible 환경이 설정되었습니다. Ansible이 작업할 호스트를 알려주는 인벤토리 파일과 플레이북 전용 디렉터리를 갖추게 되었습니다. 이러한 구조는 더 복잡한 기능을 배우고 실험할 때 Ansible 프로젝트를 더 쉽게 관리할 수 있도록 만들어 줍니다.

조건문 소개

이번 단계에서는 Ansible 조건문을 사용하여 특정 조건에 따라 작업 실행을 제어합니다. 이는 시스템 상태나 특정 변수의 값에 따라 서로 다른 작업을 수행해야 할 때 유용합니다.

조건문 사용법을 보여주는 간단한 플레이북을 만들어 보겠습니다.

nano conditional_example.yml

이 명령어는 nano 텍스트 에디터를 열어 conditional_example.yml이라는 새 파일을 생성합니다. 이제 다음 내용을 추가하세요.

---
- name: Conditional Example
  hosts: localhost
  gather_facts: yes
  tasks:
    - name: Check OS family
      debug:
        msg: "This is a Debian-based system"
      when: ansible_os_family == "Debian"

    - name: Check OS family (alternative)
      debug:
        msg: "This is not a Debian-based system"
      when: ansible_os_family != "Debian"

구조를 살펴보겠습니다.

  • 파일 상단의 ---는 YAML 문서의 시작을 나타냅니다.
  • name: Conditional Example은 플레이북의 이름을 지정합니다.
  • hosts: localhost는 이 플레이북이 로컬 머신에서 실행될 것임을 지정합니다.
  • gather_facts: yes는 작업을 실행하기 전에 시스템에 대한 정보를 수집하도록 Ansible에 지시합니다. 조건문에서 이러한 팩트(facts)를 사용하기 때문에 이는 중요합니다.
  • tasks:는 실행할 작업 목록을 시작합니다.

각 작업은 debug 모듈을 사용하여 메시지를 출력하지만, 실행 여부는 when 절에 의해 제어됩니다.

  • 첫 번째 작업은 시스템이 Debian 계열인 경우에만 실행됩니다 (ansible_os_family == "Debian").
  • 두 번째 작업은 시스템이 Debian 계열이 아닌 경우에만 실행됩니다 (ansible_os_family != "Debian").

ansible_os_family는 대상 시스템에 대해 Ansible이 수집한 팩트입니다. 여기서는 조건문이 작동하는 방식을 시연하기 위해 사용되었습니다.

nano 에디터를 저장하고 종료합니다 (Ctrl+X, Y, Enter).

이제 플레이북을 실행합니다.

ansible-playbook -i ../inventory.ini conditional_example.yml

이 명령어는 Ansible에 플레이북을 실행하도록 지시합니다. -i ../inventory.ini 옵션은 앞서 생성한 인벤토리 파일을 지정합니다.

시스템이 Debian 계열인지 여부를 나타내는 출력이 표시됩니다. 시스템의 OS 패밀리에 따라 디버그 메시지 중 하나만 표시됩니다.

이 예시는 조건문을 사용하여 플레이북을 다양한 환경에 적응할 수 있도록 만드는 방법을 보여줍니다. 실제 시나리오에서는 조건문을 사용하여 서로 다른 OS 유형에 따라 다른 패키지를 설치하거나, 파일이 이미 존재하는 경우 특정 작업을 건너뛸 수 있습니다.

조건문의 강점은 각 경우마다 별도의 플레이북을 만들 필요 없이, 플레이북을 유연하게 만들고 다양한 시나рио를 처리할 수 있도록 돕는 능력에 있다는 점을 기억하세요.

다중 조건 처리

이번 단계에서는 작업을 실행하기 전에 논리 연산자를 사용하여 여러 조건을 결합합니다. 이 패턴은 실제 플레이북에서 더 고급진 조건부 동작을 지원합니다.

multiple_conditions.yml이라는 새 파일을 생성합니다.

nano multiple_conditions.yml

이제 파일에 다음 내용을 추가합니다.

---
- name: Multiple Conditions Example
  hosts: localhost
  gather_facts: yes
  vars:
    check_memory: true
  tasks:
    - name: Check OS and Memory
      debug:
        msg: "This is a Debian-based system with more than 1GB of memory"
      when:
        - ansible_os_family == "Debian"
        - ansible_memtotal_mb > 1024
        - check_memory | bool

    - name: Print System Information
      debug:
        msg: "OS: {{ ansible_distribution }}, Memory: {{ ansible_memtotal_mb }} MB"
      when: ansible_distribution == "Ubuntu" or ansible_memtotal_mb < 2048

이 플레이북의 구성을 살펴보겠습니다.

  • 플레이북 수준에서 check_memory 변수를 정의합니다. 이는 동적으로 설정되거나 플레이북을 실행할 때 추가 변수로 전달될 수 있습니다.

  • 첫 번째 작업은 여러 조건을 사용합니다.

    • OS 패밀리가 Debian인지 확인합니다.
    • 총 메모리가 1024 MB (1 GB)를 초과하는지 확인합니다.
    • check_memory 변수가 참(true)인지 확인합니다.

    작업이 실행되려면 이 모든 조건이 참이어야 합니다. check_memory | bool|는 값을 불리언(boolean)으로 변환하는 필터입니다.

  • 두 번째 작업은 or 연산자 사용법을 보여줍니다. 배포판이 Ubuntu이거나 총 메모리가 2048 MB (2 GB) 미만인 경우에 실행됩니다.

  • 여기서는 더 많은 Ansible 팩트를 사용하고 있습니다. ansible_distribution은 특정 배포판 이름을 제공하며, ansible_memtotal_mb는 총 시스템 메모리를 메가바이트 단위로 제공합니다.

nano 에디터를 저장하고 종료합니다.

이제 이 플레이북을 실행합니다.

ansible-playbook -i ../inventory.ini multiple_conditions.yml

출력을 관찰해 보세요. 시스템의 특성에 따라 디버그 메시지 중 하나 또는 둘 다가 표시될 수 있습니다.

이 예시는 복잡한 조건을 만들어 플레이북을 다양한 시나리오에 매우 유연하게 대응하도록 만드는 방법을 보여줍니다. 다양한 시스템 팩트, 사용자 정의 변수, 논리 연산자를 결합하여 작업 실행 시점을 세밀하게 조정할 수 있습니다.

반복문 소개

이번 단계에서는 Ansible 반복문(loops)을 사용하여 서로 다른 값으로 작업을 반복합니다. 이는 여러 사용자를 생성하거나, 여러 패키지를 설치하거나, 여러 디렉터리를 만드는 등 여러 항목에 대해 동일한 작업을 수행해야 할 때 유용합니다.

반복문 사용법을 보여주는 플레이북을 만들어 보겠습니다. loop_example.yml이라는 새 파일을 생성합니다.

nano loop_example.yml

이제 다음 내용을 추가합니다.

---
- name: Loop Example
  hosts: localhost
  vars:
    fruits:
      - apple
      - banana
      - cherry
  tasks:
    - name: Print fruit names
      debug:
        msg: "Current fruit: {{ item }}"
      loop: "{{ fruits }}"

    - name: Create directories
      file:
        path: "/tmp/{{ item }}"
        state: directory
      loop:
        - dir1
        - dir2
        - dir3

구조를 살펴보겠습니다.

  • 과일 이름 리스트인 fruits 변수를 정의합니다.

  • 첫 번째 작업은 반복문을 사용하여 fruits 리스트를 순회합니다. 각 반복마다 현재 값은 {{ item }}으로 사용할 수 있습니다.

  • 두 번째 작업은 file 모듈과 함께 반복문을 사용하여 여러 디렉터리를 생성하는 방법을 보여줍니다. /tmp 폴더에 세 개의 디렉터리를 생성하고 있습니다.

  • 작업 내에서 반복문을 직접 사용하거나(두 번째 작업처럼) 변수를 참조할 수 있음(첫 번째 작업처럼)을 주목하세요.

nano 에디터를 저장하고 종료합니다.

이제 이 플레이북을 실행합니다.

ansible-playbook -i ../inventory.ini loop_example.yml

이 플레이북을 실행하면 첫 번째 작업은 각 과일 이름을 출력하고, 두 번째 작업은 /tmp에 세 개의 디렉터리를 생성하는 것을 볼 수 있습니다.

반복문은 플레이북에서 반복되는 코드의 양을 크게 줄여줄 수 있는 Ansible의 강력한 기능입니다. 사용자, 패키지, 파일과 같은 항목 리스트를 다룰 때 특히 유용합니다.

고급 반복문 기법

이번 단계에서는 고급 Ansible 반복문 기법을 사용하여 복잡한 데이터 구조를 다루고 반복 프로세스를 제어합니다.

advanced_loops.yml이라는 새 파일을 생성합니다.

nano advanced_loops.yml

이제 다음 내용을 추가합니다.

---
- name: Advanced Loop Techniques
  hosts: localhost
  vars:
    users:
      - name: alice
        groups: ["developers", "testers"]
      - name: bob
        groups: ["managers", "developers"]
  tasks:
    - name: Create users with groups
      debug:
        msg: "Creating user {{ item.name }} with groups: {{ item.groups | join(', ') }}"
      loop: "{{ users }}"

    - name: Demonstrate loop_control
      debug:
        msg: "Processing item {{ index }} - {{ item }}"
      loop: ["a", "b", "c", "d"]
      loop_control:
        index_var: index

    - name: Loop over dictionary
      debug:
        msg: "{{ key }}: {{ value }}"
      loop: "{{ {'x': 1, 'y': 2, 'z': 3} | dict2items }}"
      vars:
        key: "{{ item.key }}"
        value: "{{ item.value }}"

이러한 고급 기법들을 살펴보겠습니다.

  • 딕셔너리 리스트 순회: 첫 번째 작업은 users 리스트를 순회합니다. 여기서 각 항목은 이름과 그룹 리스트를 포함하는 딕셔너리입니다. 점 표기법(item.name, item.groups)을 사용하여 이러한 중첩된 요소에 접근할 수 있습니다.

  • loop_control 사용: 두 번째 작업은 loop_control을 보여줍니다. 이를 통해 반복 변수의 이름을 변경하고(기본값은 item) 현재 반복 인덱스에 접근할 수 있습니다. 여기서는 index_var: index를 사용하여 현재 반복 횟수를 추적하는 index 변수를 생성합니다.

  • 딕셔너리 순회: 마지막 작업은 딕셔너리를 순회하는 방법을 보여줍니다. dict2items 필터를 사용하여 딕셔너리를 반복 가능한 키-값 쌍의 리스트로 변환합니다. 그런 다음 item.keyitem.value를 사용하여 딕셔너리의 키와 값에 접근합니다.

nano 에디터를 저장하고 종료합니다.

이제 이 플레이북을 실행합니다.

ansible-playbook -i ../inventory.ini advanced_loops.yml

이 플레이북을 실행하면 이러한 고급 반복 기법이 어떻게 작동하는지 확인할 수 있습니다. 출력 결과는 다음과 같습니다.

  • 각 그룹과 함께 사용자 생성 메시지
  • 인덱스와 함께 처리되는 항목들
  • 딕셔너리의 키-값 쌍

이러한 고급 기법을 사용하면 더 복잡한 데이터 구조를 다룰 수 있고 반복문을 더욱 세밀하게 제어할 수 있습니다. 중첩된 데이터를 다룰 때, 반복문 인덱스를 추적해야 할 때, 또는 딕셔너리를 다룰 때 특히 유용합니다.

요약

이번 실습에서는 더 동적이고 효율적인 플레이북을 작성할 수 있게 해주는 강력한 두 가지 기능인 Ansible 조건문과 반복문에 대해 배웠습니다. 핵심 내용은 다음과 같습니다.

  1. 조건문(when 절)을 사용하면 대상 시스템에 대한 팩트나 사용자가 정의한 변수와 같은 특정 조건에 따라 작업 실행을 제어할 수 있습니다.
  2. andor와 같은 논리 연산자를 사용하여 여러 조건을 결합함으로써 더 복잡한 조건문을 만들 수 있습니다.
  3. 반복문(loop 키워드)을 사용하면 서로 다른 값으로 작업을 반복하여 효율성을 높이고 플레이북의 복잡성을 줄일 수 있습니다.
  4. Ansible은 리스트, 딕셔너리, 더 복잡한 데이터 구조 순회를 포함한 다양한 반복문 유형을 지원합니다.
  5. loop_control 및 딕셔너리 순회와 같은 고급 반복 기법은 반복 작업을 처리하는 데 있어 훨씬 더 많은 유연성을 제공합니다.

이러한 기능은 다양한 시나리오에 적응하고 여러 항목을 효율적으로 관리할 수 있는 유연하고 강력한 Ansible 플레이북을 만드는 데 필수적입니다. Ansible을 계속 다루면서 플레이북에 조건문과 반복문을 통합하여 더욱 동적이고 효율적으로 만들어 보세요.

이러한 기능을 사용할 때는 플레이북의 가독성과 유지보수성을 항상 고려해야 한다는 점을 기억하세요. 코드를 크게 단순화할 수 있는 반면, 과도하게 사용하거나 지나치게 복잡한 조건문과 반복문은 플레이북을 이해하고 유지보수하기 어렵게 만들 수 있습니다.