Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

AWS LambdaでRailsアプリを動かす方法!Lambyを使ったデプロイ手順を徹底解説

サーバーレスコンピューティングは、サーバーの管理やプロビジョニングの作業をクラウドプロバイダーにオフロードできる仕組みとして、多くのテックチームで急速に標準になりつつあります。その代表格がAWS Lambdaです。LambdaはNode.js、Java、Python、Rubyといった主要なプログラミング言語を幅広くサポートしています。しかし、言語そのものだけでなく、それらの言語で構築されたフレームワークの機能に依存するサーバーレス関数を実行したいケースもあるでしょう。

本記事では、RailsアプリケーションをAWS Lambda上で実行する方法を解説します。サーバーレスコンピューティングとAWS Lambdaの基礎知識がある方を対象に、「RailsをLambdaでどう動かせばよいのか」という疑問に答えていきます。Lambyというツールを使えば、RailsをLambdaで動かすのは驚くほど簡単になります。この記事では、Lambyを使ったRailsアプリのビルドとデプロイの手順を紹介します。以降、これを「Rails on Lambda」と呼びます。

Lambyとは何か?

AWS Lambdaでは、コードをアップロードするだけで、サーバーを管理することなくあらゆる規模でコードを実行できます。コードはイベント(ユーザーによるWebページへのリクエストやジョブのキュー登録など)によってトリガーされるたびに実行されます。

ただし、Lambdaにはコードの構造に関する一定の要件があります。そのため、Railsアプリのようなものをホストしたい場合は、Lambyのようなアダプターが必要になります。

LambyはシンプルなRackアダプターです。RailsアプリとAWS Lambdaの間に位置し、API GatewayやApplication Load Balancerなど、さまざまなAWSソースからのLambda呼び出しイベントを、Railsアプリが解釈できるRackイベントへと変換します。

AWS LambdaでRailsアプリを動かす方法!Lambyを使ったデプロイ手順を徹底解説
Rails Lambdaアーキテクチャ(出典:Lamby公式ドキュメント)

LambyはDockerとAWS SAMを活用して、Railsアプリのビルド・パッケージング・デプロイを行います。

AWS Serverless Application Model(AWS SAM)は、AWS上でサーバーレスアプリケーションを構築するためのオープンソースフレームワークです。サーバーレスアプリケーションとは、タスクを実行するために連携するLambda関数、イベントソース、その他のリソースの組み合わせを指します。サーバーレスアプリケーションは単なるLambda関数にとどまらず、API、データベース、イベントソースマッピングなどの追加リソースを含むこともできます。—— AWS SAMドキュメントより

Lambyを使い始めるには、Dockerのインストール、AWSアカウントの作成、そしてAWSアカウントへのプログラマティックアクセスの設定が必要です。

Dockerのインストール

AWS SAMは、Lambdaランタイム環境をシミュレートするためにDockerを使用します。また、DockerはPythonに依存するAWS CLIおよびSAM CLIのインストール作業も簡素化してくれます。まだDockerをインストールしていない場合は、公式サイトからダウンロードしてインストールするだけなので非常に簡単です。インストールが完了したかどうかは、ターミナルで以下のコマンドを実行して確認できます。バージョン番号とビルド情報が表示されれば成功です。

$ docker --version

AWS LambdaでRailsアプリを動かす方法!Lambyを使ったデプロイ手順を徹底解説
Dockerインストールの確認

AWSアカウントのセットアップ

まだAWSアカウントをお持ちでない場合は、新規に作成する必要があります。Amazonには無料利用枠(フリーティア)があり、LambdaでのRailsアプリの作成とテスト程度であれば十分カバーできます。AWSアカウントの作成と有効化の手順ガイドに従って、アカウントをセットアップしてください。

AWSプログラマティックアクセスの設定

AWSアカウントを作成したら、AWSアクセスキーIDとAWSシークレットアクセスキーを使用してプログラマティックアクセスを設定します。これらのキーをまだ持っていない場合は、以下の手順で作成できます。

  • AWSアカウントにログインします。
  • AWSマネジメントコンソールのツールバーで「サービス」をクリックします。
  • 「IAM」を検索して選択します。
  • 左側のナビゲーションから「ユーザー」をクリックします。
  • 既存のIAMユーザーが存在する場合は、自分のユーザー名を選択します。
    • 「認証情報」タブをクリックします。
    • 「アクセスキーを作成」ボタンをクリックします。
    • キーIDとシークレットを安全な場所にコピーしておきます。
  • IAMユーザーが存在しない場合は、
    • 「ユーザーを追加」をクリックします。
    • ユーザー名を入力し、「プログラムによるアクセス」オプションを選択します。
    • 画面の指示に従って処理を完了させます。

次に、Dockerを使ってCLIのプログラマティックアクセスを設定しましょう。以下のコードをターミナルに貼り付けてください。AWSアクセスキーIDとAWSシークレットアクセスキーの入力を求められるので、前のステップで取得したキーを入力します。

