配置制約

概要

YARNでは、アプリケーションはデータローカリティ(特定のノードまたはラックを優先)または(重複しない)ノードラベルの形式で配置制約を指定できます。このドキュメントでは、YARNでのより表現力豊かな配置制約に焦点を当てています。このような制約は、特にサービス、機械学習、ストリーミングワークロードなど、長時間実行されるコンテナを含むアプリケーションのパフォーマンスと回復力にとって重要です。

たとえば、ネットワークコストを削減するためにジョブの割り当てを同じラックに配置(アフィニティ制約)、リソースの干渉を最小限に抑えるために割り当てをマシン全体に分散(アンチアフィニティ制約)、または2つのバランスを取るためにノードグループ内の割り当て数を特定の上限まで許可する(カーディナリティ制約)ことが有益な場合があります。配置の決定は回復力にも影響します。たとえば、同じクラスタアップグレードドメイン内に配置された割り当ては、同時にオフラインになります。

アプリケーションは、クラスタの基礎となるトポロジ(たとえば、コンテナを配置する特定のノードまたはラックを制約で指定する必要はありません)またはデプロイされた他のアプリケーションの知識を必要とせずに制約を指定できます。現在、すべての制約はハードです。つまり、現在のクラスタの状態または競合する制約によりコンテナの制約を満たすことができない場合、コンテナ要求は保留中になるか、拒否されます。

このドキュメントでは、「割り当て」という概念を、ノードに割り当てられるリソース(CPUやメモリなど)の単位を指すために使用していることに注意してください。現在のYARNの実装では、割り当ては単一のコンテナに対応します。ただし、アプリケーションが1つの割り当てを使用して複数のコンテナを生成する場合、割り当ては複数のコンテナに対応する可能性があります。

クイックガイド

最初に、配置制約を使用したスケジューリングを有効にする方法について説明し、次に、分散シェルを使用してこの機能を実験する方法の例を提供します。分散シェルは、一連のコンテナで特定のシェルコマンドを実行できるアプリケーションです。

配置制約の有効化

配置制約を有効にするには、conf/yarn-site.xmlで次のプロパティをplacement-processorまたはschedulerに設定する必要があります。

プロパティ 説明 デフォルト値
yarn.resourcemanager.placement-constraints.handler PlacementConstraintsの処理に使用されるハンドラーを指定します。使用可能な値は、placement-processorscheduler、およびdisabledです。 disabled

次に、3つの配置制約ハンドラーのそれぞれについて詳しく説明します。

  • placement-processor:このハンドラーを使用すると、制約のあるコンテナの配置は、キャパシティまたはフェアスケジューラーが呼び出される前の前処理ステップとして決定されます。配置が決定されると、キャパシティ/フェアスケジューラーが呼び出され、実際の割り当てが実行されます。このハンドラーの利点は、すべての制約タイプ(アフィニティ、アンチアフィニティ、カーディナリティ)をサポートしていることです。さらに、一度に複数のコンテナを考慮するため、コンテナごとのアプローチよりも多くの制約を満たすことができます。メインスケジューラーの外部にあるため、キャパシティスケジューラーとフェアスケジューラーの両方で使用できます。現時点では、そのような優先度が配置制約と競合する可能性があるため、アプリケーション内のタスクの優先度を考慮していないことに注意してください。
  • scheduler:このハンドラーを使用すると、制約のあるコンテナはメインスケジューラーによって配置されます(現時点では、キャパシティスケジューラーのみがSchedulingRequestsをサポートしています)。現在、アンチアフィニティ制約をサポートしています(アフィニティまたはカーディナリティはサポートしていません)。このハンドラーの利点は、placement-processorと比較して、既存のメインスケジューラーによって適用されるキュー(利用率、優先度でソート)、アプリ(FIFO/公平性/優先度でソート)、および同じアプリ内のタスク(優先度)の同じ順序付けルールに従うことです。
  • disabled:このハンドラーを使用すると、アプリケーションによってSchedulingRequestが要求された場合、対応する割り当て呼び出しは拒否されます。

placement-processorハンドラーは、より広範囲の制約をサポートし、特にアプリケーションに厳しい制約がある場合やクラスタが高度に利用されている場合(一度に複数のコンテナを考慮するため)、より多くのコンテナを配置できます。ただし、アプリケーション内のタスクの優先度を尊重することがユーザーにとって重要であり、キャパシティスケジューラーを使用する場合は、代わりにschedulerハンドラーを使用する必要があります。

