AWS Data Pipelineから (EC2を起動させずに) LambdaをCron実行

# 追記 (2015-10-09)
Lambdaにスケジュール機能来てます。Add event sourceからどうぞー

> 【AWS発表】AWS Lambdaのアップデート – Python, VPC, 実行時間の増加, スケジュールなど
http://aws.typepad.com/aws_japan/2015/10/aws-lambda-update-python-vpc-increased-function-duration-scheduling-and-more.html

![cron.png](https://qiita-image-store.s3.amazonaws.com/0/69525/c6a8eb10-5fee-4159-e2dd-452abc40e89e.png)

こちらの記事の内容はdeprecatedとなりますが、まあそんな時代もあったよねということで一応残しておきますかね。


# はじめに

AWS Lambda。これ使い始めると、EC2無しでCron的に定期実行が出来る軽量なタスクスケジューラーがあればなー、と考える人は多いと思うんですが、今日の時点で良さげなものはAWSのサービスとしては見当たりません。

例えば、AWS Data Pipelineを使えば、aws cli経由でLambdaを定期的に起動することは出来ます。しかし、Data Pipelineは、1コマンド発行するのにわざわざEC2のインスタンスを立ち上げるという、(Lambdaに慣れた身にとっては)正直しゃらくさい挙動をしてくれるのです。そして、１日ごとぐらいなら気にならなくても、1時間ごととかで動かそうとすると、EC2の料金がちょっと気になり始める感じがしますよね。

そこで、何かWorkaroundは無いものかと、Data Pipelineのリファレンスをつらつらと見ていたところ、SnsAlarmという機能を発見。成功時/**失敗時**にSNSのNotificationを投げてくれるようです。

> SnsAlarm - AWS Data Pipeline
http://docs.aws.amazon.com/ja_jp/datapipeline/latest/DeveloperGuide/dp-object-snsalarm.html

これを使って、Data PipelineがEC2のリソースを確保しに行くところを**常に失敗する**(アクセス権が足りない)ようにして、失敗に対して飛んだSnsAlarmをトリガーにすれば、EC2が起動すること無しに、Lambdaが定期的に実行できるようになるのではないか、と思いつきまして。

実際にやってみたところ、以下の手順でなんとなく動いておりますので、メモを残しておきます。

# Steps

## 1. SNS Topicの作成

まずは、Data Pipelineから飛ばすSNSAlertの受け取り先が必要。`Create Topic`から適当にTopicを作っておきます。
![SnsTopic.png](https://qiita-image-store.s3.amazonaws.com/0/69525/1e0da9b6-e2af-e82e-992c-553f3e8568fc.png)

Subscribeでメールを受け取るようにしておくと、実行された時に確認できるのでお勧めです。


## 2. Lambda function の作成

### 2.1. 適当なLambda functionを用意

何かしらLambda functionを用意して下さい。動作確認だけならhello-world テンプレートそのままでもOKですし、自分で書いた既存のものでもOKです。

私の方では、Data Pipelineでは出来ないスポットインスタンスの作成をLambda経由でやって、そのまま小一時間処理を流して自動で終了、みたいなことをやっています。参考までに、詳細は以下にて。

> AWS Lambdaでスポットインスタンスを作成して、UserDataで環境構築や長い処理を自動で実行させる
> http://qiita.com/pyr_revs/items/c7f33d1cdee3118590e3

### 2.2. Add Event Source

起動するイベントとして、先ほど作ったSNS Topicを指定しておきましょう
![Lambda_Event_sns.png](https://qiita-image-store.s3.amazonaws.com/0/69525/91c87c97-f59f-583d-d286-368440af97f9.png)


## 3. Data Pipeline実行用のIAM role作成

Data Pipeline実行用のIAMロール作成、今回のキモです。

0. Data Pipelineと信頼関係を結んでいる
1. SNSにアクセスできる
2. そして、**EC2のインスタンスを作成できない**

というロールを作ります。

### 3.1. Create new IAM role

#### Step 1

IAM Management Consoleから`新しいロールの作成`、適当にロール名を付けます。

#### Step 2

[手順2: ロールタイプの選択]。`AWS Data Pipeline`を選択。

![DataPL_RoleType.png](https://qiita-image-store.s3.amazonaws.com/0/69525/f5a4b85b-91c1-f686-1887-d0a326a1d53c.png)

#### Step 3

[手順3]が飛ばされて、[手順4: ポリシーのアタッチ]。そのまま`AWSDataPipelineRole`にチェックを入れて次へ。

![DataPL_AttachPolycy.png](https://qiita-image-store.s3.amazonaws.com/0/69525/812c824c-2001-5a20-8ea9-6be60b338209.png)

確認画面で`ロールの作成`を押して、いったんロールを作ってしまいます。

### 3.2. Edit IAM role 

#### Step 1

リストから今作ったロールを選んで、管理ポリシーのところで**AWSDataPipelineRole**を思い切って**デタッチ**。

![Edit_Poly_1.png](https://qiita-image-store.s3.amazonaws.com/0/69525/efacdb6a-c663-261a-b1fb-f12d8e7573e1.png)

#### Step 2

代わりに、SNSのRoleをアタッチしておきます。

![Edit_Poly_2.png](https://qiita-image-store.s3.amazonaws.com/0/69525/157cbc86-38d1-aaf1-9728-5def19fe84e3.png)

#### Step 3

最後に、一番下の信頼関係。そのままでもいいんですが、emrの信頼関係は要らないので消しちゃいましょう。

![Edit_Poly_3.png](https://qiita-image-store.s3.amazonaws.com/0/69525/f1a5f3cc-88ea-85b2-cf53-6aab72b86a8d.png)

**datapipelineへの信頼関係は残しておいてください。** pipelineで指定できるroleは信頼関係が設定されているロールだけなので。


## 4. Create Data Pipeline 

前提条件は整ったので、Data Pipelineを動かすための設定をしていきます。

### 4.1. [Create Pipeline]画面で、ざっくりPipelineを作る

![DataPL_1.png](https://qiita-image-store.s3.amazonaws.com/0/69525/072bc5f4-3cc0-d5ae-0a6f-c01eec56b1e2.png)

- Nameは適当
- Source: テンプレートの**Run AWS CLI command**を選ぶ。
- AWS CLI command: なんか入力しておく必要がありますが、適当に`echo hello`とかで。実際には実行されません。

![DataPL_2.png](https://qiita-image-store.s3.amazonaws.com/0/69525/1a942005-e205-315d-8041-e671132d49ed.png)

- Schedule: とりあえずデフォルトで。
- Logging: Disbaleで。

![DataPL_3.png](https://qiita-image-store.s3.amazonaws.com/0/69525/3a1139fc-ee07-afe1-7094-e7d9658a4743.png)

- IAM roles: **Custom**を指定
- Pipeline role: 上のStepで作った、**EC2のインスタンス作成権限が無い、けどSNSのNotification飛ばす権限は有る**IAMロールを指定。
- EC2 instance role: 選べるものなら何でもOK。こちらは、EC2立ち上がってからのアクセス権の話なので、そもそも立ち上がらないように設定している今は無関係なのです。

まだ設定が足りないので、「**Edit in architect**」をおして、設定続行します。

### 4.2. [architect]画面で、リトライとSnsAlarmの設定

architect画面、右側のメニュー集を開いて設定を弄っていきます。正直使いずらいよこれ。

#### 4.2.1. Activity -> CliActivityの設定

![DataPL_4.png](https://qiita-image-store.s3.amazonaws.com/0/69525/af4f821f-f5b8-5624-2dde-a13a709db52c.png)

- **Maxium Retries**を追加して「**0**」を指定

#### 4.2.2. Resource -> EC2Instanceの設定

![DataPL_6.png](https://qiita-image-store.s3.amazonaws.com/0/69525/9d698eec-d46d-8a2e-028f-7f42bbd9569b.png)

- **Maxium Retries**を追加して「**0**」を指定

- **On Fail**を追加して「Create new action」を選ぶと、Othersの項に自動で「DefaultAction1」が追加されるはず

#### 4.2.3. Others -> SnsAlertの設定

failとRerunの挙動を決めたりする「Default」の設定の下に、EC2のResource確保のOn Failを受ける「DefaultAction1」が出来ているはず。

![DataPL_7.png](https://qiita-image-store.s3.amazonaws.com/0/69525/890dd7e6-73b2-f383-2d54-3a7bb3f3ffaa.png)

- Type: **SnsArarm**
- Topic arn: **最初のStepで作ったSNS TopicのARNを入力**
- Message: 適当
- Subject: 適当

#### 4.2.4. スケジュールの設定

![DataPL_8.png](https://qiita-image-store.s3.amazonaws.com/0/69525/3a533ff2-ba6e-b351-63d4-c8243f31f997.png)

開始時刻を指定する場合、デフォルトで入っている`Start At`を削除して、`StartDateTime`を追加の上UTCで指定する必要があります。

> スケジュール - AWS DataPipeline
https://docs.aws.amazon.com/ja_jp/datapipeline/latest/DeveloperGuide/dp-object-schedule.html

残念ながら、不等間隔(昼間だけとか)の指定はできないようですね。そういうことがしたいならLambda側で時間見て読みすてるという形になるかと思います。

## 5. 実行

準備は整ったので、Activateを押して実行します。Warning出ますが、元よりFailさせたいので無視しつつContinue
![DataPL_9.png](https://qiita-image-store.s3.amazonaws.com/0/69525/6691b502-2f0d-31bc-9e41-15e62f5006f5.png)

Pipelineの状態画面に飛んで、しばらく放置しておくとFailするのが見れるかと。

Filter = Allに変更すると、Ec2Resourceが権限足りなくてFAILEDになってるのを確認できるかと思います。
![DataPL_10.png](https://qiita-image-store.s3.amazonaws.com/0/69525/43c90cd2-bf32-d309-c487-41026fd2ddc3.png)

ここで、SNSにNotificationが飛んでれば、Lambdaがkickされているはずなので、ログを確認してみてください。また、SNSのSubscriptionでメールを指定していれば、そちらの通知も来てるはずです。

# おわりに

料金についてですが、Data Pipelineの料金表をご確認ください。

> 料金表 - AWS Data Pipeline
https://aws.amazon.com/jp/datapipeline/pricing/

低頻度(1日1回以下)なら月間0.6ドル、高頻度(1日2回以上)なら1ドルが、Pipeline一個に対してかかる、というところでしょうか。

ちなみに、低頻度について、Data Pipelineの無料枠で5件まで無料となってますが、[新規サインアップから12カ月で無くなるタイプの特典の模様なのでご注意](https://aws.amazon.com/jp/free/)。

。。。といいつつ、私去年7月にAWSに新規で利用開始しているはずなんですが、「請求 -> 料金明細」をみると「0 per month for 5 low frequnecy activities on AWS **under the free tier**」と出ています。低頻度は引き続き無料枠効いてるってことですかね？ Data Pipeline利用する場合、料金明細は要チェックですね。

# SNS + Lambda = 可能性∞ 

ここまで書いたところで、SQS とCloudWatch Alarm を利用してSNSを飛ばすという記事を発見。高頻度に使いたいなら、以下の方がよいかもしれません。

> Lambda を cron 的に使う Ver 2015.09
http://qiita.com/j3tm0t0/items/0e1320060791993a9d1a

一方Data Pipelineを使う方法では、開始時間を指定できるので、夜間バッチの起動を毎晩1度とか、2日に一回行いたいという向きには悪くないかとは思ってます。

いずれにしても、まともなスケジュール機能来るまでの繋ぎです。Azure Scheduler、同様のサービスがAWSにも欲しいですね。。。

> Azure Job Scheduler + AWS Lambdaで夢のサーバレス定期ジョブを実現する
http://marcy.hatenablog.com/entry/2015/01/17/005502