본문 바로가기

study/Ansible101 1기

Ansible101 1기 2주차 첫번째

안녕하세요, 덴고입니다.

Ansible 101 1기 2주차 스터디 공유 시작하겠습니다.

 

반복문

Ansible Loops - https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_loops.html

반복문을 사용하면 동일한 모듈을 사용하는 작업을 여러 번 작성하지 않아도 됩니다. 예를 들어 서비스에 필요한 포트를 방화벽에 추가한다고 하면, 포트를 추가하는 작업을 여러 개 작성하는 대신 loop 반복문을 이용해 작업 하나로 여러 개의 포트를 추가할 수 있습니다.

 

 

단순 반복문 : 특정 항목에 대한 작업을 반복 - item 변수, 변수 목록 지정

loop 키워드를 작업에 추가하면 작업을 반복해야 하는 항목의 목록으로 사용합니다. 그리고 해당하는 값을 사용하려면 item 변수를 이용할 수 있습니다.

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

# 프로세스 동작 확인
ansible -m shell -a "pstree |grep sshd" all
ansible -m shell -a "pstree |grep rsyslog" all

# 실행
ansible-playbook check-services.yml

 

loop반복문 적용

~/my-ansible/check-services1.yml

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

 

실행결과

 

 

그리고 loop문에는 사용하는 아에팀을 변수에 저장하면 loop 키워드에 해당 변수명을 사용할 수 있습니다.

~/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 }}"
    
##변수 목록을 loop의 변수로 사용 → 변수 목록을 별도 파일로도 가능!

실행결과

 

 

 

사전 목록에 의한 반복문 : 여러 개의 아이템을 loop 문에서 사전 목록 dictionary 으로 사용합니다.

 

하나의 아이템을 사용할 때도 있지만, 여러 개의 아이템이 필요한 경우가 발생합니다. 예를 들어 여러 개의 사용자 계정을 생성하는 플레이북을 작성한다면 사용자 계정을 생성하기 위해 필요한 이름과 패스워드 등의 여러 항목을 loop 문에서 사전 목록으로 사용할 수 있습니다.

 

플레이북 파일 생성 : loop 문에 추가된 변수를 item[’abc’]로 참조하여 사용
~/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'

결과를 확인해보면 아래 test가 잘 들어와 있네요.

 

 

참고로 이전 앤서블에서는

이전 앤서블 스타일 반복문 : 앤서블 2.5 버전 이전에는 with_ 접두사 뒤에 여러 개의 반복문 키워드를 제공하는 서로 다른 구문의 반복문 사용 ← 비권장

 

 

ansible.builtin.shell 모듈 - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/shell_module.html

 

반복문과 Register 변수 사용 : Register 변수는 반복 실행되는 작업의 출력을 캡처할 수 있습니다.

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

 

1. 파일 생성

shell 모듈을 이용하여 “I can speak~”라는 메시지를 출력합니다.

이때 loop 키워드를 이용하여 Korean과 English를 할 수 있다고 아이템을 나열합니다.

그리고 하단에 register 키워드를 이용하여 실행 결과를 result 변수에 저장합니다.

이렇게 저장된 result 변수는 debug 모듈을 통해 해당 내용을 확인합니다.

 

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

 

2. 실행 : register 키워드에 의해 저장된 result 내용에는 대괄호 ([]) 사이에 Key-Value 쌍으로 구성된 결과 값들이 모두 저장됩니다.

 

#
ansible-playbook loop_register.yml
...
TASK [Loop echo test] *************************************************************************************************************************************************************************
changed: [localhost] => (item=Korean)
changed: [localhost] => (item=English)

TASK [Show result] ****************************************************************************************************************************************************************************
ok: [localhost] => {
    "result": {
        "changed": true,
        "msg": "All items completed",
        "results": [
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": "echo 'I can speak Korean'",
                "delta": "0:00:00.002555",
                "end": "2023-12-29 05:21:52.898098",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo 'I can speak Korean'",
                        "_uses_shell": true,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true
                    }
                },
                "item": "Korean",
                "msg": "",
                "rc": 0,
                "start": "2023-12-29 05:21:52.895543",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "I can speak Korean",
                "stdout_lines": [
                    "I can speak Korean"
                ]
            },
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": "echo 'I can speak English'",
                "delta": "0:00:00.003048",
                "end": "2023-12-29 05:21:53.076240",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo 'I can speak English'",
                        "_uses_shell": true,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true
                    }
                },
                "item": "English",
                "msg": "",
                "rc": 0,
                "start": "2023-12-29 05:21:53.073192",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "I can speak English",
                "stdout_lines": [
                    "I can speak English"
                ]
            }
        ],
        "skipped": false
    }
}

 

 

