日本で 128 番目くらいに Ruby で AWS Lambda を試したメモ

日本で 128 番目くらいに Ruby で AWS Lambda を試したメモ:


加藤さん, 事件です.

ずっと待たれていたはず, もはや諦めかけていたかもしれない AWS Lambda のランタイムに Ruby が追加されたとの一報が我々の元に入りました.

https://aws.amazon.com/jp/blogs/compute/announcing-ruby-support-for-aws-lambda/

おお〜. なんちゃって Rubist の私もこれまで作ってきた Ruby スクリプトを Lambda で実行出来るかもしれないという興奮が今も続いております.


ということで

早速, 上記の URL に掲載されているサンプルを参考に簡単な Ruby スクリプトを Lambda 上で動かしてみたいと思います.


検証環境

以下のような環境で動作確認を取ります.

$ ruby --version 
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17] 
$ python --version 
Python 3.7.0 
$ sam --version 
SAM CLI, version 0.8.0 
$ aws --version 
aws-cli/1.16.66 Python/3.7.0 Darwin/17.7.0 botocore/1.12.56 
初めて sam を使ってみましたが, とても簡単に Lambda ファンクションのデプロイまで出来ました. Serverless framework と比較すると機能不足は否めませんが, AWS 純正なので新サービスへの対応も早かったりするのかなということで, もう少し使い込んでみようと思います.


まずは, サンプルイベントを生成する

とりあえず, ローカルで Ruby で書いた関数を動かしてみたいので, Lambda をローカルで実行する際に利用するサンプルイベントを生成します.

$ sam local generate-event s3 put --bucket=foo --key=bar > event_file.json 
これを実行すると, 以下のような JSON イベントが生成されます.

$ cat event_file.json 
{ 
  "Records": [ 
    { 
      "eventVersion": "2.0", 
      "eventSource": "aws:s3", 
      "awsRegion": "us-east-1", 
      "eventTime": "1970-01-01T00:00:00.000Z", 
      "eventName": "ObjectCreated:Put", 
      "userIdentity": { 
        "principalId": "EXAMPLE" 
      }, 
      "requestParameters": { 
        "sourceIPAddress": "127.0.0.1" 
      }, 
      "responseElements": { 
        "x-amz-request-id": "EXAMPLE123456789", 
        "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH" 
      }, 
      "s3": { 
        "s3SchemaVersion": "1.0", 
        "configurationId": "testConfigRule", 
        "bucket": { 
          "name": "foo", 
          "ownerIdentity": { 
            "principalId": "EXAMPLE" 
          }, 
          "arn": "arn:aws:s3:::foo" 
        }, 
        "object": { 
          "key": "bar", 
          "size": 1024, 
          "eTag": "0123456789abcdef0123456789abcdef", 
          "sequencer": "0A1B2C3D4E5F678901" 
        } 
      } 
    } 
  ] 
} 
今回は, この JSON イベントから S3 のオブジェクトキーを抜き出す関数を Ruby で書いてみます.


祝・Ruby で書く Lambda ファンクション

す, すいません. とりあえず, 雑に書きました.

def hello(event:, context:) 
  key = event["Records"][0]["s3"]["object"]["key"] 
  key 
end 
なんのひねりも, エラー処理もない, 自分の Ruby スキルのレベルが伺えるスクリプトです.


sam に必要な template.yaml

template.yaml (.yml ではない) を以下のように書きました.

AWSTemplateFormatVersion: '2010-09-09' 
Transform: AWS::Serverless-2016-10-31 
Description: 'serverless ruby sample.' 
 
Resources: 
  ServerlessRubySample: 
    Type: AWS::Serverless::Function 
    Properties: 
      Handler: sample.hello 
      Runtime: ruby2.5 
 
Outputs: 
  ServerlessRubySample: 
    Description: Serverless Ruby Sample Lambda Function ARN 
    Value: 
      Fn::GetAtt: 
      - ServerlessRubySample 
      - Arn 
なんとなく CloudFormation のテンプレートっぽい佇まいです. Runtimeruby2.5 が眩しいです.


まずはローカルでテスト

sam にもローカルで Lambda ファンクションを実行出来る local invoke というサブコマンドが用意されていますので, これを利用することで簡単にローカルで実行することが可能です.

$ sam local invoke ServerlessRubySample -e event_file.json 
2018-11-30 08:33:13 Found credentials in shared credentials file: ~/.aws/credentials 
2018-11-30 08:33:14 Invoking sample.hello (ruby2.5) 
 
