HDFS 高可用性

目的

このガイドでは、HDFS高可用性(HA)機能の概要と、NameNodeに必要な共有ストレージにNFSを使用して、HA HDFSクラスタを構成および管理する方法について説明します。

このドキュメントでは、読者がHDFSクラスタの一般的なコンポーネントとノードタイプについて一般的な理解を持っていることを前提としています。詳細は、HDFSアーキテクチャガイドを参照してください。

注記: Quorum Journal Managerまたは従来の共有ストレージの使用

このガイドでは、共有NFSディレクトリを使用してアクティブとスタンバイのNameNode間で編集ログを共有することにより、HDFS HAを構成および使用する方法について説明します。NFSの代わりにQuorum Journal Managerを使用してHDFS HAを構成する方法については、こちらの代替ガイドを参照してください。

背景

Hadoop 2.0.0より前は、NameNodeはHDFSクラスタの単一障害点(SPOF)でした。各クラスタには単一のNameNodeがあり、そのマシンまたはプロセスが利用できなくなった場合、NameNodeが再起動されるか、別のマシンで起動されるまで、クラスタ全体が利用できなくなりました。

これは、HDFSクラスタの全体的な可用性に、主に2つの方法で影響を与えました。

  • マシンクラッシュなどの計画外のイベントの場合、オペレーターがNameNodeを再起動するまで、クラスタは使用できませんでした。

  • NameNodeマシンでのソフトウェアまたはハードウェアのアップグレードなどの計画的なメンテナンスイベントにより、クラスタのダウンタイムが発生しました。

HDFS高可用性機能は、アクティブ/パッシブ構成でホットスタンバイを使用して、同じクラスタ内で2つ(Hadoop 3.0.0以降はそれ以上)の冗長NameNodeを実行するオプションを提供することにより、上記の課題に対処します。これにより、マシンクラッシュが発生した場合に新しいNameNodeに迅速にフェイルオーバーしたり、計画メンテナンスのために管理者が開始したグレースフルフェイルオーバーを行うことができます。

アーキテクチャ

典型的なHAクラスタでは、2つ以上の別々のマシンがNameNodeとして構成されます。常に、NameNodeのうちの1つだけが*アクティブ*状態になり、残りは*スタンバイ*状態になります。アクティブNameNodeはクラスタ内のすべてのクライアント操作を担当しますが、スタンバイは単にスレーブとして機能し、必要に応じて高速フェイルオーバーを提供できるだけの状態を維持します。

スタンバイノードがアクティブノードと状態を同期させるために、現在の実装では、ノードが共有ストレージデバイス(たとえば、NASからのNFSマウント)上のディレクトリにアクセスできる必要があります。この制限は、将来のバージョンで緩和される可能性があります。

アクティブノードによって名前空間の変更が実行されると、変更のレコードが共有ディレクトリに保存されている編集ログファイルに永続的に記録されます。スタンバイノードはこのディレクトリを常に監視して編集を確認し、編集を確認すると、独自の名前空間に適用します。フェイルオーバーが発生した場合、スタンバイは、アクティブ状態に昇格する前に、共有ストレージからすべての編集を読み取ったことを確認します。これにより、フェイルオーバーが発生する前に、名前空間の状態が完全に同期されます。

高速フェイルオーバーを提供するには、スタンバイノードがクラスタ内のブロックの場所に関する最新の情報を持っていることも必要です。これを達成するために、DataNodeはすべてのNameNodeの場所で構成され、すべてのNameNodeにブロックの場所情報とハートビートを送信します。

HAクラスタが正しく動作するには、一度に1つのNameNodeだけがアクティブであることが不可欠です。そうでない場合、名前空間の状態は2つの間で急速に異なり、データの損失やその他の誤った結果のリスクが生じます。この特性を確保し、いわゆる「スプリットブレインシナリオ」を防ぐために、管理者は共有ストレージに少なくとも1つの*フェンシング方法*を構成する必要があります。フェイルオーバー中に、以前のアクティブノードがアクティブ状態を放棄したことを確認できない場合、フェンシングプロセスは、以前のアクティブの共有編集ストレージへのアクセスを遮断する役割を担います。これにより、名前空間がさらに編集されるのを防ぎ、新しいアクティブが安全にフェイルオーバーを進めることができます。

