YARN+Capacity Schedulerのリソース調整

前記事で説明したYARNでのメモリ設定と並列度は、Capacity Schedulerとして特に上限を定めずに、総リソースに対してフルに動作しようとする状態における説明でした。

今回は、それに対してさらにCapacity Schedulerの機能を活用して、様々な条件でリソース上限を設定する方法を記します。



Capacity Schedulerの設定ファイル

$HADOOP_CONF_DIR/capacity-scheduler.xml です。
公式の詳しい説明は
  • Hadoop Map Reduce Next Generation-0.23.1 – Capacity Scheduler
  • 設定例はこちらになります。
  • capacity-scheduler.xmlの例

  • <queue-path>について

    Capacity Schedulerにおいて最も重要な割にあまり説明がなく挫折を誘う単語がこちらになります。queueとはMTAとかにもあるあのキューと同じで、実行予定のApplicationの集まりみたいなものですが、queueはClusterに1つではなく、pathが入ることで階層構造の複数のqueueを実現しています。

    <queue-path>の部分には必ず root が入り、それより下はドット区切りで階層構造を表します。また、rootと同階層を作ることはできません。

    そしてqueue-pathとApplicationの何が関連付けられるかですが、mapred.job.queue.name になります。例えば、mapred.job.queue.name=test としてあれば、queue-path = root.test に設定されたリソース制限が適用されます。Hiveの場合は SET することで自由にqueue-pathを指定することができます。

    特別なqueue-pathに、root.default があります。これは、mapred.job.queue.name でどれにも一致しない場合に割り当てられるデフォルトqueue-pathです。

    ジョブを実行したクライアントのUNIXユーザ名は全く関係ありません


    設定プロパティの説明

    設定について説明します。まだ判明していない効果があるかもなのでその辺はご容赦を。

    Setting up queues

    yarn.scheduler.capacity.<queue-path>.queues

    階層構造を定義します。<queue-path>には必ずrootが入り、その下にドット区切りで階層を表現します。値はカンマ区切りで複数指定できます。

    例えば、yarn.scheduler.capacity.root.queues の値に gedow を入れると root.gedow が定義されます。さらに、yarn.scheduler.capacity.root.gedow.queues に father,son を入れると root.gedow.father と root.gedow.son を定義することになります。

    root は必須であり、root と同階層に別名を定義することはできません。
    ここで定義した階層に対して他の設定をしていくことになります。逆に言うと、ここで定義されていない階層に対して他の設定をすることはできません。

    Resource Allocation

    yarn.scheduler.capacity.<queue-path>.capacity

    queueごとのリソース上限割合%を設定します。これを基本上限値とでも言っておきます。root : 100 は必須で、階層ごとの合計値が 100 になるように設定する必要があります。

    特に制限をする必要がない場合は、root : 100 と root.default : 100 のみ設定しておけば、queueの区別なくリソース100%までContainerを割り当ててくれます。もし、あるキュー名 main をメイン処理としてそれ以外から影響を受けたくない場合は、root.main : 80 , root.default : 20 とすれば、mainキューは80%までリソースを消費可能で、それ以外の全てを合わせて 20%までという状態になります。

    ただし、各キューにおける上限に達しても、空きリソースがある場合は柔軟に空きリソースを割り当ててくれます(柔軟性については後述)。

    yarn.scheduler.capacity.<queue-path>.maximum-capacity

    柔軟に空きリソースを利用された場合、基本上限値を超えてリソースを消費しますが、その基本上限値を超えてくるリソースに対する上限値になります。これを絶対上限値とでも言っておきます(適当)。現在は柔軟度の仕様によりあまり意味のない設定になっています。

    yarn.scheduler.capacity.<queue-path>.minimum-user-limit-percent

    未検証です。ユーザ数によって動的に上限値を設定します。
    100 は特に制限はありません。

    25の場合を例に出します。
    1 queue の場合は 100% 利用できます。
    2 queue の場合は 1 queue 当たり 50% まで利用できます。
    3 queue の場合は 1 queue 当たり 33% まで利用できます。
    4 queue 以上の場合は 1 queue 当たり 25% まで利用できます。

    つまり、最低値はこの設定値により決定し、最大値はユーザ数によって均等に制限されていきます。

    変動の際の既存ジョブの扱いや、maximum-capacityとの関係が気になるところです。

    yarn.scheduler.capacity.<queue-path>.user-limit-factor

    基本上限値に対してさらに強制的に上限値を下げる設定で、0.0 から 1.0 のfloat値を設定します。

    capacity が 80 で user-limit-factor が 0.9 の場合、実際のcapacityは 72 になります。表示上は切り詰められたりする部分がありますが、0.95 と細かくしても有効です。

    リソースはそもそも yarn.nodemanager.resource.memory-mb で各NodeManagerが安全になる容量を設定すべきですが、それでも心配な場合は上位階層で縮めておくとよいのではないでしょうか。

    Running and Pending Application Limits

    yarn.scheduler.capacity.maximum-applications

    未検証。Applicationの最大キュー数のようですが、実運用では役に立たなそうです。キュー数が無限に増えないようにするためにある気がしますが、キュー当たりのメモリ消費量を調べないと適正値はわかりません。

    yarn.scheduler.capacity.maximum-am-resource-percent

    ApplicationMasterがリソースを占める割合%です。float値で最大1.0まで。

    総リソースに対してこの割合でMax Active Applications (以下MAA) が決定します。例えば総リソース 8GB、Application Master 1GB に対して 0.1 にすると MAA が 7 とします。0.2 にすると 13 で、1.0 にすると 64 となります。MapReduceもあるので、1.0にしても総リソースの100%にならない計算式になっているようです。

    これは平均同時Application数や、平均MapReduce数から調整することになりますが、MapReduceが速くないとジョブが溜まる一方になるので 0.1前後で十分だと思います。

    Queue Administration & Permissions

    yarn.scheduler.capacity.<queue-path>.state

    queueに対して RUNNING か STOPPED を設定します。この設定は下の階層にも適用されます。

    STOPPEDにすると、それ以降のApplicationを受け付けません。それまで動いていたApplicationは正常に完了します。Capacity Scheduler の設定は動的に変更できるため、予期せぬ暴走ジョブが出た場合、とりあえず停止するというような使い方がありそうです。

    yarn.scheduler.capacity.<queue-path>.acl_submit_jobs

    未調査。

    yarn.scheduler.capacity.<queue-path>.acl_administer_jobs

    未調査。

    yarn.scheduler.capacity.<queue-path>.acl_administer_queues

    未調査。

    設定の動的反映

    以下のコマンドでResouce Managerを再起動することなく、設定を反映することができます。新規Applicationから設定が反映される形になります。

    定数は /etc/default/hadoop に定義されています。
    export YARN_HOME=/usr/lib/hadoop-yarn

    実際には環境変数がもろもろ必要なので、こんな感じになると思います。


    空きリソースに対する柔軟性について

    まず、Application Masterの起動には柔軟性は適用されません。必ず基本上限値に収まることになります。

    MapReduceのContainerの起動には、そのqueueが基本上限値に達していても、総リソースにまだ空きがある場合は柔軟にリソースを利用します。どのくらい柔軟かというと、そのqueueにつき 1 container までとなっているようです(※ソースを追ったわけじゃないので確定ではないです)。

    例えば、50% のqueue に対して 1 Application Master と 7 Containers of MR が動くとして、空きリソースがある場合は 8 Container まで増えることになります。なので、元の基本上限値に対する割合としては、102 ~ 125% 程度まで上がることになります。

    これは効率的に良い機能と言えますが、悪く言うと 50% queue がどれだけ空きリソースがあっても 60% 程度にしか上がらないため、queue を分割すると 100% の稼働はほぼ望めない状態になります。この、プラス 1 container という柔軟度については調整プロパティが無いようなので、今後に期待したいところです。

    良い点としては、ジョブは最低でも 1 Application Master と 1 Contaier が必要なため、できるだけ 1 Container 動こうとしてくれることは助かる場合があるかもしれません。



    と、色々書いてみましたが、まだガッツリ動かしたワケじゃないので、これから良い所と悪い所を探っていきたいと思います。

    あと管理画面の例でも載せようと思いましたが、長くなったので区切ります。