はじめに こんにちは。TIG DXチームの村瀬です。
AWS Glue利用していますか? ETL処理をする上で大変便利ですよね。しかしながら開発に必要不可欠な開発エンドポイントが少々お高く、もう少し安価に利用できればなーと思っていたところ、さすがAWSさん素敵なリリースをしてくれました。
https://aws.amazon.com/jp/about-aws/whats-new/2019/08/aws-glue-releases-binaries-of-glue-etl-libraries-for-glue-jobs/
AWS Glueとは 過去のこちらの記事もご参考ください。
ローカルPCの環境を汚さない為に 作業を開始する前に確認したところ、Glueバージョン1.0を動かす場合にはSpark2.4.3が必要でそのSparkを動かす為にはJava 8が必要でまたPythonも3.6が必要とのこと。 依存関係が結構ありそうですね。
GlueをローカルPCで動かす為にJavaやPythonのバージョン変えるの嫌だなぁ。チームメンバーも嫌がるだろうし環境構築の為の手順用意するの面倒だしトラブった時に対応したくないなと思ったのでローカルPCの環境を汚さないように今回はDockerで用意してみることにしました。
https://docs.aws.amazon.com/ja_jp/glue/latest/dg/aws-glue-programming-etl-libraries.html を参考にPython,Java,Glueライブラリ,Maven,Glueアーティファクトを取得・インストールするよう記載したDockerfileを用意して実行してみると… (※Dockerfileは後ほど出てきます)
ハマリポイント ./aws-glue-libs/bin/gluepyspark 実行時にエラー発生
~中略~ py4j.protocol.Py4JJavaError: An error occurred while calling None.org.apache.spark.api.java.JavaSparkContext. : java.lang.NoSuchMethodError: io.netty.buffer.PooledByteBufAllocator.defaultNumHeapArena()I at org.apache.spark.network.util.NettyUtils.createPooledByteBufAllocator(NettyUtils.java:113) at org.apache.spark.network.client.TransportClientFactory.<init>(TransportClientFactory.java:106) at org.apache.spark.network.TransportContext.createClientFactory(TransportContext.java:99) at org.apache.spark.rpc.netty.NettyRpcEnv.<init>(NettyRpcEnv.scala:71) at org.apache.spark.rpc.netty.NettyRpcEnvFactory.create(NettyRpcEnv.scala:461) at org.apache.spark.rpc.RpcEnv$.create(RpcEnv.scala:57) at org.apache.spark.SparkEnv$.create(SparkEnv.scala:249) at org.apache.spark.SparkEnv$.createDriverEnv(SparkEnv.scala:175) at org.apache.spark.SparkContext.createSparkEnv(SparkContext.scala:257) at org.apache.spark.SparkContext.<init>(SparkContext.scala:424)
すんなり行きませんでした。 エラーを確認するとio.netty.buffer.PooledByteBufAllocator.defaultNumHeapArena()なんて無いよと言われていますね。
無いと言われているものを探してみます。find / -name *netty*
/opt/spark-2.4.3-bin-spark-2.4.3-bin-hadoop2.8/jars/netty-3.9.9.Final.jar /opt/spark-2.4.3-bin-spark-2.4.3-bin-hadoop2.8/jars/netty-all-4.1.17.Final.jar ~中略~ /aws-glue-libs/jarsv1/netty-3.6.2.Final.jar /aws-glue-libs/jarsv1/netty-all-4.0.23.Final.jar /aws-glue-libs/jarsv1/netty-buffer-4.1.17.Final.jar /aws-glue-libs/jarsv1/netty-codec-4.1.17.Final.jar /aws-glue-libs/jarsv1/netty-codec-http-4.1.17.Final.jar /aws-glue-libs/jarsv1/netty-common-4.1.17.Final.jar /aws-glue-libs/jarsv1/netty-handler-4.1.17.Final.jar /aws-glue-libs/jarsv1/netty-resolver-4.1.17.Final.jar /aws-glue-libs/jarsv1/netty-transport-4.1.17.Final.jar
??? いっぱい見つかりますね。
先人の知恵を借りましょう。stackoverflow Spark 2.3 java.lang.NoSuchMethodError: io.netty.buffer.PooledByteBufAllocator.metric
どうやらNettyのjarのバージョンが合ってないことが原因のようです。 改めて比較して確認してみるとspark側のjarのバージョンの方が新しいですね。
spark /netty-3.9.9.Final.jar /netty-all-4.1.17.Final.jar
aws-glue-libs /netty-3.6.2.Final.jar /netty-all-4.0.23.Final.jar
またまた先人の知恵を借りましょう。GitHub gluepyspark errors on local development #25
どうやらaws-glue-libsを参照せずにsparkのjarファイルを参照すれば良いようです。ln -s ${SPARK_HOME}/jars /aws-glue-libs/jarsv1
これでdocker buildがエラーなく成功し、docker runした上でdocker execでコンテナに入り、この状態で以下のコマンドを実行すると./aws-glue-libs/bin/gluepyspark
~中略~ 19/10/25 09:58:38 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties Setting default log level to "WARN". To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel). Welcome to ____ __ / __/__ ___ _____/ /__ _\ \/ _ \/ _ `/ __/ '_/ /__ / .__/\_,_/_/ /_/\_\ version 2.4.3 /_/ Using Python version 3.6.8 (default, Aug 7 2019 17:28:10) SparkSession available as 'spark'. >>>
無事にSparkを起動できました。
Dockerfile みんなお待ちかねのDockerファイルはこちら
Dockerfile FROM centos:7 MAINTAINER Future y.muraseRUN yum install -y bzip2 bzip2-devel gcc gcc-c++ make openssl-devel readline-devel zlib-devel wget curl unzip vim epel-release git && yum install -y tig jq vim-enhanced bash-completion net-tools bind-utils \ && yum install -y https://centos7.iuscommunity.org/ius-release.rpm \ && yum install -y python36u python36u-libs python36u-devel python36u-pip \ && yum install -y java java-1.8.0-openjdk-devel \ && rm -rf /var/cache/yum/* RUN localedef -f UTF-8 -i ja_JP ja_JP.UTF-8 ENV LANG ja_JP.UTF-8 ENV LC_CTYPE "ja_JP.UTF-8" ENV LC_NUMERIC "ja_JP.UTF-8" ENV LC_TIME "ja_JP.UTF-8" ENV LC_COLLATE "ja_JP.UTF-8" ENV LC_MONETARY "ja_JP.UTF-8" ENV LC_MESSAGES "ja_JP.UTF-8" ENV LC_PAPER "ja_JP.UTF-8" ENV LC_NAME "ja_JP.UTF-8" ENV LC_ADDRESS "ja_JP.UTF-8" ENV LC_TELEPHONE "ja_JP.UTF-8" ENV LC_MEASUREMENT "ja_JP.UTF-8" ENV LC_IDENTIFICATION "ja_JP.UTF-8" ENV LC_ALL ja_JP.UTF-8 RUN git clone -b glue-1.0 --depth 1 https://github.com/awslabs/aws-glue-libs RUN curl -OL https://archive.apache.org/dist/maven/maven-3/3.6.2/binaries/apache-maven-3.6.2-bin.tar.gz RUN tar -xzvf apache-maven-3.6.2-bin.tar.gz RUN mv apache-maven-3.6.2 /opt/ RUN ln -s /opt/apache-maven-3.6.2 /opt/apache-maven ENV JAVA_HOME /usr/lib/jvm/java-1.8 .0 -openjdk/jre/ENV PATH $PATH:/opt/apache-maven/binRUN mvn -version RUN curl -OL https://aws-glue-etl-artifacts.s3.amazonaws.com/glue-1.0/spark-2.4.3-bin-hadoop2.8.tgz RUN tar -xzvf spark-2.4.3-bin-hadoop2.8.tgz RUN mv spark-2.4.3-bin-spark-2.4.3-bin-hadoop2.8 /opt/ RUN ln -s /opt/spark-2.4.3-bin-spark-2.4.3-bin-hadoop2.8 /opt/spark ENV SPARK_HOME /opt/sparkRUN unlink /bin/python RUN ln -s /bin/python3 /bin/python RUN ln -s /bin/pip3.6 /bin/pip RUN ln -s ${SPARK_HOME} /jars /aws-glue-libs/jarsv1 RUN ./aws-glue-libs/bin/gluepyspark ENTRYPOINT ["/bin/sh" , "-c" , "while :; do sleep 10; done" ]
まとめ 少々苦労しましたが先人の知恵を借りて問題解決できました。 これで複数いる開発メンバーにDockerイメージさえ渡せばローカル環境を汚すことなく簡単にかつお財布にやさしくローカルPCにGlueの開発環境が用意できますね。 Glueのローカル開発環境構築にチャレンジしたけどエラーが出て諦めてしまった人の手助けになれたら幸いです。
なお、この記事を作成する上で以下のページを参考にさせていただきました。https://aws.amazon.com/jp/about-aws/whats-new/2019/08/aws-glue-releases-binaries-of-glue-etl-libraries-for-glue-jobs/ https://docs.aws.amazon.com/ja_jp/glue/latest/dg/aws-glue-programming-etl-libraries.html https://omohikane.com/centos7_docker_python36/ https://stackoverflow.com/questions/50388919/spark-2-3-java-lang-nosuchmethoderror-io-netty-buffer-pooledbytebufallocator-me https://github.com/awslabs/aws-glue-libs/issues/25