AWS Data PipelineでPython Scriptを周期実行させる

## はじめに

AWS上でPython Scriptを定期的に実行させたい、というNeedsは結構あると思います。EC2を立ててcronで実行させる事で実現できますが、ここではAWSのData Pipelineの機能を使って実現する方法をチラ裏しておきます。

ただし、Data Pipelineの制約として、実行周期は15分以上にしか設定出来ないので注意してください、1分毎の実行などはできません。

なお、[Data PipelineでLambda Functionを周期実行させることも可能です。](http://qiita.com/taka4sato/items/e98690742d0092dd8779)ScriptがNode.js or Javaの場合は、こちらの方法でやるほうが楽だと思います。


## 全体の流れ
設定する項目の流れは、以下の様になっています。Python Script自体はすでに完成している前提です。

#### S3 BucketにPython Scriptを配置
* Python Scriptを置く為のS3 bucketを作成する(既存のBucketの流用も可)
* Python ScriptをS3 BucketにUploadする

#### Data Pipelineの作成
* Data Pipeline用のIAM Roleに、S3へのアクセス権限を付与する
* Data PipelineでShell Scriptを定期実行する様に設定する  
Shell scriptの中で、OSのMiddlewareの追加やPython Libraryの追加と、Python Script実行そのものを行う

#### Data Pipelineの処理結果の確認
* Data Pipelineのstdoutのlogを確認し、Python Scriptの実行結果が出力されている事を確認する


##### 補足
* Data PipelineのSchedule実行の周期は、最短で15分毎です

## S3 BucketにPython Scriptを配置
### S3 bucketの作成
Python Scriptを置く為のS3 bucketを作成します。もちろん既存のBucketの流用も可です。
AWS Console→S3に行き、以下の手順でS3 Bucketを作成します。

* `Create Bucket`を選択して、適当な名前を付けて作成(ここでは`datapipeline-python-test`というBucketを作成したと想定)

### Python ScriptをS3 BucketにUpload

以下の手順でPython ScriptをS3 BucketにUploadします。

* 先ほど作成したBucketに移動し、`Actions`→`Upload`を選択し、Python ScriptをUploadする  
ここでは`datapipeline_test.py`と言う、現在時刻を単にPrintする以下のScriptをUploadしたと想定  


```py:datapipeline_test.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import datetime
print 'Script run at ' + datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
```

## Data Pipelineの作成
### Data Pipelineの作成
AWS Console→Data Pipelineに行き、Data Pipelineを以下の手順で作成します。

* Nameは適当に設定(ここでは`Test Pipeline`とします)
* Sourceは`Build using a template`で`Run AWS CLI command`を選択
* Scheduleの箇所は、Run everyに`15 minutes`を指定 (1回だけ実行するなら`once on pipeline activation`を選択)
* Pipeline ConfigurationのLoggingは、上で作成した`datapipeline-python-test`というS3 bucketを指定
* Security/AccessとTagはDefaultのままでOK
* AWS CLI commandには以下のScriptを設定(内容についての補足は最後の方を参照)  

```
sudo yum -y install python-devel gcc && sudo update-alternatives --set python /usr/bin/python2.7 && curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" && sudo python ./get-pip.py && pip install boto3 --user && aws s3 cp s3://datapipeline-python-test/datapipeline_test.py ./datapipeline_test.py && cat datapipeline_test.py && python ./datapipeline_test.py
```


この設定で`Edit Architect`を選択して、Data Pipelineを一旦作成します。
作成すると、IAM Roleに`DataPipelineDefaultResourceRole`と`DataPipelineDefaultRole`という2つのIAM Roleが作成されます。
  

### IAM Roleの権限設定
IAM Role作成直後の状態では一部権限が足りない為、`DataPipelineDefaultResourceRole`と`DataPipelineDefaultRole`にS3へのアクセス権限を付与します。
AWS Console→Identity & Access Management→Rolesに行き、以下の手順で権限を付与します。

* `DataPipelineDefaultResourceRole`をクリック
* Managed Policies→Attach Policyで、`AmazonS3FullAccess`を検索して選択し、`Attach Policy`する

`DataPipelineDefaultRole`に対しても同様の権限設定を行う

### Data PipelineのActivate
AWS Console→Data Pipelineに行き、先ほど作成したData PipelineをActivateします。

* `Test Pipeline`を選択
* `Actions`→`Activate`を選択

これで、Data Pipelineの周期実行がActivateされました。15分毎の実行なので、しばらく待ちましょう。

##  Data Pipelineの処理結果の確認
AWS Console→Data Pipelineに行き、`Test Pipeline`を選択し、`CliActivity`→`Attemptsタブ`にある`Stdout`を選択し、Python Scriptにより現在の時刻が出力されている事を確認します。


## ShellScriptについての補足
大した処理はしていませんが、上記ShellScriptの中身を補足しておきます。

* `sudo yum -y install python-devel gcc`
  * OSに追加Middlewareを入れています(一部Python Libraryでgccなどが必要になる場合を想定)。Amazon Linux標準のMiddlewareで足りるなら削除可能です  
* `sudo update-alternatives --set python /usr/bin/python2.7`
  * Python2.7を指定しています。[DefaultのPython versionだと一部Libraryでエラーが出る可能性がある](http://imagawa.hatenadiary.jp/entry/2015/07/22/183000)のを回避します  
* `curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" && sudo python ./get-pip.py`
  * pipを入れています。標準のPython Libraryだけで足りるのであれば削除可能です  
* `pip install boto3 --user`
  * pipでPythonの追加Libraryを入れています。pipを使う場合にはPermissionの関係で`--user`の引数が必要です。複数Libraryを入れたければ、`pip install requests boto3 numpy --user`など列挙すればOKです  
* `aws s3 cp s3://datapipeline-python-test/datapipeline_test.py ./datapipeline_test.py`
  * Python scriptをLocalにCopyしています  
* `cat datapipeline_test.py`
  * S3からDownLoadしたfileの中身を表示しています、要らないなら削除可能です  
  
* `python ./datapipeline_test.py`
  * 最後に、Python Scriptを実行しています  


## Fail時にAlarmを飛ばす
Python Scriptが失敗した時などに、AWS SNSの機能を使ってAlarm Emailを飛ばすことも可能です。AWS SNSそのものの説明は割愛しますが、Data Pipeline上の設定を簡単に補足しておきます。

* AWS Console→Data Pipelineに行き、`Test Pipeline`を選択し、`Edit Pipeline`を選択
* 右ペインの`Activities`の`Add an optional field`→`On Fail`を選択
* `Activities`に`On Fail`と言う行が追加されるので、`Create new: Action`を選択、`DefaulAction1`が作成される
* 右ペインの`Others`に`DefaulAction1`という設定項目が出来ているので、
  * `Type`に`SnsAlarm`
  * `Topic Arn`にAWS SNSで作成したTopic Arn
  * `Message`にAlarm Emailの本文、`Subject`にAlarm EmailのSubject
  * `Role`はDefaultで`DataPipelineDefaultRole`になっているが`AmazonSNSFullAccess`のPermissionが付与されたRoleを選択

を設定すればOKです。Script Fail時やSuccess時などにAWS SNSを発火させる事が可能になります。
RoleにSnsを実行するPermissionを付与するのをお忘れなく。

## 最後に
Python ScriptをData Pipelineで周期実行できると、周期実行の為のHostを個別に確保/管理したり、実行保障する必要が無くなり、色々捗ります。