Rails
AWS
lambda
serverless
Jets

Ruby 製サーバーレスフレームワークの Jets を検証してみたら、Rails ライクに使えていい感じだった


はじめに

2018年11月29日、AWS Lambda で Ruby が正式にサポート されましたね。サーバーレスアプリケーションを試そうとしている Rubyist の方々には、念願のアップデートだったのではないでしょうか。

しかし、Lambda で Ruby がサポートされたとはいえ、どこから手をつけていいかわからない!という方が多いと思います。僕自身もそうでした。。

そんな中、Ruby 製のサーバーレスフレームワーク、Jets という gem を見つけました。どんな形で使えるか検証したところ、簡単にサーバーレスアプリケーションに入門できそうな印象を持ちました。

この記事では、そんな Jets について、簡単な概要と、とっかかりとなるサンプルアプリケーションの作成・デプロイの検証結果についてまとめてみました。


Jets とは

image.png

Jets は、Ruby 製のサーバーレスアプリケーションフレームワークです。Ruby でサーバーレスアプリケーションを実装することができます。

また Jets にはアプリケーションをビルドし、AWS Lambda にデプロイする機能が含まれているため、コマンドライン上で手間をかけずビルド・デプロイすることが可能です。


Jets の思想

Jets の利用方法をこの後書いていきますが、Jets で使うコマンドやコードは、Ruby on Rails とよく似ているところが多いです。

コマンド・コードを抜粋してみましたが、非常に Rails と似ていることがわかるのではないでしょうか。

jets new

jets generate scaffold
jets db:migrate
jets server
jets console
jets deploy
jets routes
jets call
jets status
jets url
jets delete

class PostsController < ApplicationController

def index
# renders Lambda Proxy structure compatiable with API Gateway
render json: {hello: "world", action: "index"}
end

def show
id = params[:id] # params available
# puts goes to the lambda logs
puts event # raw lambda event available
render json: {action: "show", id: id}
end
end

