Ansible 플레이북에서 SSH 연결 실패 문제 해결
이 전문가 가이드는 Ansible 플레이북 실행 시 발생하는 일반적인 SSH 연결 실패를 체계적으로 해결하는 방법을 제공합니다. 최대 상세 출력(`-vvv`)을 활용한 진단, 개인 키 및 권한 관련 인증 오류 해결, '호스트 키 확인 실패' 문제 수정, 네트워크 차단 진단 방법을 알아보세요. 실용적인 단계와 명령줄 예제를 통해 연결 시간 초과 및 권한 거부 메시지의 근본 원인을 신속하게 파악하고 해결하여 안정적인 자동화를 복원할 수 있습니다.
Ansible 플레이북에서 SSH 연결 실패 문제 해결
Ansible은 일반적으로 SSH(Secure Shell)를 사용하여 Linux 및 Unix 관리 노드와 통신합니다. 다른 연결 플러그인을 사용할 수 있으며, Windows 자동화는 종종 WinRM을 사용하지만, SSH는 대부분의 팀이 일상적으로 디버깅하는 경로입니다. Ansible 플레이북이 연결 오류로 실패하면, 거의 항상 제어 머신과 대상 호스트 간의 표준 SSH 설정에 근본적인 문제가 있음을 나타냅니다. 이러한 실패를 체계적으로 진단하는 방법을 이해하는 것은 안정적인 자동화를 유지하는 데 중요합니다.
1단계: 상세 출력 활성화 및 초기 확인
가장 빠른 방법은 출력 상세도를 높이는 것입니다. SSH 오류는 종종 가려지지만, 최대 상세도는 Ansible이 사용하는 정확한 매개변수와 기본 OpenSSH 클라이언트가 반환하는 특정 오류 메시지를 보여줍니다.
상세 플래그 사용
테스트 명령 또는 플레이북을 세 개 또는 네 개의 상세 플래그(-v, -vv, -vvv, -vvvv)와 함께 실행하세요. 대부분의 연결 문제는 -vvv 출력을 검토하여 해결됩니다.
# 인벤토리에 정의된 'webserver' 호스트에 대한 연결 테스트
ansible webserver -m ansible.builtin.ping -vvv
# 최대 디버깅으로 플레이북 실행
ansible-playbook site.yml -i inventory.ini -vvvv
인벤토리 및 호스트 상태 확인
대상 호스트가 올바르게 정의되고 연결 가능한지 확인하세요.
- 호스트 이름이 올바른가? 인벤토리 파일(
/etc/ansible/hosts또는 사용자 정의 인벤토리)에서 철자를 다시 확인하세요. - 대상이 켜져 있는가? 관리 노드가 전원이 켜져 있고 네트워크에서 액세스 가능한지 확인하세요.
- 인벤토리 변수가 올바른가?
ansible_host(IP 주소 또는 호스트 이름) 및ansible_user(원격 사용자 이름)와 같은 필수 변수가 대상 그룹 또는 호스트에 대해 올바르게 설정되었는지 확인하세요.
# 인벤토리 예시
[webservers]
web1 ansible_host=192.168.1.100 ansible_user=deploy_user ansible_port=22
2단계: 기본 수동 연결 확인
Ansible이 연결할 수 없는 경우, 첫 번째 단계는 항상 Ansible이 사용하도록 구성된 것과 동일한 사용자, 키 및 포트를 사용하여 표준 SSH가 수동으로 작동하는지 확인하는 것입니다.
수동 SSH 테스트
특정 사용자(ansible_user)와 특정 개인 키(ansible_ssh_private_key_file)를 사용하는 경우 해당 연결을 수동으로 복제하세요.
# 표준 SSH 테스트(기본 포트 및 키 사용 시)
ssh <ansible_user>@<ansible_host>
# 기본이 아닌 개인 키 및 포트를 사용한 테스트
ssh -i /path/to/private/key -p 2222 [email protected]
수동 SSH 테스트가 실패하면 먼저 수정하세요. Ansible은 동일한 SSH 경로를 래핑할 뿐이므로 SSH가 작동하기 전에 플레이북 구문을 디버깅하는 것은 일반적으로 시간 낭비입니다.
3단계: 인증 오류 진단
인증 오류는 Ansible 연결 문제의 가장 일반적인 원인입니다. 일반적으로 Authentication failed 또는 Permission denied 오류로 나타납니다.
3.1 키 권한 및 위치
Ansible이 SSH 키를 사용하는 경우, 제어 머신에서 개인 키 파일의 권한이 올바르게 제한되어 있는지 확인하세요. SSH는 종종 너무 허용적인 키를 거부합니다.
# 개인 키 파일에 올바른 권한 설정
chmod 600 /path/to/private/key
또한 SSH 에이전트를 사용하는 경우 키가 추가되었는지 확인하세요:
# 필요한 경우 에이전트 시작
eval "$(ssh-agent -s)"
# 에이전트에 키 추가
ssh-add /path/to/private/key
3.2 비밀번호 프롬프트 실패(시간 초과/비밀번호 누락)
설정에 비밀번호가 필요한 경우(프로덕션에서는 권장되지 않지만 실습 환경에서는 일반적), Ansible에 비밀번호를 제공해야 합니다. 연결이 중단되거나 시간 초과되면 Ansible이 제공되지 않은 비밀번호를 기다리고 있을 가능성이 높습니다.
--ask-pass 또는 -k 플래그를 사용하여 SSH 연결 비밀번호를 입력하라는 메시지를 표시하세요:
ansible webserver -m ansible.builtin.ping -k
3.3 원격 승인 키
개인 키에 해당하는 공개 키가 관리 노드의 ~/.ssh/authorized_keys 파일에 올바르게 설치되어 있는지, 원격 측의 파일 및 디렉토리 권한(.ssh는 700, authorized_keys는 600)이 올바른지 확인하세요.
4단계: 호스트 키 오류 해결
Ansible은 원격 서버의 디지털 지문을 저장하는 known_hosts 파일을 존중합니다. 관리 노드의 호스트 키가 변경되면(예: 재구축 또는 IP 재할당으로 인해), SSH 연결 시도는 중간자 공격처럼 보이는 경고와 함께 실패합니다.
Host key verification failed 오류
이 오류가 발생하면 충돌하는 키 항목을 업데이트하거나 제거해야 합니다.
- 오류 출력에 언급된
~/.ssh/known_hosts에서 줄 번호를 확인하세요. ssh-keygen을 사용하여 항목을 제거하세요.
# <hostname_or_ip>를 실제 실패하는 호스트로 바꾸세요
ssh-keygen -R <hostname_or_ip>
⚠️ 보안 경고: 호스트 확인 비활성화
임시 테스트 또는 호스트 불안정이 예상되는 고도로 통제된 실습 환경의 경우, Ansible이 호스트 키 확인을 무시하도록 구성할 수 있습니다. 이는 MITM 공격에 노출되므로 프로덕션 환경에서는 강력히 권장되지 않습니다.
ansible.cfg(또는 임시 환경 변수)에서:[defaults] host_key_checking = False
5단계: 네트워크, 방화벽 및 원격 환경 문제
때로는 SSH가 연결되지만 네트워크 구성 또는 대상 머신의 제한으로 인해 연결이 중단되거나 실패합니다.
5.1 방화벽 차단
프롬프트 없이 연결 시간이 초과되면 방화벽이 연결 시도를 차단하고 있을 가능성이 높습니다. 세 지점에서 방화벽을 확인하세요:
- 로컬(제어 머신): 포트 22(또는 사용자 정의 포트)의 아웃바운드 트래픽이 허용되는지 확인하세요.
- 네트워크 경로: 중간 네트워크 ACL이나 회사 방화벽이 트래픽을 차단하지 않는지 확인하세요.
- 원격(관리 노드): 원격 호스트의 방화벽(
firewalld,ufw등)에 SSH(일반적으로 포트 22)가 열려 있고 올바른 네트워크 인터페이스에 대해 구성되어 있는지 확인하세요.
5.2 Python 인터프리터 오류
Ansible은 모듈을 실행하기 위해 관리 노드에 Python 인터프리터가 필요합니다. 엄밀히 말해 SSH 실패는 아니지만, Ansible의 초기 연결 단계에는 팩트 수집이 포함되며, 이는 Python 스크립트 실행입니다. 대상 머신이 Python 3 없이 최소 설치된 경우 설정 단계에서 연결이 실패할 수 있습니다.
대상이 Python 3을 사용하지만 인터프리터 경로가 비표준인 경우(예: python3 대신 python3.8), 인벤토리에서 올바른 경로를 지정하세요:
[target_host]
ansible_python_interpreter=/usr/bin/python3.8
5.3 SELinux 또는 AppArmor 컨텍스트
드문 경우지만, RHEL/CentOS/Fedora의 SELinux 또는 Ubuntu/Debian의 AppArmor와 같은 지나치게 엄격한 보안 모듈이 SSH 세션 중에 원격 사용자의 셸 프로필이나 디렉토리 권한에 올바르게 액세스하지 못하게 할 수 있습니다. SSH 또는 사용자 홈 디렉토리 액세스와 관련된 AVC 거부에 대해 원격 호스트의 감사 로그(/var/log/audit/audit.log 또는 이와 동등한 파일)를 확인하세요.
실제 Ansible 실패의 일반적인 패턴
오류 텍스트는 일반적으로 검사해야 할 계층을 알려줍니다. UNREACHABLE!과 함께 Permission denied (publickey)는 Failed to connect to the host via ssh: Connection timed out과 같은 문제가 아닙니다. 첫 번째는 SSH 데몬이 응답했지만 자격 증명 경로를 수락하지 않았음을 의미합니다. 두 번째는 TCP 연결이 완료되지 않았거나 방화벽이 자동으로 차단했음을 의미합니다.
클라우드 인스턴스를 관리하는 경우 키를 변경하기 전에 기본 사용자 이름을 확인하세요. Amazon Linux는 일반적으로 ec2-user, Ubuntu는 ubuntu, Debian은 종종 admin 또는 debian을 사용하며, 사용자 정의 이미지는 완전히 다른 것을 사용할 수 있습니다. 올바른 키라도 원격 사용자 이름이 잘못되면 여전히 공개 키 실패가 발생합니다. 가장 빠른 확인 방법은:
ssh -i key.pem [email protected]
ssh -i key.pem [email protected]
배스천 호스트의 경우, 모든 실행이 동일한 경로를 사용하도록 인벤토리에서 점프 경로를 명시적으로 지정하세요:
[private_web]
web1 ansible_host=10.0.10.25 ansible_user=ubuntu
[private_web:vars]
ansible_ssh_common_args='-o [email protected]'
랩톱에서는 작동하지만 CI에서 실패하는 경우, CI 실행기의 SSH 버전, 개인 키 권한, known hosts 파일 및 실행기가 배스천에 도달할 수 있는지 비교하세요. CI 실패는 종종 Ansible 문제가 전혀 아닙니다. 실행기가 단순히 동일한 네트워크 경로나 에이전트 로드 키를 가지고 있지 않은 것입니다.
또 다른 패턴은 권한 상승이 연결 실패와 혼동되는 것입니다. SSH는 성공하지만 become에 sudo 비밀번호가 필요하거나 원격 사용자가 명령을 실행할 수 없기 때문에 플레이북이 중단됩니다. 이를 별도로 테스트하세요:
ansible web1 -m ansible.builtin.command -a "whoami" -vvv
ansible web1 -b -m ansible.builtin.command -a "whoami" -vvv
첫 번째 명령이 로그인 사용자를 반환하고 두 번째 명령이 실패하면 SSH 계층은 정상입니다. 키를 편집하는 대신 sudoers, ansible_become_password 또는 권한 모델을 수정하세요.
두 번 확인할 가치가 있는 인벤토리 변수
Ansible에는 비슷하게 들리는 여러 변수 이름이 있으며, 인터넷의 오래된 예제로 인해 더 혼란스러울 수 있습니다. 새 인벤토리에서는 현재 ansible_user, ansible_host, ansible_port, ansible_private_key_file 및 ansible_ssh_common_args 이름을 선호하세요. 인벤토리에 이전 이름과 새 이름이 모두 있거나 동일한 호스트가 여러 그룹에 나타나는 경우, 파일을 직접 읽는 대신 ansible-inventory --host web1을 사용하여 확인된 결과를 확인하세요.
또한 ansible_connection이 예상치 못한 곳에 설정되었는지 확인하세요. 네트워크 장치, 컨테이너, 로컬 프로비저닝 작업 및 Windows 호스트는 기본 SSH 이외의 연결 플러그인을 사용할 수 있습니다. ansible_connection=local이 있는 호스트는 원격 SSH를 전혀 테스트하지 않습니다. WinRM을 사용하는 Windows 호스트는 의도적으로 Windows에서 OpenSSH를 구성하지 않은 한 SSH 문제로 디버깅해서는 안 됩니다.
대규모 인벤토리의 경우 전체 플레이북을 실행하기 전에 하나의 호스트를 격리하세요:
ansible web1 -i inventory.ini -m ansible.builtin.ping -vvv
ansible-playbook site.yml -i inventory.ini --limit web1 --check -vvv
이렇게 하면 출력을 읽을 수 있게 유지하고 시끄러운 배치 실행이 중요한 한 줄을 숨기는 것을 방지할 수 있습니다.
일반적인 연결 오류 및 해결 방법 요약
| 오류 메시지 | 가능한 원인 | 실행 가능한 수정 |
|---|---|---|
Permission denied (publickey). |
키가 인식되지 않거나 키 권한이 잘못됨. | 개인 키에 chmod 600; 원격 호스트에서 공개 키 확인. |
Host key verification failed. |
호스트 키가 변경되었거나 known_hosts 파일이 손상됨. | ssh-keygen -R hostname을 사용하여 이전 항목 제거. |
Connection timed out. |
방화벽 차단 또는 호스트가 다운되었거나 연결할 수 없음. | 수동 연결 확인(ping, ssh); 대상 호스트의 방화벽 규칙 확인. |
| 연결이 중단되거나 지연됨. | 제공되지 않은 비밀번호 입력을 기다리는 중. | -k로 실행하거나 키 기반 인증 구성. |
실용적인 작업 순서
Ansible SSH 실패를 디버깅할 때, 한 번에 한 계층씩 증명하려고 합니다. 먼저 ansible-inventory --host <name> 또는 ansible-inventory --graph를 실행하여 Ansible이 실제로 보는 변수를 확인합니다. 인벤토리 놀라움은 흔합니다: 그룹 변수가 ansible_user를 재정의하거나, 동적 인벤토리가 개인 주소를 반환하거나, 호스트가 다른 ansible_port를 가진 그룹으로 이동되었습니다.
그런 다음 -vvv가 암시하는 정확한 SSH 명령을 복사합니다. 출력에 -o Port=2222 -o IdentityFile=/keys/deploy.pem -l ubuntu 10.0.4.18이 표시되면 해당 조합을 수동으로 테스트합니다. Ansible이 다른 키, 포트, 호스트 이름 또는 SSH 구성을 사용하는 경우 성공적인 ssh [email protected]만으로는 충분하지 않습니다.
수동 SSH는 작동하지만 Ansible이 실패하는 경우, Ansible 특정 동작을 찾습니다: ~/.ansible/cp 아래의 오래된 SSH 멀티플렉싱 소켓, 잘못된 인터프리터를 가리키는 인벤토리 변수, 연결 중단으로 오인되는 become 프롬프트, 또는 랩톱에 있는 것과 동일한 SSH 에이전트 없이 CI에서 실행되는 플레이북. 디버그 출력에 ControlMaster 또는 ControlPath가 언급된 경우 ~/.ansible/cp/*를 제거하는 것이 안전한 테스트입니다. 이렇게 하면 새 SSH 세션이 강제로 생성됩니다.
한 가지 유용한 트릭은 연결과 모듈 실행을 분리하는 것입니다. ansible host -m ansible.builtin.raw -a "whoami" -vvv는 일반 모듈보다 적은 원격 Python 지원이 필요합니다. raw는 작동하지만 ping이 실패하면 네트워크와 SSH 경로는 괜찮을 가능성이 높으며, 문제는 대상의 Python 검색, 권한 또는 셸 환경 문제일 가능성이 높습니다.
프로덕션 인벤토리의 경우 호스트 그룹 옆에 연결 가정을 문서화하세요: 예상 원격 사용자, 키 소스, 배스천 경로, SSH 포트 및 호스트 키 확인이 적용되는지 여부. 모든 사람이 디버그 로그에서 역공학하는 대신 실패한 실행을 의도된 경로와 비교할 수 있으면 다음 중단이 더 쉬워집니다.