Hadoop ssh 포트 거부
문제 상황 요약
하둡 설정을 바꾸고 재시작하는데 다음과 같은 오류가 발생했습니다.
C:\\Users\\SSAFY>docker exec -it namenode /bin/bash
root@9b739a460d5e:/# $HADOOP_HOME/sbin/stop-all.sh
Stopping namenodes on [9b739a460d5e]
9b739a460d5e: ssh: connect to host 9b739a460d5e port 22: Connection refused
이러한 문제의 원인은 크게 세가지로 파악했습니다.
- Hadoop은 SSH를 통해 노드 간 통신을 수행하는데, 현재 컨테이너에서 SSH 서버가 실행되고 있지 않음.
- stop-all.sh 또는 start-all.sh 스크립트는 내부적으로 ssh 명령어를 사용하여 노드에 접근하려고 하는데, 현재 SSH 포트(22번)로 연결이 거부됨.
- Docker 컨테이너는 기본적으로 SSH 서버가 활성화된 상태로 시작되지 않음.
SSH 포트란?
암호화된 통신을 제공하여 원격 시스템에 연결할 때 사용되는 네트워크 포트로, 인터넷을 통해 서버나 다른 컴퓨터에 안전하게 접근할 수 있게 해주는 프로토콜입니다.
해결 방법
i) ssh 설정을 해놓은 경우
service ssh start
ssh를 키고 다시 해보면 됨
ii) ssh 설정을 해 놓지 않은 경우
1. Docker 컨테이너 내부에서 SSH 서버를 설치하고 실행
apt-get update apt-get install -y openssh-server service ssh start
하지만 여기서 오류가 발생한다면 다음과 같은 단계를 밟아야한다...
🚨 SSH 명령어 부재 해결
컨테이너에 SSH 클라이언트와 서버가 아예 없어서, 저장소 주소를 변경하고 다시 설치..
docker exec -it python-namenode-1 bash -c "echo 'deb http://archive.debian.org/debian/ stretch main' > /etc/apt/sources.list"
docker exec -it python-namenode-1 bash -c "echo 'deb http://archive.debian.org/debian-security stretch/updates main' >> /etc/apt/sources.list"
docker exec -it python-namenode-1 apt-get update
docker exec -it python-namenode-1 apt-get install -y openssh-server
이걸 실행한 다음 다시 service ssh start로 SSH를 실행
2. SSH 키 생성 및 설정
SSH 접속을 위해 컨테이너 내부에서 SSH 키를 생성하고, 인증을 설정
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 0600 ~/.ssh/authorized_keys
이제 컨테이너 내에서 SSH 인증이 가능하다.
3. SSH 설정 변경
기본적으로 SSH 설정이 PermitRootLogin no로 되어 있을 수 있어서, 이를 허용하도록 수정했어.
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
service ssh restart
이제 root 계정으로 SSH 로그인할 수 있도록 설정하였다.
4. SSH localhost 접속 테스트
SSH가 정상 작동하는지 확인하기 위해 컨테이너 내에서 localhost로 접속 시도를 했다.
ssh localhost
이 단계에서 처음 접속하면 호스트 키를 확인하는 메시지가 나오는데, yes 입력 후 진행하면 됨.
5. Hadoop SSH 설정 변경
Hadoop의 노드 간 통신을 자동화하기 위해서 Hadoop이 SSH를 사용할 때 호스트 키 검사를 건너뛰도록 설정하였습니다.
이 설정을 하면 Hadoop이 마스터 노드에서 워커 노드로 SSH 접속할 때 자동으로 진행되기 때문에, start-all.sh 실행 시 오류 없이 클러스터가 정상적으로 시작할 수 있습니다.
echo "Host *
StrictHostKeyChecking no
UserKnownHostsFile=/dev/null" > $HADOOP_HOME/etc/hadoop/ssh_config
그리고 .bashrc 파일에 환경 변수를 추가했습니다.
SSH가 항상 22번 포트를 사용하도록 하는 명령어를 작성하였습니다.
echo "export HADOOP_SSH_OPTS=\"-p 22\"" >> ~/.bashrc
여기서 export ~ 를 감싸는 부분을 큰따옴표가 아니라, 작은따옴표로 설정하게 된다면
6. HADOOP_HOME 설정
$HADOOP_HOME/sbin/stop-all.sh
$HADOOP_HOME/sbin/start-all.sh
만약 하둡홈이 설정되어있지않다면 오류 발생...
export HADOOP_HOME=/usr/local/hadoop # Hadoop 설치 경로에 맞게 수정
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
잘 설정되었나 확인
echo $HADOOP_HOME
echo $PATH
7. Hadoop 서비스 재시작
컨테이너 재시작
$HADOOP_HOME/sbin/start-all.sh
오류발생
DESKTOP-USLS0BK: ssh: connect to host desktop-usls0bk port 22: Connection refused
7. SSH 연결 문제 해결
먼저 컨테이너 내에서 SSH가 제대로 실행 중인지 확인하는 작업을 하였다.
root@9b739a460d5e:/# service ssh status
[ ok ] sshd is running.
root@9b739a460d5e:/# cat /etc/ssh/sshd_config | grep Port
#Port 22
#GatewayPorts no
root@9b739a460d5e:/# ssh localhost
Linux 9b739a460d5e 5.15.153.1-microsoft-standard-WSL2 #1 SMP Fri Mar 29 23:14:13 UTC 2024 x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Sep 24 01:07:51 2024 from ::1
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
root@9b739a460d5e:~# hostname -I
172.20.0.3
root@9b739a460d5e:~# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.20.0.3 9b739a460d5e
70.12.247.135 DESKTOP-USLS0BK DESKTOP-USLS0BK.mshome.net
정상 실행 중이었고, 포트도 기본값 22으로 잘 설정되어있는 것을 확인할 수 있었다.
ssh localhost는 정상적으로 작동했는데, Windows에서 컨테이너로 접속하려고 하면 오류가 났다.
C:\Users\SSAFY>ssh root@172.20.0.3
ssh: connect to host 172.20.0.3 port 22: Connection timed out
즉, Windows에서 컨테이너 내부로 SSH 접속이 막혀 있었기 때문이었다.
8. 방화벽 설정 변경
Windows Defender 방화벽에서 TCP 22번 포트를 허용하는 규칙을 추가
- 고급 보안이 포함된 Windows Defender 방화벽 열기
- 인바운드 규칙 → 새 규칙 만들기
- 포트 → TCP 22 선택
- 연결 허용 선택
- 규칙 이름: SSH 22 설정 후 완료
파워쉘에서 포트를 허용하는 지 확인이 가능하다.
PS C:\Windows\system32> Get-NetFirewallRule -Direction Inbound | Where-Object { $_.DisplayName -like '*SSH*' -or $_.LocalPort -eq '22' }
Name : {B44F827C-536E-47D1-8768-7E3FFC9AF6BE}
DisplayName : ssh 22
Description :
DisplayGroup :
Group :
Enabled : True
Profile : Any
Platform : {}
Direction : Inbound
Action : Allow
EdgeTraversalPolicy : Block
LooseSourceMapping : False
LocalOnlyMapping : False
Owner :
PrimaryStatus : OK
Status : 저장소에서 규칙을 구문 분석했습니다. (65536)
EnforcementStatus : NotApplicable
PolicyStoreSource : PersistentStore
PolicyStoreSourceType : Local
RemoteDynamicKeywordAddresses :
PolicyAppId :
22번 포트열려있는 지 확인 (아무것도 안 떴으니 안열린거임)
C:\Users\SSAFY>netstat -an | findstr ":22"
C:\Users\SSAFY>docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9b739a460d5e bde2020/hadoop-namenode:2.0.0-hadoop3.2.1-java8 "/entrypoint.sh /bin…" 3 days ago Up 2 minutes (unhealthy) 0.0.0.0:9000->9000/tcp, 0.0.0.0:9870->9870/tcp namenode
SSH 데몬이 해당 포트에서 정상적으로 실행되지 않았을 가능성 있다고 판단하였다..
*데몬: 시스템에서 백그라운드로 실행되는 프로그램을 의미
9. SSH 접속이 가능한 새로운 컨테이너 설정
컨테이너에 SSH 서버가 없어서 22번 포트를 열 수 없고, 이로 인해 SSH 연결이 안 되는 상태이므로 SSH 서버를 컨테이너에 설치하고, SSH 서비스가 작동하도록 설정하였다.
docker exec -it namenode bash
apt-get update
apt-get install -y openssh-server
service ssh start
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
service ssh restart
SSH 서버를 설치하고, SSH 서비스가 실행되도록 설정해주며, root 사용자 로그인도 가능하도록 설정하였다.
(컨테이너 내부) SSH 접속을 위해 root 사용자의 비밀번호가 필요하기 때문에 비밀번호도 설정해준다.
passwd root
exit
Docker의 포트 포워딩 기능을 이용해 22번 포트를 호스트의 2222번 포트로 매핑하여 외부에서 접근 가능하도록 만든다.
여기서 2222포트를 사용하는 이유는 호스트 시스템에서 이 포트를 사용할 수 없거나 다른 서비스와 충돌할 수 있기 때문이다.
호스트 시스템에서 이미 22번 포트를 사용하고 있어서, 컨테이너에서 22번 포트를 사용할 수 없으므로, 다른 포트(여기서는 2222번 포트)를 사용하였다.
→ 컨테이너에서 22번 포트로 SSH 서비스를 실행하고, 호스트 시스템에서는 2222번 포트로 접근하도록 설정하여 두 포트가 충돌하지 않고, SSH 연결을 할 수 있도록 함
다음 명령어로 새로운 포트 포워딩을 추가한다. 포워딩을 했으므로, 호스트 시스템에서 2222번 포트로 들어오는 트래픽은 자동으로 컨테이너의 22번 포트로 전달되어 SSH 연결을 허용하게 된다.
* 포워딩: 호스트 시스템과 컨테이너 간에 네트워크 트래픽을 특정 포트를 통해 전달하는 방식
docker stop namenode # 기존 컨테이너 중지
docker commit namenode namenode-with-ssh # 기존 컨테이너의 상태를 새 이미지로 저장
docker run -d --name namenode-new -p 9000:9000 -p 9870:9870 -p 2222:22 --volumes-from namenode namenode-with-ssh # 새 컨테이너 실행
기존 컨테이너의 볼륨을 새 컨테이너와 공유하여 데이터 손실을 방지하였다.
기존에는 22번 포트가 열려 있지 않아서 SSH 접속이 안 되었지만, 새 컨테이너에서는 포트 포워딩이 설정되어 있으므로, SSH로 접속이 가능해졌다.
ssh root@localhost -p 2222