分散シェルを使用した配置制約の実験

ユーザーは、次のコマンドを使用して分散シェルアプリケーションを使用することで、配置制約を実験できます。

$ yarn org.apache.hadoop.yarn.applications.distributedshell.Client -jar share/hadoop/yarn/hadoop-yarn-applications-distributedshell-3.3.6.jar -shell_command sleep -shell_args 10 -placement_spec PlacementSpec

ここで、PlacementSpecは次の形式です。

PlacementSpec               => "" | PlacementExpr;PlacementSpec
PlacementExpr               => SourceTag,ConstraintExpr
SourceTag                   => String(NumContainers)
ConstraintExpr              => SingleConstraint | CompositeConstraint
SingleConstraint            => "IN",Scope,TargetTag | "NOTIN",Scope,TargetTag | "CARDINALITY",Scope,TargetTag,MinCard,MaxCard | NodeAttributeConstraintExpr
NodeAttributeConstraintExpr => NodeAttributeName=Value, NodeAttributeName!=Value
CompositeConstraint         => AND(ConstraintList) | OR(ConstraintList)
ConstraintList              => Constraint | Constraint:ConstraintList
NumContainers               => int
Scope                       => "NODE" | "RACK"
TargetTag                   => String
MinCard                     => int
MaxCard                     => int

注意

  • 分散シェルコマンドで-placement_spec引数が指定されている場合(NodeAttributeConstraintExprを除く)、-num-containers引数を使用しないでください。-num-containers引数が-placement-specと組み合わせて使用されている場合、前者は無視されます。これは、PlacementSpecではタグごとのコンテナ数を決定するため、-num-containersが冗長であり、競合する可能性があるためです。さらに、-placement_specが使用されている場合、すべてのコンテナはGUARANTEED実行タイプで要求されます。
  • NodeAttributeConstraintExprが指定されている場合、SourceTag(NumContainers)はオプションであり、要求するコンテナ数には-num-containersの値が考慮されます。

PlacementSpecの例を次に示します。

zk(3),NOTIN,NODE,zk:hbase(5),IN,RACK,zk:spark(7),CARDINALITY,NODE,hbase,1,3

上記は3つの制約をエンコードしています。

  • タグ「zk」(ZooKeeperを表す)が付いた3つのコンテナを相互にノードアンチアフィニティで配置します。つまり、ノードごとに1つ以下のコンテナを配置します(この最初の制約では、制約のSourceTagとTargetTagが一致することに注意してください)。
  • タグ「zk」が付いたコンテナが実行されているラックにアフィニティを持つ、タグ「hbase」が付いた5つのコンテナを配置します(つまり、「hbase」コンテナは、「zk」が2番目の制約のTargetTagであることを考慮すると、「zk」コンテナが実行されているラックに配置しないでください)。
  • タグ「hbase」が付いたコンテナが少なくとも1つ、3つ以下のノードに、タグ「spark」が付いた7つのコンテナを配置します。

次の別の例では、複合形式の制約を示しています。

zk(5),AND(IN,RACK,hbase:NOTIN,NODE,zk)

上記の制約では、2つの制約を組み合わせるために接続演算子ANDを使用しています。AND制約は、その両方の子制約が満たされた場合に満たされます。特定のPlacementSpecでは、少なくとも1つの「hbase」コンテナが実行されているラックで、かつ「zk」コンテナが実行されていないノードで5つの「zk」コンテナを配置するように要求します。同様に、OR演算子を使用して、少なくとも1つの子制約が満たされた場合に満たされる制約を定義できます。「zk」と「hbase」が異なるアプリケーションに属するコンテナである場合(これは実際のユースケースで最も可能性が高い)、PlacementSpecのアロケーションタグには、以下で説明するように、名前空間を含める必要があります(アロケーションタグの名前空間を参照)。

配置制約の定義

アロケーションタグ

