Gerir clusters do HDInsight com a API REST do Apache Ambari

Saiba como utilizar a API REST do Apache Ambari para gerir e monitorizar clusters do Apache Hadoop no Azure HDInsight.

O que é o Apache Ambari

O Apache Ambari simplifica a gestão e monitorização de clusters do Hadoop ao fornecer uma IU Web fácil de utilizar com as respetivas APIs REST. O Ambari é fornecido por predefinição com clusters do HDInsight baseados em Linux.

Pré-requisitos

Identificador de Recursos Uniforme Base para a API REST do Ambari

O URI (Uniform Resource Identifier) base para a API REST do Ambari no HDInsight é https://CLUSTERNAME.azurehdinsight.net/api/v1/clusters/CLUSTERNAME, onde CLUSTERNAME é o nome do cluster. Os nomes dos clusters em URIs são sensíveis a maiúsculas e minúsculas. Embora o nome do cluster na parte do nome de domínio completamente qualificado (FQDN) do URI (CLUSTERNAME.azurehdinsight.net) não seja sensível a maiúsculas e minúsculas, outras ocorrências no URI são sensíveis a maiúsculas e minúsculas.

Autenticação

A ligação ao Ambari no HDInsight requer HTTPS. Utilize o nome da conta de administrador (a predefinição é administrador) e a palavra-passe que forneceu durante a criação do cluster.

Para clusters do Pacote de Segurança Empresarial, em vez de admin, utilize um nome de utilizador completamente qualificado como username@domain.onmicrosoft.com.

Exemplos

Configuração (Preservar credenciais)

Preserve as suas credenciais para evitar reintroduzi-las para cada exemplo. O nome do cluster será preservado num passo separado.

A. Bash
Edite o script abaixo ao substituir PASSWORD pela palavra-passe real. Em seguida, introduza o comando .

export password='PASSWORD'

B. PowerShell

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

Identificar o nome do cluster corretamente maiúsculas e minúsculas

O invólucro real do nome do cluster pode ser diferente do esperado. Os passos aqui irão mostrar o invólucro real e, em seguida, armazená-lo numa variável para todos os exemplos posteriores.

Edite os scripts abaixo para substituir CLUSTERNAME pelo nome do cluster. Em seguida, introduza o comando . (O nome do cluster do FQDN não é sensível a maiúsculas e minúsculas.)

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

Analisar dados JSON

O exemplo seguinte utiliza jq ou ConvertFrom-Json para analisar o documento de resposta JSON e apresentar apenas as health_report informações dos resultados.

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

Obter o FQDN dos nós de cluster

Poderá ter de saber o nome de domínio completamente qualificado (FQDN) de um nó de cluster. Pode obter facilmente o FQDN para os vários nós no cluster com os seguintes exemplos:

Todos os nós

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

Nós principais

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

Nós de trabalho

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

Nós do 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

Obter o endereço IP interno dos nós de cluster

Os endereços IP devolvidos pelos exemplos nesta secção não são diretamente acessíveis através da Internet. Só estão acessíveis no Azure Rede Virtual que contém o cluster do HDInsight.

Para obter mais informações sobre como trabalhar com o HDInsight e redes virtuais, veja Planear uma rede virtual para o HDInsight.

Para localizar o endereço IP, tem de saber o nome de domínio completamente qualificado interno (FQDN) dos nós de cluster. Assim que tiver o FQDN, pode obter o endereço IP do anfitrião. Os exemplos seguintes consultam primeiro o Ambari para o FQDN de todos os nós de anfitrião. Em seguida, consulta o Ambari para o endereço IP de cada anfitrião.

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"
}

Obter o armazenamento predefinido

Os clusters do HDInsight têm de utilizar uma Conta de Armazenamento do Azure ou Data Lake Storage como armazenamento predefinido. Pode utilizar o Ambari para obter estas informações após a criação do cluster. Por exemplo, se quiser ler/escrever dados no contentor fora do HDInsight.

Os exemplos seguintes obtêm a configuração de armazenamento predefinida do cluster:

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'

Importante

Estes exemplos devolvem a primeira configuração aplicada ao servidor (service_config_version=1) que contém estas informações. Se obter um valor que tenha sido modificado após a criação do cluster, poderá ter de listar as versões de configuração e obter a mais recente.