ハードウェアリソース

HAクラスタをデプロイするには、以下を準備する必要があります。

  • NameNodeマシン - アクティブおよびスタンバイNameNodeを実行するマシンは、互いに同等のハードウェア、およびHA以外のクラスタで使用されるものと同等のハードウェアを持っている必要があります。

  • 共有ストレージ - NameNodeマシンが読み取り/書き込みアクセスできる共有ディレクトリが必要です。通常、これはNFSをサポートし、各NameNodeマシンにマウントされているリモートファイラーです。現在、サポートされている共有編集ディレクトリは1つだけです。したがって、システムの可用性は、この共有編集ディレクトリの可用性によって制限されるため、すべての単一障害点を削除するには、共有編集ディレクトリの冗長性が必要です。具体的には、ストレージへの複数のネットワークパス、およびストレージ自体(ディスク、ネットワーク、および電源)の冗長性です。このため、共有ストレージサーバーは、単純なLinuxサーバーではなく、高品質の専用NASアプライアンスであることが推奨されます。

HAクラスタでは、スタンバイNameNodeも名前空間の状態のチェックポイントを実行するため、HAクラスタでセカンダリNameNode、チェックポイントノード、またはバックアップノードを実行する必要はありません。実際、そうすることはエラーになります。これにより、HA対応ではないHDFSクラスタをHA対応に再構成する際に、以前にセカンダリNameNode専用にしていたハードウェアを再利用することもできます。

デプロイメント

構成の概要

フェデレーション構成と同様に、HA構成は下位互換性があり、既存の単一NameNode構成をそのまま変更せずに使用できます。新しい構成は、ノードのタイプに基づいて異なる構成ファイルを異なるマシンにデプロイする必要なく、クラスタ内のすべてのノードが同じ構成を持つことができるように設計されています。

HDFSフェデレーションと同様に、HAクラスタは*ネームサービスID*を再利用して、実際には複数のHA NameNodeで構成される単一のHDFSインスタンスを識別します。さらに、HAでは*NameNode ID*と呼ばれる新しい抽象化が追加されます。クラスタ内の個別のNameNodeごとに、それを区別するための異なるNameNode IDがあります。すべてのNameNodeの単一の構成ファイルをサポートするために、関連する構成パラメータには、*ネームサービスID*と*NameNode ID*が付加されます。

構成の詳細

HA NameNodeを構成するには、*hdfs-site.xml*構成ファイルにいくつかの構成オプションを追加する必要があります。

