« ^ »

AWS Glueを使う

所要時間: 約 5分

AWSにはデータの検出、準備、統合をする所謂ETL処理をサーバーレスで行う為のサービスとして「AWS Glue」を提供している。Pythonなどのスクリプトも実行できるため、データの加工処理の為に起動していたEC2やECSコンテナが不要になる。今回はPythonスクリプトを AWS Glue のGlueジョブとして登録し、実行する事にした。

簡単な作成と実行の手順

まずは簡単なジョブを作成し実行する。実行するスクリプトは、標準出力へ「 Ok 」と出力するだけの簡単なスクリプトを使う。

print("Ok")

ETLジョブを作成する

まずETLジョブを作成する。

  1. AWS GlueでPythonスクリプトを実行する際に使用する、実行ロール(IAM Role)を作成する。
  2. AWS ConsoleのGlueStudioでジョブの登録を開始する。 https://ap-northeast-1.console.aws.amazon.com/gluestudio/home?region=ap-northeast-1#/jobs 今回は「 Python Shell script editor 」を選択する。
  3. ローカルのファイルをアップロードする。 Optionsで「 Upload and edit an existing script 」を選択し、ファイルをアップロードする。
  4. 登録する。 「Create」ボタンをクリックし、登録する。

作成したETLジョブを設定する

作成したETLジョブを実行可能な状態になるように設定する。

  1. 「Job details」タブを表示する。
  2. 「Name」に付けたい名前を入力する。
  3. 「IAM Role」のプルダウンから、使用できるIAM Roleを選択する。
  4. 「Python version」のプルダウンから、使いたいバージョンを選択する。
  5. 「Job timeout (minutes)」を1にする。 タイムアウトは最長48時間待つ事ができる。今回の場合、直ぐに終了するため待つ事はないが、ずっと待たれても困るのでタイムアウトを1分に設定した。
  6. 「Advanced properties」の「Script Filename」に付けたいファイル名を入力する。
  7. 「Save」ボタンをクリックし保存する。

作成したETLジョブを実行し結果を確認する

  1. 「Run」ボタンをクリックする。
  2. 「Runs」タブを表示すると実行状態を確認できる。 Cloudwatch logsのログストリームを作成し追記する権限があれば、ログストリームが作られるため、Cloudwatch logsで出力を確認できる。

Pythonの実行環境

Pythonの実行環境はバージョンを幾つか選択できる。ノーマルな状態なものを使用しても、そこそこパッケージが予めインストールされている。例えばboto3やPyMySQLのようなライブラリは既に入っている。どのパッケージが入っているかは、公式のドキュメントから確認できる1

パーミッションとアシュームロール

AWS GlueのETLジョブとしてPythonシェルを使用する場合、実行ロールには最低でもS3への権限と、アシュームロールの設定が必要となる。

S3へのパーミッション

スクリプトがS3にアップロードされる事を考えると、当然S3への権限が必要となる。それについて公式のドキュメントにも記述されている2

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
             ],
            "Resource": "*"
        }
    ]
}
AWSGlueMinimalPolicy

リソースはもっと絞った方が良いかもしれない。またSSE-KMSを使う場合は、その権限も必要となる。それも公式のドキュメントに記載がある。

アシュームロール

ジョブの実行には、以下の権限が必要となる。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "glue.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

Cloudwatch Logsへのパーミッション

一応これまでの状態の権限を付けてあげれば、ジョブ自体は実行できる。ただし、標準出力や標準エラー出力はCloudwatch Logsとして出力されるため、Cloudwatch Logsへの権限がないとスクリプトの出力を確認できない。

スクリプトにパラメータを渡す

この実行方法の場合、実行環境に対して環境変数を設定する手段がない。もちろんスクリプト内で設定はできるが、それでは意味がない。変わりに起動オプションを指定できる。そこで起動オプションにパラメータを設定する事になる。

この起動オプションの仕組みが結構やっかいで、最初から設定されている起動パラメータもあり、そこに更に指定したいパラメータを追加していく。そのため、AWS Glueが必要としている物と、スクリプトが必要としている物が混在する。起動オプションだからsys.argvからアクセス可能ではあるけれど、シンプルにargparseで解析する場合、AWS Glueが必要としているオプションも解析する事になってしまう。これは面倒だ。

AWS Glueではそれを回避する為に awsglue というパッケージを提供していて、これを用いてオプションを解析できるようにしている。

例えば "–FOO_PARAM 3" と指定されるように、新しくオプションを追加した場合、 awsglue.utils.getResolvedOptions を使って解析し、最後の行が評価されると "3" という値となる。

from awsglue.utils import getResolvedOptions

aws_glue_args = getResolvedOptions(
    sys.argv, [
        "FOO_PARAM",
    ])

aws_glue_args["FOO_PARAM"]  # => "3"

VPC内での実行

VPC内に設置されているRDS等と接続する場合、Connectionsで接続設定を事前に作成しておく必要がある。これを作成した後、GlueジョブにConnectionsを関連付ける事で、VPC内にあるコンポーネントとのネットワーク接続ができるようになる3