(参考:http://rubyonjets.com/#page-top)

Jets の作者の Tung Nguyen さんは、 Jets の紹介ブログポスト で以下のようにコメントしています。


I love working with Rails, Ruby and AWS; and wanted to work with something similar in the serverless world. So I built Jets.

(意訳) 私は Rails、Ruby、AWS を使うことが好きで、サーバーレスの世界でも似たようなものを使いたいと思っていました。だから Jets を作りました。


このコメントからも、Jets が Rails の思想に影響を受けていることがわかりますね。

Rails をよく使っている方々でしたら、Rails の設計や考え方を流用して理解できるところが多く、使い方のキャッチアップもしやすいですし、設計で悩む時間も短縮できそうです。


Jets アーキテクチャ概要

Jets の README によると、Jets を利用する上でキーとなっているのが、AWS Lambda と API Gateway のようです。以下にそれぞれの役割を簡単にまとめます。

AWSサービス
役割

AWS Lambda
Fuction as a Service として扱う。Jets では AWS のインフラの詳細を気にせず Lambda Function をアップロード・実行することが可能

API Gateway
Lambda Function へのルーティングを担う。RESTful な URL エンドポイントを、Lambda Function に紐付ける

イメージ図を Jets 公式ドキュメントから引用します。API Gateway がそれぞれの Lambda Function に対し、RESTful な URL を提供していることがざっくりつかめるのではないでしょうか。

jets-web-architecture.png

(画像引用元:http://rubyonjets.com/#page-top)


Quick start で Jets アプリケーションを動かす

それでは実際に Jets アプリケーションを動かしてみたいと思います。Jets 公式ドキュメントの Quick Start を試していきますが、以下2パターンで試していきます。


  1. ローカル環境で動かす

  2. AWS 環境で動かす


環境情報


  • Mac OS X 10.13.6

  • ruby 2.5.1

  • mysql Ver 8.0.12 for osx10.13 on x86_64 (Homebrew)


1. ローカル環境で Jets を動かす

まず AWS の環境にデプロイする前に、ローカル環境で Jets アプリケーションを使えるようにします。


Jets インストール

まず gem をインストールします。コマンド一発ですね。

gem install jets


jets new:アプリケーション作成の下準備

次に、Jets アプリケーションの土台を作ります。rails new っぽいですね。

jets new jets-sandbox

cd jets-sandbox

実行時の出力を適宜省略しながら記載します。ファイル作成や gem install といった諸々の処理を実行しています。

# ファイル作成

Creating new project called jets-sandbox.
create jets-sandbox
create jets-sandbox/.env.development
create jets-sandbox/.env.test
create jets-sandbox/.env
create jets-sandbox/.gitignore
create jets-sandbox/.jetskeep
create jets-sandbox/.rspec
create jets-sandbox/Gemfile
create jets-sandbox/Procfile
create jets-sandbox/README.md
create jets-sandbox/Rakefile
create jets-sandbox/app/controllers/application_controller.rb
create jets-sandbox/app/helpers/application_helper.rb

(中略)

# gem インストール
Fetching gem metadata from https://rubygems.org/........
Resolving dependencies...
Fetching rake 12.3.2
Installing rake 12.3.2
Fetching concurrent-ruby 1.1.4
Installing concurrent-ruby 1.1.4

# yarn で JavaScript 関連ライブラリ インストール
Installing all JavaScript dependencies
run yarn add @rails/webpacker coffeescript@1.12.7 from "."

(中略)

# git commit
Initialized empty Git repository in
(中略)
49 files changed, 7094 insertions(+)

Congrats 🎉 You have successfully created a Jets project.

Cd into the project directory:
cd jets-sandbox

To start a server and test locally:
jets server # localhost:8888 should have the Jets welcome page

Scaffold example:
jets generate scaffold Post title:string body:text published:boolean

To deploy to AWS Lambda, edit your .env.development.remote and add a DATABASE_URL endpoint.
Then run:

jets deploy


jets generate scaffold:アプリケーションの雛形を作る

Jets アプリケーションの雛形を作ります。こちらも rails generate scaffold とよく似ていますね。

jets generate scaffold Post title:string

invoke active_record
create db/migrate/20180925233914_create_posts.rb
create app/models/post.rb
invoke resource_route
route resources :posts
invoke scaffold_controller
create app/controllers/posts_controller.rb
invoke erb
create app/views/posts
create app/views/posts/index.html.erb
create app/views/posts/edit.html.erb
create app/views/posts/show.html.erb
create app/views/posts/new.html.erb
create app/views/posts/_form.html.erb
invoke helper
create app/helpers/posts_helper.rb


jets db:create db:migrate:DB のマイグレーション

DB のマイグレーションを行います。こちらもrails db:create db:migrate とほとんど同じです。

jets db:create db:migrate

Created database 'jets-sandbox_development'
Created database 'jets-sandbox_test'
== 20181230024506 CreatePosts: migrating ======================================
-- create_table(:posts) -> 0.0079s
== 20181230024506CreatePosts: migrated (0.0080s)=============================


補足: DBマイグレーションでエラーが起きた場合は

もし以下のエラーが出た場合は、MySQL 5系→MySQL 8系にアップグレードしたことが原因の可能性が高いです。

ERROR 1449 (HY000): The user specified as a definer ('mysql.infoschema'@'localhost') does not exist

以下コマンドを実行し、MySQL のシステム情報をアップデートしましょう。

mysql_upgrade -u root

(参考:https://bugs.mysql.com/bug.php?id=91432)


jets server:アプリケーション起動

いよいよ Jets アプリケーションを起動します。

jets server

=> bundle exec shotgun --port 8888 --host 127.0.0.1
Jets booting up in development mode!
== Shotgun/WEBrick on http://127.0.0.1:8888/
[2018-12-30 12:11:15] INFO WEBrick 1.4.2
[2018-12-30 12:11:15] INFO ruby 2.5.1 (2018-03-29) [x86_64-darwin17]
[2018-12-30 12:11:15] INFO WEBrick::HTTPServer#start: pid=14592 port=8888

http://localhost:8888 にアクセスすると、以下のような画面が表示されます。

image.png

そして scaffold で作成した Post モデルの CRUD 操作は、http://localhost:8888/posts にアクセスして行います。

アクセスの前に、webpack でJavaScript のライブラリをバンドルしてからアクセスしましょう。

webpack -w

それぞれ URL にアクセスすると、遷移が確認できると思います。


index: http://localhost:8888/posts

image.png


new: http://localhost:8888/posts/new

image.png


show: http://localhost:8888/posts/1

image.png


2. AWS Lambda にデプロイ

ローカル環境での確認ができたので、AWS 環境に Jets アプリケーションをデプロイしましょう。


AWS シークレットキー設定

まず、Jets アプリケーションをデプロイする AWS アカウントのシークレットキーを設定します。

今回は検証のため、Administrator 権限の IAM ユーザーのシークレットキーを使いましたが、本番環境で使う場合などは、適切な IAM 権限で絞って使う必要がありそうですね。

vim ~/.aws/credentials

aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


jets deploy:アプリケーションを AWS 環境にデプロイ

それではデプロイを実行してみましょう。以下コマンド一発でOKです。

jets deploy

(中略)

Time took for stack deployment: 4min 41s.
Prewarming application.
API Gateway Endpoint: https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/

コマンドを実行すると様々な処理が走ります。

その後、出力の最後に表示される API Gateway のURL https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/ にアクセスし、アプリケーションの画面が表示されるか確認してください。

image.png

jets deploy コマンドでは、アプリケーションのビルドからデプロイまで自動で実行してくれます。


  • Lambda 用にアプリケーションの zip ファイルを作成

  • S3 に zip ファイルをアップロード

  • API Gateway の設定、Lambda Function を CloudFormation 経由で作成実行

AWS のコンソールを確認すると、それぞれ AWS リソースが作成されていることがわかると思います。


S3

image.png


API Gateway

image.png


Lambda

image.png


CloudFormation

image.png


RDS MySQL データベース作成

これでアプリケーションのデプロイ自体はできましたが、 Post モデルの CRUD 画面の確認はまだできない状態です。

そのため、AWS 環境用のデータベースとして、RDS で MySQL データベースを作成・設定することで、Post モデルの CRUD 画面も確認できるようにします。

※ Post モデルの CRUD 画面確認は不要で、デプロイ確認のみで十分な場合は、以降の手順は飛ばしてもらってOKです。

データベース作成手順は AWS の RDS ユーザーガイドが詳しいのでそちらをご参照ください。

設定内容はほとんどデフォルトにしましたが、最低限修正したところは以下の通りです。

項目
設定内容

MySQLバージョン
MySQL 8.0.11

インスタンスサイズ
db.t2.micro

インスタンス名
jets-sandbox-development-instance

データベース名
jets_sandbox_development

ユーザー名
jetssandboxuser

パスワード
任意

パブリック接続
可能

検証において考慮する点を減らすため、Lambda Function はパブリック通信で RDS データベースに接続することを想定します。(同一プライベート VPC 内に Lambda、RDS を含めればできそうですが、今回は検証対象外とします)

そこで、 RDS データベース作成後、Lambda Function からパブリック通信経由で RDS データベースにアクセスできるようにするため、セキュリティグループの設定を修正します。

RDS に設定された セキュリティグループのインバウンドを、任意の IP (0.0.0.0/0) に設定し直してください。

image.png


Jets アプリケーションの環境変数ファイル修正

Jets アプリケーションが RDS データベース接続情報を認識できるよう、データベース設定を修正します。

まず .env.development.remote というファイルを作成します。

cp .env.development .env.development.remote

ファイル内で、RDSデータベース情報を以下のように設定します。


env.development.remote

ENV_DEVELOPMENT_KEY=example1

DB_NAME=jets_sandbox_development
DB_USER=jetssandboxuser
DB_PASS=EXAMPLEPASSWORD
DB_HOST=jets-sandbox-development-instance.XXXXXXXXXXXX.us-east-1.rds.amazonaws.com


RDSデータベースに対しマイグレーション実行

RDSデータベースに対し、マイグレーションを実行します。

以下2つの環境変数の指定しつつコマンドを実行することで、.env.development.remote を参照するようになります。



  • JETS_ENV: 環境を指定


  • JETS_ENV_REMOTE: リモートの環境かどうかを指定

JETS_ENV=development JETS_ENV_REMOTE=1 jets db:create db:migrate


jets console: コンソールでアプリケーションのデバッグ

もし接続がうまくいかないよう場合は、jets console を使ってデバッグ確認してみましょう。

rails console のような形で、Post.all のようにアプリのモデルの状態を確認できます。

JETS_ENV=development JETS_ENV_REMOTE=1 jets console

Jets booting up in development mode!
irb(main):001:0> Post.all
=> #<ActiveRecord::Relation [#<Post id: 1, title: "test", created_at: "2018-12-30 05:24:18", updated_at: "2018-12-30 05:24:18">]>
irb(main):002:0>


再度デプロイ・画面確認

最後に再度デプロイします。

jets deploy

デプロイ後、https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/posts にアクセスできるか確認してください。

image.png


jets delete︰サンプルアプリケーションを削除

検証で使ったアプリケーションを最後に削除したい!という場合は、jets deleteコマンドで関連する AWS リソースを一括削除できます。

RDS データベースは、直接 RDS コンソールからインスタンスを削除してください。

jets delete

Deleting project...
Are you sure you want to want to delete the jets-sandbox-dev project? (y/N)
y
First, deleting objects in s3 bucket jets-sandbox-dev-s3bucket-uio563jvqwra
Deleting jets-sandbox-dev...
03:27:22PM DELETE_IN_PROGRESS AWS::CloudFormation::Stack jets-sandbox-dev User Initiated
03:27:23PM DELETE_IN_PROGRESS AWS::CloudFormation::Stack JetsPreheatJob
03:27:23PM DELETE_IN_PROGRESS AWS::CloudFormation::Stack ApiDeployment20181230142056
03:27:34PM DELETE_COMPLETE AWS::CloudFormation::Stack ApiDeployment20181230142056
03:27:35PM DELETE_IN_PROGRESS AWS::CloudFormation::Stack PostsController
03:27:35PM DELETE_IN_PROGRESS AWS::CloudFormation::Stack JetsPublicController
03:27:58PM DELETE_COMPLETE AWS::CloudFormation::Stack JetsPublicController
03:28:10PM DELETE_COMPLETE AWS::CloudFormation::Stack PostsController
03:28:11PM DELETE_IN_PROGRESS AWS::CloudFormation::Stack ApiGateway
03:28:22PM DELETE_COMPLETE AWS::CloudFormation::Stack ApiGateway
03:28:41PM DELETE_COMPLETE AWS::CloudFormation::Stack JetsPreheatJob
03:28:42PM DELETE_IN_PROGRESS AWS::IAM::Role IamRole
03:28:42PM DELETE_IN_PROGRESS AWS::Lambda::LayerVersion GemLayer
03:28:43PM DELETE_COMPLETE AWS::IAM::Role IamRole
Stack jets-sandbox-dev deleted.
Time took for deletion: 1m 46s.
Deleting CloudWatch logs
Project jets-sandbox-dev deleted!

こちらで検証は以上です。お疲れ様でした!


終わりに

だいぶ長くなってしまいましたが、Jets を触ってみた所感としては、Rails のコンテキストを踏まえて簡単にアプリケーションを作成・デプロイできるので、割とすんなり動かせたなと思いました。

また、コマンドラインから AWS リソースをあまり意識せずにビルド・デプロイできるのも、習得コストが少なくていい感じです。

ただ、IAM の権限制御や実際のアプリケーションのパフォーマンスといった、本番環境で実運用するための考慮点はまだまだありそうなので、また別途検証をしてみようと思います!


参考URL