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
항목의미
bvmB VM의 별칭(호스트명). 이후 명령에서 이 이름으로 부른다
ansible_hostB VM의 실제 IP 주소
ansible_userB 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에 붙기 위해 필요한 건 인벤토리 한 줄이었고, 첫 실패도 그 한 줄에 키가 빠져서였다.