Fetching lambci/lambda:ruby2.5 Docker container image...... 
2018-11-30 08:33:17 Mounting /path/to/serverless-ruby-sample as /var/task:ro inside runtime container 
START RequestId: 52fdfc07-2182-154f-163f-5f0f9a621d72 Version: $LATEST 
END RequestId: 52fdfc07-2182-154f-163f-5f0f9a621d72 
REPORT RequestId: 52fdfc07-2182-154f-163f-5f0f9a621d72  Duration: 5.64 ms       Billed Duration: 100 ms Memory Size: 128 MB     Max Memory Used: 18 MB 
"bar" 
"bar" が出力されることを確認出来ます. あっという間にローカル環境で Ruby で書いた Lambda ファンクションが動いてしまいました.


あとはデプロイ

引き続き, デプロイです. sam では CloudFormation のテンプレートを書き出して, そのテンプレートを使って Create Stack するような感じでデプロイするようです. もしかしたら, Serverless Framework も同じような挙動なのかもしれません. 以下のように 2 ステップでデプロイしました.

# packaged-template.yaml を生成 
sam package --template-file template.yaml \ 
  --output-template-file packaged-template.yaml \ 
  --s3-bucket oreno-sam-bucket 
 
# packaged-template.yaml を利用してデプロイ 
sam deploy --template-file packaged-template.yaml \ 
  --stack-name ServerlessRubySample \ 
  --capabilities CAPABILITY_IAM 
以下のように出力されました.

# packaged-template.yaml を生成 
$ sam package --template-file template.yaml \ 
> --output-template-file packaged-template.yaml \ 
> --s3-bucket oreno-sam-bucket 
Uploading to b55e36e493168dc4d6627ee148c1ac97  1275 / 1275.0  (100.00%) 
Successfully packaged artifacts and wrote output template to file packaged-template.yaml. 
Execute the following command to deploy the packaged template 
aws cloudformation deploy --template-file /Users/kawahara/sandboxies/sam/serverless-ruby-sample/packaged-template.yaml --stack-name <YOUR STACK NAME> 
 
# packaged-template.yaml を使って Create Stack しているのかな... 
$ sam deploy --template-file packaged-template.yaml \ 
> --stack-name ServerlessRubySample \ 
--capabilities CAPABILITY_IAM> --capabilities CAPABILITY_IAM 
 
Waiting for changeset to be created.. 
Waiting for stack create/update to complete 
Successfully created/updated stack - ServerlessRubySample 


動作確認

動作確認も Ruby で書きましょう. 以下のように aws-sdk-lambda を使ったコードです. 事前に aws-sdk-lambda をインストールしておきましょう.

require 'aws-sdk-lambda' 
require 'json' 
 
client = Aws::Lambda::Client.new(region: 'ap-northeast-1') 
 
payload =<<"EOS" 
{ 
  "Records": [ 
    { 
      "s3": { 
        "s3SchemaVersion": "1.0", 
        "configurationId": "testConfigRule", 
        "bucket": { 
          "name": "foo", 
          "ownerIdentity": { 
            "principalId": "EXAMPLE" 
          }, 
          "arn": "arn:aws:s3:::foo" 
        }, 
        "object": { 
          "key": "bar", 
          "size": 1024, 
          "eTag": "0123456789abcdef0123456789abcdef", 
          "sequencer": "0A1B2C3D4E5F678901" 
        } 
      } 
    } 
  ] 
} 
EOS 
 
resp = client.invoke({ 
                         function_name: 'ServerlessRubySample-ServerlessRubySample-xxxxxxxxxxx', 
                         invocation_type: 'RequestResponse', 
                         log_type: 'None', 
                         payload: payload 
                       }) 
 
res = JSON.parse(resp.payload.string) 
puts res 
function_name だけは, マネジメントコンソールで確認しましょう. このスクリプトを適当に invoke.rb とか名前をつけて保存しておきます.

$ bundle exec ruby invoke.rb 
以下のように出力されました.

$ bundle exe ruby invoke.rb 
bar 
おお〜, いい感じです. CloudWatch Logs にもログが記録されていることを確認しています.


以上

Ruby で Lambda ファンクションが書けるなんて, 今年の頭に誰が予想していたでしょうか (結構, 予想していたりしたらすいません). 本当に嬉しい限りです.

レッツ Ruby on Lambda〜〜.

コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)