ゼロから本番環境へ:AWS LambdaでスケーラブルなサーバーレスAPIを構築する

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

サーバーレスへの移行

物理サーバーや仮想サーバーの管理は、時にフルタイムの仕事のように感じられます。OSのパッチ適用、トラフィック急増時のインスタンスのスケーリング、アイドルコストの懸念など、運用負荷はすぐに積み重なります。そこで登場するのがサーバーレスコンピューティングです。インフラの世話をする代わりに、コードだけに集中できます。AWSが基盤となるリソースを管理し、需要に合わせて自動的にスケールさせます。

このアーキテクチャの核心は、2つの強力なサービス、AWS LambdaとAmazon API Gatewayにあります。Lambdaはイベントに応じてバックエンドロジックを実行し、API Gatewayはフロントドアとして機能してHTTPリクエストを関数にルーティングします。私はこの構成を、1時間に数千のリクエストを処理するマイクロサービスに使用したことがありますが、サーバーを手動で再起動することなく、極めて安定して動作し続けています。

DevOpsにおいてサーバーレスが優れている理由

DevOpsの観点からは、サーバーレスは攻撃対象領域と運用負荷を劇的に削減します。インスタンスのSSHキーを管理したり、細かなアップデートのたびにロードバランサーの設定を手動で調整したりする必要はありません。何より、料金モデルは厳密なリクエスト単位の支払いです。AWSはLambdaに対して月間100万リクエストの無料枠を提供しています。APIが誰からも呼び出されなければ、請求額は0ドルのままです。これは、トラフィックが予測しにくいスタートアップや社内ツールに最適です。

前提条件とセットアップ

AWSコンソールを操作する前に、アクティブなアカウントがあることを確認してください。長期的にはTerraformやAWS CDKのようなツールの方が管理に適していますが、初めて構築する場合は、マネジメントコンソールを使用して各パーツがどのように組み合わさるかを視覚化するのが役立ちます。

IAMロール:セキュリティの基盤

AWSは最小権限の原則に基づいて動作します。Lambda関数が実行され、CloudWatchにログを書き込むには、特定の権限が必要です。これらがないと、問題が発生したときに状況を把握できなくなります。

  1. IAM (Identity and Access Management) ダッシュボードに移動します。
  2. 新しいロール (Role) を作成します。
  3. 信頼されたエンティティとして Lambda を選択します。
  4. AWSLambdaBasicExecutionRole ポリシーをアタッチします。これにより、関数がログを生成できるようになります。
  5. 名前を my-lambda-api-role とし、保存します。

ステップバイステップの設定

ユーザー名を受け取り、パーソナライズされた挨拶を返すシンプルなAPIを構築します。これは単純な例ですが、複雑なアプリで使用するリクエスト・レスポンスのライフサイクル全体をカバーしています。

ステップ1:Lambda関数の作成

Lambda サービスに移動し、[関数の作成] をクリックします。

  • [一から作成] を選択します。
  • 関数名: hello-world-api
  • ランタイム: Python 3.12(現在の安定版の選択肢)
  • アーキテクチャ: x86_64
  • アクセス権限の下で、先ほど作成した my-lambda-api-role を選択します。

関数が準備できたら、エディタ内のボイラープレートコードを以下のスニペットに置き換えます。

import json

def lambda_handler(event, context):
    # クエリパラメータから名前を取得するか、デフォルトを "Stranger" に設定
    query_params = event.get('queryStringParameters') or {}
    name = query_params.get('name', 'Stranger')
    
    message = f"こんにちは、{name}さん!初めてのサーバーレスAPIへようこそ。"
    
    return {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*' # ブラウザからの呼び出しに必須
        },
        'body': json.dumps({
            'message': message,
            'status': 'success' # 成功
        })
    }

[Deploy] をクリックします。これでコードがAWSインフラ上で公開され、トリガーを待つ状態になります。

ステップ2:API Gatewayの設定

次に、この関数にアクセスするための公開URLが必要です。API Gateway に移動し、[APIを作成] をクリックします。

ここでは主に2つの選択肢があります。HTTP API は、従来の REST API よりも最大71%安価で、低レイテンシです。ほとんどの現代的なWebアプリには、HTTP APIの方が適しています。このガイドではこちらを使用します。

  1. HTTP APIの下にある [構築] をクリックします。
  2. [統合を追加] をクリックし、Lambda を選択します。
  3. リージョンと hello-world-api 関数を選択します。
  4. API名: serverless-greeting-api
  5. ルートを設定します:メソッドGET に、リソースパスを `/greet` に設定します。
  6. デフォルトのステージ設定を [次へ] で進み、[作成] をクリックします。

AWSが **URLを呼び出す (Invoke URL)** を生成します。通常、`https://random-id.execute-api.us-east-1.amazonaws.com` のような形式になります。

ステップ3:CORSの処理

ブラウザはセキュリティ上の理由から、デフォルトで異なるドメインへのリクエストをブロックします。ReactやVueのフロントエンドからこのAPIを呼び出す場合は、Cross-Origin Resource Sharing (CORS) を有効にする必要があります。

  • 作成したAPIを選択し、左側のサイドバーで [CORS] を見つけます。
  • [設定] をクリックします。
  • テスト用に Access-Control-Allow-Origin に `*` を追加するか、本番環境では特定のドメインを追加します。
  • Access-Control-Allow-Methods に `GET` を追加します。
  • 変更を保存します。

検証とモニタリング

準備が整ったので、エンドポイントをテストしましょう。ブラウザを使用するか、ターミナルで curl コマンドを実行します。

# 実際の呼び出しURLに置き換えてください
curl "https://your-api-id.execute-api.us-east-1.amazonaws.com/greet?name=John"

ステータス200 OKのクリーンなJSONレスポンスが表示されるはずです。成功です。

CloudWatchによるデバッグ

時には問題が発生することもあります。Pythonの KeyError やタイムアウトが発生するかもしれません。APIが 500 Internal Server Error を返しても、慌てないでください。Lambda関数の [モニター] タブに移動し、[CloudWatchのログを表示] をクリックします。すべての print() 文とエラーのトレースバックがここに保存されます。問題が発生したときに最初に確認すべき場所です。

コストの監視

AWSはミリ秒単位に切り上げられた実行時間に基づいて課金するため、Duration (実行時間) などのLambdaメトリクスは極めて重要です。関数の実行に200ミリ秒かかる場合、正確にその分だけ支払います。コードを最適化して実行速度を上げることは、文字通り節約に直結します。パフォーマンスとコストがこのように直接結びついていることは、サーバーレス開発の最もやりがいのある側面の一つです。

このパイプラインの構築は、クラウドネイティブなアーキテクチャをマスターするための第一歩です。ここから、DynamoDBテーブルに接続したり、S3を使用して画像処理をトリガーしたりすることができます。バックエンドの重い処理は、今やクリーンでスケーラブルなインターフェースの背後に隠されています。

Share: