AWS SAMを使ったAWS Lambda関数のVPC設定

はじめに

ちょっと前までAWS Lambda上で動くアプリをJavaで実装することをやっていました。

このアプリの特性として、S3やRDSと接続することになるのですが、これらの環境をマネジメントコンソールで操作するのは面倒くさいので、AWS SAMを使って実装してみることにします。

VPCの設定

マネジメントコンソール上の設定で面倒なのは、VPCの設定です。AWS SAMのドキュメントを見るとプロパティの最後にVpcConfigがあるのでこれを設定することになります。

docs.aws.amazon.com

ここでは、必要なVPCAWS SAMのテンプレートファイル(template.yml)にて作成するようにします。

  vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      InstanceTenancy: default
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: AWS-Flayway-Lambda-VPC
  private1:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.0.0/24
      VpcId: !Ref vpc
      AvailabilityZone: !Select [0, !GetAZs '']
      Tags:
        - Key: Name
          Value: AWS-Flayway-Lambda-private1
  private2:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.1.0/24
      VpcId: !Ref vpc
      AvailabilityZone: !Select [1, !GetAZs '']
      Tags:
        - Key: Name
          Value: AWS-Flayway-Lambda-private2
  # route table
  routeTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref vpc
      Tags:
        - Key: Name
          Value: AWS-Flayway-Lambda-route-table
  # route tableのアサイン
  subnet1Association:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref private1
      RouteTableId: !Ref routeTable
  subnet2Association:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref private2
      RouteTableId: !Ref routeTable
  # VPC LambdaからS3にアクセスするためのVPCエンドポイント
  vpcEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref vpc
      VpcEndpointType: Gateway
      ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
      RouteTableIds:
        - !Ref routeTable
  # Lambdaが使用するセキュリティグループ
  securityGroupForLambda:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: security-group-for-lambda
      GroupDescription: For Lambda
      VpcId: !Ref vpc
      SecurityGroupEgress:
        - CidrIp: 0.0.0.0/0
          IpProtocol: -1

ここで指定したサブネットやセキュリティグループを使ってVpcConfigを以下のように指定します。

  function:
    Type: AWS::Serverless::Function
    # 関数の定義
    Properties:
    # 中略
      VpcConfig:
        SecurityGroupIds:
          - !GetAtt securityGroupForLambda.GroupId
        SubnetIds:
          - !Ref private1
          - !Ref private2

マネジメントコンソールを使った設定で、毎回つまづくのがAWSLambdaVPCAccessExecutionRoleの不足によりVPC設定ができないということです。AWS SAMのテンプレートのPoliciesを使って必要なロールを設定しておきます。

  function:
    Type: AWS::Serverless::Function
    # 関数の定義
    Properties:
      # 省略
      Policies:
        - AWSLambdaBasicExecutionRole
        - AWSLambda_ReadOnlyAccess
        - AWSXrayWriteOnlyAccess
        - AWSLambdaVPCAccessExecutionRole
        - AmazonS3ReadOnlyAccess
     # 以下略

以上の設定からスムーズにLambda関数のVPC設定を行うことができ、またS3との接続も容易にできるようになりました。

考察

今回はAWS SAMを使ったAWS Lambda関数のVPC設定を実装しました。大量にあるプロパティの中からVPC設定の部分をマニュアルから見つけるのは難しいのですが、最近(2023年11月に)入った以下の更新で、AWS SAMの設定をSAMテンプレートファイルとしてダウンロードできるようになりました。

aws.amazon.com

今回はこの機能を使って、まずはマネジメントコンソールで設定した後、VpcConfigの設定を実装してみました。このような機能を使うといわゆるIaCも簡単に実装できるのかなと考えています。