web-dev-qa-db-ja.com

EMRのYarnがすべてのノードを実行中のSparkジョブに割り当てないのはなぜですか?

Amazon Elastic Map Reduce(EMR)のApache Sparkでジョブを実行しています。現在、Amazon Hadoop2.6.0とSpark1.5.0を含むemr-4.1.0で実行しています。

ジョブを開始すると、YARNはすべてのワーカーノードをsparkジョブに正しく割り当てました(もちろん、ドライバー用に1つ)。

魔法の「maximizeResourceAllocation」プロパティを「true」に設定し、sparkプロパティ「spark.dynamicAllocation.enabled」も「true」に設定しています。

ただし、ワーカーマシンのCOREプールにノードを追加してemrクラスターのサイズを変更すると、YARNは新しいノードのsomeのみをsparkジョブに追加します。

たとえば、今朝、26ノード(重要な場合はm3.2xlarge)を使用するジョブがありました。ドライバー用に1つ、エグゼキューター用に25個です。ジョブを高速化したかったので、さらに8つのノードを追加してみました。 YARNはすべての新しいノードを取得しましたが、そのうちの1つだけをSparkジョブに割り当てました。 Sparkは新しいノードを正常に取得し、それをエグゼキュータとして使用していますが、私の質問は、なぜYARNが他の7つのノードをアイドル状態にするのかということです。

明らかな理由で面倒です。リソースが使用されていなくても、リソースの料金を支払う必要があり、仕事がまったくスピードアップしていません。

実行中のsparkジョブにノードを追加するタイミングをYARNがどのように決定するかを知っている人はいますか?どのような変数が関係していますか?記憶? Vコア?何か?

前もって感謝します!

18
retnuH

さて、 @ sean_r_owen の助けを借りて、私はこれを追跡することができました。

問題は次のとおりです。spark.dynamicAllocation.enabledtrueに設定する場合、spark.executor.instancesを設定しないでください。明示的な値を設定すると動的割り当てが上書きされてオフになります。自分で設定しないと、EMRがバックグラウンドで設定することがわかります。目的の動作を得るには、spark.executor.instancesを明示的に0に設定する必要があります。

レコードについては、EMRクラスターを作成するときに--configurationsフラグに渡すファイルの1つの内容を次に示します。

[
    {
        "Classification": "capacity-scheduler",
        "Properties": {
            "yarn.scheduler.capacity.resource-calculator": "org.Apache.hadoop.yarn.util.resource.DominantResourceCalculator"
        }
    },

    {
        "Classification": "spark",
        "Properties": {
            "maximizeResourceAllocation": "true"
        }
    },

    {
        "Classification": "spark-defaults",
        "Properties": {
            "spark.dynamicAllocation.enabled": "true",
            "spark.executor.instances": "0"
        }
    } 
]

これにより、EMRクラスターが得られます。Sparkは、ジョブの実行時に、追加されたノードを含むすべてのノードを使用します。また、すべて/ほとんどのメモリとすべて(?)のコアを使用しているように見えます。

(実際のコアをすべて使用していることは完全にはわかりませんが、以前はなかった1つ以上のVCoreを使用していることは間違いありませんが、Glennie Hellesのアドバイスに従って、動作が改善され、リストされているVCoreの半分を使用しています。これは実際のコア数と同じようです...)

22
retnuH

Emr-5.20.0を使用して、ほぼ同じ設定で同じ動作を観察しました。クラスターがすでに実行されているときにノードを追加しようとはしませんでしたが、TASKノードを使用しました(1つのCOREノードと一緒に)。私はInstanceFleetsを使用してMASTER、CORE、およびTASKノードを定義しています(InstanceFleetsを使用すると、取得する正確なInstanceTypeがわからないため、エグゼキュータ、コア、およびエグゼキュータごとのメモリの数を自分で定義したくないのですが、自動的に最大化/最適化されます)。

これにより、2つのTASKノード(おそらく使用する準備ができている最初の2つのノード?)のみを使用しますが、より多くのTASKノードがプロビジョニングされてbootstrapフェーズを終了する間、スケールアップすることはありません。

私の場合、それが機能したのは、TASKInstanceFleetのTargetOnDemandCapacityまたはTargetSpotCapacityに使用されるのと同じ数であるspark.default.parallelismパラメーター(TASKノードのコアの総数)を設定することでした。

[
    {
        "Classification": "capacity-scheduler",
        "Properties": {
            "yarn.scheduler.capacity.resource-calculator": "org.Apache.hadoop.yarn.util.resource.DominantResourceCalculator"
        }
    },
    {
        "Classification": "spark",
        "Properties": {
            "maximizeResourceAllocation": "true"
        }
    },
    {
        "Classification": "spark-defaults",
        "Properties": {
            "spark.dynamicAllocation.enabled": "true",
            "spark.default.parallelism", <Sum_of_Cores_of_all_TASK_nodes>
        }
    } 
]

完全を期すために、主にクラスターに少なくとも3つのノード(1つのMASTER、1つのCORE、および少なくとも1つのTASKノード)があることを確認するために、1つのCOREノードと複数のTASKノードを使用しています。以前はCOREノードのみを使用しようとしましたが、私の場合と同様に、実際のタスクに応じてコアの数が計算され、1つのMASTERノードと1つのCOREノードのみで構成されるクラスターになる可能性がありました。 maximizeResourceAllocationオプションを使用すると、yarnアプリケーションマスターを実行しているエグゼキューターがその単一のCOREノードを完全に占有しているため、このようなクラスターは何もしないで実行されます。

3
Patter