これらの構成を設定する順序は重要ではありませんが、**dfs.nameservices**および**dfs.ha.namenodes.[ネームサービスID]**に選択した値によって、以下のキーが決まります。したがって、残りの構成オプションを設定する前に、これらの値を決定する必要があります。

  • **dfs.nameservices** - この新しいネームサービスの論理名

    このネームサービスの論理名(たとえば、「mycluster」)を選択し、この論理名をこの構成オプションの値として使用します。選択する名前は任意です。構成と、クラスタ内の絶対HDFSパスの認証コンポーネントの両方で使用されます。

    注記: HDFS Federationも使用している場合、この設定には、他のネームサービス(HAまたはその他)のリストをカンマ区切りで含める必要があります。

    <property>
      <name>dfs.nameservices</name>
      <value>mycluster</value>
    </property>
    
  • dfs.ha.namenodes.[ネームサービスID] - ネームサービス内の各NameNodeの一意の識別子

    カンマ区切りのNameNode IDのリストで設定します。これは、DataNodeがクラスタ内のすべてのNameNodeを特定するために使用されます。たとえば、以前にネームサービスIDとして「mycluster」を使用し、NameNodeの個々のIDとして「nn1」、「nn2」、「nn3」を使用する場合、次のように設定します。

    <property>
      <name>dfs.ha.namenodes.mycluster</name>
      <value>nn1,nn2,nn3</value>
    </property>
    

    注記: HAのNameNodeの最小数は2つですが、それ以上設定することもできます。通信オーバーヘッドのため、5を超えないようにすることをお勧めします(推奨は3 NameNode)。

  • dfs.namenode.rpc-address.[ネームサービスID].[ネームノードID] - 各NameNodeがリッスンする完全修飾RPCアドレス

    以前に設定した両方のNameNode IDについて、NameNodeプロセスの完全なアドレスとIPCポートを設定します。これは2つの別々の設定オプションになります。例:

    <property>
      <name>dfs.namenode.rpc-address.mycluster.nn1</name>
      <value>machine1.example.com:8020</value>
    </property>
    <property>
      <name>dfs.namenode.rpc-address.mycluster.nn2</name>
      <value>machine2.example.com:8020</value>
    </property>
    <property>
      <name>dfs.namenode.rpc-address.mycluster.nn3</name>
      <value>machine3.example.com:8020</value>
    </property>
    

    注記: 必要に応じて、「servicerpc-address」設定も同様に設定できます。

  • dfs.namenode.http-address.[ネームサービスID].[ネームノードID] - 各NameNodeがリッスンする完全修飾HTTPアドレス

    上記のrpc-addressと同様に、両方のNameNodeのHTTPサーバーがリッスンするアドレスを設定します。例:

    <property>
      <name>dfs.namenode.http-address.mycluster.nn1</name>
      <value>machine1.example.com:9870</value>
    </property>
    <property>
      <name>dfs.namenode.http-address.mycluster.nn2</name>
      <value>machine2.example.com:9870</value>
    </property>
    <property>
      <name>dfs.namenode.http-address.mycluster.nn3</name>
      <value>machine3.example.com:9870</value>
    </property>
    

    注記: Hadoopのセキュリティ機能が有効になっている場合は、各NameNodeに対して同様にhttps-addressを設定する必要があります。

  • dfs.namenode.shared.edits.dir - 共有ストレージディレクトリの場所

    これは、Standby NameNodeがActive NameNodeが行うすべてのファイルシステムの変更を最新の状態に保つために使用するリモート共有編集ディレクトリへのパスを設定する場所です。これらのディレクトリのうち1つだけを設定する必要があります。 このディレクトリは、NameNodeマシンにr/wでマウントする必要があります。この設定の値は、NameNodeマシン上のこのディレクトリへの絶対パスである必要があります。例:

    <property>
      <name>dfs.namenode.shared.edits.dir</name>
      <value>file:///mnt/filer1/dfs/ha-name-dir-shared</value>
    </property>
    
  • dfs.client.failover.proxy.provider.[ネームサービスID] - HDFSクライアントがActive NameNodeに接続するために使用するJavaクラス

    DFSクライアントがどのNameNodeが現在アクティブであるか、したがってどのNameNodeが現在クライアント要求を処理しているかを判断するために使用されるJavaクラスの名前を設定します。現在Hadoopに付属している2つの実装は、ConfiguredFailoverProxyProviderRequestHedgingProxyProvider(最初の呼び出しでは、すべてのアクティブなネームノードを同時に呼び出してアクティブなネームノードを決定し、後続の要求では、フェイルオーバーが発生するまでアクティブなネームノードを呼び出します)です。カスタムプロキシプロバイダーを使用していない限り、これらのいずれかを使用してください。

    <property>
      <name>dfs.client.failover.proxy.provider.mycluster</name>
      <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
    </property>
    
  • dfs.ha.fencing.methods - フェイルオーバー中にActive NameNodeをフェンスするために使用されるスクリプトまたはJavaクラスのリスト

    システムの正確性を確保するために、常に1つのNameNodeのみがアクティブ状態であることが重要です。したがって、フェイルオーバー中は、別のNameNodeをアクティブ状態に移行する前に、まずActive NameNodeがスタンバイ状態であるか、プロセスが終了していることを確認します。これを行うには、少なくとも1つのフェンシング方法を設定する必要があります。これらは、改行区切りのリストとして設定され、フェンシングが成功したことを示すまで順番に試行されます。Hadoopには、shellsshfenceの2つの方法が付属しています。独自のカスタムフェンシング方法を実装する方法については、org.apache.hadoop.ha.NodeFencerクラスを参照してください。


    sshfence - Active NameNodeにSSH接続してプロセスを強制終了する

    sshfenceオプションは、ターゲットノードにSSH接続し、fuserを使用してサービスのTCPポートでリッスンしているプロセスを強制終了します。このフェンシングオプションが機能するには、パスフレーズを提供せずにターゲットノードにSSH接続できる必要があります。したがって、SSH秘密鍵ファイルのカンマ区切りリストであるdfs.ha.fencing.ssh.private-key-filesオプションも設定する必要があります。例:

        <property>
          <name>dfs.ha.fencing.methods</name>
          <value>sshfence</value>
        </property>
    
        <property>
          <name>dfs.ha.fencing.ssh.private-key-files</name>
          <value>/home/exampleuser/.ssh/id_rsa</value>
        </property>
    

    必要に応じて、SSHを実行するための標準以外のユーザー名またはポートを設定できます。また、SSHのタイムアウト(ミリ秒単位)を設定することもできます。タイムアウトを超えると、このフェンシング方法は失敗したと見なされます。次のように設定できます。

    <property>
      <name>dfs.ha.fencing.methods</name>
      <value>sshfence([[username][:port]])</value>
    </property>
    <property>
      <name>dfs.ha.fencing.ssh.connect-timeout</name>
      <value>30000</value>
    </property>
    

    shell - 任意のシェルコマンドを実行してActive NameNodeをフェンスする

    shellフェンシング方法は、任意のシェルコマンドを実行します。次のように設定できます。

    <property>
      <name>dfs.ha.fencing.methods</name>
      <value>shell(/path/to/my/script.sh arg1 arg2 ...)</value>
    </property>
    

    「(」と「)」の間の文字列はbashシェルに直接渡され、閉じ括弧を含めることはできません。

    シェルコマンドは、現在のすべてのHadoop設定変数が含まれるように設定された環境で実行されます。設定キーの「.」文字は「_」文字に置き換えられます。使用される設定では、ネームノード固有の設定がすでに汎用形式に昇格されています。たとえば、dfs.namenode.rpc-address.ns1.nn1として変数を指定した場合でも、dfs_namenode_rpc-addressにはターゲットノードのRPCアドレスが含まれます。

    さらに、フェンスされるターゲットノードを参照する次の変数も使用できます。

    $target_host フェンスされるノードのホスト名
    $target_port フェンスされるノードのIPCポート
    $target_address 上記の2つをhost:portとして組み合わせたもの
    $target_nameserviceid フェンスされるNNのネームサービスID
    $target_namenodeid フェンスされるNNのネームノードID

    これらの環境変数は、シェルコマンド自体で置換としても使用できます。例:

    <property>
      <name>dfs.ha.fencing.methods</name>
      <value>shell(/path/to/my/script.sh --nameservice=$target_nameserviceid $target_host:$target_port)</value>
    </property>
    

    シェルコマンドが終了コード0を返すと、フェンシングは成功したと判断されます。他の終了コードが返された場合、フェンシングは失敗し、リストの次のフェンシング方法が試行されます。

    注記: このフェンシング方法はタイムアウトを実装していません。タイムアウトが必要な場合は、シェルスクリプト自体に実装する必要があります(たとえば、サブシェルをフォークして、数秒後にその親を強制終了します)。


  • fs.defaultFS - Hadoop FSクライアントがパスプレフィックスが指定されていない場合に使用するデフォルトのパスプレフィックス

    必要に応じて、Hadoopクライアントが新しいHA対応の論理URIを使用するようにデフォルトパスを設定できます。以前にネームサービスIDとして「mycluster」を使用した場合、これはすべてのHDFSパスの認証部分の値になります。これは、core-site.xmlファイルで次のように設定できます。

    <property>
      <name>fs.defaultFS</name>
      <value>hdfs://mycluster</value>
    </property>
    
  • dfs.ha.nn.not-become-active-in-safemode - セーフモードのネームノードがアクティブになるのを防ぐかどうか

    セーフモードのネームノードがアクティブになるのを許可するかどうか。trueに設定すると、セーフモードのネームノードは、自動フェイルオーバーがオンの場合、ZKFCにSERVICE_UNHEALTHYを報告します。自動フェイルオーバーがオフの場合は、例外をスローしてアクティブへの移行を失敗させます。例:

    <property>
      <name>dfs.ha.nn.not-become-active-in-safemode</name>
      <value>true</value>
    </property>
    

デプロイメントの詳細

必要なすべての設定オプションを設定したら、最初に2つのHA NameNodeのオンディスクメタデータを同期する必要があります。

  • 新しいHDFSクラスタをセットアップする場合は、最初にいずれかのNameNodeでフォーマットコマンド(hdfs namenode -format)を実行する必要があります。

  • NameNodeをすでにフォーマットしている場合、またはHA対応でないクラスタをHA対応に変換する場合は、フォーマットされていないNameNodeで「hdfs namenode -bootstrapStandby」コマンドを実行して、NameNodeメタデータディレクトリのコンテンツを他のフォーマットされていないNameNodeにコピーする必要があります。このコマンドを実行すると、共有編集ディレクトリ(dfs.namenode.shared.edits.dirで設定)に、両方のNameNodeを起動できるのに十分な編集トランザクションが含まれていることも確認されます。

  • HAではないNameNodeをHAに変換する場合は、「hdfs -initializeSharedEdits」コマンドを実行する必要があります。これにより、ローカルNameNode編集ディレクトリからの編集データで共有編集ディレクトリが初期化されます。

この時点で、NameNodeを通常どおり起動するのと同じように、すべてのHA NameNodeを起動できます。

設定されたHTTPアドレスを参照することで、各NameNodeのWebページを個別に表示できます。設定されたアドレスの横には、NameNodeのHA状態(「スタンバイ」または「アクティブ」)が表示されます。HA NameNodeが起動すると、最初はスタンバイ状態になります。

