AWS Lambda

# Lets Dive Deep into AWS Lambda

## Serverlessとは

  • インフラのプロビジョニング不要、管理不要
    • プロビジョニングが不要
    • キャパシティプランニングが不要
    • セキュリティパッチ適用といった保守作業が不要
  • 自動でスケール
    • リスエスト数に応じて起動数がコントロールされる
    • シームレスにスケール
    • 基本的にスケーリングに上限なし
  • 価値に対する支払い
    • 事前に必要なコストが存在しない
    • リクエスト数ならびに処理の実行時間に対しての課金
    • コスト効率が良い
  • 高可用かつ安全
    • メンテナンス時間や定期的なダウンタイムが存在しない
    • 高い可用性になるように設計されている

 

## AWS Computeサービス

  • EC2 インスタンス・ハードウエア)
  • Container Services(アプリケーション・OS
  • Lambda(関数・ランタイム)

基本的に下に行くほど自由度は低くなるが管理の手間が少なくなる

 

## Lambda の基本

  • サポートされている言語、またはカスタムランタイムで用意した言語を利用
  • それぞれが隔離されたコンテナ内で実行される
  • 利用する言語の関数もしくはメソッドをハンドラーとして指定し、実行の際に呼び出す
  • コードは依存関係も含めてビルド、パッケージングした上でアップロード
    • ZIP形式
    • アップロードしたものはS3に保存され、実行時以外は暗号化される
    • S3ARNを指定することも可能

 

  • Lambda 関数 - 基本設定
    • メモリとCPUは比例
    • メモリ容量が増えると、使用するコア数も増えるのでマルチコアを活用するようなコードを実装すルことでより効率よく処理できる
    • タイムアウトは最大15
    • Lambda から実行できるAWSリソースを指定できる

 

  • 制限
    • インバウンド接続はブロックされる
    • アウトバウンドはTCP/IPUDP/IPソケットのみ
    • ptrace system callはブロックされる
    • 25番ポート(SMTPメールサーバ)のトラフィックはブロックされる

 

  • イベントソース
    • 起動方法
      • ポーリングベース
        • ストリームベース
        • それ以外
      • 他のAWSリソースから呼び出される
    • イベントソースによって呼び出しタイプが異なる
      • リトライの動きも異なる
      • 呼び出しのタイプも呼び出し元のAWSサービスによって異なる(同期、非同期)
  • 呼び出しタイプ
    • Tips
      • カスタムアプリケーションによる呼び出し、CLIなどを用いての手動実行の場合呼び出しタイプを指定できる
      • AWSサービスの場合、サービスごとに事前に決まっており変更できない
    • タイプ
      • 非同期呼び出し
        • Invocation Type Event
        • レスポンス内容はリクエストが正常に受け付けられたかどうかのみ
      • 同期呼び出し
        • InvocationtypeRequestResponse
        • 実効完了時にレスポンスが返ってくる
  • 関数のリトライ
    • ストリームベースでないイベントソース
      • 同期呼び出し
        • エラー発生時にはレスポンスヘッダにFunctionError が含まれる
      • 非同期呼び出し
        • 自動的に2回までリトライされ、その後イベントは破棄される
        • リトライには遅延がある
        • Dead Letter Queue を設定することで未処理のイベントをSQSキューまたはSNSトピックに移動させることができる
    • ポーリングベース
      • ストリームベース
        • データの有効期限が切れるまでリトライを行う
        • 失敗したレコードの有効期限が切れるか処理が成功するまで、そのシャードからの読み込みはブロックされ新しいレコードの読み込みは行われない
      • ストリームベースではない
        • メッセージは全てキューに帰り Visibility Timeout が過ぎればまた処理が行われ、その後成功すればキューが削除される
        • 新しいメッセージの処理はブロックされない
  • VPCアクセス
    • VPC内のリソースへインターネットを経由せずにアクセス可能
    • Lambda に対してVPCサブネットおよびセキュリティグループを指定
      • 後から設定することも可能
      • AZごとに1つ以上のサブネットを指定しておくことを推奨
    • ENIを利用して実現
      • 作成削除はLambdaによってコントロール
      • ENIには指定したサブネットのIPDHCPで動的に割り当てられる
      • 関数に指定のIAM Roleをアタッチ
    • 注意点
      • 設定したタイミングからインターネットアクセスが不可になる
      • 必要な場合はNATインスタンスを用意するかNAT gatewayを利用する
      • 十分な数のENIまたはサブネットIPがない場合はリクエスト数が増えた場合に失敗する
      • 任意のプライベートIPを指定することはできない(Lambdaによって作成・削除されるため)
      • グローバルIPアドレスはコンテナで指定することはできないが、NATインスタンスを利用することで可能
      • オンプレミスにあるリソースにアクセスしたい -> DirectConnectVPNで実現可能
      • ENIを作成する場合は10秒から60秒かかる
      • ENIは複数のLambda関数から共用される
  • IAMを用いたアクセス許可
    • Lambda関数およびレイヤーようにリソースベースのアクセス許可ポリシーをサポート
      • リソースごとに他のアカウントに使用許可を与えられる
      • AWSサービスによる関数呼び出しを許可することも可能
  • 同時実効数
    • デフォルトでは1000
    • 同時実効数を超えると429エラー
    • アカウントで同時実効数に上限があるが、関数ごとに指定することも可能
    • ポーリングベースかつストリームベースだとシャード数と等しい
    • ポーリングベースでストリームベースではない
      • 同時実効数までスケールアップするが、クセあり
      • アカウントの同時実行数までスケールして、他のLambdaの起動を妨げる可能性あり
  • 自動スケーリング
    • 許可された値まで自動でスケーリング
    • バースト後に1分ごとに500ずつ同時実効数がスケールしていく
    • この値の上限緩和は不可

 

## Lambda 関数のライフサイクル

  1. ENIの作成(VPCを利用する場合は初期化に10~60秒かかる)
  2. コンテナの作成
  3. デプロイパッケージのロード
  4. デプロイパッケージの展開
  5. ランタイムの起動・初期化
  6. 関数/メソッドの実行(ここの実行時間に対して課金される)
  7. コンテナの破棄

 

## Lambda 関数の設定

  • 同時実行数の管理(スロットリング
    • DBへの書き込みや外部APIの呼び出し等の流量制御やENI/IPの総利用数のコントロールしたいときに便利
  • 環境変数
    • 環境変数KMSで暗号化される
    • KMSを独自に利用することも可能
  • バージョニング・エイリアス
    • ある一時点のLambdaをバージョンとして管理できる
    • エイリアスは特定バージョンに対するAlias
    • 通常はAlias が別の関数バージョンを示すように更新されるとすぐに切り替わる
    • Routing-config を利用することで2つのバージョン間でのリクエストラフィックの割合を決められる
  • Lambda Layers
    • 特徴
      • 複数のLambdaで利用される共通コンポーネントLayerとして定義できる
      • 共通コンポーネントZIPとしてアップロード
      • 途中で削除しても参照していた側は利用し続けられる
    • 注意点
      • Layer 1つの関数で5つまで
      • Layerの展開順
      • 各言語に依存を解決する固有パスがある
  • タグ付け
  • デッドレターキュー(DLQ)
    • 2回のリトライを経て失敗した場合SQS,SNSに飛ばすことができる
  • カスタムランタイム
    • Runtime bootstrap を含める必要がある
    • Initialization Tasks
      • 環境変数の読み取りなど
      • 関数の初期化
      • エラーハンドリング
    • Processing tasks
      • イベントの取得
      • トレーシングヘッダの電波
      • コンテキストオブジェクトの作成
      • 関数ハンドラの呼び出し
      • レスポンスのハンドリング
      • エラーハンドリング
      • クリーンアップ
    • Runtime Interface
      • カスタムランタイムのためのHTTP API
    • 使い所
      • Lambda の言語サポートのアップデートを待てない場合
      • 古いバージョンを使い続けたい場合
      • サポートされていない言語を利用したい場合
  • モニタリング
    • CloudWatch を用いたMetrices の監視
      • 呼び出されれば最低1回実行することを保証しているので、呼び出されない場合、複数回呼び出されることはあり得る
      • 冪等性の担保は自身でする必要がある
      • メトリクスの意味を理解してみるとボトルネックが見えてくる
    • AWS X-Ray を用いたトラブルシュート
      • 特徴
        • リクエスト実行状況の確認
        • アプリケーションの問題の検出
        • AWSとの連携
        • アプリケーションのパフォーマンス向上
        • 様々なアプリケーション向けの設計
      • 使い方
        • デプロイパッケージにX-Ray SDKを追加し、アクティブトレースをONにする
        • 実行ロールの権限追加
      • サービスグラフ
      • X-Ray デーモン
        • X-Ray デーモンによりLambdaリソースを少し消費
    • CloudTrail によるログ記録
    • CloudWatch Events でスケジュール実行
  • アプリケーションの管理
    • 管理する対象
      • Lambda関数
      • イベントソース
      • その他のリソース
    • ツールセット
      • AWS Serverless Application Repository
    • AWS SAM
      • CloudFormation の拡張
      • サーバレスアプリケーションの定義とパッケージング・デプロイ
    • CLI

 

## 雑感

Lambda はなんでもできるし小さいところでAWSリソース同士をつなぐ役割を果たしたりできるので使い所を選ばない感じだ。ただ、リソースをどのくらい割り当てるかや、周辺リソースを勘案してチューニングする必要があるし、実行タイプ(同期、非同期、ストリームベース)などによって、大量に利用した時にパフォーマンスや料金が変わってくるので大切な要素だと思った。

今回はPart 1と Part2で 3と4に関してはベストプラクティスよりの話っぽい感じだった。ただYouTube でしか用意がないので、見られるタイミングで見たい。