Serverless FrameworkでVPC作るところからHello Worldまで全部自動化してみた!

Serverless FrameworkでVPC作るところからHello Worldまで全部自動化してみた!:


はじめに

この記事は 「ハンズラボ Advent Calendar 2018」 22日目の記事です。

業務でAWSを利用することになったため、いろいろ自動化したいと思ってServerless Frameworkについて調べた内容をまとめました。

具体的には、Serverless Frameworkを使って以下の作業を行なっていきます。

  1. 事前準備(stage, profile, regionなどの設定)
  2. VPCの作成
  3. InternetGatewayの作成
  4. EIPの作成
  5. NatGatewayの作成
  6. Private Subnetの作成
  7. Public Subnetの作成
  8. APIGateway(Public Subnet)の作成
  9. Lambda(Private Subnet)の作成
  10. Serverlessでdeployしてみる
  11. Labmdaを実際に実行してみる
  12. 最後に
なお、本記事はAWSを初めて2ヶ月弱。

Serverless Frameworkを使い出して1週間の状態でいろいろ調べた結果をまとめた内容になっています。

このため、不備などあればぜひコメントで教えていただけるとうれしいです!


1. 事前準備(stage, profile, regionなどの設定)

今回は東京リージョンで、python3.7を指定して環境構築を行なっていきます。

profileは適宜ご自身の環境のものを利用してもらえればと思います。

また、serverless-python-requirementspluginも利用しますので、インストールをお願いします。

serverless.yml
provider: 
  name: aws 
  stage: ${opt:stage, 'stg'} 
  profile: serverless-sample-${self:provider.stage} 
  region: ap-northeast-1 
  runtime: python3.7 
  timeout: 30 
  memorySize: 128 
  versionFunctions: false 
  environment: 
    TZ: Asia/Tokyo 
 
plugins: 
  - serverless-python-requirements 
 
custom: 
  pythonRequirements: 
    dockerizePip: true 
  prefix: ${self:service}-${self:provider.stage} 


1. VPCの作成

Resources配下に以下を追記します。

今回はサンプル環境のため、DeletionPolicyにDeleteを指定しています。

serverless.yml
# リソースの構築 
resources: 
  Resources: 
 
    SampleVPC: 
      Type: AWS::EC2::VPC 
      DeletionPolicy: Delete 
      Properties: 
        CidrBlock: 10.1.0.0/16 
        Tags: 
          - Key: Name 
            Value: SampleVPC 


2. InternetGatewayの作成

Resources配下に以下を追記します。

serverless.yml
SampleInternetGateway: 
      Type: AWS::EC2::InternetGateway 
      Properties: 
        Tags: 
          - Key: Name 
            Value: SampleInternetGateway 
 
    VPCGatewayAttachment: 
      Type: AWS::EC2::VPCGatewayAttachment 
      Properties: 
        VpcId: !Ref SampleVPC 
        InternetGatewayId: !Ref SampleInternetGateway 


3. EIPの作成

Resources配下に以下を追記します。

なお、他のResourceと同じようにPropertiesでTagsを試したところ、未サポートでしたのでコメントアウトしてあります。

EIPはVPC内に作成できる上限値があったりするので注意が必要です。

serverless.yml
SampleElasticIp: 
      Type: AWS::EC2::EIP 
      Properties: 
        Domain: vpc 
        # Tags: 
        #   - Key: Name 
        #     Value: SampleElasticIp 


4. NatGatewayの作成

Resources配下に以下を追記します。

なお、AllocationIdの指定でしばらくハマりました。

当初は、!Ref SampleElasticIpとしていたのですが、この指定だとEIPのIPアドレスが取得されてしまい、NatGatewayの作成で失敗してしまうため、注意が必要です。

serverless.yml
SampleNatGateway: 
      DependsOn: SampleElasticIp 
      Type: AWS::EC2::NatGateway 
      Properties: 
        AllocationId: !GetAtt SampleElasticIp.AllocationId 
        SubnetId: !Ref SamplePublicSubnet 
        Tags: 
          - Key: Name 
            Value: SampleNatGateway 