管理コマンド

HA NameNodeが設定され、起動したので、HA HDFSクラスタを管理するため追加のコマンドにアクセスできるようになります。具体的には、「hdfs haadmin」コマンドのすべてのサブコマンドに精通する必要があります。追加の引数を指定せずにこのコマンドを実行すると、次の使用法情報が表示されます。

Usage: DFSHAAdmin [-ns <nameserviceId>]
    [-transitionToActive <serviceId>]
    [-transitionToStandby <serviceId>]
    [-failover [--forcefence] [--forceactive] <serviceId> <serviceId>]
    [-getServiceState <serviceId>]
    [-getAllServiceState]
    [-checkHealth <serviceId>]
    [-help <command>]

このガイドでは、これらの各サブコマンドの使用方法の概要について説明します。各サブコマンドの具体的な使用方法については、「hdfs haadmin -help <command>」を実行してください。

  • transitionToActiveおよびtransitionToStandby - 指定されたNameNodeの状態をアクティブまたはスタンバイに移行する

    これらのサブコマンドは、指定されたNameNodeをそれぞれアクティブ状態またはスタンバイ状態に移行させます。これらのコマンドはフェンシングを実行しようとしないため、めったに使用しないでください。 代わりに、ほとんどの場合、「hdfs haadmin -failover」サブコマンドを使用することをお勧めします。

  • failover - 2つのNameNode間のフェイルオーバーを開始する

    このサブコマンドは、最初に指定されたNameNodeから2番目に指定されたNameNodeへのフェイルオーバーを引き起こします。最初のNameNodeがスタンバイ状態の場合、このコマンドはエラーなしで2番目のNameNodeをアクティブ状態に移行します。最初のNameNodeがアクティブ状態の場合、それを正常にスタンバイ状態に移行しようとします。これが失敗した場合、フェンシング方法(dfs.ha.fencing.methodsで設定)が成功するまで順番に試行されます。このプロセスが完了した後でのみ、2番目のNameNodeがアクティブ状態に移行されます。フェンシング方法が成功しない場合、2番目のNameNodeはアクティブ状態に移行されず、エラーが返されます。

  • getServiceState - 指定されたNameNodeがアクティブかスタンバイかを判別する

    指定されたNameNodeに接続して現在の状態を判断し、STDOUTに「スタンバイ」または「アクティブ」を適切に出力します。このサブコマンドは、NameNodeが現在アクティブかスタンバイかによって動作が異なる必要があるcronジョブまたは監視スクリプトで使用できます。

  • getAllServiceState - すべてのNameNodeの状態を返す

    設定されたNameNodeに接続して現在の状態を判断し、STDOUTに「スタンバイ」または「アクティブ」を適切に出力します。

  • checkHealth - 指定されたNameNodeのヘルスチェックを実行する

    指定されたNameNodeに接続して、そのヘルスチェックを実行します。NameNodeは、内部サービスが期待どおりに実行されているかどうかを確認するなど、自身でいくつかの診断を実行できます。このコマンドは、NameNodeが正常な場合は0を返し、それ以外の場合は0以外を返します。このコマンドは監視目的で使用できます。

    注記: これはまだ実装されておらず、現時点では、指定されたNameNodeが完全にダウンしている場合を除き、常に成功を返します。

