목차
- Ansible Playbook 디버깅, 처음엔 저도 막막했습니다
- Ansible Playbook 디버깅이란? 기본 개념부터 잡고 가기
- 디버깅 전에 먼저 해야 할 것들: 사전 점검
- 1. --syntax-check로 문법 먼저 확인
- 2. --check 모드로 드라이런(Dry-run) 실행
- Ansible Playbook 디버깅 핵심 도구: 상세 출력과 debug 모듈
- Verbosity(상세 출력) 레벨 활용
- debug 모듈로 변수 값 확인하기
- register로 태스크 결과 캡처하기
- Ansible 오류 유형별 해결 방법: 실전 트러블슈팅
- ⚠️ 오류 1: UNREACHABLE — 호스트에 접근 불가
- ⚠️ 오류 2: 변수 undefined — 변수를 찾을 수 없음
- ⚠️ 오류 3: 권한 오류 — Permission Denied
- ⚠️ 오류 4: 조건부 실행 문제 — when 절 오작동
- ⚠️ 오류 5: 모듈 파라미터 오류
- 고급 디버깅 기법: 실무에서 정말 유용한 것들
- 특정 태스크만 실행하기 — tags 활용
- 특정 태스크부터 시작하기 — --start-at-task
- ansible-lint로 Playbook 품질 검사
- Callback Plugin으로 출력 가독성 높이기
- Ansible 오류 유형별 빠른 참조 표
- 멱등성(Idempotency) 확인: 자동화 스크립트의 핵심
- 자주 묻는 질문 (FAQ)
- Q. Ansible Playbook 실행 중에 특정 호스트만 실패했을 때 어떻게 하나요?
- Q. 변수 우선순위가 헷갈려요. 어떻게 확인하나요?
- Q. ansible-playbook 실행이 너무 느린데 디버깅 말고 속도 개선 방법은요?
- 마무리: 디버깅도 실력이다
Ansible Playbook 디버깅, 처음엔 저도 막막했습니다
자동화 스크립트를 짜놓고 실행했는데 갑자기 빨간 글씨가 쭉 올라올 때... 그 순간의 당혹감, 혹시 공감되시나요? 저도 처음 Ansible을 도입했을 때 Playbook이 중간에 뻗어버리면 어디서부터 봐야 할지 몰라서 진짜 한참 헤맸거든요. 에러 메시지는 길고, 어디가 문제인지는 모르겠고, 설상가상으로 운영 서버에서 터지기라도 하면... 식은땀이 흘렀죠.
13년 동안 인프라 엔지니어로 일하면서 Ansible을 본격적으로 쓴 게 벌써 7년이 넘었는데, 그 사이에 정말 별의별 Ansible 오류를 다 겪어봤습니다. 오늘은 그 삽질의 결정체를 모아서, Ansible Playbook 디버깅을 어떻게 체계적으로 접근하면 되는지 실전 경험 기반으로 정리해드릴게요. 처음 보시는 분도, 어느 정도 써보셨는데 아직도 에러 앞에서 막히시는 분도 모두 도움이 됐으면 합니다.
▲ Ansible Playbook 디버깅의 전체 흐름 — 오류 발생부터 해결까지 단계별 접근 방법
Ansible Playbook 디버깅이란? 기본 개념부터 잡고 가기
쉽게 말해, Ansible Playbook 디버깅은 자동화 스크립트(Playbook)가 의도한 대로 동작하지 않을 때 원인을 찾고 수정하는 과정이에요. 일반적인 코드 디버깅이랑 비슷하긴 한데, Ansible만의 특성이 있어서 접근 방식이 좀 달라요.
Ansible은 기본적으로 YAML(야믈, 사람이 읽기 쉬운 데이터 직렬화 형식) 기반의 선언형 자동화 도구거든요. 그래서 오류가 크게 세 가지 층위에서 발생합니다.
- YAML 문법 오류: 들여쓰기 하나 잘못되면 바로 터집니다
- Ansible 모듈 오류: 모듈(Module, Ansible의 기능 단위) 파라미터가 잘못되거나 버전이 맞지 않을 때
- 원격 호스트 오류: 대상 서버에서 실제로 실행했을 때 발생하는 문제
이 세 가지를 구분할 수 있어야 Ansible Playbook 디버깅이 빨라져요. 저도 처음엔 이게 다 뒤섞여 보여서 엄청 헤맸는데, 익숙해지면 에러 메시지만 봐도 어느 층위 문제인지 바로 감이 오더라고요.
디버깅 전에 먼저 해야 할 것들: 사전 점검
1. --syntax-check로 문법 먼저 확인
실행하기 전에 문법 검사를 먼저 돌리는 게 기본 중의 기본입니다. 이거 안 하고 바로 돌리다가 원격 서버에서 절반쯤 실행되다 터지면 더 골치 아파요.
# Playbook 문법 검사
ansible-playbook site.yml --syntax-check
# 인벤토리 파일 지정하는 경우
ansible-playbook -i inventory/production site.yml --syntax-check
문법 오류가 있으면 이렇게 나와요:
ERROR! Syntax Error while loading YAML.
found character that cannot start any token
The error appears to be in '/home/user/playbooks/site.yml': line 15, column 3
13: tasks:
14: - name: Install nginx
15: apt: # <--- 여기 들여쓰기 문제
^ here
라인 번호까지 알려주니까 찾기는 어렵지 않아요. 근데 YAML 들여쓰기는 진짜... 탭(Tab)이랑 스페이스(Space)를 섞으면 절대 안 됩니다. 이거 때문에 저도 초반에 얼마나 삽질했는지 ㅎㅎ
2. --check 모드로 드라이런(Dry-run) 실행
실제로 변경을 가하지 않고 "만약 실행하면 어떻게 될까"를 미리 보는 방법이에요. Check Mode(체크 모드)라고도 하고, Dry-run(드라이런, 실제 적용 없이 테스트 실행)이라고도 해요.
# 드라이런 실행
ansible-playbook site.yml --check
# 드라이런 + 변경 예정 내용 상세 확인
ansible-playbook site.yml --check --diff
💡 팁: --diff 옵션을 같이 쓰면 파일이 어떻게 변경될지 diff 형식으로 보여줍니다. 설정 파일 배포 전에 꼭 써보세요. 진짜 유용해요.
Ansible Playbook 디버깅 핵심 도구: 상세 출력과 debug 모듈
Verbosity(상세 출력) 레벨 활용
이게 제가 가장 자주 쓰는 방법이에요. -v 옵션을 붙이면 더 자세한 출력이 나오는데, 최대 4개까지 붙일 수 있습니다.
# -v: 기본 상세 출력 (task 결과)
ansible-playbook site.yml -v
# -vv: 더 자세히 (파일/디렉토리 작업 포함)
ansible-playbook site.yml -vv
# -vvv: 연결 정보까지 (SSH 연결 디버깅에 유용)
ansible-playbook site.yml -vvv
# -vvvv: 가장 상세 (네트워크 패킷 수준)
ansible-playbook site.yml -vvvv
저는 보통 -vv나 -vvv를 주로 써요. -vvvv는 너무 많이 나와서 오히려 찾기 어려울 때도 있거든요.
debug 모듈로 변수 값 확인하기
Ansible 문제 해결에서 제일 많이 쓰는 게 바로 debug 모듈이에요. 변수 값이 의도한 대로 들어가 있는지 확인할 때 필수입니다.
---
- name: 변수 디버깅 예제
hosts: webservers
vars:
app_version: "1.2.3"
deploy_path: "/opt/myapp"
tasks:
- name: 변수 값 확인
debug:
msg: "앱 버전: {{ app_version }}, 경로: {{ deploy_path }}"
- name: 전체 변수 목록 확인 (hostvars)
debug:
var: hostvars[inventory_hostname]
- name: 특정 변수만 확인
debug:
var: app_version
verbosity: 2 # -vv 이상일 때만 출력
verbosity 파라미터가 있는 게 포인트예요. 평소엔 안 보이다가 디버깅할 때만 출력되게 설정할 수 있거든요. 프로덕션 Playbook에 debug 태스크를 남겨둘 때 이렇게 해두면 깔끔합니다.
register로 태스크 결과 캡처하기
태스크(Task, Ansible의 개별 작업 단위) 실행 결과를 변수에 저장해서 다음 단계에서 활용하거나 디버깅할 수 있어요.
tasks:
- name: 서비스 상태 확인
command: systemctl status nginx
register: nginx_status
ignore_errors: yes # 오류가 나도 계속 진행
- name: 결과 출력
debug:
var: nginx_status
- name: 특정 필드만 확인
debug:
msg: |
Return Code: {{ nginx_status.rc }}
stdout: {{ nginx_status.stdout }}
stderr: {{ nginx_status.stderr }}
▲ debug 모듈과 register를 조합한 Ansible Playbook 디버깅 — 태스크 결과를 변수에 저장하고 단계별로 확인하는 방법
Ansible 오류 유형별 해결 방법: 실전 트러블슈팅
⚠️ 오류 1: UNREACHABLE — 호스트에 접근 불가
이거 처음 보면 당황하는 분들이 많은데, 대부분 SSH(시큐어 쉘, 원격 접속 프로토콜) 문제예요.
TASK [Gathering Facts] *****
fatal: [192.168.1.100]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh", "unreachable": true}
체크리스트:
- SSH 키 등록 여부 확인:
ssh -i ~/.ssh/id_rsa user@192.168.1.100 - 인벤토리(Inventory, 관리 대상 호스트 목록) 파일의 IP/호스트명 확인
- ansible_user, ansible_port 변수 확인
- 방화벽 규칙 확인
# SSH 연결 직접 테스트
ansible all -m ping -i inventory/hosts -vvv
# 특정 호스트만 테스트
ansible webserver01 -m ping -i inventory/hosts
⚠️ 오류 2: 변수 undefined — 변수를 찾을 수 없음
Jinja2(진자2, Ansible의 템플릿 엔진) 템플릿에서 변수를 참조했는데 정의가 안 되어 있을 때 발생해요. 저도 이거 때문에 한참 헤맸습니다.
fatal: [server01]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'db_password' is undefined"}
해결 방법:
tasks:
# 방법 1: default 필터로 기본값 지정
- name: DB 설정
template:
src: db.conf.j2
dest: /etc/myapp/db.conf
vars:
db_password: "{{ db_password | default('changeme') }}"
# 방법 2: vars_prompt로 실행 시 입력 받기
vars_prompt:
- name: db_password
prompt: "DB 패스워드를 입력하세요"
private: yes # 입력 내용 숨김
# 방법 3: ansible-vault로 암호화된 변수 파일 사용
# ansible-playbook site.yml --ask-vault-pass
⚠️ 오류 3: 권한 오류 — Permission Denied
원격 서버에서 sudo(슈퍼유저 권한 실행) 권한이 필요한 작업을 할 때 자주 만나는 Ansible 오류예요.
---
- name: 웹서버 설정
hosts: webservers
become: yes # sudo 권한으로 실행
become_user: root # root로 전환
tasks:
- name: nginx 설치
apt:
name: nginx
state: present
# 특정 태스크만 권한 상승
- name: 로그 파일 수정
file:
path: /var/log/myapp
mode: '0755'
become: yes
become_user: www-data
# sudo 비밀번호 입력이 필요한 경우
ansible-playbook site.yml --ask-become-pass
⚠️ 오류 4: 조건부 실행 문제 — when 절 오작동
When(조건절) 설정이 잘못되면 실행되어야 할 태스크가 건너뛰어지거나, 반대로 실행되면 안 되는 게 실행되는 상황이 생겨요. 이거 진짜 찾기 어렵습니다.
tasks:
- name: OS 정보 수집
setup:
gather_subset:
- distribution
- name: 변수 타입 확인 (디버깅용)
debug:
msg: |
OS Family: {{ ansible_os_family }}
Distribution: {{ ansible_distribution }}
Version: {{ ansible_distribution_version }}
# 잘못된 예 — 문자열 비교 실수
- name: Ubuntu에서만 실행 (잘못된 방법)
apt:
name: nginx
when: ansible_distribution == 'ubuntu' # 대소문자 주의!
# 올바른 예
- name: Ubuntu에서만 실행 (올바른 방법)
apt:
name: nginx
state: present
when: ansible_distribution == 'Ubuntu' # 대문자 U
# 복잡한 조건 — 가독성 높게 작성
- name: 특정 환경에서만 실행
command: /opt/deploy.sh
when:
- ansible_distribution == 'Ubuntu'
- ansible_distribution_version is version('20.04', '>=')
- env == 'production'
⚠️ 오류 5: 모듈 파라미터 오류
Ansible 버전이 올라가면서 deprecated(더 이상 사용 안 하는) 파라미터가 생기거나, 파라미터명이 바뀌는 경우가 있어요. 이런 Ansible 오류는 메시지가 꽤 친절하게 나옵니다.
[DEPRECATION WARNING]: The 'include' module is deprecated, use 'import_tasks' or 'include_tasks' instead.
# 또는
[WARNING]: Module did not set no_log for password
tasks:
# 구식 방법 (deprecated)
- include: tasks/setup.yml
# 새로운 방법
- import_tasks: tasks/setup.yml # 정적 포함 (컴파일 타임)
- include_tasks: tasks/setup.yml # 동적 포함 (런타임)
고급 디버깅 기법: 실무에서 정말 유용한 것들
특정 태스크만 실행하기 — tags 활용
Playbook 전체를 돌리지 않고 문제가 있는 태스크만 콕 집어서 실행할 수 있어요. 태그(Tag) 기능인데, Ansible Playbook 디버깅할 때 진짜 유용합니다.
tasks:
- name: 패키지 설치
apt:
name: "{{ item }}"
state: present
loop:
- nginx
- git
- curl
tags:
- packages
- install
- name: 설정 파일 배포
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
tags:
- config
- nginx
# 특정 태그만 실행
ansible-playbook site.yml --tags "config"
# 특정 태그 제외하고 실행
ansible-playbook site.yml --skip-tags "packages"
# 여러 태그 지정
ansible-playbook site.yml --tags "config,nginx"
특정 태스크부터 시작하기 — --start-at-task
중간에 실패했을 때 처음부터 다시 돌리기 싫을 때 쓰는 방법이에요. 저 이거 알고 나서 삽질 시간이 확 줄었어요.
# 특정 태스크명부터 실행
ansible-playbook site.yml --start-at-task "설정 파일 배포"
# step 모드: 태스크마다 실행 여부 물어봄
ansible-playbook site.yml --step
ansible-lint로 Playbook 품질 검사
ansible-lint(앤서블 린트)는 Playbook의 코드 품질을 자동으로 검사해주는 도구예요. 문법 오류뿐 아니라 Best Practice(베스트 프랙티스, 모범 사례) 위반도 잡아줍니다.
# 설치
pip install ansible-lint
# 검사 실행
ansible-lint site.yml
# 특정 규칙 무시하고 실행
ansible-lint site.yml --exclude-path .ansible-lint
# .ansible-lint 설정 파일
skip_list:
- yaml[line-length] # 줄 길이 규칙 무시
- name[casing] # 이름 대소문자 규칙 무시
warn_list:
- experimental # 실험적 규칙은 경고만
Callback Plugin으로 출력 가독성 높이기
기본 출력이 너무 지저분하다 싶으면 Callback Plugin(콜백 플러그인, 출력 형식 변환 도구)을 바꿔보세요.
# ansible.cfg 설정
[defaults]
stdout_callback = yaml # YAML 형식으로 출력 (가독성 좋음)
# stdout_callback = dense # 간결하게 출력
# stdout_callback = debug # 디버깅용 상세 출력
callback_whitelist = profile_tasks # 각 태스크 실행 시간 표시
저는 yaml 콜백이랑 profile_tasks 조합을 제일 좋아해요. 어느 태스크가 오래 걸리는지 한눈에 보이거든요.
▲ yaml callback plugin 적용 전후 비교 — 출력 가독성이 크게 향상되어 Ansible 문제 해결이 훨씬 수월해집니다
Ansible 오류 유형별 빠른 참조 표
자주 만나는 오류들을 정리해봤습니다. 북마크해두고 쓰세요 ✅
| 오류 유형 | 주요 증상 | 원인 | 해결 방법 |
|---|---|---|---|
| UNREACHABLE | 호스트 연결 실패 | SSH 설정 문제, 네트워크 오류 | SSH 키 확인, 인벤토리 점검, -vvv로 연결 추적 |
| FAILED (문법) | Playbook 시작 전 종료 | YAML 들여쓰기, 문법 오류 | --syntax-check, ansible-lint |
| FAILED (변수) | undefined variable 에러 | 변수 미정의, 오타 | debug 모듈로 변수 확인, default 필터 |
| FAILED (권한) | Permission denied | sudo 설정 미흡 | become/become_user 설정, sudoers 확인 |
| SKIPPED (예상치 못한) | 태스크가 건너뜀 | when 조건 오류 | debug로 변수 값 확인, 조건식 재검토 |
| CHANGED (의도치 않은) | 멱등성(Idempotency) 깨짐 | 모듈 사용 오류, command 모듈 남용 | 전용 모듈 사용, changed_when 설정 |
| MODULE ERROR | 모듈 실행 실패 | 파라미터 오류, 버전 불일치 | 공식 문서 확인, -vv로 상세 확인 |
멱등성(Idempotency) 확인: 자동화 스크립트의 핵심
멱등성(Idempotency, 동일한 작업을 여러 번 실행해도 결과가 같아야 하는 성질)은 Ansible의 핵심 철학이에요. 이게 깨지면 Playbook을 두 번 돌렸을 때 뭔가 이상해지는 상황이 생기더라고요.
tasks:
# 나쁜 예: command 모듈은 멱등성이 없음
- name: 디렉토리 생성 (나쁜 방법)
command: mkdir /opt/myapp
# 좋은 예: file 모듈은 멱등성 보장
- name: 디렉토리 생성 (좋은 방법)
file:
path: /opt/myapp
state: directory
mode: '0755'
owner: www-data
# command/shell을 써야 할 때는 changed_when으로 제어
- name: 애플리케이션 초기화 (한 번만 실행)
command: /opt/myapp/init.sh
args:
creates: /opt/myapp/.initialized # 이 파일 있으면 건너뜀
# 또는 register + when 조합
- name: 초기화 여부 확인
stat:
path: /opt/myapp/.initialized
register: init_check
- name: 초기화 실행
command: /opt/myapp/init.sh
when: not init_check.stat.exists
자주 묻는 질문 (FAQ)
Q. Ansible Playbook 실행 중에 특정 호스트만 실패했을 때 어떻게 하나요?
A. --limit 옵션으로 특정 호스트만 재실행할 수 있어요. 실패한 호스트 목록은 .retry 파일에 자동 저장되기도 합니다.
# 특정 호스트만 실행
ansible-playbook site.yml --limit webserver01
# retry 파일 활용
ansible-playbook site.yml --limit @site.retry
Q. 변수 우선순위가 헷갈려요. 어떻게 확인하나요?
A. Ansible 변수 우선순위(Variable Precedence)는 복잡한데, ansible-config dump나 debug 모듈로 실제 적용된 값을 확인하는 게 제일 빠릅니다. 공식 문서에 22단계 우선순위가 나와 있는데... 저도 다 외우진 못해요 ㅎㅎ
Q. ansible-playbook 실행이 너무 느린데 디버깅 말고 속도 개선 방법은요?
A. 이건 별도로 다룰 주제인데, Forks(병렬 실행 수) 조정, Fact Caching(팩트 캐싱), Pipelining(파이프라이닝) 활성화가 주요 방법이에요. 다음 글에서 Ansible 성능 최적화를 다룰 예정입니다.
마무리: 디버깅도 실력이다
▲ Ansible Playbook 디버깅 핵심 방법 요약 — syntax-check부터 debug 모듈, 태그 활용까지 단계별 접근법
오늘 다룬 내용을 간단히 정리하면요:
- ✅ 실행 전:
--syntax-check로 문법 검사,--check --diff로 드라이런 - ✅ 실행 중:
-v~-vvv상세 출력,debug모듈로 변수 확인 - ✅ 범위 좁히기:
--tags,--limit,--start-at-task활용 - ✅ 코드 품질: ansible-lint로 사전 검사, 멱등성 확인
- ✅ 가독성: yaml callback plugin + profile_tasks로 출력 개선
솔직히 말씀드리면, 처음에 Ansible 오류를 만났을 때 저도 막막했어요. 에러 메시지가 길고 복잡해 보이는데, 결국 패턴이 있더라고요. 오늘 소개한 접근 방법들을 익히면 웬만한 Ansible 문제 해결은 훨씬 수월해질 거예요.
🎉 핵심은 체계적인 접근이에요. 무턱대고 코드 고치지 말고, 문법 → 연결 → 변수 → 모듈 순서로 하나씩 좁혀가는 거죠. 그리고 debug 모듈은 정말 친한 친구처럼 자주 써보세요. 저도 매일 씁니다.
다음 글에서는 Ansible Vault(앤서블 볼트)를 활용한 시크릿(Secret, 민감한 정보) 관리 방법을 다뤄볼 예정이에요. 패스워드나 API 키 같은 민감한 정보를 Playbook에 안전하게 넣는 방법인데, 이것도 실무에서 꼭 알아야 할 내용이라 기대해주세요.
궁금한 점이나 여러분이 겪었던 특이한 Ansible 오류 경험이 있으시면 댓글로 남겨주세요. 같이 해결해봐요! 😊
'IT > Cloud' 카테고리의 다른 글
| [Cloud] Terraform 원격 상태 관리: S3, GCS, Azure Blob 백엔드 설정 가이드 (0) | 2026.04.28 |
|---|---|
| [Cloud] Terraform 멀티 클라우드 IaC 자동화 가이드 — AWS/GCP/Azure 통합 관리 (0) | 2026.04.21 |
| [Cloud] Terraform 멀티 클라우드 관리 가이드 - AWS/GCP/Azure 한 번에 관리하기 (0) | 2026.04.21 |
| [Cloud] GitHub Actions 자체 호스팅 러너 보안 강화: 백도어 방지 및 2026년 최신 가이드 (0) | 2026.04.16 |
| [Cloud] 쿠버네티스 보안: RBAC 권한 오남용 방지 및 클라우드 계정 탈취 대응 전략 (0) | 2026.04.14 |
| [Cloud] AWS EC2 자동 복구 설정 가이드 (2026년) (2) | 2026.04.14 |