5 PrivateSubnetの作成

Resources配下に以下を追記します。

serverless.yml
SamplePrivateSubnet: 
      DependsOn: SampleVPC 
      Type: AWS::EC2::Subnet 
      Properties: 
        VpcId: !Ref SampleVPC 
        # AvailabilityZone: ${self:provider.region}a 
        CidrBlock: 10.1.1.0/24 
        Tags: 
          - Key: Name 
            Value: SamplePrivateSubnet 
 
    SamplePrivateRouteTable: 
      Type: AWS::EC2::RouteTable 
      Properties: 
        VpcId: !Ref SampleVPC 
        Tags: 
          - Key: Name 
            Value: SamplePrivateRouteTable 
 
    SamplePrivateRoute: 
      Type: AWS::EC2::Route 
      Properties: 
        RouteTableId: !Ref SamplePrivateRouteTable 
        DestinationCidrBlock: 0.0.0.0/0 
        NatGatewayId: !Ref SampleNatGateway 
 
    SubnetRouteTableAssociationPrivateSubnet: 
      Type: AWS::EC2::SubnetRouteTableAssociation 
      Properties: 
        SubnetId: !Ref SamplePrivateSubnet 
        RouteTableId: !Ref SamplePrivateRouteTable 


6. PublicSubnetの作成

Resources配下に以下を追記します。

serverless.yml
SamplePublicSubnet: 
      DependsOn: SampleVPC 
      Type: AWS::EC2::Subnet 
      Properties: 
        VpcId: !Ref SampleVPC 
        # AvailabilityZone: ${self:provider.region}a 
        CidrBlock: 10.1.11.0/24 
        Tags: 
          - Key: Name 
            Value: SamplePublicSubnet 
 
    SamplePublicRouteTable: 
      Type: AWS::EC2::RouteTable 
      Properties: 
        VpcId: !Ref SampleVPC 
        Tags: 
          - Key: Name 
            Value: SamplePublicRouteTable 
 
    SamplePublicRoute: 
      Type: AWS::EC2::Route 
      Properties: 
        RouteTableId: !Ref SamplePublicRouteTable 
        DestinationCidrBlock: 0.0.0.0/0 
        GatewayId: !Ref SampleInternetGateway 
 
    SubnetRouteTableAssociationPublicSubnet: 
      Type: AWS::EC2::SubnetRouteTableAssociation 
      Properties: 
        SubnetId: !Ref SamplePublicSubnet 
        RouteTableId: !Ref SamplePublicRouteTable 


7. APIGatewayの作成

Resources配下に以下を追記します。

今回はサンプル環境のため、DeletionPolicyにDeleteを指定しています。

serverless.yml
SampleApiGatewayRestApi: 
      Type: AWS::ApiGateway::RestApi 
      DeletionPolicy: Delete 
      Properties: 
        EndpointConfiguration: 
          Types: 
            - REGIONAL 
        Name: ${self:service}-${self:provider.stage} 


8. SecurityGroupの作成

Resources配下に以下を追記します。

serverless.yml
SampleSecurityGroup: 
      DependsOn: SampleVPC 
      Type: AWS::EC2::SecurityGroup 
      Properties: 
        GroupDescription: SecurityGroup for Sample Functions 
        VpcId: !Ref SampleVPC 


9. Lambdaの作成

Resources配下に以下を追記します。

serverless.yml
functions: 
  api: 
    # warmup: true 
    name: ${self:custom.prefix}-api 
    handler: lambda_function.lambda_handler 
    module: functions/api 
    vpc: 
      securityGroupIds: 
        - !Ref SampleSecurityGroup 
      subnetIds: 
        - !Ref SamplePrivateSubnet 
    events: 
      - http: 
          integration: lambda-proxy 
          path: helloworld 
          method: POST 
          cors: true 
    environment: 
      test: api-test 
  batch: 
    name: ${self:custom.prefix}-batch 
    handler: lambda_function.lambda_handler 
    module: functions/batch 
    vpc: 
      securityGroupIds: 
        - !Ref SampleSecurityGroup 
      subnetIds: 
        - !Ref SamplePrivateSubnet 
    environment: 
      test: batch-test 
