【初学者向け】サーバーレスを学ぶための実践演習1

9月 14, 2020APIGateway,AWS,Lambda

演習1: LambdaからHello World

 

はじめに

  • Lambdaは、すでに定番となったAWSが提供するサーバーレスのコンピューティングサービスですね。今回から数回のシリーズでLambda を基礎から学習するための演習を発信したいと思いますー!
  • これまで業務でLambdaを使った案件はありますが、正直お決まりのアーキテクチャにコードをデプロイしたのみ…。私自身のレベルアップのための勉強と初学者向けの方が取り組む実践的な課題としてまとめ、発信していきます。
 

Lambdaの特徴と制限

  • 先ずは、Lambdaの特徴と制限を以下にまとめます。

特徴

  • Lambdaはサーバーレスのプログラム実行環境であり、AWSのマネージドサービスです。EC2などのIaaSと比べ、OSやフレームワークなどの構築・保守を必要としません。サーバーレスの一番の目的は、インフラの管理が不要になることであり、開発者が本来のコーディングに注力できます。
  • Lambdaはトラフィックの増加に応じて自動でスケールアウトします。オンプレやEC2であれば、サービスの特性に応じてサーバーの可用性を考慮することはユーザー側の責任であり、どの様にスケールするかのポリシーもユーザー側で定義しなければいけません。Lambdaであれば、可用性と自動のスケールをAWSがマネージします。
  • Lambdaは実行時間に対する課金です。稼働中は継続的にコストが発生するEC2と比べると、コスト削減が可能です。但し、前述のスケールアウトでLambdaの同時実行数が増えることで、思わぬ使用料が請求されることもありますので、あらかじめLambdaの同時実行数を制限することも考えます。Lambdaの料金は、こちらを参照。

制限

  • Lambda関数のタイムアウトは900 秒 (15 分)。15分以上実行し続けなければいけないプログラムは、別のプロダクトを選びます。
  • Lambdaの同時実行数は、デフォルトで1,000に制限されています。AWSに引き上げをリクエストすることが可能です。Lambdaの制限については、こちらを参照。
  • Lambdaの開発では、プログラムに冪等性を持たせます。重複するイベントを正しく処理するようなロジックを設計する必要があります。Lambdaの冪等性を持たせたベストプラクティスは、こちらを参照。
 

演習1 の概要

  • 演習1は、"Hello World" を 2パターン作成します。
  • 1つ目はLambda を単体で実行します。2つ目はAPI Gateway + Lambdaを使った構成です。
  • 今回のゴールは、LambdaとAPI Gateway の作り方を覚えることです。
  • 前提条件として、事前にLambdaの実行ロールを準備します。ロールには、少なくとも下記のポリシーをアタッチします。
    • AWSLambdaBasicExecutionRole
   

演習1 Hello Worldのパターン1

システム構成

  • 本演習のシステム構成は、下記の通りです。
     

構築してみる

Lambda を作る

  • Lambdaのコンソールを開き、一から作成します。関数名を入力、ランタイム(今回はPython 3.8とします)、実行ロールを選択します。
   
  • Lambda関数が作成されました。デフォルトで準備されている下記のコードを利用します。

import json
def lambda_handler(event, context):
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }
       

テストしてみる

  • 上記画像右上の[テスト]ボタンを押します。 下記テストイベントの設定画面が表示されます。[イベント名]を入力、今回は内容はそのままの状態で[保存]ボタンを押して、テストイベントを設定します。
     
  • 設定したテストイベント(例: Hello1)が選択されている状態で、[テスト]ボタンを押します。実行結果が表示されます。無事、期待通りの結果が表示されました。
   
  • また、CloudWatch Logsにも結果がログ出力されていることを確認します。
   

演習1 Hello Worldのパターン2

システム構成

  • 本演習のシステム構成は、下記の通りです。パターン1 の続きとして作成し、LambdaのフロントにAPI Gatewayを配置します。クライアントからのAPIコールを受けて、Hello を返す処理を行います。
   

構築してみる

API Gateway を作る

  • API Gateway のコンソールを開き、Create API を選択します。API typeは、REST API を選択します。
  • プロトコルに「REST」、APIに「New API」、API nameにAPI名、Endpoint Typeに「Regional」or 「Edge optimized」を選択します。(Endpoint Typeは後から変更できませんので、ご注意ください)
    • エッジ最適化 API エンドポイントは、地理的に分散されたクライアントに最適なエンドポイントであり、デフォルトのエンドポイントタイプです。APIリクエストは、最寄りのCloudFrontエッジにルーティングされます。
    • リージョン API エンドポイントは、同じリージョンのクライアントを対象とします。
   
  • [Resources]ペインにて、[Actions]から[Create Method]を選択し、メソッドをGET とします。次に、Integration type にて、[Lambda Function]を選択し、[Lambda Region]と[Lambda Function]をパターン1で作成した関数を指定します。
   
  • API GatewayにLambda関数を呼び出す権限の付与を、[OK]とします。
   
  • APIをデプロイします。[Actions]から[Deploy API]を選択します。(今回は[New Stage])、Stage nameにステージ名(今回はdev)を設定し、デプロイを行います。
     

Lambda を作る

  • Lambdaのコンソールに戻り、API GatewayがLambdaのトリガーとして設定されたことを確認します。
   
  • パターン2 のLambdaは、デフォルトのコードを変更します。下記ドキュメントを参考に、CloudWatch Logsに詳細なログを出力させるサンプルコードに変更します。コードを差し替え後、[Save]を押します。

import json
import os
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
    logger.info('## ENVIRONMENT VARIABLES')
    logger.info(os.environ)
    logger.info('## EVENT')
    logger.info(event)
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }
 

テストしてみる

  • curlコマンドで、作成したAPI Gatewayにリクエストを投げます。200 OK およびLambdaに設定したコードの通りBodyが返却されることを確認します。

niikawa@niikawa1:~$ curl 'https://xxxxxxg290.execute-api.ap-northeast-1.amazonaws.com/dev'
{"statusCode": 200, "body": "\"Hello from Lambda!\""}
 
  • また、パターン1と比べ、CloudWatch Logsのログが詳しく出力されていることを確認します。
 

おさらい

  • 演習1では、パターン1で基本的なLambdaの作り方と単体でテストする方法、パターン2でAPI Gateway + Lambda 構成を構築する方法とcurlを使ったAPI のリクエスト仕方について学びました。簡単に作れることが伝わったと思いますので、実際に手を動かして理解してください。
 

参考資料