自動フェイルオーバー

はじめに

上記のセクションでは、手動フェイルオーバーの構成方法について説明しています。そのモードでは、アクティブノードに障害が発生した場合でも、システムはアクティブNameNodeからスタンバイNameNodeへのフェイルオーバーを自動的にトリガーしません。このセクションでは、自動フェイルオーバーの構成とデプロイ方法について説明します。

コンポーネント

自動フェイルオーバーは、HDFSデプロイメントに2つの新しいコンポーネントを追加します。ZooKeeperクォーラムとZKFailoverControllerプロセス(ZKFCと略記)です。

Apache ZooKeeperは、少量の調整データを維持し、クライアントにそのデータの変更を通知し、クライアントの障害を監視するための高可用性サービスです。HDFSの自動フェイルオーバーの実装は、次の点でZooKeeperに依存しています。

  • 障害検出 - クラスタ内の各NameNodeマシンは、ZooKeeperで永続セッションを維持します。マシンがクラッシュすると、ZooKeeperセッションが期限切れになり、他のNameNodeにフェイルオーバーをトリガーする必要があることが通知されます。

  • アクティブNameNodeの選出 - ZooKeeperは、ノードをアクティブとして排他的に選出するための簡単なメカニズムを提供します。現在のアクティブNameNodeがクラッシュした場合、別のノードがZooKeeperで特別な排他ロックを取得して、次のアクティブになる必要があることを示す場合があります。

ZKFailoverController(ZKFC)は、ZooKeeperクライアントであり、NameNodeの状態を監視および管理する新しいコンポーネントです。NameNodeを実行する各マシンはZKFCも実行し、そのZKFCは次の役割を担います。

  • ヘルスモニタリング - ZKFCは、ヘルスチェックコマンドを使用して、定期的にローカルNameNodeにpingを送信します。NameNodeが正常な状態でタイムリーに応答する限り、ZKFCはそのノードを正常と見なします。ノードがクラッシュ、フリーズ、またはその他の異常な状態になった場合、ヘルスモニターはそれを異常とマークします。

  • ZooKeeperセッション管理 - ローカルNameNodeが正常な場合、ZKFCはZooKeeperでセッションを開いたままにします。ローカルNameNodeがアクティブな場合、特別な「ロック」znodeも保持します。このロックは、ZooKeeperの「ephemeral」ノードのサポートを使用します。セッションが期限切れになると、ロックノードは自動的に削除されます。

  • ZooKeeperベースの選出 - ローカルNameNodeが正常であり、ZKFCが他のノードが現在ロックznodeを保持していないことを確認した場合、ZKFC自体がロックの取得を試みます。成功した場合、それは「選出に勝利」し、ローカルNameNodeをアクティブにするためのフェイルオーバーを実行する責任を負います。フェイルオーバープロセスは、上記の手動フェイルオーバーと似ています。最初に、必要に応じて以前のアクティブノードがフェンスされ、次にローカルNameNodeがアクティブ状態に移行します。

