AWS Glue for Spark のジョブから AWS CodeArtifact を経由して PyPI のライブラリをインストールする
こんにちは、リテールアプリ共創部のmorimorikochanです。
re:Invent 2024で公開されたAWS Glue 5.0の新機能の一つとして、AWS Glue for Spark のジョブで利用するPythonのライブラリをrequirements.txt
で指定できるようになりました。
しかし、企業のセキュリティポリシーによっては、PyPIからの直接インストールが自由に許可できない場合やインターネットに直接接続できないような環境もあるかと思います。
そのような場合には AWS CodeArtifactにPyPIのライブラリ管理を集約しつつAWS Glueのジョブから利用したくなると思うので、可能なのかを実際に検証してみました。
先に結論
requirements.txt
で指定する場合
ライブラリをrequirements.txt
ファイル内で直接--trusted-host
と--index-url
を指定することでAWS CodeArtifact経由でインストールすることができます。
その一方で、Job parametersの--python-modules-installer-option
オプションで直接--trusted-host
と--index-url
を指定してもエラーが出て異常終了します。
--additional-python-modules
にインラインで指定する場合
ライブラリをJob parametersの--python-modules-installer-option
オプションに直接--trusted-host
と--index-url
を指定することでインストールすることができます。
検証
以下の記事と同様の環境を用意しました。requirements.txt
指定でライブラリをインストールするAWS Glue 5.0のジョブがあればなんでもOKです。
AWS CodeArtifactの準備
AWS CodeArtifactのドメインとリポジトリを作成します。
こちらの検証内容を参考にリポジトリの作成を進めると、以下のような2つのリポジトリが作成されます。この時点ではリポジトリに何もライブラリが保存されていません。
aws-glue-package-installing-demo
リポジトリからインデックスURLを取得します。
$ CODEARTIFACT_AUTH_TOKEN=`aws codeartifact get-authorization-token --domain aws-glue-package-installing-demo --domain-owner 151671725617 --output text --query authorizationToken`
$ INDEX_URL=https://aws:$CODEARTIFACT_AUTH_TOKEN@aws-glue-package-installing-demo-151671725617.d.codeartifact.ap-northeast-1.amazonaws.com/pypi/aws-glue-package-installing-demo/simple/
ちなみに、末尾の/simple/
はPEP 503(Simple Repository API)で定義されたエンドポイントの仕様です。このエンドポイントの仕様に従ってpipなどのPythonパッケージマネージャーがパッケージのリストと関連メタデータを単純なHTML形式で取得するために使用するようです。
AWS CodeArtifactを知らない人向けの情報
このインデックスURLを使ってpip installを行うことで、AWS CodeArtifactに保存されているライブラリをインストールすることができます。
AWS CodeArtifactにまだ登録されていないライブラリは自動でAWS CodeArtifactがPyPIからダウンロードしてくれます。
# ローカルで指定した時
$ python3 -m pip install --no-cache --no-cache-dir -U --index-url INDEX_URL art
Looking in indexes: https://aws:****@aws-glue-package-installing-demo-151671725617.d.codeartifact.ap-northeast-1.amazonaws.com/pypi/aws-glue-package-installing-demo/simple
Collecting art
Downloading https://aws-glue-package-installing-demo-151671725617.d.codeartifact.ap-northeast-1.amazonaws.com/pypi/aws-glue-package-installing-demo/simple/art/6.5/art-6.5-py3-none-any.whl (610 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 610.4/610.4 kB 2.5 MB/s eta 0:00:00
Installing collected packages: art
Successfully installed art-6.5
[notice] A new release of pip is available: 25.0 -> 25.1
[notice] To update, run: pip install --upgrade pip
Glue 5.0のジョブのJob parameters設定
AWS Glue Studioのジョブの設定画面で、Job details > Advanced properties > Job parameters に2組のパラメータを設定し、実行します。
キー | 値 |
---|---|
--python-modules-installer-option | -r --index-url https://aws:****@aws-glue-package-installing-demo-151671725617.d.codeartifact.ap-northeast-1.amazonaws.com/pypi/aws-glue-package-installing-demo/simple --trusted-host aws-glue-package-installing-demo-151671725617.d.codeartifact.ap-northeast-1.amazonaws.com |
--additional-python-modules | {requirements.txtを指すS3URI} |
結果は、以下の通りエラーが発生しジョブが異常終了してしまいました。
STDError Stream: ERROR: Invalid requirement: '/tmp/glue-job-7009979284799843628/requirements.txt'Hint: It looks like a path. The path does exist. The argument you provided (/tmp/glue-job-7009979284799843628/requirements.txt) appears to be a requirements file. If that is the case, use the '-r' flag to install the packages specified within it.
エラーメッセージ
ERROR 2025-04-27T08:15:26,631 19580 com.amazonaws.services.glue.utils.concurrent.PythonModuleTask [pool-4-thread-1] 36 Setting Up Virtual Env and Application Python Modules encountered exception. Exception: Installation of Additional Python Modules failed, please see the logs for more details
com.amazonaws.services.glue.PythonModuleInstallException: Installation of Additional Python Modules failed, please see the logs for more details
at com.amazonaws.services.glue.PythonModuleInstaller.installCustomerPythonModules(PythonModuleInstaller.scala:139) ~[0rJH7L-aws-glue-di-package-5.0.400.jar:?]
at com.amazonaws.services.glue.utils.concurrent.PythonModuleTask.call(PythonModuleTask.scala:31) ~[0rJH7L-aws-glue-di-package-5.0.400.jar:?]
at com.amazonaws.services.glue.utils.concurrent.PythonModuleTask.call(PythonModuleTask.scala:14) ~[0rJH7L-aws-glue-di-package-5.0.400.jar:?]
at com.amazonaws.services.glue.utils.concurrent.GlueConcurrentAsyncProcessingService.$anonfun$processTaskAndReturnFuture$1(GlueConcurrentAsyncProcessingService.scala:40) ~[0rJH7L-aws-glue-di-package-5.0.400.jar:?]
at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:659) ~[scala-library-2.12.18.jar:?]
at scala.util.Success.$anonfun$map$1(Try.scala:255) ~[scala-library-2.12.18.jar:?]
at scala.util.Success.map(Try.scala:213) ~[scala-library-2.12.18.jar:?]
at scala.concurrent.Future.$anonfun$map$1(Future.scala:292) ~[scala-library-2.12.18.jar:?]
at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:33) ~[scala-library-2.12.18.jar:?]
at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:33) ~[scala-library-2.12.18.jar:?]
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64) [scala-library-2.12.18.jar:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
at java.lang.Thread.run(Thread.java:840) [?:?]
Caused by: java.lang.RuntimeException
... 14 more
INFO 2025-04-27T08:15:26,630 19579 com.amazonaws.services.glue.PythonModuleInstaller [pool-4-thread-1] 183 STDOUT Stream: additionalOptions -r --index-url https://aws:****@aws-glue-package-installing-demo-151671725617.d.codeartifact.ap-northeast-1.amazonaws.com/pypi/aws-glue-package-installing-demo/simple --trusted-host aws-glue-package-installing-demo-151671725617.d.codeartifact.ap-northeast-1.amazonaws.com, additionalPythonModules /tmp/glue-job-7009979284799843628/requirements.txt, virtualEnv /tmp/glue_venv Defaulting to user installation because normal site-packages is not writeable
INFO 2025-04-27T08:15:26,631 19580 com.amazonaws.services.glue.PythonModuleInstaller [pool-4-thread-1] 184 STDError Stream: ERROR: Invalid requirement: '/tmp/glue-job-7009979284799843628/requirements.txt'Hint: It looks like a path. The path does exist. The argument you provided (/tmp/glue-job-7009979284799843628/requirements.txt) appears to be a requirements file. If that is the case, use the '-r' flag to install the packages specified within it.
INFO 2025-04-27T08:15:26,630 19579 com.amazonaws.services.glue.PythonModuleInstaller [pool-4-thread-1] 182 exitCode Code: 1
どうやら、--python-modules-installer-option
オプションには-r
のみを指定しないといけないようです。
--index-url
と--trusted-host
を書いてみる
requirements.txtに直接一般的に、pipを使う際のオプションはrequirements.txt
ファイル内に直接記載することも可能なようです。私は今まで全く知りませんでした。
その仕組みを利用して、requirements.txt
ファイル内に--index-url
と--trusted-host
を以下のように直接書いてみます。
--index-url https://aws:****@aws-glue-package-installing-demo-151671725617.d.codeartifact.ap-northeast-1.amazonaws.com/pypi/aws-glue-package-installing-demo/simple --trusted-host aws-glue-package-installing-demo-151671725617.d.codeartifact.ap-northeast-1.amazonaws.com
art==6.4
このときの`requirements.txt`の内容
キー | 値 |
---|---|
--python-modules-installer-option | -r |
--additional-python-modules | {requirements.txtを指すS3URI} |
するとジョブは成功しライブラリを使った処理が正常に実行されました。
また、AWS CodeArtifactの画面からも該当のライブラリがリポジトリに登録されていることが確認できました。
requirements.txtを使わない場合
利用するライブラリを--additional-python-modules
にインラインで指定する場合は、--python-modules-installer-option
オプションに直接--index-url
と--trusted-host
を指定することでインストールすることができました。
キー | 値 |
---|---|
--python-modules-installer-option | --index-url https://aws:****@aws-glue-package-installing-demo-151671725617.d.codeartifact.ap-northeast-1.amazonaws.com/pypi/aws-glue-package-installing-demo/simple --trusted-host aws-glue-package-installing-demo-151671725617.d.codeartifact.ap-northeast-1.amazonaws.com |
--additional-python-modules | art==6.4 |
まとめ
ここまでの結果をまとめると以下のようになりました。
この機能のおかげで、AWS Glue for Sparkのジョブで利用するPyPIライブラリの厳密な管理が可能になったり、インターネット外からAWS CodeArtifactを経由してPyPIライブラリの利用が可能になったりと、AWS Glueを採用できる場面が増えたのではないでしょうか。
ライブラリをrequirements.txt
で指定する場合
requirements.txt
内で--trusted-host
と--index-url
を指定することでAWS CodeArtifact経由でインストールすることができます。
この設定方法はPypiやpipの使い方に慣れていないとなかなか気づかない部分だと思います。
その一方で、Job parametersの--python-modules-installer-option
オプションで直接--trusted-host
と--index-url
を指定してもエラーが出て異常終了します。
ライブラリを--additional-python-modules
にインラインで指定する場合
Job parametersの--python-modules-installer-option
オプションに直接--trusted-host
と--index-url
を指定することでAWS CodeArtifact経由でインストールすることができます。
参考情報
- https://peps.python.org/pep-0503/
- https://dev.classmethod.jp/articles/install-private-package-from-codeartifact/
- https://blog.hirokiky.org/entry/2024/12/24/091910
- https://docs.aws.amazon.com/ja_jp/glue/latest/dg/setup-vpc-for-pypi.html
- https://dev.classmethod.jp/articles/install-library-pip-without-internet-with-codeartifact/
- https://dev.classmethod.jp/articles/aws-glue5-python-requirements-txt/