aws ec2에서 Hadoop을 설치할 때

ec2를 할당 받을 때 사용하는 기본 host 이름을 사용하면, 해당 host로 접근하기가 상당히 불편하기 때문에 보통은 아래와 같이 host 명과 도메인 명을 설정하게 된다.

  1. hostname 변경
    • sudo hostname -F t001
  2. 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 오류도 해결이 된다. 미소

댓글

Designed by JB FACTORY