こんにちは。
前回の記事(下記)に引き続き、Pig on Tez on CDHのお試しです。
http://qiita.com/kimutansk/items/8a91baf476fff4232634
Pig on Tez on CDHでGPLライブラリを追加してみる理由
Pigを使う際、前提となるライブラリや設定の追加が必要になるケースがあるためです。
Pig UDFの場合はPig Script中で明示的にロードを行うため、
HDFS上にファイルをアップしておけば、Tez上で動作させても問題なく可能でしょう。
ただ、特定のファイルを扱うためにクラスが設定して指定されてロードされるケース、
例えばLzoなんかをどうやって設定すればいいのかについては疑問が残ります。
ですので、実際にやってみよう、という形です。
必要環境/パッケージのインストール
前提とする環境として、Lzoを含むGPLEXTRAのParcelを導入しておく必要があります。
Cloudera Managerのトップメニューから「Parcel」>「設定」を選択し、下記のリポジトリを追加します。
https://archive.cloudera.com/gplextras5/parcels/{latest_supported}
追加した上で「新しいPercel のチェック」を実行すると、「GPLEXTRAS」が一覧に出てきますので、
それを「ダウンロード」>「配布」>「アクティブ化」と実行して有効化しておきます。
パッケージに対する設定実施
パッケージがインストールできたので、次は設定です。
該当のクラスタで「HDFS」>「設定」を選択し、下記のように設定項目に値を追加します。
- 設定項目:io.compression.codecs
- 追加内容:com.hadoop.compression.lzo.LzoCodec
- 追加内容:com.hadoop.compression.lzo.LzopCodec
追加したら必要なサービスを再起動しておきます。
すると、下記のファイル中の設定に反映されていることがわかります。
- /etc/hadoop/conf/core-site.xml
読み込み用ディレクトリ/ファイルの作成
実際に読み込むためのファイルとして、前回使用した data_noheader.csv
を圧縮して使用します。
下記コマンドを実行し、圧縮ファイルを作成します。
$ sudo yum install -y lzop
$ lzop data_noheader.csv
作成されたファイル( data_noheader.csv.lzo
)をHDFSの /user/pub/example-lzo
配下にアップしておきます。
Pigスクリプトの実行>失敗
Pigスクリプトを下記のように修正し、実行します。
loadresult = LOAD '/user/pub/example-lzo';
limitedresult = LIMIT loadresult 10;
logs_count = FOREACH (GROUP loadresult ALL) GENERATE COUNT(loadresult);
DUMP logs_count
DUMP limitedresult;
/opt/pig/bin/pig -x tez -f test-lzo-count.pig
実行すると、案の定というか、下記のエラーが発生して実行は失敗します。
/opt/pig/bin/pig -x tez -f test-lzo-count.pig
2016-04-24 18:44:47,043 [PigTezLauncher-0] INFO org.apache.pig.backend.hadoop.executionengine.tez.TezJob - DAG Status: status=FAILED, progress=TotalTasks: 2 Succeeded: 0 Running: 0 Failed: 1 Killed: 1 FailedTaskAttempts: 4, diagnostics=Vertex failed, vertexName=scope-10, vertexId=vertex_1461490474710_0001_1_00, diagnostics=[Task failed, taskId=task_1461490474710_0001_1_00_000000, diagnostics=[TaskAttempt 0 failed, info=[Error: exceptionThrown=java.lang.IllegalArgumentException: Compression codec com.hadoop.compression.lzo.LzoCodec not found.
at org.apache.hadoop.io.compress.CompressionCodecFactory.getCodecClasses(CompressionCodecFactory.java:135)
at org.apache.hadoop.io.compress.CompressionCodecFactory.<init>(CompressionCodecFactory.java:175)
at org.apache.hadoop.mapreduce.lib.input.LineRecordReader.initialize(LineRecordReader.java:87)
at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigRecordReader.initialize(PigRecordReader.java:181)
at org.apache.tez.mapreduce.lib.MRReaderMapReduce.setupNewRecordReader(MRReaderMapReduce.java:152)
at org.apache.tez.mapreduce.lib.MRReaderMapReduce.setSplit(MRReaderMapReduce.java:85)
at org.apache.tez.mapreduce.input.MRInput.initFromEventInternal(MRInput.java:614)
at org.apache.tez.mapreduce.input.MRInput.processSplitEvent(MRInput.java:566)
at org.apache.tez.mapreduce.input.MRInput.handleEvents(MRInput.java:530)
at org.apache.tez.runtime.LogicalIOProcessorRuntimeTask.handleEvent(LogicalIOProcessorRuntimeTask.java:631)
at org.apache.tez.runtime.LogicalIOProcessorRuntimeTask.access$600(LogicalIOProcessorRuntimeTask.java:98)
at org.apache.tez.runtime.LogicalIOProcessorRuntimeTask$1.runInternal(LogicalIOProcessorRuntimeTask.java:694)
at org.apache.tez.common.RunnableWithNdc.run(RunnableWithNdc.java:35)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: Class com.hadoop.compression.lzo.LzoCodec not found
at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:1980)
at org.apache.hadoop.io.compress.CompressionCodecFactory.getCodecClasses(CompressionCodecFactory.java:128)
... 13 more
(省略)
]], Vertex did not succeed due to OWN_TASK_FAILURE, failedTasks:1 killedTasks:0, Vertex vertex_1461490474710_0001_1_00 [scope-10] killed/failed due to:null]
Vertex killed, vertexName=scope-11, vertexId=vertex_1461490474710_0001_1_01, diagnostics=[Vertex received Kill while in RUNNING state., Vertex did not succeed due to OTHER_VERTEX_FAILURE, failedTasks:0 killedTasks:1, Vertex vertex_1461490474710_0001_1_01 [scope-11] killed/failed due to:null]
DAG did not succeed due to VERTEX_FAILURE. failedVertices:1 killedVertices:1, counters=Counters: 4
org.apache.tez.common.counters.DAGCounter
NUM_FAILED_TASKS=4
TOTAL_LAUNCHED_TASKS=4
AM_CPU_MILLISECONDS=1730
AM_GC_TIME_MILLIS=56
PigTezLauncherの段階でHadoopの設定ファイルを読み込んだ際にこけているようですね。
かつ、TezのYARNコンテナでも同種のエラーは発生するでしょうから、下記の対応が必要になりそうです。
- Pig起動プロセスのクラスパスにLzoライブラリを追加
- TezのYARNコンテナのクラスパスにLzoライブラリを追加
Pig on TezにLzoライブラリの設定を追加
- Pig起動プロセスのクラスパスにLzoライブラリを追加
これはPigの起動スクリプトの頭に追加しても、
Tezのライブラリディレクトリにシンボリックリンクをはってもどちらでもいいのですが、
Pigの起動スクリプトに追加したのは完全にTezの設定ですので、Tezを使うのは確定だろう、
ということで後者で実施します。
$ ln -s /opt/cloudera/parcels/GPLEXTRAS/lib/hadoop/lib/hadoop-lzo.jar /opt/tez-lib/hadoop-lzo.jar
- TezのYARNコンテナのクラスパスにLzoライブラリを追加
/opt/tez-conf/tez-site.xml
に下記の設定を追加します。
<property>
<name>tez.cluster.additional.classpath.prefix</name>
<value>/opt/cloudera/parcels/GPLEXTRAS/lib/hadoop/lib/hadoop-lzo.jar</value>
</property>
Pigスクリプトの再実行
再度hdfsユーザでPigスクリプトを実行してみます。すると・・・
/opt/pig/bin/pig -x tez -f test-lzo-count.pig
(省略)
2016-04-24 20:03:40,460 [main] INFO org.apache.pig.tools.pigstats.tez.TezPigScriptStats - Script Statistics:
HadoopVersion: 2.6.0-cdh5.7.0
PigVersion: 0.15.0
TezVersion: 0.7.0
UserId: hdfs
FileName: /tmp/test-lzo-count.pig
StartedAt: 2016-04-24 20:03:28
FinishedAt: 2016-04-24 20:03:40
Features: GROUP_BY
Success!
DAG PigLatin:test-lzo-count.pig-0_scope-0:
ApplicationId: job_1461490474710_0014
TotalLaunchedTasks: 2
FileBytesRead: 99
FileBytesWritten: 67
HdfsBytesRead: 61480
HdfsBytesWritten: 7
Input(s):
Successfully read 1744 records (61480 bytes) from: "/user/pub/example-lzo"
Output(s):
Successfully stored 1 records (7 bytes) in: "hdfs://hadoophost01:8020/tmp/temp-1823417929/tmp552056591"
(1744)
(1871-01-01,4.44,0.26,0.4,12.46,5.32,84.52,4.95,7.61,,,,,,,)
(1871-02-01,4.5,0.26,0.4,12.84,5.32,83.12,4.8,7.39,,,,,,,)
(1871-03-01,4.61,0.26,0.4,13.03,5.33,83.91,4.73,7.28,,,,,,,)
(1871-04-01,4.74,0.26,0.4,12.56,5.33,89.54,4.91,7.56,,,,,,,)
(1871-05-01,4.86,0.26,0.4,12.27,5.33,93.95,5.03,7.73,,,,,,,)
(1871-06-01,4.82,0.26,0.4,12.08,5.34,94.64,5.11,7.85,,,,,,,)
(1871-07-01,4.73,0.26,0.4,12.08,5.34,92.87,5.11,7.85,,,,,,,)
(1871-08-01,4.79,0.26,0.4,11.89,5.34,95.56,5.19,7.98,,,,,,,)
(1871-09-01,4.84,0.26,0.4,12.18,5.35,94.29,5.07,7.79,,,,,,,)
(1871-10-01,4.59,0.26,0.4,12.37,5.35,88.04,4.99,7.67,,,,,,,)
実行に成功しました。
前回と比べると、読込ファイルサイズが下記のように変わっているので、確かに圧縮したファイルを読み込んだことがわかります。
Successfully read 1744 records (116662 bytes) from: "/user/pub/example-data"
Successfully read 1744 records (61480 bytes) from: "/user/pub/example-lzo"
が、しかし・・・?
ただ、ここで上手く行ったと思って別のユーザ(今回はビルド用ユーザのbuild)で実行してみると、
何故か読込に失敗する事象が発生しました。
/opt/pig/bin/pig -x tez -f test-lzo-count.pig
2016-04-24 20:13:44,815 [main] INFO org.apache.pig.tools.pigstats.tez.TezPigScriptStats - Script Statistics:
HadoopVersion: 2.6.0-cdh5.7.0
PigVersion: 0.15.0
TezVersion: 0.7.0
UserId: build
FileName: test-lzo-count.pig
StartedAt: 2016-04-24 20:13:26
FinishedAt: 2016-04-24 20:13:44
Features: GROUP_BY
Failed!
DAG PigLatin:test-lzo-count.pig-0_scope-0:
ApplicationId: job_1461490474710_0015
TotalLaunchedTasks: 4
FileBytesRead: 0
FileBytesWritten: 0
HdfsBytesRead: 0
HdfsBytesWritten: 0
Input(s):
Failed to read data from "/user/pub/example-lzo"
Output(s):
Failed to produce result in "hdfs://hadoophost01:8020/tmp/temp-1843801261/tmp-1479312519"
2016-04-24 20:13:44,912 [main] ERROR org.apache.pig.tools.grunt.Grunt - ERROR 1066: Unable to open iterator for alias logs_count. Backend error : Vertex failed, vertexName=scope-10, vertexId=vertex_1461490474710_0015_1_00, diagnostics=[Task failed, taskId=task_1461490474710_0015_1_00_000000, diagnostics=[TaskAttempt 0 failed, info=[Error: exceptionThrown=java.lang.IllegalArgumentException: Compression codec com.hadoop.compression.lzo.LzoCodec not found.
違いはどこにある?
どこに違いがあるのかざっと追ってみると、下記の2つの時点で差分があることがわかりました。
- 1. YARNコンテナ起動時の環境変数設定(YARNの一時ファイル)
- buildユーザで実行した側は
tez.cluster.additional.classpath.prefix
の設定がない
- buildユーザで実行した側は
- 2. Pigから呼び出されたTezClient中の処理(リモートデバッグ)
- buildユーザで実行した側は
tez.cluster.additional.classpath.prefix
の設定がない
- buildユーザで実行した側は
つまりはHadoopコマンド > Pig > Tezとなる中で設定が欠落しているのですが、
ざっとデバッグした時点では結論は見えずという状況。
ですので、Pigが読み込んでHadoopの設定に含めているファイルの pig.properties
に設定を追記して試してみました。
$ echo "tez.cluster.additional.classpath.prefix=/opt/cloudera/parcels/GPLEXTRAS/lib/hadoop/lib/hadoop-lzo.jar" >> /opt/pig/conf/pig.properties
再度実行
すると・・・?
/opt/pig/bin/pig -x tez -f test-lzo-count.pig
2016-04-24 22:16:17,439 [main] INFO org.apache.pig.tools.pigstats.tez.TezPigScriptStats - Script Statistics:
HadoopVersion: 2.6.0-cdh5.7.0
PigVersion: 0.15.0
TezVersion: 0.7.0
UserId: build
FileName: test-lzo-count.pig
StartedAt: 2016-04-24 22:16:06
FinishedAt: 2016-04-24 22:16:17
Features: GROUP_BY
Success!
DAG PigLatin:test-lzo-count.pig-0_scope-0:
ApplicationId: job_1461490474710_0025
TotalLaunchedTasks: 2
FileBytesRead: 99
FileBytesWritten: 67
HdfsBytesRead: 61480
HdfsBytesWritten: 7
Input(s):
Successfully read 1744 records (61480 bytes) from: "/user/pub/example-lzo"
Output(s):
Successfully stored 1 records (7 bytes) in: "hdfs://hadoophost01:8020/tmp/temp-1901693688/tmp-778527532"
(1744)
(1871-01-01,4.44,0.26,0.4,12.46,5.32,84.52,4.95,7.61,,,,,,,)
(1871-02-01,4.5,0.26,0.4,12.84,5.32,83.12,4.8,7.39,,,,,,,)
(1871-03-01,4.61,0.26,0.4,13.03,5.33,83.91,4.73,7.28,,,,,,,)
(1871-04-01,4.74,0.26,0.4,12.56,5.33,89.54,4.91,7.56,,,,,,,)
(1871-05-01,4.86,0.26,0.4,12.27,5.33,93.95,5.03,7.73,,,,,,,)
(1871-06-01,4.82,0.26,0.4,12.08,5.34,94.64,5.11,7.85,,,,,,,)
(1871-07-01,4.73,0.26,0.4,12.08,5.34,92.87,5.11,7.85,,,,,,,)
(1871-08-01,4.79,0.26,0.4,11.89,5.34,95.56,5.19,7.98,,,,,,,)
(1871-09-01,4.84,0.26,0.4,12.18,5.35,94.29,5.07,7.79,,,,,,,)
(1871-10-01,4.59,0.26,0.4,12.37,5.35,88.04,4.99,7.67,,,,,,,)
pig.properties
に設定した分はbuildユーザでも問題なく読み込むことがわかりました。
差分が発生する原因はわかりませんが、とりあえず解消はできた、という形になりますね。
クラスパスからHadoop設定オブジェクトを生成するときの挙動の差のようですが、
これは気長に追ってみることにします・・・
まとめ
- Pig on TezにLzoを追加する場合は下記の対応が必要
- Pig on Tez起動時のクラスパスにLzoライブラリを含める
- Tez動作時の追加クラスパス(
tez-site.xml
)にLzoライブラリを含める- ただし、一部のユーザでは
tez-site.xml
に含めても動作しない(原因が現状不明) - 上記の場合、
pig.properties
に記述すれば動作する。
- ただし、一部のユーザでは