aws ec2에서 Hadoop을 설치할 때
- 개발관련팁/Hadoop
- 2013. 2. 14.
ec2를 할당 받을 때 사용하는 기본 host 이름을 사용하면, 해당 host로 접근하기가 상당히 불편하기 때문에 보통은 아래와 같이 host 명과 도메인 명을 설정하게 된다.
- hostname 변경
- sudo hostname -F t001
- domain 변경
- /etc/resolv.conf 맨 마지막에
- search recopick.com
그런 다음 아래와 같이 FQDN을 확인할 수 있다.
$ hostname –f
t001.recopick.com
그리고 난 다음, https://kr.dnsever.com/ 와 같은 서비스를 통해 원하는 도메인을 특정 ip로 mapping을 시켜주면 된다.
ec2의 경우, elastic IP를 연결하거나, 혹은 nslookup 을 통해 해당 instance의 public ip를 찾아 연결하면 편리하다.
이 상태에서 바로 Hadoop을 설치하고 실행하면 아래와 같은 오류가 뜬다.
---------------------------------------------------------
2013-02-07 16:42:54,867 ERROR org.apache.hadoop.hdfs.server.namenode.NameNode: java.net.BindException: Problem binding to t001.recopick.com/54.*.*.143:9000 : Cannot assign requested address
at org.apache.hadoop.ipc.Server.bind(Server.java:227)
at org.apache.hadoop.ipc.Server$Listener.<init>(Server.java:301)
at org.apache.hadoop.ipc.Server.<init>(Server.java:1483)
at org.apache.hadoop.ipc.RPC$Server.<init>(RPC.java:545)
at org.apache.hadoop.ipc.RPC.getServer(RPC.java:506)
at org.apache.hadoop.hdfs.server.namenode.NameNode.initialize(NameNode.java:294)
at org.apache.hadoop.hdfs.server.namenode.NameNode.<init>(NameNode.java:496)
at org.apache.hadoop.hdfs.server.namenode.NameNode.createNameNode(NameNode.java:1279)
at org.apache.hadoop.hdfs.server.namenode.NameNode.main(NameNode.java:1288)
Caused by: java.net.BindException: Cannot assign requested address
at sun.nio.ch.Net.bind(Native Method)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:126)
at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:59)
at org.apache.hadoop.ipc.Server.bind(Server.java:225)
... 8 more
---------------------------------------------------------
이는 ec2에서 public ip를 binding 하려고 시도하면 오류가 발생하기 때문이다. 아래와 같은 간단한 파이썬 스크립트를 통해 확인할 수 있다.
#!/usr/bin/env python
import socket
hostList =['10.*.*.223','ip-10-*-*-223.ap-northeast-1.compute.internal','54.*.*.143','ec2-54-*-*-143.ap-northeast-1.compute.amazonaws.com','t001.recopick.com']
port = 5000
for host in hostList:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.close()
port += 1
print "success %s:%d"%( host, port)
except :
print "fail %s:%d"%( host, port)
실행결과:
success 10.*.*.223:5001
success ip-10-*-*-223.ap-northeast-1.compute.internal:5002
fail 54.*.*.143:5002
success ec2-54-*-*-143.ap-northeast-1.compute.amazonaws.com:5003
fail t001.recopick.com:5004
private ip, private dns, public dns는 binding이 되지만, public ip(elastic ip)는 binding이 안 된다. (아마 ec2의 특성인 듯?) public dns의 경우, 외부에서 조회를 하면, public ip가 뜨지만, 내부에서 조회를 하면, private ip가 뜨기 때문에 binding이 되는 것 같다. 하여간 public ip로 바로 binding이 안되면 상당히 귀찮은 일들이 많이 발생한다. (apache hadoop의 namenode도 실행이 안되고, CDH hadoop도 제대로 실행이 안 된다)
어떻게 해결할까?
각 host 별로 /etc/hosts 파일의 마지막에 아래와 같은 라인을 추가한다.
10.*.*.223 t001.recopick.com t001
이렇게 추가되면, t001 혹은 t001.recopick.com 에 대해서는 private ip를 받아오기 때문에, 정상적으로 binding이 되고, 하둡의 namenode 오류도 해결이 된다.