$ docker run \
  --interactive \
  --tty \
  --rm \
  --volume "${HOME}/.aws:/root/.aws" \
  "amazon/aws-cli" \
  configure

AWS LambdaでRailsアプリを動かす方法!Lambyを使ったデプロイ手順を徹底解説

新しいRailsアプリケーションの作成

Railsプロジェクトの雛形は、SAM CLIを使って生成します。AWS SAM CLIでは、GitHubリポジトリのテンプレート(一般にcookiecutterと呼ばれます)から新しいプロジェクトを初期化できます。ここではDockerコンテナ内でsam initを実行し、Lamby Cookiecutterのプロジェクトテンプレートを利用して新しいプロジェクトフォルダを作成します。プロジェクト名の入力を求められますが、ここでは「rails_on_lambda」を使用します。

$ docker run \
  --rm \
  --interactive \
  --volume "${PWD}:/var/task:delegated" \
  lambci/lambda:build-ruby2.7 \
  sam init --location "gh:customink/lamby-cookiecutter"

AWS LambdaでRailsアプリを動かす方法!Lambyを使ったデプロイ手順を徹底解説

生成された新しいSAMプロジェクトフォルダには、Rails on Lambdaプロジェクトに必要なものがすべて揃っています。大まかにいうと、以下のものが含まれています。

  • Dockerfileとdocker-composeの両方を使ったDocker環境のセットアップ
  • libディレクトリ、Bundler、テストを備えた動作するRubyプロジェクト
  • SAMのtemplate.yamlファイル

セットアップとデプロイ

Railsアプリを作成したら、次はLambdaへのデプロイ準備です。以下の2つのコマンドは、Docker開発イメージのビルドとgemのバンドルを行うスクリプトを実行します。bootstrapコマンドは一度だけ実行すればよく、setupコマンドは新しい依存関係を追加するたびに実行します。

$ ./bin/bootstrap
$ ./bin/setup

これらのコマンドが正常に完了したら、プロジェクトはSAM経由でデプロイできる状態になっています。デプロイは、Railsアプリのビルド・パッケージング・デプロイを行うLambyのスクリプトを使って行います。

./bin/deploy

deployコマンドは、現在のプロジェクトディレクトリをローカルの.lambyディレクトリに複製し、デプロイに必要な3つのSAMコマンドを実行するLambyのビルドスクリプトを起動します。

  • sam build
  • sam package
  • sam deploy

スクリプトが期待どおりに実行されると、SAMのCloudFormationデプロイタスクの出力が表示され、最後に以下のようなメッセージが現れます。

AWS LambdaでRailsアプリを動かす方法!Lambyを使ったデプロイ手順を徹底解説

ターミナル出力の中にURLも表示されているはずです。このURLは、Rack経由でRailsアプリケーションを呼び出すAPI Gateway HTTP APIエンドポイントです。ブラウザで開くと、おなじみの「Yay! You're on Rails!」の画面が表示されます。

AWS LambdaでRailsアプリを動かす方法!Lambyを使ったデプロイ手順を徹底解説

AWSコンソールからRailsアプリを呼び出す

Lambdaダッシュボードからもアプリをテストできます。AWSマネジメントコンソールにログインし、以下の手順に進んでください。

  • ツールバーの「サービス」をクリックします。
  • サービス検索フィールドに「Lambda」と入力して選択します。

このページに、新しくデプロイした「RailsOnLambda」プロジェクトが表示されます。

AWS LambdaでRailsアプリを動かす方法!Lambyを使ったデプロイ手順を徹底解説

  • 「RailsOnLambda」関数を開きます。
  • 右上の「テスト」ボタンをクリックします。
  • 「Amazon API Gateway Proxy」イベントテンプレートを選択します(対応するフィールドは下記のJSONテンプレートで更新してください)。
  • イベント名を「RailsOnLambdaTest」とします。
  • 「作成」ボタンをクリックします。
  • 「テスト」ボタンをクリックしてLambdaを呼び出します。
{
  "body": "",
  "path": "/",
  "httpMethod": "GET",
  "queryStringParameters": {},
  "multiValueQueryStringParameters": {},
  "pathParameters": {
    "proxy": "/"
  },
  "stageVariables": {},
  "requestContext": {
    "path": "/",
    "httpMethod": "GET"
  }
}

すべてが順調に進めば、以下のような出力が表示されるはずです。

AWS LambdaでRailsアプリを動かす方法!Lambyを使ったデプロイ手順を徹底解説

おめでとうございます!これでRails on Lambdaの完成です。といっても、Lambda上のRailsアプリケーションは、通常のRailsアプリケーションとほぼ変わりません。唯一の違いは、Lamby gemがAPI Gateway HTTP API、API Gateway REST API、Application Load BalancerのターゲットイベントをRack互換のenvオブジェクトに変換してRailsに渡す点です。Railsはイベントの処理結果を、プロジェクト内で定義されたLambdaハンドラーに返します。