アロケーションタグは、アプリケーションが(グループの)コンテナに関連付けることができる文字列タグです。タグは、アプリケーションのコンポーネントを識別するために使用されます。たとえば、HBase Master割り当てには「hbase-m」、Region Serversには「hbase-rs」というタグを付けることができます。その他の例として、割り当てのより一般的な要求を指す「レイテンシクリティカル」、またはジョブIDを表す「app_0041」があります。アロケーションタグは、共通のタグを共有する複数の割り当てを参照できるため、制約において重要な役割を果たします。

アロケーションタグを定義するために ResourceRequest オブジェクトを使用する代わりに、新しい SchedulingRequest オブジェクトを使用することに注意してください。これには ResourceRequest と多くの類似点がありますが、要求されたアロケーションのサイズ(アロケーションの数とサイズ、優先度、実行タイプなど)と、これらのアロケーションをどのように配置するかを指示する制約(リソース名、緩和された局所性)がより適切に分離されています。アプリケーションは引き続き ResourceRequest オブジェクトを使用できますが、アロケーションタグと制約を定義するためには、SchedulingRequest オブジェクトを使用する必要があります。単一の AllocateRequest 内では、アプリケーションは ResourceRequest オブジェクトまたは SchedulingRequest オブジェクトのどちらかを使用する必要がありますが、両方を使用することはできません。

アロケーションタグの名前空間

アロケーションタグは、同じまたは異なるアプリケーションのコンテナを参照することができ、それぞれアプリケーション内またはアプリケーション間の制約を表すために使用されます。アロケーションタグが参照できるアプリケーションのスコープを指定するために、アロケーションタグの名前空間を使用します。アロケーションタグを名前空間と組み合わせることで、タグが同じアプリケーションに属するコンテナ、特定のアプリケーショングループに属するコンテナ、またはクラスタ内の任意のアプリケーションに属するコンテナを対象とするかどうかを制限できます。

現在、次の名前空間をサポートしています。

名前空間 構文 説明
SELF self/${allocationTag} アロケーションタグは、現在のアプリケーション(制約が適用されるアプリケーション)のコンテナを参照します。これはデフォルトの名前空間です。
NOT_SELF not-self/${allocationTag} アロケーションタグは、現在のアプリケーションに属さないコンテナのみを参照します。
ALL all/${allocationTag} アロケーションタグは、任意のアプリケーションのコンテナを参照します。
APP_ID app-id/${applicationID}/${allocationTag} アロケーションタグは、指定されたアプリケーションIDを持つアプリケーションのコンテナを参照します。
APP_TAG app-tag/application_tag_name/${allocationTag} アロケーションタグは、指定されたアプリケーショングループでタグ付けされたアプリケーションのコンテナを参照します。

アロケーションタグの名前空間 ns をターゲットタグ targetTag にアタッチするには、PlacementSpec で ns/allocationTag という構文を使用します。デフォルトの名前空間は SELF であり、アプリケーション内の制約に使用されることに注意してください。残りの名前空間タグは、アプリケーション間の制約を指定するために使用されます。名前空間がタグの横に指定されていない場合、SELF が想定されます。

上記の制約の例は、次のように名前空間で拡張できます。

zk(3),NOTIN,NODE,not-self/zk:hbase(5),IN,RACK,all/zk:spark(7),CARDINALITY,NODE,app-id/appID_0023/hbase,1,3

これらの制約の意味は次のとおりです。

  • 他のアプリケーションからの "zk" コンテナが実行されていないノードに、"zk" (ZooKeeper を表す) タグを持つ 3 つのコンテナを配置します。
  • (同じアプリケーションでも異なるアプリケーションでも)"zk" タグを持つコンテナが実行されているラックにアフィニティを持つ "hbase" タグを持つ 5 つのコンテナを配置します。
  • ID が appID_0023 のアプリケーションに属する "hbase" タグを持つコンテナが少なくとも 1 つ、最大 3 つあるノードに、"spark" タグを持つ 7 つのコンテナを配置します。

ノードラベル、ノード属性、アロケーションタグの違い

アロケーションタグとノードラベルまたはノード属性の違いは、アロケーションタグがノードではなくアロケーションにアタッチされることです。スケジューラによってアロケーションがノードに割り当てられると、そのアロケーションのタグセットがアロケーションの期間中、自動的にノードに追加されます。したがって、ノードは現在ノードに割り当てられているアロケーションのタグを継承します。同様に、ラックはそのノードのタグを継承します。さらに、ノードラベルと同様に、ノード属性とは異なり、アロケーションタグには値がアタッチされていません。以下に示すように、制約はアロケーションタグだけでなく、ノードラベルやノード属性も参照できます。

