エキサイト株式会社で新規事業の開発を行っている森脇です。
新規事業ではawsを使いシステムの構築を行っています。 当初の計画ではAPIをLambdaで作成する予定になっており開発を進めておりましたが、 幾つか課題が出てきてしまい、その時の話を書こうと思います。
言語はGoを採用し、最初は小規模の認識で開発を行っていたが、仕様がどんどん膨らみ気づいた時にはエンドポイントが150を超え、そしてやってきたリソース制限
Template format error: Number of resources, 206, is greater than maximum allowed, 200
ネストさせることで回避できることを知り、ネストするもsam build
できず、結局ネストされた各アプリケションを個別にビルドし、マージするシェルを書いて運用していました。
苦労した話を書こうと思って調べていると、いつの間にかネストされたアプリケーションのビルドができるようになっていた!!!
前段の話が長くなりましたが、Lambdaでネストされたアプリケーションを簡単に構築できる話です
構築
2つのアプリケーションにネストさせる例です
template.yaml
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > lambda-go Sample SAM Template for lambda-go Parameters: Region: Type: String Default: ap-northeast-1 Stage: Type: String Default: Dev ApiDomainName: Type: String Default: api.example.com Resources: # Lambda Application App1Application: Type: AWS::Serverless::Application Properties: Location: app1.yaml Parameters: Region: !Ref Region Stage: !Ref Stage ApiDomainName: !Ref ApiDomainName App2Application: Type: AWS::Serverless::Application Properties: Location: app2.yaml Parameters: Region: !Ref Region Stage: !Ref Stage ApiDomainName: !Ref ApiDomainName
アプリケーション1
app1.yaml
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > lambda-go Sample SAM Template for lambda-go # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst Globals: Function: Timeout: 10 Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object Variables: REGION: !Ref Region Parameters: Stage: Type: String Region: Type: String ApiDomainName: Type: String Resources: # ロール App1Role: Type: AWS::IAM::Role Properties: RoleName: app1-role Policies: - PolicyName: app1-policy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - ec2:CreateNetworkInterface - ec2:DescribeNetworkInterfaces - ec2:DetachNetworkInterface - ec2:DeleteNetworkInterface Resource: '*' AssumeRolePolicyDocument: { Version: "2012-10-17", Statement: [ { Effect: "Allow", Principal: { Service: [ "lambda.amazonaws.com" ] }, Action: [ "sts:AssumeRole" ] } ] } ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Path: / # Api Gateway ApiGateway: Type: AWS::Serverless::Api Properties: StageName: !Ref Stage # Base path mapping ApiGatewayBasePathMapping: Type: AWS::ApiGateway::BasePathMapping Properties: DomainName: !Ref ApiDomainName RestApiId: !Ref ApiGateway BasePath: app1 Stage: !Ref ApiGateway.Stage # Lambda Function Test1Function: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: ../../test1/ Handler: test1 Runtime: go1.x Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html Role: !GetAtt App1Role.Arn Events: GET: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: RestApiId: !Ref ApiGateway Path: /test1 Method: GET Test2Function: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: ../../test2/ Handler: test2 Runtime: go1.x Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html Role: !GetAtt App1Role.Arn Events: GET: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: RestApiId: !Ref ApiGateway Path: /test2 Method: GET Test3Function: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: ../../test3/ Handler: test3 Runtime: go1.x Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html Role: !GetAtt App1Role.Arn Events: GET: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: RestApiId: !Ref ApiGateway Path: /test3 Method: GET
アプリケーション2
app2.yaml
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > lambda-go Sample SAM Template for lambda-go # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst Globals: Function: Timeout: 10 Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object Variables: REGION: !Ref Region Parameters: Stage: Type: String Region: Type: String ApiDomainName: Type: String Resources: # ロール App2Role: Type: AWS::IAM::Role Properties: RoleName: app2-role Policies: - PolicyName: app2-policy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - ec2:CreateNetworkInterface - ec2:DescribeNetworkInterfaces - ec2:DetachNetworkInterface - ec2:DeleteNetworkInterface Resource: '*' AssumeRolePolicyDocument: { Version: "2012-10-17", Statement: [ { Effect: "Allow", Principal: { Service: [ "lambda.amazonaws.com" ] }, Action: [ "sts:AssumeRole" ] } ] } ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Path: / # Api Gateway ApiGateway: Type: AWS::Serverless::Api Properties: StageName: !Ref Stage # Base path mapping ApiGatewayBasePathMapping: Type: AWS::ApiGateway::BasePathMapping Properties: DomainName: !Ref ApiDomainName RestApiId: !Ref ApiGateway BasePath: app2 Stage: !Ref ApiGateway.Stage # Lambda Function Test10Function: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: ../../test10/ Handler: test10 Runtime: go1.x Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html Role: !GetAtt App2Role.Arn Events: GET: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: RestApiId: !Ref ApiGateway Path: /test10 Method: GET Test11Function: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: ../../test11/ Handler: test11 Runtime: go1.x Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html Role: !GetAtt App2Role.Arn Events: GET: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: RestApiId: !Ref ApiGateway Path: /test11 Method: GET Test12Function: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: ../../test12/ Handler: test12 Runtime: go1.x Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html Role: !GetAtt App2Role.Arn Events: GET: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: RestApiId: !Ref ApiGateway Path: /test12 Method: GET
ネスト以外のポイントとして、API GatewayのAPI マッピングを使ってネストされたアプリケーションをマッピングしています。
ApiGatewayBasePathMapping: Type: AWS::ApiGateway::BasePathMapping Properties: DomainName: !Ref ApiDomainName RestApiId: !Ref ApiGateway BasePath: app2 Stage: !Ref ApiGateway.Stage
これをすると、template.yaml
で指定している、ApiDomainName
(api.example.com)で各ネストされたアプリケーションにアクセスできるようになる
例えば、https://api.example.com/app1/test1 とか https://api.example.com/app2/test10 など
*実際に試して頂く場合はApiDomainName
を変更して頂く必要があります
デプロイ
デプロイ時にはcapabilities
にCAPABILITY_AUTO_EXPAND
を指定しデプロイをおこないます、成功するとCloudFormationでネストされたアプリケーションが表示されます
ソース
参考までにソースを公開します