AWS GlueでSpark開発をする

AWS Glueはフルマネージド名ETL(データの抽出、変換、ロード)サービスです。 S3やRDBのデータから、その形式を推定してカタログ登録してくれる機能があり、複数のデータソースを横断して処理するのにとても便利な感じです。 裏はSparkで動いており、SparkやPySparkのコードを書いて実行されるのと、ある程度の処理はWeb上でスクリプトを生成できるため、かなり取っつきやすいです。 Sparkは通常時は起動していないので立ち上がりに時間がかかりますが、Sparkのおもりをしなくて良いのはとても楽で、 バッチ処理といったそこまで応答速度を求められない処理に対してはかなりいい感じでフィットします。

実行のたびにゼロからSparkを起動するJob以外にも、常時稼働する開発エンドポイントやJupyter Notebookが用意されているため、Sparkの処理を自分で書く場合も開発しやすいです。 開発エンドポイントは裏でEMRが動いておりそれに皮をかぶせているだけっぽいんですが、コードを実行する以上の事をしようとすると少々面倒です。 今回はその辺りのコツみたいなのをまとめておきます。

AWS Glueの開発エンドポイントでWeb UIを見る

Spark開発において、Web UIは各ノードの状態やDataFrameがどのように処理されているのかを調べるのにとても便利です。 AWS GlueでVPC内に開発用のノートブックを実行すると、以下のようにSpark UIのリンクとして表示されますが、実際には内部のアドレスが使われるため通常はアクセスできません。 Spark Web UI

きちんと設定することでアクセスできそうですが、開発エンドポイントはずっと起動しておくにはコストが高く、使い終わったら消すといった運用の方が便利であり、都度設定するのは少々面倒(そう)でした。 今回は、VPC内に外部からAWS内に接続するための踏み台サーバがあったため、そこからSSHによってWeb UIを表示するという方法を取りました。

具体的には、開発エンドポイントに自分のマシンのSSHキーを登録します。 その後、開発エンドポイントのプライベートアドレスを調べ、以下のコマンドでlocalhost:20888を開発エンドポイントの同じポートに飛ばします。 なお、踏み台サーバは~/.ssh/configにgateway_serverという定義を書いて接続できるようにしていますので、適度に読み替えてください。
ssh -L 20888:AWS_PRIVATE_ADDRESS:20888 gateway_server

開発エンドポイントの設定画面

最後にSparkのapplication idを取得します。 PySparkを使ってる場合は、SparkContextのapplicationId以下のようにするため、spark_context.applicationIdを使います。

SparkのWeb UIは/proxy/APPLICATION_ID/jobs/以下にあるので、さっきのSSHによるローカルフォワードと合わせて以下のURLにアクセスすると、Web UIが表示されます。
http://localhost:20888/proxy/APPLICATION_ID/jobs/

PyCharmを使ったAWS Glue開発

開発エンドポイントに対してノートブックが使えるのは便利ですが、しっかり開発するとなると補完が使えるPyCharmが欲しくなります。 これに関しては、AWS GlueではzipにまとめたPythonライブラリを読み込む機能がサポートされているため、手元で開発した物を開発エンドポイント上で動かすことができます。
AWS Glue での Python ライブラリの使用

ただし、デバッグはしづらいためやはりブレークポイントといった物が使いたくなります。 幸いにも、PyCharmではリモートのPythonインタプリタに対してブレークポイントを仕掛けることができ、かつそれがAWS GlueのPythonインタプリタでも使えるため、 AWS GlueのPySparkで動くスクリプトを手元のPyCharmから開発出来ます。

基本的には以下の手順通りに設定をしていきます。

ただし、前述のようにVPC内にある開発エンドポイントには直接アクセスできません。 そのため、SFTPは以下のようにローカルフォワードする必要があります、なおローカル側のポート番号は10022にしています。 ssh -L :10022:AWS_PRIVATE_ADDRESS:22 gateway_server

また、開発エンドポイントからローカルに接続できるように、リモートフォワードも行います。 まずはssh -g -R :9001:localhost:9001 gateway_serverで踏み台サーバに入り、さらに ssh -g -R :9001:localhost:9001 glue@AWS_PRIVATE_ADDRESSで開発エンドポイント上のlocalhost:9001を手元のPyCharmまで通るようにします1

最後に、PyCharmのデバッグサーバを立ち上げ、開発エンドポイント上でpydevd.settrace('localhost',port=9001,suspend=False,stderrToServer=True)を書いたスクリプトを実行すると、手元のPyCharmでデバッグができるようになります。 また、前述した手順でapplication idを取得しておくとWeb UIで状態の確認もできるためとても快適に開発できます。


  1. 1個のコマンドで書けそうなんですが、なんか上手くいかなかったので2回SSHしています… ↩︎