2022年2月18日金曜日

「AWS Glueをローカル環境で実行してみた」をやったときのメモ

クラスメソッドのAWS Glueをローカル環境で実行してみた をやってみましたが、バージョン違いの設定で大変でした。二年半くらい経っているから当然なのかも。以下、エラー回避のメモ。

うまく行ったときのバージョン

  • Ubuntu 20.04
  • Python 3.7
  • aws-cli/2.4.11
  • Apach maven 3.6.3
  • Java java-8-openjdk-amd64
  • Apach Spark spark-2.4.3-bin-hadoop2.8
  • LocalStack 0.14.0
  • docker-compose version 1.29.2


https://github.com/localstack/localstack

https://github.com/awslabs/aws-glue-libs

https://docs.aws.amazon.com/ja_jp/glue/latest/dg/aws-glue-programming-etl-libraries.html#develop-local-python


SPARK

対応するバージョンをダウンロードして、SPARK_HOMEを設定するだけでよい。

SPARK_HOME=自分のフォルダ.../spark-2.4.3-bin-spark-2.4.3-bin-hadoop2.8

aws-glue-libs

glueのバージョンに合わせてブランチを選んでclone

https://github.com/awslabs/aws-glue-libs


ここでは、フォルダ名を変えている。/aws-glue-libs-2.0/


LocalStack

こちらを参考にした。

https://zenn.dev/s_ryuuki/articles/412b5f004595b7


awslocalを使う

endpointを解決してくれるので便利

--endpoint-url http://localhost:45xx という指定を省いてよい。

https://github.com/localstack/awscli-local



--profile localstack を使って以下のようなコマンドで操作


awslocal dynamodb create-table \

    --table-name aws-glue-local-test-table \

    --attribute-definitions \

        AttributeName=Id,AttributeType=S \

    --key-schema AttributeName=Id,KeyType=HASH \

    --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 \

    --profile localstack



awslocal dynamodb put-item \

    --table-name aws-glue-local-test-table  \

    --item \

        '{"Id": {"S": "test"}, "Column1": {"S": "test1"}, "Column2": {"S": "test2"}, "Column3": {"S": "test3"}}' \

    --profile localstack



awslocal s3api create-bucket \

    --bucket aws-glue-local-test-bucket \

    --profile localstack



awslocal s3api list-buckets \

    --profile localstack



awslocal s3api list-objects \

    --bucket aws-glue-local-test-bucket \

    --profile localstack

エンドポイントが合っていないというエラー

あとでも出てくる

Connection was closed before we received a valid response from endpoint URL: "http://localhost:4572/aws-glue-local-test-bucket".


    ports:

      - "4566:4566"

      - "4571:4571"

にするとできた。

4566は全てのサービスのポート?TODO


OKのとき

docker container ls

CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS                                                                     NAMES

89b2de708a51        localstack/localstack   "docker-entrypoint.sh"   2 minutes ago       Up 2 minutes        0.0.0.0:4566->4566/tcp, 4510-4559/tcp, 5678/tcp, 0.0.0.0:4571->4571/tcp   localstack


NGのとき

CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS              											NAMES

b7a6a3bf62f6        localstack/localstack   "docker-entrypoint.sh"   53 seconds ago      Up 49 seconds       4510-4559/tcp, 0.0.0.0:4569->4569/tcp, 4566/tcp, 0.0.0.0:4572->4572/tcp, 5678/tcp, 0.0.0.0:8080->8080/tcp   localstack


実行

./bin/gluesparksubmit ./src/sample.py --JOB_NAME='dummy'


最初はGlue ETLライブラリのバイナリをダウンロードするので時間かかる。

37分だった。

logが多数でるが、INFO、WARNは軽く読んでERRORに対処する。

WARNだとこういうのもあったが無視した。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-expired-token/


JDKが入っていないので、/jre/tools.jarがないというエラー

[INFO] ------------------------------------------------------------------------

[INFO] BUILD FAILURE

[INFO] ------------------------------------------------------------------------

[INFO] Total time:  37:51 min

[INFO] Finished at: 2022-02-17T11:07:06+09:00

[INFO] ------------------------------------------------------------------------

[ERROR] Failed to execute goal on project AWSGlueETLPython: Could not resolve dependencies for project com.amazonaws:AWSGlueETLPython:jar:3.0.0: Could not find artifact jdk.tools:jdk.tools:jar:1.8 at specified path /usr/lib/jvm/java-8-openjdk-amd64/jre/../lib/tools.jar -> [Help 1]

[ERROR]