O valor devolvido é semelhante a um dos seguintes exemplos:

  • wasbs://CONTAINER@ACCOUNTNAME.blob.core.windows.net - Este valor indica que o cluster está a utilizar uma conta de Armazenamento do Azure para armazenamento predefinido. O ACCOUNTNAME valor é o nome da conta de armazenamento. A CONTAINER parte é o nome do contentor de blobs na conta de armazenamento. O contentor é a raiz do armazenamento compatível com HDFS para o cluster.

  • abfs://CONTAINER@ACCOUNTNAME.dfs.core.windows.net- Este valor indica que o cluster está a utilizar Azure Data Lake Storage Gen2 para armazenamento predefinido. Os ACCOUNTNAME valores e CONTAINER têm os mesmos significados que para o Armazenamento do Azure mencionado anteriormente.

  • adl://home- Este valor indica que o cluster está a utilizar Azure Data Lake Storage Gen1 para armazenamento predefinido.

    Para localizar o nome da conta Data Lake Storage, utilize os seguintes exemplos:

    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'
    

    O valor devolvido é semelhante a ACCOUNTNAME.azuredatalakestore.net, em que ACCOUNTNAME é o nome da conta Data Lake Storage.

    Para localizar o diretório no Data Lake Storage que contém o armazenamento do cluster, utilize os seguintes exemplos:

    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'
    

    O valor devolvido é semelhante a /clusters/CLUSTERNAME/. Este valor é um caminho dentro da conta Data Lake Storage. Este caminho é a raiz do sistema de ficheiros compatível com HDFS para o cluster.

Nota

O cmdlet Get-AzHDInsightCluster fornecido pelo Azure PowerShell também devolve as informações de armazenamento do cluster.

Obter todas as configurações

Obtenha as configurações que estão disponíveis para o cluster.

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

Este exemplo devolve um documento JSON que contém a configuração atual dos componentes instalados. Veja o valor da etiqueta . O exemplo seguinte é um excerto dos dados devolvidos de um tipo de cluster do Spark.

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

Obter a configuração para um componente específico

Obtenha a configuração do componente no qual está interessado. No exemplo seguinte, substitua INITIAL pelo valor da etiqueta devolvido do pedido anterior.

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

Este exemplo devolve um documento JSON que contém a configuração atual do livy2-conf componente.

Configuração da atualização

  1. Criar newconfig.json.
    Modifique e, em seguida, introduza os comandos abaixo:

    • Substitua livy2-conf pelo novo componente.

    • Substitua pelo INITIAL valor real obtido para tag de Obter todas as configurações.

      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
      O script do PowerShell utiliza jq. Edite C:\HD\jq\jq-win64 abaixo para refletir o caminho real e a versão do 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
      

      O Jq é utilizado para transformar os dados obtidos do HDInsight num novo modelo de configuração. Especificamente, estes exemplos fazem as seguintes ações:

    • Cria um valor exclusivo que contém a cadeia "versão" e a data, que é armazenada no newtag.

    • Cria um documento de raiz para a nova configuração.

    • Obtém o conteúdo da .items[] matriz e adiciona-o no elemento desired_config .

    • Elimina os hrefelementos , versione Config , uma vez que estes elementos não são necessários para submeter uma nova configuração.

    • Adiciona um tag elemento com um valor de version#################. A parte numérica baseia-se na data atual. Cada configuração tem de ter uma etiqueta exclusiva.

      Por fim, os dados são guardados no newconfig.json documento. A estrutura do documento deve ser semelhante ao seguinte exemplo:

      {
        "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. Editar newconfig.json.
    Abra o newconfig.json documento e modifique/adicione valores no properties objeto. O exemplo seguinte altera o valor de de "livy.server.csrf_protection.enabled""true" para "false".

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

    Guarde o ficheiro quando terminar de efetuar modificações.

  3. Submeta newconfig.json.
    Utilize os seguintes comandos para submeter a configuração atualizada para o 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
    

    Estes comandos submetem o conteúdo do ficheiro newconfig.json para o cluster como a nova configuração. O pedido devolve um documento JSON. O elemento versionTag neste documento deve corresponder à versão que submeteu e o objeto configs contém as alterações de configuração pedidas.

Reiniciar um componente de serviço

Neste momento, a IU da Web do Ambari indica que o serviço Spark tem de ser reiniciado antes de a nova configuração poder entrar em vigor. Utilize os seguintes passos para reiniciar o serviço.

  1. Utilize o seguinte para ativar o modo de manutenção para o serviço 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. Verificar o modo de manutenção

    Estes comandos enviam um documento JSON para o servidor que ativa o modo de manutenção. Pode verificar se o serviço está agora no modo de manutenção com o seguinte pedido:

    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
    

    O valor devolvido é ON.

  3. Em seguida, utilize o seguinte para desativar o serviço 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
    

    A resposta é semelhante ao seguinte exemplo:

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

    Importante

    O href valor devolvido por este URI está a utilizar o endereço IP interno do nó de cluster. Para utilizá-la de fora do cluster, substitua a 10.0.0.18:8080 parte pelo FQDN do cluster.

  4. Verifique o pedido.
    Edite o comando abaixo ao substituir 29 pelo valor real para id devolvido do passo anterior. Os seguintes comandos obtêm o estado do pedido:

    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
    

    Uma resposta de COMPLETED indica que o pedido foi concluído.

  5. Depois de concluído o pedido anterior, utilize o seguinte para iniciar o serviço 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
    

    O serviço está agora a utilizar a nova configuração.

  6. Por fim, utilize o seguinte para desativar o modo de manutenção.

    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"}}}'
    

Passos seguintes

Para obter uma referência completa da API REST, veja Referência da API do Apache Ambari V1. Veja também Autorizar utilizadores para as Vistas do Apache Ambari