3.

앞서 result 내의 results의 실행 결과는 배열 형식으로 저장된 것을 볼 수 있다. 이때 results의 특정 값을 플레이북에서 사용할 경우 loop문을 이용할 수 있습니다.

아래 예제는 debug 모듈에 loop 키워드를 사용하여 result.results아이템 변수로 사용한 것입니다.

그리고 해당 아이템의 stdout의 값을 출력할 때는 item.stdout이라는 변수로 결과값을 출력합니다.

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

4. 실행

 

 

조건문

이제 조건문에 대해서 알아보겠습니다.

Conditionals when 

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_conditionals.html

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

 

조건 작업 구문 : when 문은 조건부로 작업을 실행할 때 테스트할 조건을 값으로 사용합니다.

조건이 충족되면 작업이 실행되고, 조건이 충족되지 않으면 작업을 건너뜁니다.

when 문을 테스트하는 가장 간단한 조건 중 하나는 Boolean 변수가 true인지 false인지 여부입니다.

 

1. 플레이북 생성 : 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

 

2. 실행

 

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

실행 해보면 해당 태스크를 수행하지 않고 건너 뜁니다. (skipping)

 

 

 

조건 연산자

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

예를 들어 when 문에 ansible_facts[’machine’] == “x86_64” 라는 구문을 사용했다면 ansible_facts[’machine’] 값이 x86_64일 때만 해당 태스크를 수행합니다.

 

그럼, OS 종류에 따라 태스크를 수행하는 예제를 통해 조건 연산자 사용법에 대해 알아보겠습니다.

 

1. 플레이북 파일 생성 : 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

2. 실행 : ansible_facts['distribution' 값이 ‘Ubuntu’ 나 ‘CentOS’ 면 출력(태스트 수행)

 

 

복수 조건문: when 문은 단일 조건문 뿐만 아니라 복수 조건문도 사용할 수 있습니다.

예를 들어 CentOS이고 서버 타입이 x86_64일 경우에만 작업이 실행되게 구성할 수 있습니다.

그럼 운영체제가 CentOS이거나 우분투일 경우 작업이 수행되는 예제를 통해 복수 조건문 사용 예를 살펴보겠습니다.

 

1. 파일 생성 : when 문에 값에 or 구문 사용

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

 

2. 실행

 

3. Ubuntu 이고, Version이 22.04 이 경우만 작업 수행 되게 and 연산자 사용

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

 4. 실행

 

5. and 연산자는 조건문에서 바로 사용하거나 아래 플레이북처럼 사전 형태의 목록으로 표현하는 방법 두 가지가 있습니다.

 

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

 

6. 실행결과 확인

 

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

다음 플레이북은 두 연산자를 함께 사용한 예제로, CentOS이면서 8 이거나, Ubuntu이면서 22.04 인 경우를 표현합니다.

 

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

 8. 실행

 

 

ansible.builtin.command 모듈 - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html

 

이제 반복문과 조건문 둘다 함께 사용해 보겠습니다.

1. 플레이북 파일 생성 : when 문의 item[’mount’]은 loop문에서 선언한 ansible_facts의 mounts 중 mount 값과 size_available 값을 사용해 구현.

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

2. 실행하면

앤서블 팩트에서 mounts라는 사전 타입의 변수값을 반복하면서 mount가 ‘/’ 이고 size_available 값이 ‘300000000’(300메가)보다 큰 경우에만 메시지를 출력하고, 그렇지 않을 경우에는 작업을 건너뜁니다.

# 모니터링
watch -d -n 1 ls -l ~/my-ansible/myfacts

#
ansible-playbook check-mount.yml --flush-cache

 

 

3. 조건문을 사용할 때는 반복문뿐만 아니라 register 키워드로 작업 변수도 사용할 수 있습니다.

아래 예제는 systemctl 명령어로 rsyslog가 active인지를 체크하여 해당 결과를 result 변수에 저장하고, Print rsyslog status 태스크에서 result.stdout 값이 active 일 경우에만 해당 값을 출력합니다.

 

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

4. 실행

각 호스트의 rsyslog 상태를 확인하고 해당 결과를 출력

'study > Ansible101 1기' 카테고리의 다른 글

Ansible101 1기 3주차 두번째  (0) 2024.01.28
Ansible101 1기 3주차 첫번째  (0) 2024.01.28
Ansible101 1기 2주차 두번째  (0) 2024.01.14
Ansible101 1기 1주차  (0) 2024.01.07
Ansible101 1기 실습환경 구성  (0) 2024.01.06