[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.

[ERROR] Re-run Maven using the -X switch to enable full debug logging.

[ERROR]

[ERROR] For more information about the errors and possible solutions, please read the following articles:

[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

インストールする

sudo apt-get install openjdk-8-jdk

確認 

/usr/lib/jvm/java-8-openjdk-amd64$ find ./ -type f | grep tools 

./lib/tools.jar が出るはず


BUILDは成功するがその後でエラー

再実行。同じコマンド(./bin/gluesparksubmit ./src/sample.py --JOB_NAME='dummy')で

2分くらいでできた。


sample.pyでjob.initがおかしいらしい

22/02/17 12:58:57 INFO BlockManagerMaster: Registered BlockManager BlockManagerId(driver, 192.168.10.105, 41321, None)

22/02/17 12:58:57 INFO BlockManager: Initialized BlockManager: BlockManagerId(driver, 192.168.10.105, 41321, None)

22/02/17 12:58:57 INFO GlueContext: GlueMetrics not configured

22/02/17 12:58:57 INFO GlueContext: fs.s3.impl hadoop configuration is not set. Setting fs.s3.impl to org.apache.hadoop.fs.s3a.S3AFileSystem

Traceback (most recent call last):

  File ".../aws-glue-libs/./src/sample.py", line 19, in <module>

    job.init(JOB_NAME, args)

  File ".../aws-glue-libs/PyGlue.zip/awsglue/job.py", line 42, in init

  File "/home/shimo/Desktop/app/spark-2.2.1-bin-hadoop2.7/python/lib/py4j-0.10.4-src.zip/py4j/java_gateway.py", line 1133, in __call__

  File "/home/shimo/Desktop/app/spark-2.2.1-bin-hadoop2.7/python/lib/pyspark.zip/pyspark/sql/utils.py", line 63, in deco

  File "/home/shimo/Desktop/app/spark-2.2.1-bin-hadoop2.7/python/lib/py4j-0.10.4-src.zip/py4j/protocol.py", line 319, in get_return_value

py4j.protocol.Py4JJavaError: An error occurred while calling z:com.amazonaws.services.glue.util.Job.init.

: java.lang.NoSuchMethodError: scala.Product.$init$(Lscala/Product;)V


tokenがエラー( The security token included in the request is invalid)

An error occurred (UnrecognizedClientException) when calling the CreateTable operation: The security token included in the request is invalid.

これは認証というよりエンドポイントの問題だった


Python2.7, glue 0.9にしたがNG

sudo pip2 install pyspark


Python2.7用にしようかとglue0.9を入れたりしたが、submit実行してもうまく行かず。このエラーのdynamicframeが見つからないというのは、モジュールのルートの選択がおかしいようですが、いまいち進めず。


rm: cannot remove '.../aws-glue-libs-0.9/conf/spark-defaults.conf': No such file or directory

.../aws-glue-libs-0.9

SLF4J: Class path contains multiple SLF4J bindings.

SLF4J: Found binding in [jar:file:.../aws-glue-libs-0.9/jars/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]

SLF4J: Found binding in [jar:file:/home/shimo/Desktop/app/spark-2.2.1-bin-hadoop2.7/jars/slf4j-log4j12-1.7.16.jar!/org/slf4j/impl/StaticLoggerBinder.class]

SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.

SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]

Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties

22/02/17 14:06:58 WARN Utils: Your hostname, v3268 resolves to a loopback address: 127.0.1.1; using 192.168.10.105 instead (on interface enp2s0)

22/02/17 14:06:58 WARN Utils: Set SPARK_LOCAL_IP if you need to bind to another address

Traceback (most recent call last):

  File ".../aws-glue-libs-0.9/./src/sample.py", line 2, in <module>

    from awsglue.transforms import ApplyMapping

  File ".../aws-glue-libs-0.9/PyGlue.zip/awsglue/__init__.py", line 13, in <module>

ModuleNotFoundError: No module named 'dynamicframe'


awsglue2.0, Python3.7にする

改めてやり直して実行してエラー。

22/02/17 15:30:31 WARN EC2MetadataUtils: Unable to retrieve the requested metadata (/latest/dynamic/instance-identity/document). Failed to connect to service endpoint:

com.amazonaws.SdkClientException: Failed to connect to service endpoint:


22/02/17 15:49:35 ERROR Executor: Exception in task 0.0 in stage 0.0 (TID 0)

java.lang.RuntimeException: Could not lookup table aws-glue-local-test-table in DynamoDB.


この一文によると、us-east-1にアクセスしている→これはエンドポイントの指定ができていないときのデフォルトだった

22/02/17 15:49:34 INFO DynamoDBUtil: Using endpoint for DynamoDB: dynamodb.us-east-1.amazonaws.com


spark-defaults.confを正しく設定すると動いた

あれこれエラーが出ていたけど、これで直った。(他にも効いているかもしれないけど)

confにポートの情報を入れているけど、上書きされて消えている

.../aws-glue-libs-2.0/conf/spark-defaults.conf


bin/glue-setup.shがconfファイルをいじっているようなので、ここらへんをコメントアウト

mkdir $SPARK_CONF_DIR

rm $SPARK_CONF_DIR/spark-defaults.conf

Generate spark-defaults.conf

echo "spark.driver.extraClassPath $GLUE_JARS_DIR/*" >>$SPARK_CONF_DIR/spark-defaults.conf

echo "spark.executor.extraClassPath $GLUE_JARS_DIR/*" >>$SPARK_CONF_DIR/spark-defaults.conf


docker-compose.ymlのポート部分を変えている

version: "3.3"


services:

  localstack:

    container_name: localstack

    image: localstack/localstack

    ports:

      - "4566:4566"

      - "4571:4571"

    environment:

      - DOCKER_HOST=unix:///var/run/docker.sock

      - DEFAULT_REGION=ap-northeast-1

      - SERVICES=dynamodb,s3


 

spark-defaults.conf 

はこうしておく


spark.hadoop.dynamodb.endpoint http://localhost:4566

spark.hadoop.fs.s3a.endpoint http://localhost:4566

spark.hadoop.fs.s3a.path.style.access true

spark.hadoop.fs.s3a.signing-algorithm S3SignerType


どちらもlocalhost:4566 にした。他のポートでもできるのかもTODO

0 件のコメント:

コメントを投稿