def handler(event:, context:)
 Lamby.handler $app, event, context
end

Rails on Lambdaのパフォーマンスはどう?

Rails on Lambdaでは、デプロイ直後の最初のリクエストに対するレスポンスが遅くなります。これは「コールドスタート」と呼ばれる現象です。しかし、最初のリクエスト以降のパフォーマンスは優れており、EC2に匹敵、あるいはそれ以上の性能を発揮します。最初のリクエスト後に後続のリクエストがない場合、Railsアプリを処理していたサーバーリソースは約5〜7分後に他のLambda関数へ動的に割り当てられます。その結果、新しいリクエストで再びコールドスタートが発生します。コールドスタートを回避し、Railsアプリをウォームな状態に保つには、いくつかの方法があります。

CloudWatchタイマー

1分ごとにRails on Lambda関数へpingを送信するよう設定すれば、アプリをウォームな状態に保てます。AWSコンソールを開いてCloudWatchを検索し、「イベント」→「ルールを作成」の順に進みます。イベントタイプを「スケジュール」に設定し、1分ごとにこのイベントを実行するようにします。

AWS LambdaでRailsアプリを動かす方法!Lambyを使ったデプロイ手順を徹底解説

プロビジョニングされた同時実行数

プロビジョニングされた同時実行数(Provisioned Concurrency)は、未使用のコンテナを常時稼働させておく代わりに追加料金を支払うことで、コールドスタートを防げるAWSの機能です。Railsアプリ向けに設定するには、AWSコンソールを開いてLambdaサービスページに移動します。

  • 対象の関数(rails-on-lambda)を選択します。
  • 「設定」を選択し、「同時実行」を選びます。
  • 「プロビジョニングされた同時実行数の設定」の下にある「設定を追加」をクリックします。
  • エイリアスまたはバージョンを選択します。
  • 割り当てるプロビジョニングされた同時実行数(例:500)を入力します。
  • 変更を保存します。

プロビジョニングされた同時実行数は、AWS CLIから以下のコマンドでも設定できます。

aws lambda put-provisioned-concurrency-config --function-name my-function \
--qualifier BLUE --provisioned-concurrent-executions 100

AWS Lambdaの料金はいくら?

AWS Lambdaでは、使用した分だけ支払う従量課金制です。料金は「リクエスト数」と「コード実行時間」の組み合わせで決まります。実行時間の単価は、関数に割り当てるメモリ量によって異なります。メモリサイズは128MBから10,240MBまで選択でき、ニーズに応じて任意の容量を割り当てられます。以下のグラフは、Lambda関数を10万回呼び出した場合の実行時間別のコストを示しています。

AWS LambdaでRailsアプリを動かす方法!Lambyを使ったデプロイ手順を徹底解説
Lambdaの料金

Rails on Lambdaに向かないケース

RailsアプリをAWS Lambdaで実行できることはわかりましたが、すべてのRailsアプリケーションがLambdaに適しているわけではありません。Railsは従来型のサーバー上での動作を前提として設計されており、サーバーレス環境では問題になる操作があります。例えば、ファイルや画像のアップロードは、永続的なファイルシステムにアクセスできないため、Rails on Lambdaでは動作しません。また、WebSocket通信も、リクエストがない間はサーバーが存在しないため、Lambdaでは利用できません。

まとめ

本記事では基本的なRailsアプリケーションのデプロイ方法を紹介しましたが、大規模なアプリケーションでも同じ手順で対応できます。ぜひコントローラーやルートを自由に追加して、コンソールやPostmanなどのHTTPクライアントから動作をテストしてみてください。

  1. RubyでAWS Lambda関数を構築・テスト・デプロイする完全ガイド

    ソフトウェア開発は決して簡単ではありませんが、それ以上に大変なのが保守運用です。保守にはソフトウェアのパッチ適用やサーバーの管理が含まれます。この記事では、その中でも特にサーバー管理と運用に焦点を当てて解説します。 従来、サーバーはオンプレミス環境に設置され、物理ハードウェアの購入と維持管理が必要でした。しかしクラウドコンピューティングの登場により、物理的なサーバーを所有する必要はなくなりました。2006年、AmazonがAWSを開始しEC2サービスを発表したことで、現代のクラウドコンピューティングの時代が幕を開けました。この種のサービスにより、物理サーバーの管理やハードウェアのアップグレード

  2. Rails5でのAngularの使用

    あなたは前にその話を聞いたことがあります。分散型で完全に機能するバックエンドAPIと、通常のツールセットで作成されたフロントエンドで実行されているアプリケーションがすでにあります。 次に、Angularに移動します。または、AngularをRailsプロジェクトと統合する方法を探しているだけかもしれません。これは、この方法を好むためです。私たちはあなたを責めません。 このようなアプローチを使用すると、両方の世界を活用して、たとえばRailsとAngularのどちらの機能を使用してフォーマットするかを決定できます。 構築するもの 心配する必要はありません。このチュートリアルは、この目的のた