AWS Lambdaとは?サーバーレスの基本
AWS Lambdaとは?サーバーレスの基本概念
AWSの学習を始めると、真っ先に目にする「サーバーレス」という言葉。そしてその代表格として必ず名前が挙がるのが「AWS Lambda」です。今回は、Lambdaを理解する上で絶対に外せない土台となる考え方について、一緒に紐解いていきましょう。
サーバーレスコンピューティングの定義と役割
「サーバーレス」という名前から、「サーバーがまったく存在しないサービスなの?」と疑問に思う方も少なくないと思います。結論から言うと、Lambdaの裏側ではもちろんAWSのサーバーが動いています。
では、なぜ「サーバーレス」と呼ぶのか。それは、「利用者(開発者)がサーバーを意識・管理しなくてよい」という点に由来しています。
従来のAWSでのシステム開発、例えばEC2(仮想サーバー)を使う場合を想像してみてください。アプリケーションを動かすために、サーバーのOSを設定し、メモリやCPUのサイズを決め、定期的にOSのアップデートやセキュリティパッチを当てる必要があります。さらに、アクセスが増えたときにはサーバーを増やす手配もしなければなりません。この一連の「サーバーの準備(プロビジョニング)や管理」は、本来やりたかった「アプリケーションの開発」に対する大きな足かせになります。
Lambdaは、こうした面倒なインフラ管理をすべてAWS側で引き受けてくれます。開発者は「どんな処理をしたいか」というコードを書いて渡すだけでOKです。サーバーを立ち上げる必要も、止める必要もありません。
また、Lambdaはアクセス数(トラフィック)に応じて自動的に処理能力を調整してくれますし、デフォルトで複数のデータセンター(マルチAZ)で動くため、サーバーが故障しても影響を受けにくい高い可用性も備わっています。つまり、サーバーレスとは「サーバーの存在を隠蔽し、開発に集中させる」という役割を持ったコンピューティングの形なのです。
イベント駆動型アーキテクチャの基本
Lambdaを語る上で、もう一つ欠かせないキーワードが「イベント駆動型」です。
私たちが普段使っているスマートフォンのアプリやWebサイトは、ユーザーが「ボタンを押した」「画面をスクロールした」といった操作をしたときに反応しますよね。Lambdaの仕組みもこれととても似ています。
Lambdaは、ずっと起動して待機しているわけではありません。「何かが起こった(イベント)」という明確なきっかけがあって初めて、ピョコンと起動して処理を実行し、終わったら静かに待機状態に戻ります。
この「何かが起こる」の具体例を挙げると、以下のようなものがあります。
- Amazon S3(ファイル保存場所)に画像がアップロードされた
- ユーザーからAPI経由でデータの送信リクエストが来た
- 決められた時刻になった(スケジュール実行)
- データベースのデータが更新された
これらのイベントを検知すると、Lambdaはそのイベントに関する情報(誰が、いつ、何をしたか等)をJSONというデータ形式で受け取り、その内容に沿って処理を進めます。
この仕組みの素晴らしいところは、システム全体を「疎結合(そけつごう)」にできる点です。疎結合とは、「各機能が互いに依存しすぎず、独立している状態」を指します。例えば「画像アップロード処理」と「メール送信処理」が直接繋がっていると、メール送信のシステムがトラブルで止まったとき、画像アップロードまで連鎖して止まってしまうかもしれません。しかしイベント駆動の場合、「画像がアップロードされたらイベントを飛ばす」という仕組みだけを繋ぐため、一つの機能が壊れても他の機能が影響を受けにくくなります。
Note
イベント駆動型アーキテクチャは、システム同士がネットワークを経由して通信する仕組み上、どうしても少しのタイムラグ(レイテンシー)が発生します。株取引のように、数ミリ秒単位の極めて低い遅延が求められるリアルタイムシステムには不向きな場合があるため、適材適所での活用が大切です。
このように、Lambdaは「サーバーを管理しない(サーバーレス)」であり、「イベントが起きた時にだけ動く(イベント駆動)」という2つの大きな特徴を持っています。この基本概念を頭の片隅に置いておくだけで、次からの具体的な仕組みの解説がぐっと理解しやすくなるはずです。
Lambdaを支える4つの重要な基本概念
前のセクションでは、Lambdaがどんなサービスかについてお話ししました。ここからは少し視点を変えて、実際にLambdaを使いこなすために絶対に知っておきたい「4つの重要な基本概念」について解説していきます。最初は聞き馴染みのない言葉が並ぶかもしれませんが、一つ一つ紐解いていきましょう。
Lambda関数と関数ハンドラー
Lambdaにおける「関数」とは、イベントに応答して実行されるコードの塊のことです。皆さんが書いたPythonのスクリプトやNode.jsのコードが、これに該当します。
そして、その関数の中には必ず「ハンドラー」と呼ばれるものを一つだけ用意する必要があります。ハンドラーは、簡単に言うと「処理のエントリポイント(玄関)」です。イベントが発生してLambdaが起動すると、まず最初にこのハンドラーが呼び出され、そこから様々な処理がスタートします。コードの中に複数の関数やメソッドを書いても構いませんが、Lambdaが直接実行を開始できるハンドラーは必ず1つでなければなりません。
ここで重要になってくるのが、「1つの関数には、1つの特定の目的を持たせる」という考え方です。例えば、「画像をリサイズする処理」と「メールを送信する処理」を、1つのLambda関数の中に一緒に書いてしまうのは避けた方が良いです。そうではなく、「画像リサイズ専用の関数」と「メール送信専用の関数」のように分けます。
これには明確な理由があります。一つの関数に色々な役割を詰め込むと、画像リサイズの仕様を変えたい時にメール送信の部分まで影響が出てしまうリスクがあるからです。役割を細かく分けることで、修正やテストが格段にやりやすくなり、トラブルが起きても原因を特定しやすくなります。
実行環境とランタイム
Lambda関数は、皆さんのパソコン上で直接動いているわけではありません。AWSが用意した「実行環境」と呼ばれる、安全に隔離された専用のスペースの中で動きます。他のユーザーの処理とは完全に分けられているため、お互いに干渉することはありません。
この実行環境の中には、皆さんが選んだプログラミング言語を実行するための「ランタイム」が用意されています。ランタイムとは、例えばPythonならPythonのコードを読み取って実行するための言語固有の環境のことです。
Lambdaは、Python、Node.js、Java、Ruby、Goなど、主要なプログラミング言語に対応したランタイムを公式に提供しています。従来のサーバー構築であれば、OSのインストールから言語のセットアップまで自前で行う必要がありました。しかしLambdaの場合は、実行したい言語のランタイムを選ぶだけで準備が完了します。
また、AWSが管理しているマネージドランタイムを選んだ場合、セキュリティアップデートやパッチの適用もAWS側で自動的に行ってくれます。これは、開発者がインフラの保守から解放されるというサーバーレスの大きなメリットの一部です。
トリガーとイベントソース
Lambda関数は、単独で勝手に動き出すことはありません。「何かが起きたら動く」というイベント駆動型の性質を持っているため、動くためのスイッチが必要になります。このスイッチの役割を果たすのが「トリガー」です。
トリガーになるのは様々なAWSサービスです。例えば、「Amazon S3(ファイル保存場所)に画像がアップロードされた時」「API Gateway経由でユーザーからWebリクエストがあった時」「EventBridgeで毎日午前9時になった時」などがトリガーになります。
そして、トリガーが引かれた時、Lambda関数には「イベント」というデータが渡されます。このイベントデータは必ずJSON形式になっており、その中身は「どのトリガーから来たか」によって全く異なります。
例えば、S3がトリガーとなった場合、イベントのJSONには「どのバケットに」「どんな名前のファイルが」「何KBのサイズで」アップロードされたかという情報が含まれています。API Gateway経由であれば、「どんなURLに」「どんなパラメータが」送られてきたかの情報が入ります。
Tip
イベントのJSON構造を調べる際は、AWS公式ドキュメントの「他の AWS のサービスから Lambda を呼び出す」の項目を見るのが一番確実です。また、実際にテスト実行して、コンソール上で渡ってきたJSONの中身をそのまま確認するのも、理解を深める良い方法です。
アクセス許可とIAMロール
Lambda関数の中で「S3に保存されている画像を取得したい」「DynamoDB(データベース)にデータを書き込みたい」といった場面はよくあります。しかし、Lambda関数が作られたばかりの状態では、他のAWSサービスにアクセスする権限を一切持っていません。
AWSの世界では、セキュリティを担保するために「最小権限の原則」という考え方が非常に重要視されています。これは、「その処理を行うために必要な権限だけを、必要な時だけ与える」というルールです。何でもかんでも全権限を与えてしまうと、もしコードに不具合があったり悪意のある第三者がアクセスしたりした際に、大惨事に繋がるからです。
この権限をLambda関数に付与するために使うのが「IAMロール(実行ロール)」です。IAMロールは、Lambda関数に手渡す「身分証明書とアクセス権限のセット」のようなものです。
例えば、S3から画像を読み取るだけの関数を作るなら、「S3の読み取り権限」だけを持ったIAMロールを作成し、その関数に割り当てます。データベースへの書き込み権限や、他のアカウントのリソースへのアクセス権限は含めません。
Important
Lambda関数を作成する際、テストを簡単にしたいからといって「管理者権限」などの強力なIAMロールを安易に付与しないでください。本番環境では、必ず関数の目的に合った最小限の権限に絞ったIAMロールを設計・付与することが、安全なシステム運用において不可欠です。
Lambdaの呼び出し方法とAWSサービスとの連携
Lambdaが「何かをきっかけに動く」ということは前のセクションでお話ししました。では、具体的にどんな風にそのきっかけ(トリガー)がLambdaに伝わるのでしょうか。
実は、AWSのサービスがLambdaを呼び出す方法には、大きく分けて「プッシュモデル」と「プルモデル」の2つのパターンがあります。さらに、それらをうまく仲介してくれる便利なサービスもあります。ここでは、それぞれの仕組みと特徴を整理していきましょう。
直接呼び出し(プッシュモデル)の仕組み
プッシュモデルは、名前の通り「他のAWSサービスが、Lambdaに向かってイベントを押し込む(プッシュする)」仕組みです。
例えば、ユーザーがWebサイトでボタンを押したときに動くAPI Gatewayや、Amazon S3のバケットに画像がアップロードされた瞬間などがこれに当たります。「何かが起きたよ!」という通知が直接Lambdaに届き、それを受け取ったLambdaが仕事を始めます。
このプッシュモデルには、さらに「同期呼び出し」と「非同期呼び出し」の2種類があります。
同期呼び出しは、呼び出し元がLambdaの処理が終わるのを待つ方式です。API Gateway経由でユーザーからリクエストがあった場合などに使われます。「このデータを処理して」と言って、結果が返ってくるまで待機します。もしLambda内でエラーが起きても、その場でエラーが返されるだけで自動的には再試行されません。
非同期呼び出しは、呼び出し元がLambdaの処理結果を待たない方式です。S3にファイルがアップロードされたときなどに使われます。「これ処理しといて」と言いっぱなしにして、呼び出し元はすぐに次の作業に移ります。
Important
非同期呼び出しでLambdaの実行に失敗した場合、AWS側で自動的に2回まで再試行が行われます。それでも解決しない場合、処理をスキップしてしまうとデータが消失するリスクがあります。そのため、非同期呼び出しを利用する際は、失敗したイベントを別のキュー(デッドレターキューなど)に退避させる設定をしておくことが不可欠です。
イベントソースマッピング(プルモデル)の仕組み
一方で、Lambdaの方から「データないかな?」と自発的に取りに行く仕組みをプルモデルと呼びます。これを設定することを「イベントソースマッピング」と言います。
代表例としては、メッセージを一時的に溜めておくAmazon SQSや、データベースの変更履歴を流し続けるDynamoDB Streamsなどがあります。
このプルモデルの強みは、ストリーミングデータのバッチ処理との相性が抜群に良いことです。データが1件届くたびにいちいちLambdaを動かすのではなく、「溜まったらまとめて取得する」ということが可能です。例えば、DynamoDB Streamsをイベントソースに設定した場合、最大で1万件までのレコードをひとまとめにしてLambdaに渡すことができます。
大量のデータが継続的に発生するシステムにおいて、通信のオーバーヘッド(無駄なやり取り)を減らしながら効率よく処理を進められるため、バッチ処理やリアルタイムのデータ連携でよく活用されます。プッシュモデルが「トリガー元のサービスで設定する」のに対し、プルモデルは「Lambda側の設定画面で、どこからデータを持ってくるかを紐づける」という違いがあるので、覚えておくと設定時に迷わずに済みます。
EventBridgeを活用したイベントルーティング
最後にご紹介するのは、Amazon EventBridgeです。EventBridgeは、さまざまなAWSサービスから発生するイベントを「受け取って、条件に合った宛先に振り分ける」という、イベントの交差点のような役割を果たすサービスです。
EventBridgeを経由してLambdaを呼び出すと、単なる直接連携よりも柔軟で高度なシステムを構築できます。主に以下の2つの使い方が実務では頻出です。
1つ目はスケジュール実行です。「毎日午前9時に処理を走らせたい」「30分おきにデータを収集したい」といった場合、EventBridgeのルールにcron式やrate式(例:rate(30 minutes))を設定し、ターゲットにLambdaを指定するだけで、手軽に定期実行の仕組みが作れます。
2つ目は条件付きのイベントルーティングです。「EC2インスタンスが停止した時だけ通知したい」「特定のS3バケットに画像がアップロードされた時だけサムネイルを作りたい」といったケースです。EventBridgeはJSON形式のイベントデータの中身を見て、「どのサービスで」「どんな種類の変化が起きて」「どんな詳細状態か」という条件を細かく指定できます。この条件にマッチしたイベントだけをLambdaに送ることができるため、Lambdaが無駄な処理をせずに済むというメリットがあります。
Warning
EventBridgeからLambdaをターゲットとして設定する際、忘れがちなのが「IAMロールの権限設定」です。EventBridgeが「あなたのLambdaを呼び出していいですか?」という許可を持っていないと、ルールを作ってもエラーになってLambdaが起動しません。設定画面に表示される権限の作成オプションは必ず有効にするようにしてください。
このように、プッシュ、プル、EventBridgeと呼び出しのバリエーションを理解しておくことで、「今作ろうとしている機能は、どの連携方法が一番適しているかな?」と最適な設計を選びやすくなります。
Lambdaを採用する3つの大きなメリット
ここまでLambdaの基本概念や連携方法について見てきましたが、「結局のところ、どうして皆さんLambdaを使いたがるのでしょうか?」と疑問に思うかもしれません。最初は「サーバーがないなんて不安だな」と感じる方もいるでしょう。しかし実際に触れてみると、これまでのサーバー運用の常識を覆すような、理にかなったメリットがたくさんあります。ここでは、Lambdaを採用する最大の理由を3つに絞ってお話しします。
サーバー管理の不要化による運用負荷軽減
Lambda最大の魅力、それはずばり「面倒なインフラ管理から解放される」という点です。
従来のAmazon EC2などの仮想サーバーを使う場合、サーバーを立てるだけでは終わりません。OSのアップデートや、深刻な脆弱性を見つけてすぐに当てるセキュリティパッチの適用、ディスク容量の監視など、アプリケーションのコードを書く以外にも山のような作業が発生します。休日にパッチ適用のメンテナンスを行った経験がある方も少なくないのではないでしょうか。
Lambdaでは、これらがすべてAWS側で自動的に行われます。開発者は、OSがどうなっているかや、ランタイム(PythonやNode.jsなどの実行環境)のセキュリティ更新を気にする必要がありません。関数のコードと設定だけをAWSに渡せば、あとはAWSが安全に隔離された実行環境を用意してくれます。これにより、私たちは本来やりたかった「ビジネスロジックの開発」にじっくりと時間を割けるようになります。
トラフィックに応じた自動スケーリング
「明日のプレゼンで自社サービスのURLを共有するから、アクセスが急増するかも…」そんな時、従来のサーバーならキャパシティプランニングに頭を悩ませる必要がありました。あらかじめ大きめのサーバーを用意しておくのか、監視ツールでトラフィックを検知して自動でサーバーを増やす設定(オートスケーリング)を組んでおくのか。どちらにしても設定ミスのリスクはつきまといます。
Lambdaは、このあたりの心配を一切不要にしてくれます。ユーザーからのアクセス(リクエスト)が来たタイミングで、自動的にその数に合わせて実行環境を複製し、処理を分散させます。1秒間に10件のリクエストが来れば10個の環境が立ち上がり、1万件来れば1万個立ち上がるイメージです。しかも、デフォルトで「マルチAZ構成」となっており、1つのデータセンターが障害を起こしても別のデータセンターで処理が継続されるよう、高い可用性が最初から備わっています。ユーザー側で細かいスケーリングの設定をしなくても、トラフィックの波に自動で乗ってくれるのは非常に心強いポイントです。
使った分だけ課金されるコスト最適化
Lambdaの料金体系は「従量課金制」です。具体的には、コードが実際に実行されている時間(ミリ秒単位)と、実行された回数の2つだけで課金されます。
例えば、月に数回しか動かないバッチ処理や、昼休みの12時〜13時だけアクセスが集中する社内ツールをEC2で動かしていたとします。この場合、夜間や週末など誰もアクセスしていない時間帯でも、サーバーを起動しておけば毎月数千円〜数万円の固定費が発生し続けます。
しかしLambdaであれば、誰もアクセスしていないアイドル状態の時には費用が「完全にゼロ」になります。リクエストが来てコードが動いている数秒間だけ、微小な単位で課金される仕組みです。また、AWSアカウントを作成すると「毎月100万回のリクエスト」と「毎月40万GB-秒の実行時間」まで無料で使える無料枠がついてくるため、個人の学習や小規模な検証であれば、実質的にタダで使い倒すことも可能です。
Tip
Lambdaは「メモリの割り当て量」を128MB〜10,240MBの間で自由に設定できます。実は、メモリを増やすとそれに比例してCPUの性能も向上する仕組みになっています。そのため、メモリを2倍にして処理時間が半分以下になれば、結果的に課金額が安くなるという逆説的なコスト削減テクニックがよく使われます。時間のかかる処理がある場合は、メモリ量を調整して最適なコスパのポイントを探してみてください。
Lambdaの制限(クォータ)と設計上の注意点
ここまでLambdaの魅力や仕組みについてお話ししてきましたが、どんな素晴らしいサービスにも得意・不得意はあります。「サーバーレスだから何でもできる」と思って設計に入ると、後で大きな壁にぶつかることになります。
Lambdaの制限を見落として設計に取り掛かると、後で大きな壁にぶつかることになります。ここでは、Lambdaを設計するうえで絶