A VM에서 B VM으로 처음 보낸 Ansible 명령은 ping이었다. 돌아온 답은 pong이 아니라 UNREACHABLE!이었다.
앞 글에서 Multipass로 만든 VM 두 대 위에서 이어가는 실습이다. A(dsoserver)를 컨트롤 노드로, B(dsoserver2)를 관리 대상 노드로 둔다. 이 글에서는 인벤토리 파일 한 줄로 B를 등록하고 ping과 ad-hoc 명령을 거쳐 첫 플레이북으로 B에 파일을 만드는 데까지 정리한다.
실습 환경: 같은 네트워크의 Ubuntu VM 두 대
Name State IPv4 Image
dsoserver Running 192.168.64.10 Ubuntu 24.04 LTS
dsoserver2 Running 192.168.64.11 Ubuntu 24.04 LTS
인벤토리 한 줄이 곧 접속 정보다
Ansible은 관리 대상에 에이전트를 깔지 않고, SSH로 들어가 모듈을 실행한 뒤 나온다. 그래서 Ansible이 호스트에 대해 알아야 하는 것은 어디로, 누구로 접속하느냐뿐이다. 그 정보를 적는 파일이 인벤토리다.
# VM A 접속
multipass shell dsoserver
# ansible_hosts 라는 파일을 "인벤토리"로 사용하여 관리할 호스트(서버) 지정하기
echo "bvm ansible_host=192.168.64.11 ansible_user=ubuntu" > ~/ansible_hosts
| 항목 | 의미 |
|---|---|
bvm | B VM의 별칭(호스트명). 이후 명령에서 이 이름으로 부른다 |
ansible_host | B VM의 실제 IP 주소 |
ansible_user | B VM에 SSH로 접속할 때 쓰는 사용자명(예: ubuntu, multipass 등) |
첫 ping이 publickey에서 막힌 이유
인벤토리만 만들고 ansible -i ~/ansible_hosts bvm -m ping을 치면 B에 닿지 못한다. 에러는 Permission denied (publickey)다. Ansible은 기본 키로 SSH 접속을 시도하는데, B에 등록해 둔 키는 id_ansible이었기 때문이다. 키 위치를 명시하면 바로 통과한다.
# Ansible에 명시적으로 SSH 비밀키 위치를 지정하는 방법
ansible -i ~/ansible_hosts bvm -m ping --private-key=~/.ssh/{비밀키 이름}
# 실제 입력한 명령어: ansible -i ~/ansible_hosts bvm -m ping --private-key=~/.ssh/id_ansible

성공 출력 위에 붙은 [WARNING]은 B의 Python 인터프리터(/usr/bin/python3.12)를 자동으로 찾아 썼다는 알림이다. ping 결과에는 영향이 없다. 여기서 -m ping은 ICMP ping이 아니라 SSH로 들어가 Python 모듈을 실행할 수 있는지 확인하는 Ansible 모듈이라, 인터프리터 이야기가 같이 나온다.
매번 --private-key를 붙이는 대신 인벤토리에 ansible_ssh_private_key_file로 키를 적어 둘 수 있다.
vi ~/ansible_hosts
# 아래 내용으로 수정(비밀키 지정)
bvm ansible_host=192.168.64.11 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/{비밀키 이름}
이제는 ansible -i ~/ansible_hosts bvm -m ping만 쳐도 핑테스트가 통과한다. 접속 방법은 명령어가 아니라 인벤토리에 두는 게 맞다. 호스트가 늘어날수록 차이가 커진다.
ad-hoc 명령: A에서 쳤는데 B의 결과가 나온다
-a로 명령을 넘기면 B에서 실행한 결과가 A 터미널에 찍힌다. 모듈을 지정하지 않으면 기본 command 모듈이 쓰인다.
ansible -i ~/ansible_hosts bvm -a "date"
# bvm | CHANGED | rc=0 >>
# Sun Jun 1 23:18:40 KST 2025
ansible -i ~/ansible_hosts bvm -a "ls -a"
# bvm | CHANGED | rc=0 >>
# .
# ..
# .ansible
# .bash_history
# .bash_logout
# .bashrc
# .cache
# .profile
# .ssh
# .viminfo
# test
첫 플레이북: B VM에 test.txt 만들기
ad-hoc 명령이 한 줄짜리 원격 실행이라면, 플레이북은 “어떤 호스트가 어떤 상태여야 하는가"를 YAML로 적은 파일이다. A VM에서 hello.yml을 만든다.
# A VM에서 vi hello.yml
---
- name: 테스트 파일 생성 실습
hosts: bvm
tasks:
- name: test.txt 파일 만들기
copy:
content: "안녕하세요, Ansible 실습입니다!"
dest: /home/ubuntu/test.txt
ansible-playbook -i ~/ansible_hosts hello.yml
# B VM에 test.txt 파일 생성 완료
copy 모듈은 content를 그대로 dest에 쓴다. 생각보다 금방 끝났다. 같은 플레이북을 한 번 더 돌리면 changed가 아니라 ok로 나오는지, 이건 다음에 다시 봐야겠다.
정리
B에 붙기 위해 필요한 건 인벤토리 한 줄이었고, 첫 실패도 그 한 줄에 키가 빠져서였다.