안녕하세요, 덴고입니다.
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 |