自動フェイルオーバーの設計の詳細については、Apache HDFS JIRAのHDFS-2185に添付されている設計ドキュメントを参照してください。

ZooKeeperのデプロイ

典型的なデプロイメントでは、ZooKeeperデーモンは3つまたは5つのノードで実行するように構成されます。ZooKeeper自体はリソース要件が軽いため、ZooKeeperノードをHDFS NameNodeおよびスタンバイノードと同じハードウェアに配置することは許容されます。多くの運用担当者は、3番目のZooKeeperプロセスをYARN ResourceManagerと同じノードにデプロイすることを選択します。最適なパフォーマンスと分離を実現するために、ZooKeeperノードがHDFSメタデータとは別のディスクドライブにデータを格納するように構成することをお勧めします。

ZooKeeperのセットアップはこのドキュメントの範囲外です。3つ以上のノードで実行されているZooKeeperクラスターをセットアップし、ZK CLIを使用してその正常な動作を確認済みであると想定します。

始める前に

自動フェイルオーバーの構成を開始する前に、クラスターをシャットダウンする必要があります。現在、クラスターの実行中に手動フェイルオーバー設定から自動フェイルオーバー設定に移行することはできません。

自動フェイルオーバーの構成

自動フェイルオーバーの構成には、構成に2つの新しいパラメーターを追加する必要があります。 hdfs-site.xmlファイルに、以下を追加します。

 <property>
   <name>dfs.ha.automatic-failover.enabled</name>
   <value>true</value>
 </property>

これは、クラスターが自動フェイルオーバー用に設定されることを指定します。 core-site.xmlファイルに、以下を追加します。

 <property>
   <name>ha.zookeeper.quorum</name>
   <value>zk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181</value>
 </property>

これは、ZooKeeperサービスを実行しているホストとポートのペアを一覧表示します。

ドキュメントの前半で説明したパラメーターと同様に、これらの設定は、構成キーにネームサービスIDをサフィックスとして付けることで、ネームサービスごとに構成できます。たとえば、フェデレーションが有効になっているクラスターでは、dfs.ha.automatic-failover.enabled.my-nameservice-idを設定することにより、ネームサービスの1つに対してのみ自動フェイルオーバーを明示的に有効にできます。

自動フェイルオーバーの動作を制御するために設定できる他の構成パラメーターもいくつかありますが、ほとんどのインストールでは必要ありません。詳細については、構成キーの特定のドキュメントを参照してください。

ZooKeeperでのHA状態の初期化

構成キーが追加された後、次の手順はZooKeeperで必要な状態を初期化することです。これを行うには、NameNodeホストの1つから次のコマンドを実行します。

[hdfs]$ $HADOOP_HOME/bin/zkfc -formatZK

これにより、ZooKeeperにznodeが作成され、自動フェイルオーバーシステムはその中にデータを格納します。

start-dfs.shを使用したクラスターの起動

構成で自動フェイルオーバーが有効になっているため、start-dfs.shスクリプトは、NameNodeを実行するマシンでZKFCデーモンを自動的に起動するようになります。ZKFCが起動すると、アクティブになるNameNodeの1つが自動的に選択されます。

クラスターの手動起動

クラスター上のサービスを手動で管理する場合、NameNodeを実行する各マシンでzkfcデーモンを手動で起動する必要があります。デーモンを起動するには、以下を実行します。

[hdfs]$ $HADOOP_HOME/bin/hdfs --daemon start zkfc

ZooKeeperへのアクセスの保護

セキュアなクラスターを実行している場合は、ZooKeeperに格納されている情報も保護されていることを確認する必要があります。これにより、悪意のあるクライアントがZooKeeperのメタデータを変更したり、誤ったフェイルオーバーを発生させたりするのを防ぎます。

ZooKeeperの情報 bảo vệるには、最初にcore-site.xmlファイルに以下を追加します。

 <property>
   <name>ha.zookeeper.auth</name>
   <value>@/path/to/zk-auth.txt</value>
 </property>
 <property>
   <name>ha.zookeeper.acl</name>
   <value>@/path/to/zk-acl.txt</value>
 </property>

