Miscellaneous notes

主に技術的な雑記的な

Azure Job Scheduler + AWS Lambdaで夢のサーバレス定期ジョブを実現する

GoAzureがやっていたので、フラフラとAzureのWebサイトを見ていたりしました。

で、Azureのサービスの中に、AWSには無いJob Schedulerのサービスがあって、

これずっと欲しかったやつや!

ってなったので、ちょっと調べてました。

余談ですが、Jobの発行元の可用性担保と実行保証って面倒くさいんですよね。二重発行させる訳にもいかないですし、そのためだけにHA組む?みたいな所もあり…
発行されたJobを実行する所ではSQSとかELBとか挟めばどうとでもなるんですけど…
そんな訳で、フルマネージドなJob Schedulerはとても魅力的なわけです。

で、まず思ったのが「ここからLambdaキックできたらサーバレス定期ジョブでアツいなー」ってことです。

Job Schedulerができることは大別して以下の2つです。

  1. 同じAzureのStorage Queueへのメッセージキューイング
  2. HTTP(S)リクエスト

この内、2のHTTPリクエストがGET,POST,PUTメソッドに対応しています。
どれも、動的にリクエストの内容は組み立てられないのでLambda:InvokeAsyncAPIをコールするのは無理です。
ただ、一個だけ(?)Lambdaを静的なリクエストで起動する方法があります。

S3 event notifications(S3更新通知)です。

認証付きのSOAP APISDKから呼ぶやつ)ではなく、REST APIPUTなら単純な静的リクエストから更新ができます。

手順など

まず、PUTするS3バケットを作成し、以下のようなバケットポリシーを適用します。

S3 BucketLamda Functionのリージョンが同じになるよう注意しましょう。

{
    "Version": "2008-10-17",
    "Id": "PolicyLambdaScheduler",
    "Statement": [
        {
            "Sid": "StmtLambdaScheduler",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::lambda-scheduler-sample/<random-strings>/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "0.0.0.0/0"
                }
            }
        }
    ]
}

許可するのは、万が一のイタズラを考えて十分に長いランダム文字列を含んだパス等にすると良いかと思います。

次に、Lambda Functionを登録します。

lambchopというgemが手元のスクリプトをサクッと上げれて、実行結果のログをtailするように見られて素敵なので、使わせていただいてます。

lambchop 0.0.2: Invoke AWS Lambda function from local as normally script - so what

こんな感じで適当です。

#!/usr/bin/env lambchop
/*
function_name: lambda-scheduler
runtime: nodejs
mode: event
description: 'Lambda scheduled job publish from Azure Job Scheduler'
timeout: 3
memory_size: 128
role: arn:aws:iam::<your-account-number>:role/lambda_exec_role
handler: lambda-scheduler.handler
*/
console.log('Loading event');
var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});
require('date-utils');

exports.handler = function(event, context) {
   var d = new Date();
   console.log('Received event:');
   console.log(JSON.stringify(event, null, '  '));
   console.log('DateTime:',d.toFormat("YYYY-MM-DD HH24:MI:SS"));
   console.log('Invoked from Azure Job Scheduler!!');
};

登録したLambda FunctionをS3 event notificationsで起動するよう設定します。

Lambdaのメニューを開きます。

f:id:FumblePerson:20150117003946p:plain

変更します。

f:id:FumblePerson:20150117003616p:plain

そして、Azure Job Schedulerのジョブを作成します

Job Schedulerを選択します。

f:id:FumblePerson:20150117004156p:plain

先ほどS3のバケットポリシーで許可したURLを入力して作成します。

f:id:FumblePerson:20150118002810p:plain

とりあえず、2分毎で。
※無料トライアル枠の無い方は1時間より大きい周期でないと有料です。

f:id:FumblePerson:20150117004658p:plain

暫く、lambchopの出力を眺めると…

f:id:FumblePerson:20150117005238p:plain

f:id:FumblePerson:20150117005243p:plain

2分毎に起動してる!!

夢のサーバレス定期ジョブや!!

Azure良いかも

良さそうなサービスがけっこうあって、ちょっとAWSを使い始めた頃のワクワクが蘇った感じがしてて良いかもです。
AWSはもちろん素晴らしいし、これからも使っていきますが、色んなクラウドの良いサービスはガンガン使って、組み合わせて良いものが作れるように精進していきたいと思います。