apiディレクトリ配下にapi用のPythonスクリプトlambda_function.pyおよび、空のファイルrequirements.txtを用意してください。

※ requirements.txtserverless-python-requirementsを利用している関係で必要となります。

api/lambda_function.py
import os 
import logging 
 
logger = logging.getLogger()  
logLevel = logging.WARNING 
 
def lambda_handler(event, context): 
 
    # Immediate response for WarmUP plugin 
    if event.get('source', None) == 'serverless-plugin-warmup': 
        logger.info('WarmUP - Lambda is warm!') 
        return 'Lambda is warm!' 
 
    return { 
        "statusCode": 200, 
        "body": "{\"message\": \"hello lambda api!\", \"input\": {\"test\": \"" + os.environ["test"] + "\"}}" 
    } 
batchディレクトリ配下にbatch用のPythonスクリプトlambda_function.pyおよび、空のファイルrequirements.txtを用意してください。

※ requirements.txtserverless-python-requirementsを利用している関係で必要となります。

batch/lambda_function.py
import os 
import logging 
 
logger = logging.getLogger()  
logLevel = logging.WARNING 
 
def lambda_handler(event, context): 
    return { 
        "message": "hello lambda batch!", "input": {"test": os.environ["test"]} 
    } 


10. Serverlessでdeployしてみる

profileの設定などを確認して、以下のコマンドを実行します。

$ serverless deploy 
1から環境を構築するため、数分かかります。

のんびり気長に待ってください。

以下のような結果が表示されれば環境構築成功です。

Serverless: Packaging service... 
Serverless: Excluding development dependencies... 
Serverless: Excluding development dependencies... 
Serverless: Creating Stack... 
Serverless: Checking Stack create progress... 
..... 
Serverless: Stack create finished... 
Serverless: Uploading CloudFormation file to S3... 
Serverless: Uploading artifacts... 
Serverless: Uploading service .zip file to S3 (1.64 KB)... 
Serverless: Uploading service .zip file to S3 (1.64 KB)... 
Serverless: Validating template... 
Serverless: Updating Stack... 
Serverless: Checking Stack update progress... 
................................................................................. 
Serverless: Stack update finished... 
Service Information 
service: serverless-sample 
stage: stg 
region: ap-northeast-1 
stack: serverless-sample-stg 
api keys: 
  None 
endpoints: 
  POST - https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/stg/helloworld 
functions: 
  api: serverless-sample-stg-api 
  batch: serverless-sample-stg-batch 
layers: 
  None 


11. Labmdaを実際に実行してみる


11.1. functionのapiを実行する

functionのapiはapigatewayと関連付けしているため、作成されたendpointをcurlで実行してみます。

$ curl -X POST -H "Content-Type: application/json" https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/stg/helloworld 
以下のようなレスポンスが返却されてくれば成功です。

{"message": "hello lambda api!", "input": {"test": "api-test"}} 


11.2. functionのbatchを実行する

functionのbatchはapigatewayと関連付けしていないため、serverlessコマンドで実行します。

$ serverless invoke -f batch 
以下のようなレスポンスが返却されてくれば成功です。

{ 
    "message": "hello lambda batch!", 
    "input": { 
        "test": "batch-test" 
    } 
} 


12. 最後に

UnixやLinuxをオンプレ環境で構築したことなどはあったのですが、AWSでServerless Frameworkなどを使って環境構築などをすれば、再現性もあり非常に便利だなと感じました。

今後もAWSについてもっと勉強していきたいと思います。

「ハンズラボ Advent Calendar 2018」 の23日目は、@daisudaisuke さんの「Amazon Managed Blockchainでフリマアプリ作りたい Part1」です!

コメント

このブログの人気の投稿

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-04-30 23:37:32 RSSフィード2021-04-30 23:00 分まとめ(42件)

投稿時間:2023-02-05 02:09:04 RSSフィード2023-02-05 02:00 分まとめ(9件)