2014-10-30 210 views
6

命令:任何獲得hadoop中nameservice的活動namenode的命令?

hdfs haadmin -getServiceState machine-98 

只有當你知道機器名的作品。有沒有像任何命令:

hdfs haadmin -getServiceState <nameservice> 

它可以告訴你活躍名稱節點的IP /主機名?

+1

+1:好問題。最可能的答案是「不」。即使沒有HA,也沒有命令顯示namenode的主機名/ ip ASFAIK。 'hdfs dfsadmin -report'只顯示數據節點。有解決方法,但是。 – blackSmith 2014-10-30 10:35:36

回答

11

要打印出namenodes使用這個命令:

hdfs getconf -namenodes 

要打印出二次namenodes:

hdfs getconf -secondaryNameNodes 

要打印出來的備份namenodes:

hdfs getconf -backupNodes 

注意:這些命令使用Hadoop 2.4.0進行測試。

更新 2014年10月31日:

這裏是一個Python腳本,將讀取配置文件中涉及的Hadoop HA的NameNodes,並確定它們中的哪是使用HDFS haadmin命令活躍。由於我沒有配置高可用性,因此該腳本未完全測試。只使用基於Hadoop HA文檔的示例文件來測試解析。隨意使用並根據需要進行修改。

#!/usr/bin/env python 
# coding: UTF-8 
import xml.etree.ElementTree as ET 
import subprocess as SP 
if __name__ == "__main__": 
    hdfsSiteConfigFile = "/etc/hadoop/conf/hdfs-site.xml" 

    tree = ET.parse(hdfsSiteConfigFile) 
    root = tree.getroot() 
    hasHadoopHAElement = False 
    activeNameNode = None 
    for property in root: 
     if "dfs.ha.namenodes" in property.find("name").text: 
      hasHadoopHAElement = True 
      nameserviceId = property.find("name").text[len("dfs.ha.namenodes")+1:] 
      nameNodes = property.find("value").text.split(",") 
      for node in nameNodes: 
       #get the namenode machine address then check if it is active node 
       for n in root: 
        prefix = "dfs.namenode.rpc-address." + nameserviceId + "." 
        elementText = n.find("name").text 
        if prefix in elementText: 
         nodeAddress = n.find("value").text.split(":")[0]     

         args = ["hdfs haadmin -getServiceState " + node] 
         p = SP.Popen(args, shell=True, stdout=SP.PIPE, stderr=SP.PIPE) 

         for line in p.stdout.readlines(): 
          if "active" in line.lower(): 
           print "Active NameNode: " + node 
           break; 
         for err in p.stderr.readlines(): 
          print "Error executing Hadoop HA command: ",err 
      break    
    if not hasHadoopHAElement: 
     print "Hadoop High-Availability configuration not found!" 
+1

啊,這不會告訴我活動的namenode,是嗎? – Dragonborn 2014-10-31 06:31:53

+1

@Dragonborn我錯過了關於HA正在使用的部分。回答用python腳本更新以解析hdfs配置並針對每臺機器運行haadmin命令。腳本會報告哪些是活動的。 – 2014-10-31 18:52:26

+1

+1教導一個新的命令。但他們應該爲此提供了一個直接的途徑。即使是活動的namenode名稱後的'*'也足夠了。 – blackSmith 2014-11-05 07:38:51

4

你也可以用hdfs cli調用bash來做到這一點。有一點需要注意的是,這需要多一點時間,因爲它是連續調用API的一些方法,但這可能更適合使用python腳本。

這是用Hadoop 2.6.0

