AWS Glueジョブには2つの種類が存在します。
- ETLジョブ(Spark)
PySparkコードが実行できるジョブ。
最低でも10並列で実行するので、DynamicFrame/DataFrame操作以外の処理はPython Shellジョブを使ったほうがよい。
- Python Shellジョブ
通常のPythonコードを実行することのできるジョブ。
上記のジョブはともにAWSが提供する固定のコンテナイメージを使ってFaaSとして実行されます。なので、あらかじめ用意されたPythonパッケージがプリロードされた状態でコードを実行します。
コード内にプリロードされていないPythonパッケージを使う場合は、Pythonパッケージの導入を設定する必要があります。
AWS Glueのドキュメントにかかれている方法は以下のとおり
- library-setを使う(Python Shell Python3.9ジョブのみ)
library-setというパラメータに"analytics"を指定すると、データ分析によく使われるパッケージがプリインストールされます(導入されるパッケージはドキュメントを参照してください)。このプリインストールパッケージで済む場合は、この方法を使ってください。
ただし、これはPython ShellジョブだけなのでETLジョブの場合は使用できません。
- S3上にライブラリを配置してジョブから参照させる
ExtraPythonLibsS3Path/--extra-py-filesというパラメータを使うと、ジョブスクリプトファイル以外のPythonコードファイルを追加できます。このパラメータにファイルもしくはファイル群(Zip)をS3に置いて実行時参照させることができます。Zipではなくwhlファイルでも有効らしいのですが私はためしていません。そして重要なことは、純粋なPythonコードのみが対象になります。libxxxx.soなどのシェアードオブジェクトを使うPythonライブラリの場合Zipに含めても動作しませんでした(個人試行の結果です)。
ジョブ実行ロールにS3へのアクセス許可設定は必要です。
- --additional-python-modulesを使ってPythonパッケージをpip installさせる
このオプションを使うとスクリプト実行前にpip installしてくれます。先程シェアードオブジェクトを含むzipがうまくいかないという場合は、こちらを試してみてください。ただし、AWS GlueジョブがIGW経由でPyPIにつながるVPC環境で実行される必要があります。PROXY指定しないとインターネットへ接続できない環境下のVPCの場合は失敗します。
AWS Glueジョブは公式ドキュメントどおりのセキュリティグループ設定をすると、接続するDBがある場合はそのDBがあるVPC内にコンテナが作られているかのような動作を行います。コンテナ自体のIPアドレスはAutoNumberになっていて、正直どのVPC傘下なのかわかっていませんが、おそらくAWS Glue用のプライベートVPCが暗黙にあって、そこでインスタンス化され、指定のセキュリティグループの許可する通信のみを実行するようです。そこで何も接続しない場合はよいのですがDB接続などを指定したジョブはそのDBにしかつながらなくなるようなのです。これも私個人の経験則ですけど..
- Pythonジョブスクリプト内でpip installを実行する(Python Shellジョブのみ)
PROXY管理下のVPC環境などでpip installしたい場合は、スクリプトの中でpip install --proxy http://proxy.sample.com:8080 hogehogeするしかありません。
Python Shellジョブをlibrary-set:analyticsにして動かすとプリインストールパッケージにpipがあるので、このライブラリを使ってinstallします。
import pip
def pip_install(package:str, proxy_url=None) ->None:
if hasattr(pip, 'main'):
if proxy_url is None:
pip.main(['install', package])
#print('pip.main no_proxy')
else:
pip.main(['install', '--proxy', proxy_url, package])
#print(f'pip.main proxy:{proxy_url}')
else:
if proxy_url is None:
pip._internal.main(['install', package])
#print('pip._internal.main no_proxy')
else:
pip._internal.main(['install', '--proxy', proxy_url, package])
#print(f'pip._internal.main proxy:{proxy_url}')
pip_install('psycopg2-binary', 'http://proxy.sample.com:8080')
AWS Glueは提供側の想定がデータ分析が中心なので、ここまでして外部ライブラリをインストールしないといけない場合は、他の方法での実装が正しい解なのかもしれませんが..ご参考まで。