これらの値の「@」文字に注意してください。これは、構成がインラインではなく、ディスク上のファイルを指していることを示します。認証情報は、CredentialProviderを介して読み取ることもできます(hadoop-commonプロジェクトのCredentialProviderAPIガイドを参照してください)。

最初に構成されたファイルは、ZK CLIで使用されるのと同じ形式で、ZooKeeper認証のリストを指定します。たとえば、次のようなものを指定できます。

digest:hdfs-zkfcs:mypassword

…ここで、hdfs-zkfcsはZooKeeperの一意のユーザー名であり、mypasswordはパスワードとして使用される一意の文字列です。

次に、次のようなコマンドを使用して、この認証に対応するZooKeeper ACLを生成します。

[hdfs]$ java -cp $ZK_HOME/lib/*:$ZK_HOME/zookeeper-3.4.2.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider hdfs-zkfcs:mypassword
output: hdfs-zkfcs:mypassword->hdfs-zkfcs:P/OQvnYyU/nF/mGYvB/xurX8dYs=

この出力の「->」文字列の後の部分をコピーして、文字列「digest:」を前に付けてzk-acls.txtファイルに貼り付けます。例えば

digest:hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=:rwcda

これらのACLを有効にするには、上記のようにzkfc -formatZKコマンドを再実行する必要があります。

その後、次のようにZK CLIからACLを確認できます。

[zk: localhost:2181(CONNECTED) 1] getAcl /hadoop-ha
'digest,'hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=
: cdrwa

自動フェイルオーバーの確認

自動フェイルオーバーが設定されたら、その動作をテストする必要があります。そのためには、まずアクティブなNameNodeを見つけます。NameNodeのWebインターフェースにアクセスすることで、どのノードがアクティブであるかを確認できます。各ノードは、ページの上部にHA状態を報告します。

アクティブなNameNodeを見つけたら、そのノードで障害を発生させることができます。たとえば、kill -9 <NNのpid>を使用してJVMクラッシュをシミュレートできます。または、マシンの電源を再投入したり、ネットワークインターフェースを取り外したりして、別の種類の停止をシミュレートすることもできます。テストする停止をトリガーした後、他のNameNodeは数秒以内に自動的にアクティブになるはずです。障害を検出してフェイルオーバーをトリガーするのに必要な時間は、ha.zookeeper.session-timeout.msの構成によって異なりますが、デフォルトは5秒です。

テストが成功しない場合は、構成が間違っている可能性があります。問題をさらに診断するには、zkfcデーモンとNameNodeデーモンのログを確認してください。

自動フェイルオーバーFAQ

  • ZKFCとNameNodeデーモンを特定の順序で起動することが重要ですか?

    いいえ。任意のノードで、対応するNameNodeの前後にZKFCを起動できます。

  • 他にどのような監視を実施する必要がありますか?

    NameNodeを実行する各ホストに監視を追加して、ZKFCが実行され続けていることを確認する必要があります。たとえば、ZooKeeperの特定の種類の障害では、ZKFCが予期せず終了する可能性があり、システムが自動フェイルオーバーの準備ができていることを確認するために再起動する必要があります。

    さらに、ZooKeeperクォーラムの各サーバーを監視する必要があります。ZooKeeperがクラッシュすると、自動フェイルオーバーは機能しません。

  • ZooKeeperがダウンするとどうなりますか?

    ZooKeeperクラスターがクラッシュした場合、自動フェイルオーバーはトリガーされません。ただし、HDFSは影響を受けることなく引き続き実行されます。ZooKeeperが再起動されると、HDFSは問題なく再接続します。

  • NameNodeの1つをプライマリ/優先として指定できますか?

    いいえ。現在、これはサポートされていません。最初に起動されたNameNodeがアクティブになります。優先ノードが最初に起動するように、特定の順序でクラスターを起動することを選択できます。

  • 自動フェイルオーバーが構成されている場合、手動フェイルオーバーをどのように開始できますか?

    自動フェイルオーバーが構成されている場合でも、同じhdfs haadminコマンドを使用して手動フェイルオーバーを開始できます。調整されたフェイルオーバーが実行されます。