Apache Hadoop — 1つのPodにHDFSとYARNを立てて運用する
2Gi の Pod に合わせてコンテナサイズを決め、キューを分ける
目標
ResourceManagerのREST APIで、このクラスターが提供できるリソースを確認し、それより大きなコンテナを要求するジョブがどう終わるかを見ます。Capacity Schedulerにetl・adhocのキューを作ってジョブを送り、存在しないキューが拒否されることと、終了したジョブのログを集約して読む方法まで扱います。
なぜ重要なのか
YARNは、クラスターのメモリとコアをコンテナ単位で分け与えるリソースマネージャーです。NodeManagerは、自分が提供できる取り分(yarn.nodemanager.resource.memory-mb)を知らせ、ResourceManagerのスケジューラーは、要求を最小割り当て単位に引き上げて確保し、最大割り当てより大きければ拒否します。MapReduceでもSparkでも、YARNの上で動くものは、すべてこの規則に従います。
本番で「ジョブがACCEPTEDから動きません」と「ジョブがすぐに死にます」は、たいていこれらの数値の問題です。コンテナのサイズがノードの取り分より大きければ、永遠に場所が空かず、最大割り当てより大きければ、すぐに拒否されます。このPodはメモリが2Giなので、ノードの取り分を1024MBに設定してあります。数値が小さいので、規則がよりよく見えます。
キューは、1つのクラスターを複数のチームで分け合う方法です。Capacity Schedulerは、キューごとに、保証枠(capacity)と、借りて使える上限(maximum-capacity)を設けます。同じ親の下の保証枠の合計は100である必要があり、設定ファイルを変更したあとは、refreshQueuesで再読み込みされます。終了したコンテナのログは、NodeManagerがHDFSに集約しておくので(ログ集約)、Podが消えたあとも、yarn logsで読めます。
ステップ
lab-hadoop start yarnでYARNを起動し、curl -s http://localhost:8088/ws/v1/cluster/metricsのレスポンスを、/root/hdp/yarn/metrics.jsonに保存してください。- サンプルjarの
piを-D mapreduce.map.memory.mb=2048で実行して、ジョブを終了させたあと、そのアプリケーションのyarn application -status <애플리케이션 ID>の出力を、/root/hdp/yarn/toobig.txtに保存してください(プレースホルダーはアプリケーションIDです)。 - /opt/hadoop/etc/hadoop/capacity-scheduler.xmlを変更して、
rootの下のキューをdefault,etl,adhocに、保証枠を20・50・30に、adhocの上限を50にしたあと、yarn rmadmin -refreshQueuesを実行し、yarn queue -status etlの出力を、/root/hdp/yarn/etl.txtに保存してください。 /data/books/book-1.txtをHDFSにアップロードし(アップロード先: /user/root/yarn/in/)、wordcountを-D mapreduce.job.queuename=etlで実行して、結果を、/user/root/yarn/wc-etlに書き込んでください。- 同じwordcountを、存在しないキュー
nopeで投入してみて(出力先: /user/root/yarn/wc-nope)、エラー出力を、/root/hdp/yarn/badqueue.txtに保存してください。 curl -s http://localhost:8088/ws/v1/cluster/schedulerのレスポンスを、/root/hdp/yarn/scheduler.jsonに保存してください。- ステップ4のジョブのアプリケーションログを、
yarn logs -applicationId <애플리케이션 ID>で集約して、/root/hdp/yarn/etl-logs.txtに保存してください(プレースホルダーはアプリケーションIDです)。 - /root/hdp/yarn/report.mdに、
## 컨테이너 크기・## 대기열・## 로그の3つの節を書いてください(見出しは韓国語で、順に「コンテナのサイズ」「キュー」「ログ」を意味します)。最初の節に、ステップ1のtotalMBと、ステップ2で要求した2048を入れてください。
参考
- このPodのYARN: NodeManagerの取り分1024MB・コア2、最小割り当て128MB、最大割り当て1024MB、AM 384MB、マップ・リデュース256MB(
yarn-site.xml・mapred-site.xml)。 - ジョブID
job_<A>_<B>とアプリケーションIDapplication_<A>_<B>は、同じ数字を使います。終了したジョブの履歴は、/tmp/hadoop-yarn/staging/history/done_intermediate/root/に残ります。 - 履歴サーバーを起動していないので、失敗したジョブは、クライアントが最終状態を取得するときに接続エラー(10020)で終わることがあります。ジョブの本当の結果は、
yarn application -statusや履歴ファイルで見てください。 - よくあるミスは、保証枠の合計を100に合わせず、refreshQueuesが拒否されること、キュー名に
root.を付けて投入すること(名前だけを書きます)、アプリケーションが終わる前にyarn logsを呼ぶことです。 - 公式ドキュメント: Apache Hadoop YARN・Capacity Scheduler・ResourceManager REST APIs・yarn-default.xml
クラスターが提供できるもの
lab-hadoop start yarnでYARNを起動し、curl -s http://localhost:8088/ws/v1/cluster/metricsのレスポンスのJSONを、/root/hdp/yarn/metrics.jsonに保存してください。
clusterMetricsのtotalMB・totalVirtualCores・activeNodesが、NodeManagerが知らせた取り分です。Podは2GiなのにtotalMBがそれよりはるかに小さい理由を考えてみてください。HDFSとYARNの4つのデーモンと、クライアントのJVMが、先に場所を占めるからです。
最大割り当てより大きいコンテナ
yarn jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.5.0.jar pi -D mapreduce.map.memory.mb=2048 1 10を実行してジョブを終了させたあと、そのアプリケーションのyarn application -status application_<…>の出力を、/root/hdp/yarn/toobig.txtに保存してください。
マップ1つが2048MBを要求していますが、最大割り当ては1024MBです。AMは、マップコンテナを要求する前に、ジョブをKILLEDで終了させます。アプリケーションIDはジョブIDの数字そのままで、履歴フォルダーで、名前がQuasiMonteCarloのKILLEDのジョブを探せばよいです。診断(Diagnostics)行が理由を教えてくれます。
3つのキューを作る
/opt/hadoop/etc/hadoop/capacity-scheduler.xmlで、yarn.scheduler.capacity.root.queuesをdefault,etl,adhocに、root.default.capacity・root.etl.capacity・root.adhoc.capacityを20・50・30に、root.adhoc.maximum-capacityを50にしてください。yarn rmadmin -refreshQueuesで再読み込みされたあと、yarn queue -status etlの出力を、/root/hdp/yarn/etl.txtに保存してください。
同じ親の下の保証枠(capacity)の合計が100でなければ、refreshQueuesが受け付けません。上限(maximum-capacity)は、余ったリソースを借りて使える限界です。設定ファイルを変更するだけでは、何も起こりません。再読み込みされる必要があります。
etlキューにジョブを送る
/data/books/book-1.txtをHDFSにアップロードし(アップロード先: /user/root/yarn/in/)、yarn jar <예제 jar> wordcount -D mapreduce.job.queuename=etl /user/root/yarn/in /user/root/yarn/wc-etlで実行してください(プレースホルダーはサンプルjarです)。
キューは名前だけを書きます(root.なしで)。ジョブ履歴ファイル名のキューの欄に、root.etlが出力されるかを見てください。採点ツールは、その欄と出力の_SUCCESSを確認します。
存在しないキューは投入で拒否される
同じwordcountを、-D mapreduce.job.queuename=nopeで、/user/root/yarn/wc-nopeに投入してみて、エラー出力(標準エラー出力を含む)を、/root/hdp/yarn/badqueue.txtに保存してください。
存在しないキューは、スケジューラーがアプリケーションを受け取る瞬間に拒否します。ジョブは開始すらしないので、履歴にも残りません。そのため、このエラーは、投入した側の出力にしかありません。
スケジューラーから見たキュー
curl -s http://localhost:8088/ws/v1/cluster/schedulerのレスポンスのJSONを、/root/hdp/yarn/scheduler.jsonに保存してください。
レスポンスのscheduler.schedulerInfo.queues.queueに、キューごとのcapacity・maxCapacity・usedCapacityがあります。採点ツールは、その値が自分で変更した設定ファイルと同じかを確認します。refreshQueuesが本当に効いたかを確認するわけです。
終了したジョブのログを集約して読む
ステップ4のジョブのアプリケーションID(application_<…>)で、yarn logs -applicationId <ID>を実行して、出力を、/root/hdp/yarn/etl-logs.txtに保存してください。
NodeManagerは、コンテナが終わると、そのログをHDFSの/tmp/logs/<사용자>/の下に集約します(プレースホルダーはユーザーです)。そのため、ノードが消えても、ログが残ります。集約はアプリが終わってから数秒かかるので、すぐに呼ぶと、空の出力が出ることがあります。出力には、コンテナごとにContainer:のヘッダーと、LogType:syslog・stdout・stderrが順に出てきます。
リソースの数値を書き残す
/root/hdp/yarn/report.mdに、## 컨테이너 크기・## 대기열・## 로그の3つの節を書いてください(見出しは韓国語で、順に「コンテナのサイズ」「キュー」「ログ」を意味します)。最初の節に、ステップ1のtotalMBと、ステップ2で要求した2048を、数値で入れてください。
ノードの取り分・最小割り当て・最大割り当て・AMのサイズがどう噛み合うか、キューの保証枠と上限が何を意味するか、ログがどこに集約されたかを書いてください。