[レポート] サーバーレスアプリケーション向けネットワークのベストプラクティス Networking best practices for serverless applications #SVS404 #reinvent

2019.12.05

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

CX事業本部@大阪の岩田です。 本エントリはAWS re:Invent 2019のセッションSVS404 Networking best practices for serverless applicationsのレポートとなります。

セッション情報

Serverless technologies such as AWS Lambda have removed the burden of server management, but what about networking? When should you put a Lambda in an Amazon VPC? How do you balance security vs. the flexibility offered by Lambda? What are the best practices for working with private endpoints, NATs, and peering? In this session, we go over the best practices of working with Lambda functions from a networking perspective. We talk about how networking impacts performance and cost and how to make sure that your network design allows for scale and meeting strict security concerns.

レポート

Lambda × VPC

LambdaからVPCリソースにアクセスしたい場合にVPC Lambdaを使う

VPC Lambdaの改善について

  • 数ヶ月前にVPC Lambdaのアーキテクチャ改善が適用された
    • 旧アーキテクチャではコールドスタート時に必要に応じてENIの作成とVPCへのアタッチを行なっていた
    • この初期化処理に多くの時間がかかっていた
  • 新アーキテクチャではHyperplane ENIから顧客VPC内のENIにNAT処理を行うようなアーキテクチャに変わった
    • ENIの作成はLambda作成時もしくは既存のLambdaをVPCにアタッチした際に実行されるようになった
    • このアーキテクチャの改善によりコールドスタート時のパフォーマンスが大きく改善した
  • ENIはセキュリティグループとサブネットの組み合わせごとに作成される
    • つまり、セキュリティグループとサブネットが同一であれば複数のLambdaが1つのENIを共有することができる

新アーキテクチャでも変わらないこと

  • 必要なIAMの権限は変わっていない
    • ec2:CreateNetworkInterface
    • ec2:DescribeNetworkInterfaces
    • ec2:DeleteNetworkInterface
  • セキュリティグループの管理も必要
  • インターネットアクセスにはNat Gatewayが必要
  • AWSリソースへのアクセスであればVPC Endpointの利用も可能

ベストプラクティス

  • VPC Lambdaから非VPCリソースへのアクセスが必要な場合はVPCエンドポイントを使う
  • VPCエンドポイントには2種類ある
インターフェースエンドポイント

  • PrivateLinkを利用して接続する
  • DNSを利用して接続する
  • 各サービスのエンドポイントをVPCエンドポイントネットワークインターフェースのプライベートアドレスに解決する
ゲートウェイエンドポイント

  • S3とDynamoDBが該当
  • VPCエンドポイント向けのルートテーブルを追加することで接続する

デモ

  • VPC LambdaからSSMパラメータストアにアクセスするデモ
  • コールドスタートを引いても274msで処理が完了しており、非常に高速化されていることが分かる

API Gatewayに関するベストプラクティス

様々なコンポーネントがAPI GWのクライアントになり得る

  • 非AWS環境
    • モバイルアプリ
    • Webサイト
    • サービス
  • AWS環境
    • 同一AWSリージョンのアプリケーションやサービス
    • 同一VPCのアプリケーションやサービス

プライベート API GateWayのベストプラクティス

※それぞれの構成の課題に言及している部分が良く聞き取れなかったので、動画が公開され次第追記/編集を行います

VPC内からPrivate DNSが有効化されたプライベートAPI Gatewayにアクセスする場合

  • ホスト名とホストヘッダが.execute...になる
VPC内からPrivate DNSが無効化されたプライベートAPI Gatewayにアクセスする場合

  • ホスト名とホストヘッダが<VPCエンドポイントのID>.execute...になる
VPC外からプライベートAPI Gatewayにアクセスする場合

  • ホスト名とホストヘッダが<VPCエンドポイントのID>.execute...になる
  • オンプレからのアクセスは問題ないが、別VPCからのアクセスに問題がある
    • 独自 ドメインを使用しつつ、どこからでもプライベートAPI Gatewayにアクセスしてもらうにはどのような構成を取ると良いか?
    • ALBとNginx Plusのようなリバースプロキシを使う

  • クライアントからのリクエストは一旦ALBで受ける

  • ALBからリバースプロキシに流し、リバースプロキシがホストヘッダを書き換えた後にAPI Gatewayに転送する

パブリックAPI GateWayのベストプラクティス

  • パブリックAPI Gatewayのエンドポイントにはエッジ最適化API エンドポイントとリージョンAPI エンドポイントの2種類がある

    • エッジ最適化APIエンドポイントは前段にCloudFrontを利用している
    • デフォルトはエッジ最適化APIエンドポイント
    • それぞれメリット/デメリットがある

    • エッジ最適化APIエンドポイント
      • 地理的に分散したクライアントに有利
    • リージョンAPIエンドポイント
      • クライアントが同一AWSリージョンのEC2等の場合に有利
    • SAMやServerlessFrameworkを使ってデプロイするとエッジ最適化エンドポイントでデプロイされる

API Gatewayへの要求を転送するためだけにLambdaを使わない

  • Dont use Lambda to transport only transform

  • API Gatewayに流れてきたリクエストをそのままDynamoDBに流すだけならLambdaを挟む必要はない

スロットリングについて

  • API GatewayにはAWSアカウントに対して10,000 リクエスト/秒 (RPS) という制限がある
  • 使用量プランの機能を利用する
    • 使用量プランの機能を利用するとAPIキーごとにスロットリングの制限を設定することができる
    • クライアントはHTTPヘッダにAPIキーをセットしてリクエストしてもらう
    • APIレベル、ステージレベルで制限が可能
  • スロットリングに関する設定は以下の優先順位で適用される
  1. 使用量プランで設定したクライアントあたり、メソッドあたりのスロットリング制限
  2. 使用量プランで設定したクライアントあたりのスロットリング制限
  3. ステージ設定で設定した、デフォルトのメソッドあたりの制限および個別のメソッドあたりの制限
  4. アカウントレベルの制限(上限緩和申請可能)

キャッシュ

  • API Gatewayのキャッシュ機能を活用する
  • ステージレベルのキャッシュ設定メソッドレベルのキャッシュ設定でオーバライドが可能

その他

  • Lambdaの実装でもキャッシュを有効活用し、通信量を削減する
  • 例えばSSMパラメータストアから取得したパラメータを使った処理を実行する場合、最初に取得した結果をグローバル変数にセットしておくことで2回目以後はパラメータストアへのアクセスが不要になる
    • メモリ上でのキャッシュなのでLambda実行環境を跨いでキャッシュを共有することはできない
    • 参考 ssm-cache-python

まとめ

普段API Gatewayを前段においてLambdaに流して...という鉄板な構成しか触っておらず、オンプレ環境やEC2との統合まで考慮したAPI Gatewayの構成がとても新鮮でした。サーバーレスアーキテクチャと非サーバーレスアーキテクチャを組み合わせた複雑な構成でも、適切なアーキテクチャを検討できるように勉強していきたいと思います!