目次 †
template.yml †Lambda単体 †AWS::Lambda::Function リソースを使用して定義した場合、コード変更だけ行った場合に aws cloudformation deploy では更新されない(※)ので、素直に AWS::Serverless変換 を使用した方が良さそう。 参考 AWSTemplateFormatVersion : '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: Sample Lambda Resources: CloudFormationLambda2: Type: "AWS::Serverless::Function" Properties: FunctionName: CloudFormationLambda2 Description: "CloudFormationで作成したLambda2(AWS::Serverless変換)" Runtime: python3.6 Handler: index.handler # CodeUri に指定したパス配下がアップロードされる # ※S3のPATHを指定する事も可能。(自分でS3にアップロードする必要あり) # ※省略した場合はカレント配下のファイルが全てアップロード対象となる。 CodeUri: ./src MemorySize: 128 Timeout: 60 Role: !GetAtt CloudFormationLambda2Role.Arn CloudFormationLambda2Role: Type: "AWS::IAM::Role" Properties: RoleName: CloudFormationLambda2Role AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: "lambda.amazonaws.com" Action: "sts:AssumeRole" Policies: - PolicyName: "CloudFormationLambda2Policy" PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: "*" Lambda & API Gateway (AWS::Serverless 変換を利用する場合) †AWS::Serverless 変換を使用しない場合と比べるとかなりシンプルに書ける。 AWSTemplateFormatVersion : '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: Test serverless application. Resources: SampleApi: Type: AWS::Serverless::Function Properties: FunctionName: CloudFormationApiLambda2 Description: "CloudFormationApiLambda2" Handler: index.handler Runtime: python3.6 CodeUri: ./src Events: ListApi: Type: Api Properties: Path: / Method: get GetApi: Type: Api Properties: Path: /{id} Method: get Role: !GetAtt CloudFormationApiLambda2Role.Arn CloudFormationApiLambda2Role: Type: "AWS::IAM::Role" Properties: RoleName: CloudFormationApiLambda2Role AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: "lambda.amazonaws.com" Action: "sts:AssumeRole" Policies: - PolicyName: "CloudFormationApiLambda2Policy" PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: "*" Outputs: SampleBookApiUri: # 作成したAPIのURIをエクスポートしておく(AWS::Serverless::Function を使用した場合、ステージは Stage,Prod の2つが作成される) # ※AWS::Serverless変換を使用した場合の RestApi は "ServerlessRestApi" という論理名で定義されるので、これを使用してAPIのIDを取得する事が可能。 Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/" Export: Name: CloudFormationApiLambda2Uri ※実際の運用ではカスタムドメインを使用してベースパスマッピングを設定する事になるが、ここでは割愛する。(関連: CloudFormationでカスタムドメイン対応の API Gateway を作成する) Lambda & API Gateway (AWS::Serverless 変換を利用しない場合) †上記にも記載したが、AWS::Lambda::Function リソースを使用して定義した場合、コード変更だけ行った場合に cloudformation deploy では更新されない為、 AWSTemplateFormatVersion : '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: Sample API Gateway template. Parameters: StageName: Type: "String" Default: "dev" Resources: # Lambda本体 SampleFunction1: Type: "AWS::Serverless::Function" Properties: FunctionName: SampleFunction1 Runtime: python3.6 Handler: index.handler CodeUri: ./src MemorySize: 128 Timeout: 60 Role: !GetAtt SampleFunction1Role.Arn # Lambdaのロール SampleFunction1Role: Type: "AWS::IAM::Role" Properties: RoleName: SampleFunction1Role AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: "lambda.amazonaws.com" Action: "sts:AssumeRole" Policies: - PolicyName: "SampleFunction1Policy" PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: "*" # RestApiの定義 # (AWS::ApiGateway::Resource と AWS::ApiGateway::Method に分けて書くこともできるが、 # ここでは Body プロパティに全て定義した。) SampleRestApi1: Type: 'AWS::ApiGateway::RestApi' Properties: Body: swagger: '2.0' info: version: '1.0' title: !Ref 'AWS::StackName' paths: /: get: # Lambdaプロキシ統合をONにする場合は x-amazon-apigateway-integration オブジェクトを使用して type: aws_proxy を指定する # (参考) https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-swagger-extensions-integration.html x-amazon-apigateway-integration: httpMethod: POST # 統合リクエストで使用されるHTTP メソッド。Lambdaの場合はPOSTを指定 type: aws_proxy # Lambdaプロキシ統合 uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${SampleFunction1.Arn}/invocations" responses: {} '/{id}': get: x-amazon-apigateway-integration: httpMethod: POST type: aws_proxy uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${SampleFunction1.Arn}/invocations" responses: {} # API GatewayへのLambda実行許可 SampleRestApi1Permission: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:invokeFunction' Principal: apigateway.amazonaws.com FunctionName: !Ref SampleFunction1 Principal: "apigateway.amazonaws.com" # SourceArn でURI毎に個別定義する事もできる #SourceArn: !Sub # - >- # arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/{id} # - __Stage__: Prod # __ApiId__: !Ref SampleRestApi1 # デプロイ対象ステージの作成 # (カスタムドメインやステージ変数を使用しない場合は、定義しなくてもOK) #SampleRestApi1ProdStage: # Type: 'AWS::ApiGateway::Stage' # Properties: # DeploymentId: !Ref SampleRestApi1Deploy # RestApiId: !Ref SampleRestApi1 # StageName: !Ref StageName # ステージへのデプロイ SampleRestApi1Deploy: Type: 'AWS::ApiGateway::Deployment' #DependsOn: "SampleApiMethod" Properties: RestApiId: !Ref SampleRestApi1 StageName: !Ref StageName Outputs: SampleRestApi1Uri: Export: Name: SampleRestApi1Uri Value: !Sub "https://${SampleRestApi1}.execute-api.${AWS::Region}.amazonaws.com/${StageName}/" デプロイ用シェル †デプロイ処理をシェルやMakefileにしておくと、開発、運用ともに楽。 デプロイと動作確認 †# デプロイ ./build.sh # スタック状況確認 ./build.sh events # アンデプロイ ./build.sh delete |