get_active_nn(){ 
    ha_name=$1 #Needs the NameServiceID 
    ha_ns_nodes=$(hdfs getconf -confKey dfs.ha.namenodes.${ha_name}) 
    active="" 
    for node in $(echo ${ha_ns_nodes//,/ }); do 
    state=$(hdfs haadmin -getServiceState $node) 
    if [ "$state" == "active" ]; then 
     active=$(hdfs getconf -confKey dfs.namenode.rpc-address.${ha_name}.${node}) 
     break 
    fi 
    done 
    if [ -z "$active" ]; then 
    >&2 echo "ERROR: no active namenode found for ${ha_name}" 
    exit 1 
    else 
    echo $active 
    fi 
} 
+1

如何編程(java,scala任何東西),但只使用API​​調用。 – Sohaib 2015-10-20 16:42:57

+0

試試HAUtil.getAddressOfActive(FileSystem fs) – Lhfcws 2017-03-02 09:53:40

11

測試發現這一點:

https://gist.github.com/cnauroth/7ff52e9f80e7d856ddb3

這工作了我CDH5 namenodes箱子,雖然我不知道其他的Hadoop分配將有http://namenode:50070/jmx可用 - 如果沒有,我認爲可以通過部署Jolokia添加。

實施例:

curl 'http://namenode1.example.com:50070/jmx?qry=Hadoop:service=NameNode,name=NameNodeStatus' 
{ 
    "beans" : [ { 
    "name" : "Hadoop:service=NameNode,name=NameNodeStatus", 
    "modelerType" : "org.apache.hadoop.hdfs.server.namenode.NameNode", 
    "State" : "active", 
    "NNRole" : "NameNode", 
    "HostAndPort" : "namenode1.example.com:8020", 
    "SecurityEnabled" : true, 
    "LastHATransitionTime" : 1436283324548 
    } ] 

所以通過燒製關閉一個http請求到每個名稱節點(這應該是快速),我們可以計算出哪一個是活動的一個。

另外值得一提的是,如果你跟WebHDFS REST API到無效的NameNode,你會得到一個403禁止和下面的JSON:

{"RemoteException":{"exception":"StandbyException","javaClassName":"org.apache.hadoop.ipc.StandbyException","message":"Operation category READ is not supported in state standby"}} 
+0

嗨..你知道如何連接到啓用了Kerberos的NameNode JMX嗎?我們在curl命令之前運行了kinit。但是我們得到了一個無法連接的錯誤 – myloginid 2015-11-20 10:23:59

+0

也許http://www.cloudera.com/content/www/en-us/documentation/archive/cdh/4-x/4-3-2/CDH4-Security-Guide/ cdh4sg_topic_7_2.html可以幫助你嗎? – 2015-11-21 11:20:28

1

閱讀所有現有的答案後,似乎沒有這三個步驟的結合:

  1. 確定集羣中的名稱節點。
  2. 將節點名稱解析爲host:port。
  3. 檢查每個節點的狀態(不需要 羣集管理權限)。

以下解決方案將調用和JMX服務調用組合爲節點狀態。

#!/usr/bin/env python 

from subprocess import check_output 
import urllib, json, sys 

def get_name_nodes(clusterName): 
    ha_ns_nodes=check_output(['hdfs', 'getconf', '-confKey', 
     'dfs.ha.namenodes.' + clusterName]) 
    nodes = ha_ns_nodes.strip().split(',') 
    nodeHosts = [] 
    for n in nodes: 
     nodeHosts.append(get_node_hostport(clusterName, n)) 

    return nodeHosts 

def get_node_hostport(clusterName, nodename): 
    hostPort=check_output(
     ['hdfs','getconf','-confKey', 
     'dfs.namenode.rpc-address.{0}.{1}'.format(clusterName, nodename)]) 
    return hostPort.strip() 

def is_node_active(nn): 
    jmxPort = 50070 
    host, port = nn.split(':') 
    url = "http://{0}:{1}/jmx?qry=Hadoop:service=NameNode,name=NameNodeStatus".format(
      host, jmxPort) 
    nnstatus = urllib.urlopen(url) 
    parsed = json.load(nnstatus) 

    return parsed.get('beans', [{}])[0].get('State', '') == 'active' 

def get_active_namenode(clusterName): 
    for n in get_name_nodes(clusterName): 
     if is_node_active(n): 
      return n 

clusterName = (sys.argv[1] if len(sys.argv) > 1 else None) 
if not clusterName: 
    raise Exception("Specify cluster name.") 

print 'Cluster: {0}'.format(clusterName) 
print "Nodes: {0}".format(get_name_nodes(clusterName)) 
print "Active Name Node: {0}".format(get_active_namenode(clusterName)) 
0

在高可用性Hadoop集羣中,將有2個名稱節點 - 一個活動節點和一個備用節點。

要找到活動的namenode,我們可以嘗試在每個namenode上執行test hdfs命令,並找到與成功運行相對應的活動名稱節點。

如果名稱節點處於活動狀態,則下面的命令執行成功,而如果它是備用節點,則命令失敗。

hadoop fs -test -e hdfs://<Name node>/ 

的Unix腳本

active_node='' 
if hadoop fs -test -e hdfs://<NameNode-1>/ ; then 
active_node='<NameNode-1>' 
elif hadoop fs -test -e hdfs://<NameNode-2>/ ; then 
active_node='<NameNode-2>' 
fi 

echo "Active Dev Name node : $active_node"