使用 Apache Ambari REST API 來管理 HDInsight 叢集

了解如何使用 Apache Ambari REST API 來管理和監視 Azure HDInsight 中的 Apache Hadoop 叢集。

什麼是 Apache Ambari

Apache Ambari 提供由 REST API (英文) 支援的易用 Web UI,可簡化 Hadoop 叢集的管理和監視。 以 Linux 為基礎的 HDInsight 叢集預設會提供 Ambari。

必要條件

Ambari REST API 的基底統一資源識別項

Ambari REST API 在 HDInsight 上的基底統一資源識別項 (URI) 是 https://CLUSTERNAME.azurehdinsight.net/api/v1/clusters/CLUSTERNAME,其中 CLUSTERNAME 是您叢集的名稱。 URI 中的叢集名稱會區分大小寫。 URI (CLUSTERNAME.azurehdinsight.net) 完整網域名稱 (FQDN) 部分的叢集名稱會區分大小寫,URI 中的其他項目也會區分大小寫。

驗證

連線到 HDInsight 上的 Ambari 需要 HTTPS。 請使用您在叢集建立期間所提供的管理帳戶名稱 (預設值是 admin) 和密碼。

針對企業安全性套件叢集,請使用 username@domain.onmicrosoft.com 這類完整使用者名稱,而不要使用 admin

範例

設定 (保留認證)

保留認證就不必為每個範例重新輸入。 叢集名稱會在另一個步驟中予以保留。

A. Bash
編輯以下指令碼,用您的實際密碼取代 PASSWORD。 然後輸入命令。

export password='PASSWORD'

B. PowerShell

$creds = Get-Credential -UserName "admin" -Message "Enter the HDInsight login"

找出大小寫正確的叢集名稱

叢集名稱的實際大小寫可能與您預期的不同。 這裡列出的步驟會顯示實際的大小寫並將其儲存在變數中,供之後所有範例使用。

編輯以下指令碼,用您的叢集名稱取代 CLUSTERNAME。 然後輸入命令。 (FQDN 的叢集名稱不會區分大小寫)。

export clusterName=$(curl -u admin:$password -sS -G "https://CLUSTERNAME.azurehdinsight.net/api/v1/clusters" | jq -r '.items[].Clusters.cluster_name')
echo $clusterName
# Identify properly cased cluster name
$resp = Invoke-WebRequest -Uri "https://CLUSTERNAME.azurehdinsight.net/api/v1/clusters" `
    -Credential $creds -UseBasicParsing
$clusterName = (ConvertFrom-Json $resp.Content).items.Clusters.cluster_name;

# Show cluster name
$clusterName

剖析 JSON 資料

下列範例會使用 jq (英文) 或 ConvertFrom-Json 剖析 JSON 回應文件,然後只顯示結果中的 health_report 資訊。

curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName" \
| jq '.Clusters.health_report'
$resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName" `
    -Credential $creds -UseBasicParsing
$respObj = ConvertFrom-Json $resp.Content
$respObj.Clusters.health_report

取得叢集節點的 FQDN

您或許需要知道叢集節點的完整網域名稱 (FQDN)。 您可以使用下列範例,輕鬆地擷取叢集中不同節點的 FQDN:

所有節點

curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/hosts" \
| jq -r '.items[].Hosts.host_name'
$resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/hosts" `
    -Credential $creds -UseBasicParsing
$respObj = ConvertFrom-Json $resp.Content
$respObj.items.Hosts.host_name

前端節點

curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/HDFS/components/NAMENODE" \
| jq -r '.host_components[].HostRoles.host_name'
$resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/HDFS/components/NAMENODE" `
    -Credential $creds -UseBasicParsing
$respObj = ConvertFrom-Json $resp.Content
$respObj.host_components.HostRoles.host_name

背景工作節點

curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/HDFS/components/DATANODE" \
| jq -r '.host_components[].HostRoles.host_name'
$resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/HDFS/components/DATANODE" `
    -Credential $creds -UseBasicParsing
$respObj = ConvertFrom-Json $resp.Content
$respObj.host_components.HostRoles.host_name

Zookeeper 節點

curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/ZOOKEEPER/components/ZOOKEEPER_SERVER" \
| jq -r ".host_components[].HostRoles.host_name"
$resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/ZOOKEEPER/components/ZOOKEEPER_SERVER" `
    -Credential $creds -UseBasicParsing
$respObj = ConvertFrom-Json $resp.Content
$respObj.host_components.HostRoles.host_name

取得叢集節點的內部 IP 位址

本節中範例所傳回的 IP 位址無法直接透過網際網路存取, 只能在包含 HDInsight 叢集的 Azure 虛擬網路內存取。

如需進一步了解如何將 HDInsight 與虛擬網路搭配使用,請參閱為 Azure HDInsight 規劃虛擬網路

