タスクの結果をS3に保存してみた | Luigi Advent Calendar 2016 #08

2016.12.08

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

好物はインフラとフロントエンドのかじわらゆたかです。

このエントリは『Luigi Advent Calendar 2016』8日目の内容となります。
今回はS3にファイルを保存していきたいと思います。

先日7日目は設定ファイルを記載してみたでした。

今まではLuigiの出力結果はローカルに保存するのみでしたが、
出力結果をS3に保存してみたいと思います。
また、上記に伴うCredentialの扱いについても調べてみたいと思います。

下準備

import luigi
import datetime


class createTargetFile(luigi.Task):
    fileName = luigi.Parameter()

    def output(self):
        return luigi.LocalTarget(self.fileName)

    def run(self):
        with self.output().open('w') as out_file:
            out_file.write(datetime.datetime.now().isoformat())

if __name__ == '__main__':
    luigi.run()

パラメータ名にファイル名を指定し、そのファイルに対して日付を書き込んでローカルに保存すると言ったタスクになります。

タスクの結果をS3へ保存してみた

LuigiではS3に保存するためのクラスが既に用意されているため、それらを用いてS3への保存を行います。
ファイルの保存についてはローカルにファイルを書き出したときと同様です。

outputメソッドの戻り値にluigi.s3.S3Targetで出力先を指定し、
runメソッドでそれらの中身に対して書き込みを行うと行った形です。

上記のファイル参照と合わせると以下のようになります。

putS3.py

import luigi
import datetime
import luigi.s3


class createTargetFile(luigi.Task):
    fileName = luigi.Parameter()

    def output(self):
        return luigi.LocalTarget(self.fileName)

    def run(self):
        with self.output().open('w') as out_file:
            out_file.write(datetime.datetime.now().isoformat())
class putS3(luigi.Task):

    bucketName = luigi.Parameter(default="cm-kajiwara-luigi-study")
    fileName = luigi.Parameter(default="outputSample.txt")

    def requires(self):
        return createTargetFile(self.fileName)

    def output(self):
        return luigi.s3.S3Target("s3://{}/{}".format(self.bucketName, self.fileName))

    def run(self):
        with self.input().open('r') as input, self.output().open('w') as out_file:
            for line in input:
                out_file.write(line)

動かすに当たってはPythonのAWS SDKであるbotoが必要です。
boto3ではなく、botoなのでインストールするライブラリには注意が必要です。
インストール自体はpipで管理をしているならば、以下コマンドで対応が可能です。

$ pip install boto

AWSリソースを動かすためのCredentialの指定について調べていきます。

Credentialの指定 環境変数に対してCredentialを直接記載

これはbotoの機能になるのですが、環境変数にACCESS_KEY/SECRET_ACCESS_KEYを記載することで、動かすことが可能です。

$ AWS_ACCESS_KEY_ID=<AWS_ACCESS_KEY_ID> AWS_SECRET_ACCESS_KEY=<AWS_SECRET_ACCESS_KEY> python ./putS3.py --local-scheduler putS3

なお、上記を動かすと以下のようなファイルがS3に配置されます。

outputSample.txt

2016-11-17T04:11:47.347900

Credentialの指定 環境変数に対してProfileを指定

複数のAWS Credentialを扱う方法として、~/.aws/credential に複数記載し、profileで指定すると言ったことも可能です。 この場合は以下のようになります。

$ AWS_PROFILE=sample_profile python ./putS3.py --local-scheduler putS3
[sample_profile]
aws_access_key_id = <AWS_ACCESS_KEY_ID> 
aws_secret_access_key = <AWS_SECRET_ACCESS_KEY>

Credentialの指定 Luigiの設定ファイルに記載

設定ファイルにaws_access_key_id / aws_secret_access_keyを書くことも可能です。
この場合は以下の様な設定ファイルを用意することで、起動時のオプション等は意識することがなくなります。
設定ファイルの細かい挙動については、前回の記事を読んでいただければと思います。

luigi.cfg

[s3]
aws_access_key_id = <AWS_ACCESS_KEY_ID> 
aws_secret_access_key = <AWS_SECRET_ACCESS_KEY>

Credentialの指定 IAM Roleの利用

IAM RoleでS3にアクセスできるようになっているインスタンスにおいては、起動オプション無しでIAM Roleの権限で動くことになります。

他にも、BOTOの設定としてCredentialを指定するといった方法もあるのですが、
設定ファイルが多岐に渡ってしまうと、いざ変更をしようとした際に変更箇所がわからなくなてしまうと言った恐れがあります。
そういったことを避けるためにも上記辺りでとどめておくのが良いかと思います。

まとめ

タスクの結果であるファイルをS3に保存してみました。 次回はS3にあるファイルを参照してみたいと思います。

参考資料

luigi/s3.py at master · spotify/luigi
Boto Config — boto v2.43.0
Luigi逆引きリファレンス - Qiita