AWSでサーバレスアーキテクチャで開発する際のいくつかの制約について
現在開発中の新規サービスは、AWSを利用したサーバレスアーキテクチャを採用しています。
Angular2のSPAをS3に配置してCloudFrontで配信、データ取得などのためのAPIをAWS 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-swaggerでserverless.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 GatewayのAPIに対応するのですが、カスタムドメインを複数のAPIにマッピングする場合は一意のベースパスの設定が必要となります。
そのため、複数サービスに分割する際はそれを考慮する必要があります。
今回はSwaggerで定義したAPIのパスの最初のディレクトリで機械的に分割してグルーピング、そしてそのディレクトリはserverless.ymlのAPIのパスからは除外するという形で対応しています。
RESTfulなAPIであればそこまで大きな問題にはならないと思いますが、今回のサービスではログイン中ユーザに依存する情報を取得する際のAPIとして/user
を複数定義していたため、論理的にはあまり関連のないAPIが同じサービスに含まれるような形となってしまいました。
サーバレスアーキテクチャを採用したAPIを開発する中で遭遇した、AWSのいくつかの制約についてあげてみました。
それなりの規模のAPIをServeress、もしくはCloudFormationで管理する場合、リソースの最大数が200という制約で、必然的にいくつかのグループに分割する必要が生じるというのが、それなりに大きいかと思います。
AWS CLIを利用して直接リソースを作成すればその制約を受けることはありませんが、今度は依存関係の解決が難しくなってきます。
今回のプロジェクトは、サーバレスアーキテクチャを利用したステートフルなバックエンド開発、その過程でserverless-import-swaggerなどいくつかツールを開発したので、ブログで紹介していきたいと思います。