読者です 読者をやめる 読者になる 読者になる

AWSでサーバレスアーキテクチャで開発する際のいくつかの制約について

現在開発中の新規サービスは、AWSを利用したサーバレスアーキテクチャを採用しています。
Angular2のSPAをS3に配置してCloudFrontで配信、データ取得などのためのAPIAWS Lambda + API Gatewayで実装する、教科書通りの構成をとっています。
そこまで大規模なサービスではないのですが、現時点でのAPI数は約100弱。それを手作業で管理するのはよろしくないということで、Serverless Frameworkを用いて管理しているのですが、その中でいくつかの制約に遭遇したのでまとめておきます。
なお、Serverless Frameworkはv1.5を利用しています。現在の最新版はv1.9.0なので、Serverlessに関するいくつかの項目は解決されている場合もあります。

AWS Lambda

関数名の長さ

関数名の長さが64文字までの制限があります。参考: CreateFunction
Serverlessは関数名にサービス名とステージを組み合わせて、${service-name}-${stage}-${functionName}という名前でLambda関数を作成します。
プロジェクトではSwaggerでAPIの振る舞いを定義し、独自に開発したAKIRA-MIYAKE/serverless-import-swaggerserverless.ymlを自動的に生成するようにしているのですが、APIのパスやパラメータに基づいて自動生成した関数名がたまにこの制約に引っかかってしまいました。
任意の関数名を決める場合なら問題にはならないのですが、関数名を自動生成する場合は(そういう人がどれくらいいるかは不明ですが)一意に識別可能でかつ可能な限り短い名前を生成することを意識する必要があります。

CloudFormation

リソースの最大数

ServerlessはCloudFormationを利用してAWS LambdaとAPI Gatewayへのデプロイを実行するのですが、その際に関数や関連するリソースが多すぎると、テンプレートで宣言できるリソースの最大数200の制約に引っかかります。参考: AWS CloudFormation の制限
例えばHTTPをイベントソースとする関数だとAPI Gatewyのリソースやメソッドの定義が必要となるため、関数が30に近いあたりからこの制約に引っかかる可能性が出てきます。
そのため、ある程度の規模のAPIを構築する場合、サービスを分割する必要が出てきます。

出力の最大数

CloudFormationには出力の最大数が60までという制約があります。
Serverless v1.5までは作成されたスタックを全て出力される設定となっているため、それ以上の規模のサービスを定義することができません。
v1.6以上では、CloudFormationの出力が削除されているため、この制約に引っかかることはなくなったのですが、代わりに次の問題が生じるようになっています。

LogGroup作成時のエラー

Serverless v1.5では発生しないのですが、v1.6以降で遭遇するエラー。

An error occurred while provisioning your stack: IamPolicyLambdaExecution
     - Template error: LogGroup /aws/lambda/my-service-name-dev-functionName
     doesn't exist.

v1.6からロググループの作成方法が変更になったようなのですが、どうやら#2614 (comment)にあるように、CloudFormationレベルのバグに起因するもののよう。
関数名のプレフィックスの命名に注意すれば回避できるようですが、あまり好ましい解決策ではない。。

API Gateway

カスタムドメインへの複数APIマッピング

CloudFormationの制約で、それなりの規模のAPIの場合、サービスを分割することが必要。
ServerlessのサービスがAPI GatewayAPIに対応するのですが、カスタムドメインを複数のAPIマッピングする場合は一意のベースパスの設定が必要となります。
そのため、複数サービスに分割する際はそれを考慮する必要があります。
今回はSwaggerで定義したAPIのパスの最初のディレクトリで機械的に分割してグルーピング、そしてそのディレクトリはserverless.ymlのAPIのパスからは除外するという形で対応しています。
RESTfulなAPIであればそこまで大きな問題にはならないと思いますが、今回のサービスではログイン中ユーザに依存する情報を取得する際のAPIとして/userを複数定義していたため、論理的にはあまり関連のないAPIが同じサービスに含まれるような形となってしまいました。


サーバレスアーキテクチャを採用したAPIを開発する中で遭遇した、AWSのいくつかの制約についてあげてみました。
それなりの規模のAPIをServeress、もしくはCloudFormationで管理する場合、リソースの最大数が200という制約で、必然的にいくつかのグループに分割する必要が生じるというのが、それなりに大きいかと思います。
AWS CLIを利用して直接リソースを作成すればその制約を受けることはありませんが、今度は依存関係の解決が難しくなってきます。

今回のプロジェクトは、サーバレスアーキテクチャを利用したステートフルなバックエンド開発、その過程でserverless-import-swaggerなどいくつかツールを開発したので、ブログで紹介していきたいと思います。