소개
Ansible 은 시스템 관리자와 개발자가 인프라를 효율적으로 관리할 수 있도록 돕는 강력한 자동화 도구입니다. Ansible 플레이북을 통해 스크립트나 명령을 실행할 때, 모니터링 및 문제 해결을 위해 해당 출력값을 캡처하고 표시하는 것이 매우 중요합니다.
이 실습에서는 Ansible 플레이북에서 스크립트 출력을 효과적으로 표시하는 방법을 배우게 됩니다. Ansible 플레이북의 기본 구조부터 시작하여, 명령 출력값을 캡처하고 표시하는 다양한 기술을 살펴보고, 마지막으로 출력 데이터를 형식화하고 필터링하는 몇 가지 고급 방법을 다룰 것입니다.
이 실습을 마치면 Ansible 에서 스크립트 출력을 처리하는 다양한 접근 방식에 대한 실질적인 경험을 얻게 되어, 더 많은 정보를 제공하고 디버깅이 용이한 자동화 워크플로우를 만들 수 있게 됩니다.
첫 번째 Ansible 플레이북 설정
스크립트 출력을 표시하는 방법을 살펴보기 전에, 기본적인 Ansible 환경을 설정하고 첫 번째 플레이북을 만들어야 합니다.
Ansible 설치
먼저 Ansible 이 시스템에 설치되어 있는지 확인해 보겠습니다.
sudo apt update
sudo apt install -y ansible
이 명령은 Ubuntu 시스템에 Ansible 을 설치합니다. 설치가 완료되면 Ansible 버전을 확인하여 설치를 확인합니다.
ansible --version
다음과 유사한 출력이 표시되어 Ansible 이 올바르게 설치되었음을 확인할 수 있습니다.
ansible [core 2.12.x]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.10.x (default, Mar 14 2023, 14:50:41) [GCC 11.3.0]
jinja version = 3.0.3
libyaml = True
Ansible 인벤토리 이해
Ansible 은 연결할 호스트를 알아야 합니다. 이 실습에서는 로컬 머신만 포함하는 간단한 인벤토리 파일을 사용합니다.
Ansible 프로젝트를 위한 디렉토리를 만듭니다.
mkdir -p ~/project/ansible-lab
cd ~/project/ansible-lab
이제 inventory.ini라는 이름의 인벤토리 파일을 만듭니다.
echo "localhost ansible_connection=local" > inventory.ini
이 인벤토리 파일은 Ansible 에게 SSH 를 사용하지 않고 로컬 머신에서 명령을 실행하도록 지시합니다.
첫 번째 플레이북 만들기
이제 기본적인 Ansible 플레이북을 만들어 보겠습니다. WebIDE 에서 ~/project/ansible-lab 디렉토리에 다음 내용으로 first_playbook.yml이라는 새 파일을 만듭니다.
---
- name: My First Ansible Playbook
hosts: localhost
gather_facts: yes
tasks:
- name: Display a simple message
debug:
msg: "Hello from Ansible!"
- name: Display system information
debug:
msg: "You are running {{ ansible_distribution }} {{ ansible_distribution_version }}"
이 간단한 플레이북에는 두 가지 작업이 있습니다.
- 간단한 인사말 메시지 표시
- 실행 중인 운영 체제에 대한 정보 표시
이 플레이북을 실행하여 작동 방식을 확인해 보겠습니다.
cd ~/project/ansible-lab
ansible-playbook -i inventory.ini first_playbook.yml
다음과 유사한 출력이 표시됩니다.
PLAY [My First Ansible Playbook] *********************************************************
TASK [Gathering Facts] *******************************************************************
ok: [localhost]
TASK [Display a simple message] **********************************************************
ok: [localhost] => {
"msg": "Hello from Ansible!"
}
TASK [Display system information] ********************************************************
ok: [localhost] => {
"msg": "You are running Ubuntu 22.04"
}
PLAY RECAP *******************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
이 출력은 다음을 보여줍니다.
- 플레이북이 성공적으로 실행되었습니다.
- 모든 작업이 "ok" 상태로 완료되었습니다.
- 각 디버그 작업의 출력이 표시됩니다.
이제 기본적인 플레이북이 작동하므로, 스크립트를 실행하고 해당 출력을 더 자세히 표시하는 방법을 살펴볼 수 있습니다.
스크립트 실행 및 출력 캡처
이제 기본적인 Ansible 환경이 설정되었으므로, command 및 shell 모듈을 사용하여 스크립트를 실행하고 출력을 캡처하는 방법을 살펴보겠습니다.
Command 와 Shell 모듈의 차이점
Ansible 은 명령을 실행하기 위한 두 가지 주요 모듈을 제공합니다.
- command: 셸을 거치지 않고 원격 노드에서 명령을 실행합니다. 즉,
|,>,<,&와 같은 셸 연산자는 작동하지 않습니다. - shell: 셸을 통해 명령을 실행하여 셸 연산자와 환경 변수를 사용할 수 있습니다.
실행할 간단한 스크립트 만들기
먼저 Ansible 로 실행할 수 있는 간단한 셸 스크립트를 만들어 보겠습니다. ~/project/ansible-lab 디렉토리에 system_info.sh라는 파일을 만듭니다.
cd ~/project/ansible-lab
WebIDE 에서 다음 내용으로 파일을 만듭니다.
#!/bin/bash
echo "=== System Information ==="
echo "Hostname: $(hostname)"
echo "Kernel Version: $(uname -r)"
echo "CPU Info: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d':' -f2 | xargs)"
echo "Memory Info: $(free -h | grep Mem | awk '{print $2 " total, " $3 " used, " $4 " free"}')"
echo "Disk Usage: $(df -h / | grep / | awk '{print $5 " of " $2 " used"}')"
스크립트를 실행 가능하게 만듭니다.
chmod +x ~/project/ansible-lab/system_info.sh
이제 이 스크립트를 수동으로 실행하여 어떤 출력을 생성하는지 확인해 보겠습니다.
./system_info.sh
다음과 유사한 출력이 표시됩니다.
=== System Information ===
Hostname: labex-xxxxxxxx
Kernel Version: 5.15.0-xx-generic
CPU Info: Intel(R) Xeon(R) xxxxxx
Memory Info: 8.0G total, 1.2G used, 5.8G free
Disk Usage: 15% of 50G used
Ansible 로 스크립트 실행
이제 이 스크립트를 실행하고 출력을 캡처하는 새 플레이북을 만들어 보겠습니다. ~/project/ansible-lab 디렉토리에 script_output.yml이라는 파일을 만듭니다.
---
- name: Run Script and Capture Output
hosts: localhost
gather_facts: no
tasks:
- name: Run system info script
command: ./system_info.sh
register: script_result
- name: Display script output
debug:
msg: "{{ script_result.stdout }}"
이 플레이북은 두 가지 작업을 수행합니다.
command모듈을 사용하여system_info.sh스크립트를 실행합니다.register키워드를 사용하여 출력을script_result라는 변수에 저장합니다.debug모듈을 사용하여 캡처된 출력을 표시합니다.
이 플레이북을 실행해 보겠습니다.
cd ~/project/ansible-lab
ansible-playbook -i inventory.ini script_output.yml
다음과 유사한 출력이 표시됩니다.
PLAY [Run Script and Capture Output] ***************************************************
TASK [Run system info script] ***********************************************************
changed: [localhost]
TASK [Display script output] ************************************************************
ok: [localhost] => {
"msg": "=== System Information ===\nHostname: labex-xxxxxxxx\nKernel Version: 5.15.0-xx-generic\nCPU Info: Intel(R) Xeon(R) xxxxxx\nMemory Info: 8.0G total, 1.2G used, 5.8G free\nDisk Usage: 15% of 50G used"
}
PLAY RECAP *****************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
출력이 줄 바꿈 문자 (\n) 가 있는 단일 문자열로 표시되는 것을 확인하세요. 다음 섹션에서 표시를 개선해 보겠습니다.
Register 변수 이해
register 키워드는 명령의 출력뿐만 아니라 여러 속성을 포함하는 변수를 생성합니다. 이러한 속성을 탐색하기 위해 새 플레이북을 만들어 보겠습니다.
~/project/ansible-lab 디렉토리에 register_details.yml이라는 파일을 만듭니다.
---
- name: Explore Register Variable
hosts: localhost
gather_facts: no
tasks:
- name: Run system info script
command: ./system_info.sh
register: script_result
- name: Display all register properties
debug:
var: script_result
- name: Display just stdout
debug:
var: script_result.stdout
- name: Display stdout as a list of lines
debug:
var: script_result.stdout_lines
이 플레이북을 실행합니다.
ansible-playbook -i inventory.ini register_details.yml
script_result 변수의 모든 속성을 보여주는 더 자세한 출력을 볼 수 있습니다. 여기에는 다음이 포함됩니다.
stdout: 표준 출력을 단일 문자열로 표시stderr: 표준 오류 (있는 경우)rc: 반환 코드 (0 은 성공을 의미)stdout_lines: 표준 출력을 줄 목록으로 분할
마지막 작업은 출력을 줄 목록으로 형식화하여 훨씬 더 읽기 쉽게 만듭니다.
고급 출력 처리 기술
이제 스크립트 출력을 캡처하는 기본 사항을 이해했으므로, Ansible 플레이북에서 출력을 처리하고 표시하는 몇 가지 더 고급 기술을 살펴보겠습니다.
스크립트 오류 처리
스크립트를 실행할 때 오류 조건을 적절하게 처리하는 것이 중요합니다. Ansible 은 명령이 0 이 아닌 종료 코드를 반환하면 작업을 실패로 표시합니다. 오류 처리를 보여주는 플레이북을 만들어 보겠습니다.
~/project/ansible-lab 디렉토리에 error_handling.yml이라는 파일을 만듭니다.
---
- name: Handling Script Errors
hosts: localhost
gather_facts: no
tasks:
- name: Run a command that might fail
command: ls /nonexistent_directory
register: cmd_result
ignore_errors: yes
- name: Show error message if command failed
debug:
msg: "Command failed with error: {{ cmd_result.stderr }}"
when: cmd_result.rc != 0
- name: Show success message if command succeeded
debug:
msg: "Command succeeded with output: {{ cmd_result.stdout }}"
when: cmd_result.rc == 0
이 플레이북에서:
- 존재하지 않는 디렉토리를 나열하려고 시도합니다.
- 명령이 실패하더라도 플레이북이 중지되지 않도록
ignore_errors: yes를 사용합니다. - 반환 코드 (
cmd_result.rc) 를 확인하여 명령이 성공했는지 실패했는지 확인합니다. - 결과에 따라 적절한 메시지를 표시합니다.
이 플레이북을 실행해 보겠습니다.
cd ~/project/ansible-lab
ansible-playbook -i inventory.ini error_handling.yml
다음과 유사한 출력이 표시됩니다.
PLAY [Handling Script Errors] ***********************************************************
TASK [Run a command that might fail] ***************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["ls", "/nonexistent_directory"], "delta": "0:00:00.003398", "end": "2023-09-15 12:34:56.789012", "msg": "non-zero return code", "rc": 2, "start": "2023-09-15 12:34:56.785614", "stderr": "ls: cannot access '/nonexistent_directory': No such file or directory", "stderr_lines": ["ls: cannot access '/nonexistent_directory': No such file or directory"], "stdout": "", "stdout_lines": []}
...ignoring
TASK [Show error message if command failed] *********************************************
ok: [localhost] => {
"msg": "Command failed with error: ls: cannot access '/nonexistent_directory': No such file or directory"
}
TASK [Show success message if command succeeded] ****************************************
skipping: [localhost]
PLAY RECAP *******************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=1
명령이 실패했음에도 불구하고 플레이북이 계속 실행되고 오류 메시지가 표시되는 것을 확인하세요.
여러 줄 출력 형식 지정
여러 줄 출력을 생성하는 더 복잡한 스크립트를 만들고 플레이북에서 이를 깔끔하게 형식 지정해 보겠습니다.
~/project/ansible-lab 디렉토리에 package_info.sh라는 파일을 만듭니다.
#!/bin/bash
echo "TOP 5 LARGEST INSTALLED PACKAGES"
echo "================================"
dpkg-query -W -f='${Installed-Size}\t${Package}\n' | sort -n -r | head -5
실행 가능하게 만듭니다.
chmod +x ~/project/ansible-lab/package_info.sh
이제 이 스크립트를 실행하고 출력을 깔끔하게 형식 지정하는 플레이북을 만듭니다. formatted_output.yml이라는 파일을 만듭니다.
---
- name: Format Script Output
hosts: localhost
gather_facts: no
tasks:
- name: Run package info script
shell: ./package_info.sh
register: pkg_info
- name: Display raw output
debug:
msg: "{{ pkg_info.stdout }}"
- name: Display formatted output with a title
debug:
msg: |
Below is the package information:
--------------------------------
{% for line in pkg_info.stdout_lines %}
{{ line }}
{% endfor %}
--------------------------------
Total lines: {{ pkg_info.stdout_lines | length }}
이 플레이북은 다음을 수행합니다.
package_info.sh스크립트를 실행합니다.- 원시 출력을 표시합니다.
- Jinja2 템플릿을 사용하여 제목과 바닥글로 출력을 형식 지정합니다.
실행해 보겠습니다.
ansible-playbook -i inventory.ini formatted_output.yml
다음과 같이 깔끔하게 형식 지정된 출력이 표시됩니다.
PLAY [Format Script Output] ***********************************************************
TASK [Run package info script] ********************************************************
changed: [localhost]
TASK [Display raw output] *************************************************************
ok: [localhost] => {
"msg": "TOP 5 LARGEST INSTALLED PACKAGES\n================================\n112233\tsome-large-package\n99887\tanother-package\n...\n"
}
TASK [Display formatted output with a title] ******************************************
ok: [localhost] => {
"msg": "Below is the package information:\n--------------------------------\nTOP 5 LARGEST INSTALLED PACKAGES\n================================\n112233\tsome-large-package\n99887\tanother-package\n...\n--------------------------------\nTotal lines: 7"
}
PLAY RECAP ****************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
조건부 출력 표시
때로는 상세 모드로 실행하는 경우와 같이 특정 조건에서만 출력을 표시하고 싶을 수 있습니다. 이를 수행하는 방법을 살펴보겠습니다.
~/project/ansible-lab 디렉토리에 conditional_output.yml이라는 파일을 만듭니다.
---
- name: Conditional Output Display
hosts: localhost
gather_facts: yes
tasks:
- name: Get disk usage information
shell: df -h
register: disk_info
- name: Display disk usage (always shown)
debug:
msg: "{{ disk_info.stdout_lines[0:2] }}"
- name: Display detailed disk usage (only in verbose mode)
debug:
msg: "{{ disk_info.stdout_lines }}"
verbosity: 1
이 플레이북에서:
- 디스크 사용량 정보를 캡처합니다.
- 항상 요약 (처음 두 줄) 을 표시합니다.
- 상세 모드 (
-v플래그 사용) 로 실행할 때만 전체 세부 정보를 표시합니다.
먼저 일반 모드로 실행해 보겠습니다.
ansible-playbook -i inventory.ini conditional_output.yml
이제 상세 모드로 실행해 보겠습니다.
ansible-playbook -i inventory.ini conditional_output.yml -v
상세 모드에서는 전체 디스크 사용량 정보를 얻고, 일반 모드에서는 요약만 표시되는 것을 확인할 수 있습니다.
이 기술은 기본적으로 잠재적으로 민감하거나 압도적인 출력을 숨기는 데 유용하며, 디버깅에 필요한 경우에도 사용할 수 있습니다.
요약
이 랩에서는 Ansible 플레이북에서 스크립트 출력을 캡처하고 표시하는 다양한 기술을 배웠습니다.
- 기본적인 Ansible 환경을 설정하고 첫 번째 플레이북을 만들었습니다.
command및shell모듈을 사용하여 스크립트를 실행하는 방법을 배웠습니다.register지시문을 사용하여 스크립트 출력을 캡처했습니다.debug모듈을 사용하여 다양한 형식으로 출력을 표시했습니다.- 오류 조건을 처리하고 조건부 출력 표시를 구현했습니다.
- 출력을 더 읽기 쉽게 만들기 위해 형식 지정 기술을 적용했습니다.
이러한 기술을 통해 실행 중에 명확한 피드백을 제공하는 더 많은 정보를 제공하는 Ansible 플레이북을 만들 수 있습니다. 이러한 가시성은 자동화된 프로세스를 모니터링하고 문제가 발생할 때 문제 해결하는 데 매우 중요합니다.
이러한 출력 처리 기술을 활용하여 작업을 수행할 뿐만 아니라 각 단계에서 무슨 일이 일어나고 있는지 명확하게 전달하는 더 강력한 자동화 워크플로우를 구축할 수 있습니다. 이렇게 하면 자동화가 더 투명해지고 특히 팀 환경이나 복잡한 인프라에서 작업할 때 유지 관리가 더 쉬워집니다.


