はじめに
2018年11月29日、AWS Lambda で Ruby が正式にサポート されましたね。サーバーレスアプリケーションを試そうとしている Rubyist の方々には、念願のアップデートだったのではないでしょうか。
しかし、Lambda で Ruby がサポートされたとはいえ、どこから手をつけていいかわからない!という方が多いと思います。僕自身もそうでした。。
そんな中、Ruby 製のサーバーレスフレームワーク、Jets という gem を見つけました。どんな形で使えるか検証したところ、簡単にサーバーレスアプリケーションに入門できそうな印象を持ちました。
この記事では、そんな Jets について、簡単な概要と、とっかかりとなるサンプルアプリケーションの作成・デプロイの検証結果についてまとめてみました。
Jets とは
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 を提供していることがざっくりつかめるのではないでしょうか。
(画像引用元:http://rubyonjets.com/#page-top)
Quick start で Jets アプリケーションを動かす
それでは実際に Jets アプリケーションを動かしてみたいと思います。Jets 公式ドキュメントの Quick Start を試していきますが、以下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
にアクセスすると、以下のような画面が表示されます。
そして scaffold で作成した Post モデルの CRUD 操作は、http://localhost:8888/posts
にアクセスして行います。
アクセスの前に、webpack
でJavaScript のライブラリをバンドルしてからアクセスしましょう。
webpack -w
それぞれ URL にアクセスすると、遷移が確認できると思います。
index: http://localhost:8888/posts
new: http://localhost:8888/posts/new
show: http://localhost:8888/posts/1
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/
にアクセスし、アプリケーションの画面が表示されるか確認してください。
jets deploy
コマンドでは、アプリケーションのビルドからデプロイまで自動で実行してくれます。
- Lambda 用にアプリケーションの zip ファイルを作成
- S3 に zip ファイルをアップロード
- API Gateway の設定、Lambda Function を CloudFormation 経由で作成実行
AWS のコンソールを確認すると、それぞれ AWS リソースが作成されていることがわかると思います。
S3
API Gateway
Lambda
CloudFormation
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) に設定し直してください。
Jets アプリケーションの環境変数ファイル修正
Jets アプリケーションが RDS データベース接続情報を認識できるよう、データベース設定を修正します。
まず .env.development.remote
というファイルを作成します。
cp .env.development .env.development.remote
ファイル内で、RDSデータベース情報を以下のように設定します。
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
にアクセスできるか確認してください。
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 の権限制御や実際のアプリケーションのパフォーマンスといった、本番環境で実運用するための考慮点はまだまだありそうなので、また別途検証をしてみようと思います!