본문 바로가기

Hadoop

[Hadoop] Active Namenode 구하는 법

distcphadoop fs 같은 하둡 커맨드를 사용할 때 Active Namenode를 통해서 잡을 수행해야 하는데, Active/StandBy 로 Namenode가 구성되면 HA 구성된 Namenode들 중 Active Namenode를 찾아 잡을 수행시켜야 한다.

이번 포스팅은 커버로스 인증이 적용된 하둡 클러스터에서 Active Namenode를 찾아내는 몇가지 방법에 대해 정리해 보고자 한다.

1. shell을 통한 Active Namenode 구하기

//커버로스 인증이 필요할 경우 키탭을 이용하여 커버로스 티켓을 생성한다.
$ kinit -kt ${keytab_path} ${principal}
$ curl --negotiate -u : http://${namenode_domain}:50070/jmx\?qry=Hadoop:service=NameNode,name=NameNodeStatus

요청 결과

# Active Namenode일 경우
{
  "beans" : [ {
    "name" : "Hadoop:service=NameNode,name=NameNodeStatus",
    "modelerType" : "org.apache.hadoop.hdfs.server.namenode.NameNode",
    "SecurityEnabled" : true,
    "NNRole" : "NameNode",
    "HostAndPort" : "xxx:8020",
    "LastHATransitionTime" : 15667852225,
    "State" : "active"
  } ]
}%

## Standby Namenode일 경우
{
  "beans" : [ {
    "name" : "Hadoop:service=NameNode,name=NameNodeStatus",
    "modelerType" : "org.apache.hadoop.hdfs.server.namenode.NameNode",
    "State" : "standby",
    "SecurityEnabled" : true,
    "NNRole" : "NameNode",
    "HostAndPort" : "xxx:8020",
    "LastHATransitionTime" : 15667852225
  } ]
}%

요청 결과의 State를 보면 Active와 Standby를 구분할 수 있다.

2. Java를 이용한 Active Namenode 구하기

Java에서는 kerb4j 라이브러리를 이용하면 쉽게 구할 수 있다.

pom.xml

<dependencies>
    <dependency>
        <groupId>com.kerb4j</groupId>
        <artifactId>kerb4j-client</artifactId>
        <version>0.0.8</version>
    </dependency>

    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.7</version>
    </dependency>
</dependencies>

Main.Java

import com.kerb4j.client.SpnegoClient;
import com.kerb4j.client.SpnegoContext;
import org.apache.commons.io.IOUtils;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;

public class Main {
    public static final int JMX_PORT = 50070;
    public static final List<String> nameNodeList = Arrays.asList("hadoop-nn1.io", "hadoop-nn2.io");
    public static final Pattern ACTIVE_NN_PATTERN = Pattern.compile("\"State\"(\\s)*:(\\s)*\"active\"");
    public static void main(String[] args) {

        SpnegoClient spnegoClient = SpnegoClient.loginWithKeyTab("${kerberos_principal}", "${keytab_path}");



        Optional<String> activeNameNode = nameNodeList.stream().filter(nn -> {
           try {
               URL url = new URL("http://" + nn + ":" + JMX_PORT + "/jmx?qry=Hadoop:service=NameNode,name=NameNodeStatus");
               SpnegoContext spnegoContext = spnegoClient.createContext(new URL("http://" + nn));
               HttpURLConnection connection = (HttpURLConnection) url.openConnection();
               connection.setRequestProperty("Authorization", spnegoContext.createTokenAsAuthroizationHeader());
               connection.setRequestMethod("GET");

               connection.setDoOutput(true);

               if(connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                   String body = IOUtils.toString(connection.getInputStream(), "utf-8");
                   return ACTIVE_NN_PATTERN.matcher(body).find();
               }
               return false;
           }
           catch (Exception e) {
               e.printStackTrace();
               return false;
           }
        }).findFirst();

        System.out.println(activeNameNode.get());
    }
}

Spring에서는 아래의 라이브러리를 추가 한 후 SpnegoClient를 Bean으로 등록해서 쓰면 추가 설정없이 자동으로 커버로스 티켓이 갱신되어 편하게 사용할 수 있다.

<dependency>
    <groupId>org.springframework.security.kerberos</groupId>
    <artifactId>spring-security-kerberos-client</artifactId>
    <version>1.0.1.RELEASE</version>
</dependency>

<dependency>
    <groupId>com.kerb4j</groupId>
    <artifactId>kerb4j-server-spring-security</artifactId>
    <version>0.0.8</version>
</dependency>

'Hadoop' 카테고리의 다른 글

[Apache Avro] Avro 구조와 사용법  (0) 2022.02.03