AWS Glue -> Athena -> Lambdaと使ってみてハマったこと


AthenaはデータソースにS3を指定できて気軽に使えるんですが、ハマるときはハマる。

An error occurred (InvalidRequestException) when calling the Start QueryExecution operation: Unable to verify/create output bucket

AthenaのOutputLocationに対して権限が足りないと言われる。

IAMのPolicyでResourceに必要なarnを指定していましたが、
arn:aws:s3:::athena-target-data/inpot/*
arn:aws:s3:::athena-target-data/export/*
これだとエラーになりました。不十分なようです。
arn:aws:s3:::athena-target-data/*
ならばと、すべて与えてみましたがこれもエラー。

正確には、
arn:aws:s3:::athena-target-data
と指定しないと十分なResourceの指定とならないようでした。
(S3権限付与の一般常識なのかもしれない)

以下が正常に動いた時の設定。

"LambdaAthenaPolicy": {
    "Type": "AWS::IAM::ManagedPolicy",
    "Properties": {
    "ManagedPolicyName": "athena-query-excute-lambda-policy",
    "PolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
        {
            "Effect": "Allow",
            "Action": ["s3:*"],
            "Resource": [
            "arn:aws:s3:::athena-target-data",
            "arn:aws:s3:::athena-target-data/*"
            ]
        },

Hiveのpartitionに沿ったkeyにしたらLambdaが反応しない

Hiveのpartitionを利用したかったので以下のようなkeyに出力結果を出していました。

export/id=hogehoge/year=2017/month=12/day=19/1234567890.csv

このkeyに対してLambda functionを仕込もう思い、下記のようにprefixを指定したが発火しませんでした。

                {
                    "Name": "prefix",
                    "Value": "export/id="
                }

原因はどうやら = らしく、これを取ると発火するようになりました。
試してないですがもしかしたらURLエンコードをすればよいのかも。

以下が正常に動いた時の設定。

"S3Bucket": {
    "Type": "AWS::S3::Bucket",
    "Properties": {
    "BucketName": "athena-target-data",
    "NotificationConfiguration": {
        "LambdaConfigurations": [
        {
            "Function": {
            "Fn::GetAtt": ["LambdaCopyFile", "Arn"]
            },
            "Event": "s3:ObjectCreated:*",
            "Filter": {
            "S3Key": {
                "Rules": [
                {
                    "Name": "prefix",
                    "Value": "export/id"
                },
                {
                    "Name": "suffix",
                    "Value": "csv"
                }
                ]
            }
            }
        },

zipでも読み込めると書いてあったが読み込めない

Adding Classifiers to a Crawler - AWS Glue
Supported Data Formats, SerDes, and Compression Formats - Amazon Athena

Files in the following compressed formats can be classified:

ZIP (as compression format, not as archive format)
BZIP
GZIP
LZ4
Snappy (as standard Snappy format, not as Hadoop native Snappy format)

CSVのときと同じ設定でよろしくやってくれると思ったんですが、そこまで甘くはなかった。
SERDEの設定を変える必要があると思うのだが、何に変えればいいのかがわからなかった。
ドキュメントを見ても見当たらなかったので、Crawlerでターゲットのzipを対象にして作成したテーブル設定を見ることで解決。

SERDEが org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe になっていたが、 org.apache.hadoop.hive.serde2.OpenCSVSerde でもOK.

Crawlerを使うとTable propertiesに compressionType : ziptypeOfData : file が付いてくるので必要そうに見えるが、これらは不要。
あくまでもタグとしての利用っぽい。

さいごに

ちょっと癖はあるけど設定できてしまえばS3をさくさく検索できてとっても便利。
だけどS3 SELECTのほうが気軽に使えるし速いし、今後はAthena使うこと減りそうな気もする。
GlueのJobはしっかり使えればかなり便利になりそうなので、Glueは引き続き使っていこうと思う。