若要尋找 IP 位址,您必須知道叢集節點的內部完整網域名稱 (FQDN)。 一旦您擁有 FQDN,就可以取得主機的 IP 位址。 下列範例會先在 Ambari 查詢所有主機節點的 FQDN, 再於 Ambari 查詢每個主機的 IP 位址。

for HOSTNAME in $(curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/hosts" | jq -r '.items[].Hosts.host_name')
do
    IP=$(curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/hosts/$HOSTNAME" | jq -r '.Hosts.ip')
  echo "$HOSTNAME <--> $IP"
done
$uri = "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/hosts" 
$resp = Invoke-WebRequest -Uri $uri -Credential $creds -UseBasicParsing
$respObj = ConvertFrom-Json $resp.Content
foreach($item in $respObj.items) {
    $hostName = [string]$item.Hosts.host_name
    $hostInfoResp = Invoke-WebRequest -Uri "$uri/$hostName" `
        -Credential $creds -UseBasicParsing
    $hostInfoObj = ConvertFrom-Json $hostInfoResp
    $hostIp = $hostInfoObj.Hosts.ip
    "$hostName <--> $hostIp"
}

取得預設儲存體

HDInsight 叢集必須使用 Azure 儲存體帳戶或 Data Lake Storage 作為預設儲存體。 在建立叢集之後,您可以使用 Ambari 來擷取這項資訊。 例如,如果您想要讀取/寫入資料至 HDInsight 以外的容器。

下列範例會從叢集擷取預設儲存體組態:

curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/configurations/service_config_versions?service_name=HDFS&service_config_version=1" \
| jq -r '.items[].configurations[].properties["fs.defaultFS"] | select(. != null)'
$resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/configurations/service_config_versions?service_name=HDFS&service_config_version=1" `
    -Credential $creds -UseBasicParsing
$respObj = ConvertFrom-Json $resp.Content
$respObj.items.configurations.properties.'fs.defaultFS'

重要

這些範例會傳回套用至伺服器的第一個組態 (service_config_version=1),其包含這項資訊。 如果您擷取在叢集建立後已修改過的值,您可能需要列出組態版本並擷取最新的版本。

傳回值會類似下列其中一個範例︰

  • wasbs://CONTAINER@ACCOUNTNAME.blob.core.windows.net - 這個值表示叢集是使用 Azure 儲存體帳戶做為預設儲存體。 ACCOUNTNAME 值是儲存體帳戶的名稱。 CONTAINER 部分是儲存體帳戶中 blob 容器的名稱。 容器是叢集的 HDFS 相容儲存體的根目錄。

  • abfs://CONTAINER@ACCOUNTNAME.dfs.core.windows.net - 這個值表示叢集會使用 Azure Data Lake Storage Gen2 作為預設儲存體。 ACCOUNTNAMECONTAINER 值與先前所述的 Azure 儲存體具有相同的意義。

  • adl://home - 這個值表示叢集會使用 Azure Data Lake Storage Gen1 作為預設儲存體。

    若要尋找 Data Lake Storage 帳戶名稱,請使用下列範例:

    curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/configurations/service_config_versions?service_name=HDFS&service_config_version=1" \
    | jq -r '.items[].configurations[].properties["dfs.adls.home.hostname"] | select(. != null)'
    
    $resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/configurations/service_config_versions?service_name=HDFS&service_config_version=1" `
        -Credential $creds -UseBasicParsing
    $respObj = ConvertFrom-Json $resp.Content
    $respObj.items.configurations.properties.'dfs.adls.home.hostname'
    

    傳回值類似 ACCOUNTNAME.azuredatalakestore.net,其中 ACCOUNTNAME 是 Data Lake Storage 帳戶的名稱。

    若要在包含叢集儲存體的 Data Lake Storage 內尋找此目錄,請使用下列範例:

    curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/configurations/service_config_versions?service_name=HDFS&service_config_version=1" \
    | jq -r '.items[].configurations[].properties["dfs.adls.home.mountpoint"] | select(. != null)'
    
    $resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/configurations/service_config_versions?service_name=HDFS&service_config_version=1" `
        -Credential $creds -UseBasicParsing
    $respObj = ConvertFrom-Json $resp.Content
    $respObj.items.configurations.properties.'dfs.adls.home.mountpoint'
    

    傳回值類似 /clusters/CLUSTERNAME/。 這個值是 Data Lake Storage 帳戶內的路徑。 這個路徑是叢集的 HDFS 相容檔案系統的根目錄。

注意

Azure PowerShell 提供的 Get-AzHDInsightCluster Cmdlet 也會傳回叢集的儲存體資訊。

取得所有設定

取得可供您的叢集使用的組態。

curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName?fields=Clusters/desired_configs"
$respObj = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName`?fields=Clusters/desired_configs" `
    -Credential $creds -UseBasicParsing
$respObj.Content

此範例會傳回包含已安裝元件目前設定的 JSON 文件, 請參閱 tag 值。 下列範例是從 Spark 叢集類型傳回之資料的摘要。

"jupyter-site" : {
  "tag" : "INITIAL",
  "version" : 1
},
"livy2-client-conf" : {
  "tag" : "INITIAL",
  "version" : 1
},
"livy2-conf" : {
  "tag" : "INITIAL",
  "version" : 1
},

取得特定元件的設定

針對您感興趣的元件取得其設定。 在下列範例中,以前一個要求傳回的標記值取代 INITIAL

curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/configurations?type=livy2-conf&tag=INITIAL"
$resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/configurations?type=livy2-conf&tag=INITIAL" `
    -Credential $creds -UseBasicParsing
$resp.Content

此範例會傳回 JSON 文件,其中包含 livy2-conf 元件的目前組態。

更新 設定

  1. 建立 newconfig.json
    加以修改,然後輸入以下命令:

    • 用新的元件取代 livy2-conf

    • 用您在取得所有設定一節擷取的 tag 實際值取代 INITIAL

      A. Bash

      curl -u admin:$password -sS -G "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/configurations?type=livy2-conf&tag=INITIAL" \
      | jq --arg newtag $(echo version$(date +%s%N)) '.items[] | del(.href, .version, .Config) | .tag |= $newtag | {"Clusters": {"desired_config": .}}' > newconfig.json
      

      B. PowerShell
      PowerShell 指令碼使用 jq (英文)。 編輯以下的 C:\HD\jq\jq-win64,以反映您的實際路徑和 jq (英文) 版本。

      $epoch = Get-Date -Year 1970 -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0
      $now = Get-Date
      $unixTimeStamp = [math]::truncate($now.ToUniversalTime().Subtract($epoch).TotalMilliSeconds)
      $resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/configurations?type=livy2-conf&tag=INITIAL" `
        -Credential $creds -UseBasicParsing
      $resp.Content | C:\HD\jq\jq-win64 --arg newtag "version$unixTimeStamp" '.items[] | del(.href, .version, .Config) | .tag |= $newtag | {"Clusters": {"desired_config": .}}' > newconfig.json
      

      Jq 是用來將從 HDInsight 擷取到的資料轉換至新的組態範本。 具體來說,這些範例會執行下列動作︰

    • 建立唯一的值,其中包含字串 "version" 和日期,會儲存在 newtag

    • 為新設定建立根文件。

    • 取得 .items[] 陣列的內容,並且新增在 desired_config 元素下。

    • 刪除 hrefversionConfig 元素,因為提交新組態時不需要這些元素。

    • 使用 version################# 的值新增 tag 元素。 數字部分是根據目前的日期。 每個組態都必須有唯一的標記。

      最後,將資料儲存至 newconfig.json 文件。 此文件結構應會顯示為類似下列範例:

      {
        "Clusters": {
          "desired_config": {
            "tag": "version1552064778014",
            "type": "livy2-conf",
            "properties": {
              "livy.environment": "production",
              "livy.impersonation.enabled": "true",
              "livy.repl.enableHiveContext": "true",
              "livy.server.csrf_protection.enabled": "true",
                ....
            },
          },
        }
      }
      
  2. 編輯 newconfig.json
    開啟 newconfig.json 文件,並且在 properties 物件中修改/新增值。 下列範例會將 "livy.server.csrf_protection.enabled"的值從 "true"變更為 "false"

    "livy.server.csrf_protection.enabled": "false",
    

    完成修改之後,請儲存檔案。

  3. 提交 newconfig.json
    使用以下命令將更新的組態提交至 Ambari。

    curl -u admin:$password -sS -H "X-Requested-By: ambari" -X PUT -d @newconfig.json "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName"
    
    $newConfig = Get-Content .\newconfig.json
    $resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName" `
        -Credential $creds -UseBasicParsing `
        -Method PUT `
        -Headers @{"X-Requested-By" = "ambari"} `
        -Body $newConfig
    $resp.Content
    

    這些命令會將 newconfig.json 檔案的內容提交至叢集作為新設定。 要求會傳回 JSON 文件。 這份文件中的 versionTag 元素應符合您所提交的版本,configs 物件將會包含您所要求的組態變更。

重新啟動服務元件

在這個階段,Ambari Web UI 會指出必須重新啟動 Spark 服務,新設定才會生效。 使用下列步驟重新啟動服務。

  1. 使用以下命令啟用 Spark2 服務的維護模式:

    curl -u admin:$password -sS -H "X-Requested-By: ambari" \
    -X PUT -d '{"RequestInfo": {"context": "turning on maintenance mode for SPARK2"},"Body": {"ServiceInfo": {"maintenance_state":"ON"}}}' \
    "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/SPARK2"
    
    $resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/SPARK2" `
        -Credential $creds -UseBasicParsing `
        -Method PUT `
        -Headers @{"X-Requested-By" = "ambari"} `
        -Body '{"RequestInfo": {"context": "turning on maintenance mode for SPARK2"},"Body": {"ServiceInfo": {"maintenance_state":"ON"}}}'
    
  2. 驗證維護模式

    這些命令會將 JSON 文件傳送至伺服器,該伺服器以維護模式開啟。 您可以使用下列要求驗證服務現在處於維護模式中:

    curl -u admin:$password -sS -H "X-Requested-By: ambari" \
    "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/SPARK2" \
    | jq .ServiceInfo.maintenance_state
    
    $resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/SPARK2" `
        -Credential $creds -UseBasicParsing
    $respObj = ConvertFrom-Json $resp.Content
    $respObj.ServiceInfo.maintenance_state
    

    傳回值為 ON

  3. 接著,使用下列命令關閉 Spark2 服務:

    curl -u admin:$password -sS -H "X-Requested-By: ambari" \
    -X PUT -d '{"RequestInfo":{"context":"_PARSE_.STOP.SPARK2","operation_level":{"level":"SERVICE","cluster_name":"CLUSTERNAME","service_name":"SPARK"}},"Body":{"ServiceInfo":{"state":"INSTALLED"}}}' \
    "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/SPARK2"
    
    $resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/SPARK2" `
        -Credential $creds -UseBasicParsing `
        -Method PUT `
        -Headers @{"X-Requested-By" = "ambari"} `
        -Body '{"RequestInfo":{"context":"_PARSE_.STOP.SPARK2","operation_level":{"level":"SERVICE","cluster_name":"CLUSTERNAME","service_name":"SPARK"}},"Body":{"ServiceInfo":{"state":"INSTALLED"}}}'
    $resp.Content
    

    回應如下列範例所示:

    {
        "href" : "http://10.0.0.18:8080/api/v1/clusters/CLUSTERNAME/requests/29",
        "Requests" : {
            "id" : 29,
            "status" : "Accepted"
        }
    }
    

    重要

    這個 URI 所傳回的 href 值會使用叢集節點的內部 IP 位址。 若要在叢集外部使用此位址,請用叢集的 FQDN 取代 10.0.0.18:8080 部分。

  4. 驗證要求。
    編輯以下命令,用上一個步驟傳回的 id 實際值取代 29。 下列命令會擷取要求的狀態:

    curl -u admin:$password -sS -H "X-Requested-By: ambari" \
    "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/requests/29" \
    | jq .Requests.request_status
    
    $resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/requests/29" `
        -Credential $creds -UseBasicParsing
    $respObj = ConvertFrom-Json $resp.Content
    $respObj.Requests.request_status
    

    COMPLETED 的回應表示要求已完成。

  5. 前一項要求完成後,使用以下命令啟動 Spark2 服務。

    curl -u admin:$password -sS -H "X-Requested-By: ambari" \
    -X PUT -d '{"RequestInfo":{"context":"_PARSE_.START.SPARK2","operation_level":{"level":"SERVICE","cluster_name":"CLUSTERNAME","service_name":"SPARK"}},"Body":{"ServiceInfo":{"state":"STARTED"}}}' \
    "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/SPARK2"
    
    $resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/SPARK2" `
        -Credential $creds -UseBasicParsing `
        -Method PUT `
        -Headers @{"X-Requested-By" = "ambari"} `
        -Body '{"RequestInfo":{"context":"_PARSE_.START.SPARK2","operation_level":{"level":"SERVICE","cluster_name":"CLUSTERNAME","service_name":"SPARK"}},"Body":{"ServiceInfo":{"state":"STARTED"}}}'
    $resp.Content
    

    服務現在使用新的組態。

  6. 最後,使用以下命令來關閉維護模式。

    curl -u admin:$password -sS -H "X-Requested-By: ambari" \
    -X PUT -d '{"RequestInfo": {"context": "turning off maintenance mode for SPARK2"},"Body": {"ServiceInfo": {"maintenance_state":"OFF"}}}' \
    "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/SPARK2"
    
    $resp = Invoke-WebRequest -Uri "https://$clusterName.azurehdinsight.net/api/v1/clusters/$clusterName/services/SPARK2" `
        -Credential $creds -UseBasicParsing `
        -Method PUT `
        -Headers @{"X-Requested-By" = "ambari"} `
        -Body '{"RequestInfo": {"context": "turning off maintenance mode for SPARK2"},"Body": {"ServiceInfo": {"maintenance_state":"OFF"}}}'
    

下一步

如需 REST API 的完整參考,請參閱 Apache Ambari API 參考 V1 \(英文\)。 另請參閱授權 Apache Ambari 檢視的使用者