配置制約 API

アプリケーションは、配置制約を構築するために PlacementConstraints のパブリック API を使用できます。制約を構築するためのメソッドについて説明する前に、制約で使用されるターゲット式を構築するために使用される PlacementTargets クラスのメソッドについて説明します。

メソッド 説明
allocationTag(String... allocationTags) アロケーションタグのターゲット式を構築します。指定されたタグのいずれかを持つアロケーションがある場合に満たされます。
allocationTagWithNamespace(String namespace, String... allocationTags) allocationTag(String...) と同様ですが、指定されたアロケーションタグの名前空間を指定できます。
nodePartition(String... nodePartitions) ノードパーティションのターゲット式を構築します。nodePartitions のいずれかに属するノードで満たされます。
nodeAttribute(String attributeKey, String... attributeValues) ノード属性のターゲット式を構築します。指定されたノード属性に指定された値のいずれかがある場合に満たされます。

上記の nodeAttribute メソッドは、現在進行中のノード属性機能を必要とするため、まだ機能しません。

制約を構築するための PlacementConstraints クラスのメソッドは次のとおりです。

メソッド 説明
targetIn(String scope, TargetExpression... targetExpressions) 指定されたスコープ(例:ノードまたはラック)内のすべてのターゲット式を満たすノードにアロケーションを配置する必要がある制約を作成します。たとえば、targetIn(RACK, allocationTag("hbase-m")) は、"hbase-m" タグを持つアロケーションが少なくとも1つあるラックに属するノードのアロケーションを許可します。
targetNotIn(String scope, TargetExpression... targetExpressions) いずれのターゲット式も満たさないスコープ(例:ノードまたはラック)に属するノードにアロケーションを配置する必要がある制約を作成します。
cardinality(String scope, int minCardinality, int maxCardinality, String... allocationTags) 指定されたスコープ(例:ノードまたはラック)内のアロケーション数を制限する制約を作成します。たとえば、cardinality(NODE, 3, 10, "zk") は、"zk" タグを持つアロケーションが 3 つ以上、10 つ以下のノードで満たされます。
minCardinality(String scope, int minCardinality, String... allocationTags) cardinality(String, int, int, String...) と同様ですが、最小カーディナリティのみを決定します(最大カーディナリティはバインドされていません)。
maxCardinality(String scope, int maxCardinality, String... allocationTags) cardinality(String, int, int, String...) と同様ですが、最大カーディナリティのみを決定します(最小カーディナリティは 0 です)。
targetCardinality(String scope, int minCardinality, int maxCardinality, String... allocationTags) この制約は、カーディナリティ制約とターゲット制約を一般化したものです。制約で指定されたスコープに属するノードのセット N を考えます。ターゲット式がノードセット N で少なくとも minCardinality 回、最大で maxCardinality 回満たされている場合、制約は満たされます。たとえば、targetCardinality(RACK, 2, 10, allocationTag("zk")) では、"zk" タグを持つ他のアロケーションが少なくとも 2 つ、最大で 10 個あるラック内にアロケーションを配置する必要があります。

PlacementConstraints クラスには、複合制約(複数の制約を持つ AND/OR 式)を構築するためのメソッドも含まれています。複合制約のサポートの追加は進行中です。

アプリケーションでの制約の指定

アプリケーションは、各制約が有効になるコンテナを指定する必要があります。このために、アプリケーションはアロケーションタグのセット(ソースタグ)から配置制約へのマッピングを提供できます。たとえば、このマッピングのエントリは "hbase"->constraint1 であり、これは "hbase" タグを持つ各アロケーションをスケジュールするときに constraint1 が適用されることを意味します。

placement-processor ハンドラを使用する場合(配置制約の有効化を参照)、この制約マッピングは RegisterApplicationMasterRequest 内で指定されます。

scheduler ハンドラを使用する場合、制約は各 SchedulingRequest オブジェクトに追加することもできます。このような各制約は、そのスケジュール要求のタグに対して有効です。制約が RegisterApplicationMasterRequest とスケジュール要求の両方で指定されている場合、後者が前者をオーバーライドします。