初めてのサーバーレスアプリケーション開発 ~Serverless Framework と Codeシリーズを連携させる~

Serverless Frameworkで開発したアプリケーションをCodeシリーズを使ってAWS上にデプロイしてみます。

デプロイ対象のServerless Frameworkのサービスは前回のエントリ初めてのサーバーレスアプリケーション開発 ~Serverless Framework を使ってAWSリソースをデプロイする~で作成したものを利用します。

前提となる知識もありますので、必要に応じて以下のエントリも参考にしてください。

対象読者

  • サーバーレスアプリケーション開発未経験の方
  • サーバーレスに縁のないインフラエンジニアの方

本記事を実践して、Serverless Framework + Codeシリーズと仲良くなりましょう!!

それでは本題に入っていきます。

サーバーレスアプリケーション超入門

今回構築するアプリケーションの全体構成はこちら。

Serverless Frameworkで「クライアントからリクエストを受けて、DynamoDBの情報を返却する」簡単なアプリケーションを作成します。

AWSにデプロイされるまでの流れは以下のようになります。

  • ローカルでServerless Frameworkを使ったアプリケーションを作成する
  • コードをCodeCommitにpushする
  • CodeCommitの変更をトリガーにCodeBuildを実行する
  • CodeBuildでServerless Frameworkのコマンドを使ってAWS上にリソースをデプロイする

「CodeCommitの変更を検知しCodeBuildを実行する」部分はCodePipelineを使って実現します。

Codeシリーズ

今回利用するCodeCommit、CodeBuild、CodePipelineの概要を確認しておきましょう。

CodeCommitとは

公式ドキュメントよりCodeCommitの概要を抜粋します。

AWS CodeCommit は、フルマネージド型のソースコントロールサービスです。このサービスにより、企業ではセキュアかつ非常にスケーラブルなプライベート Git リポジトリを簡単にホストできます。

CodeCommitの特徴

  • AWSによるフルマネージドなGitリポジトリ
  • 容易にスケール
  • 他のAWSサービスやサードパーティと連携可能

CodeBuildとは

公式ドキュメントよりCodeBuildの概要を抜粋します。

AWS CodeBuild は、完全マネージド型のビルドサービスです。ソースコードをコンパイルし、テストを実行し、デプロイできるようにソフトウェアパッケージを作成できます。CodeBuild により、ビルドサーバーのプロビジョニング、管理、スケーリングが不要になります。

CodeBuildの特徴

  • AWSによるフルマネージドなビルドサービス
  • ユーザーが指定した処理をビルドコンテナ内で順に実行することが可能

CodePipelineとは

公式ドキュメントよりCodePipelineの概要を抜粋します。

AWS CodePipeline は、迅速で信頼性の高いアプリケーションのアップデートを可能にする継続的デリバリーサービスです。CodePipeline を使用すると、コードが変更されるたびに、お客様が定義したリリースプロセスモデルに基づいて、コードを構築、テスト、デプロイできます。

CodePipelineの特徴

  • リリースプロセスを自動化
  • リリースプロセスの進捗状況を可視化

今回はCodePipelineでCodeCommit、CodeBuildを連携させるイメージになります。

もう少し詳しく知りたい方は、Black Beltの資料もご覧ください。 ※資料は最新のものではないため適宜公式ドキュメントを参照してください。

CodeCommit作成

まずはCodeCommitを構築していきます。

AWSマネジメントコンソールよりCodeCommitを選択し、「今すぐ始める」をクリックします。

リポジトリ名にdemo-repoを入力し「リポジトリの作成」をクリックします。

今回はメールの通知は実施しないので「スキップ」をクリックします。

gitリポジトリが作成されました。

初期状態ではブランチが作成されていないため、README.mdを追加しておきます。ファイルの追加から「ファイルの作成」をクリックします。

READMEに任意の文言を追加した後、ファイル名にREADME.md、作者名、Eメールアドレスに任意の値を入力し「ファイルをコミット」をクリックします。

これでmasterブランチが作成されました。

CodeBuild作成

次にCodeBuildを構築していきます。

AWSマネジメントコンソールよりCodeBuildを選択します。

「プロジェクトの作成」をクリックします。

プロジェクトの設定情報を入力します。プロジェクト名はdemo-build、ソースプロバイダはAWS CodeCommit、リポジトリはdemo-repoとします。

ビルド方法を入力します。環境イメージはDockerイメージの指定、環境タイプはLinux、カスタムイメージタイプはその他、カスタムイメージIDはaws/codebuild/eb-nodejs-4.4.6-amazonlinux-64:2.1.3とします。その他はデフォルト値で構いません。カスタムイメージIDはAWS CodeBuild に用意されている Docker イメージよりserverless framework実行可能なイメージを選択しています。

その後プロジェクトを「保存」するとdemo-buildプロジェクトが作成されます。

IAMに権限を追加

CodeBuildで利用するコンテナからServerless Frameworkのコマンドを実行するため、上記で作成したIAMロールに権限を追加します。

IAMのロールよりcodebuild-demo-build-service-roleをクリックします。

ポリシーのアタッチをクリックします。

AdministratorAccessにチェックを入れ、ポリシーのアタッチをクリックします。

codebuild-demo-build-service-roleAdministratorAccessの権限が追加されました。

CodePipeline作成

CodePipelineを構築していきます。

AWSマネジメントコンソールよりCodePipelineを選択し、「今すぐ始める」をクリックします。

パイプライン名にdemo-pipelineを入力し、「次のステップ」をクリックします。

ソースの場所を指定します。ソースプロバイダにAWS CodeCommit、リポジトリ名にdemo-repo、ブランチ名にmasterを入力し、「次のステップ」をクリックします。

ビルドを指定します。ビルドプロバイダにAWS CodeBuild、プロジェクト名にdemo-buildを入力し、「次のステップ」をクリックします。

デプロイを指定します。今回の場合はビルド内でデプロイコマンドを実行するためデプロイの指定は不要です。デプロイプロバイダにはCodeDeployやCloudFormationなどを指定することができます。

AWSサービスロールを指定します。パイプラインを初めて作成する際には、「ロールの作成」を実施した後、「次のステップ」をクリックします。

「パイプラインの作成」をクリックします。

パイプラインが作成されました。

ローカル開発

CodeCommitへの接続

初めてのサーバーレスアプリケーション開発 ~Serverless Framework を使ってAWSリソースをデプロイする~で作成したCloud9の環境を利用します。

公式ドキュメントに従いAWS Cloud9 と AWS CodeCommit を統合して行きます。

Cloud9を利用していない場合はこちらを参考に接続してください。

Cloud9のコンソールでGitと関連付けるユーザー名と E メールアドレスを設定します。ユーザー名と E メールアドレスは任意のものに変更してください。

$ git config --global user.name "Mary Major"
$ git config --global user.email mary.major@example.com

HTTPS 接続用の AWS CLI の認証情報ヘルパーを設定します。

$ git config --global credential.helper '!aws codecommit credential-helper $@'
$ git config --global credential.UseHttpPath true

AWS CodeCommit リポジトリのクローンを作成します。

CodeCommitよりクローンURLを取得します。

コードをcloneします。

$ git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/demo-repo

ローカルにファイルが作成されました。

$ ll demo-repo/
total 4
-rw-rw-r-- 1 ec2-user ec2-user 30 Aug 30 10:21 README.md

serverless frameworkサービス作成

demo-repoフォルダにてserverless frameworkの新規サービスを作成します。

$ cd demo-repo/
$ sls create --template aws-python3 --path demo-cicd-service

serverless.ymlhandler.pyをそれぞれ以下のように変更します。

service: demo-cicd-service
  
provider:
  name: aws
  runtime: python3.6
  region: ap-northeast-1  
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:*
      Resource: "*"
  
functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: /
          method: get
          integration: lambda
          request:
            template:
              application/json: '{ "person_id" : "$input.params("person_id")" }'
resources:
  Resources:
    DemoDynamoDbTable:
      Type: 'AWS::DynamoDB::Table'
      Properties:
        AttributeDefinitions:
          -
            AttributeName: person_id
            AttributeType: S
        KeySchema:
          -
            AttributeName: person_id
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 5
          WriteCapacityUnits: 5
        TableName: demo-sls-person
import boto3
   
dynamodb = boto3.resource('dynamodb')
table    = dynamodb.Table('demo-sls-person')
  
def get_person(id):
    response = table.get_item(
            Key={
                 'person_id': id
            }
        )
    return response['Item']
 
def get_persons():
    response = table.scan()
    return response['Items']
    
def hello(event, context):
    return get_persons() if event['person_id'] == '' else get_person(event['person_id'])

ビルド定義作成

demo-repo直下にbuildspec.ymlを作成します。このファイルに記載した内容を元にCodeBuildがAWS上にリソースをデプロイします。記載内容の詳細を知りたい方は公式ドキュメントを参照してください。

version: 0.2

phases:
  install:
    commands:
      - npm install -g serverless
  build:
    commands:
      - echo Build started on `date`
      - cd demo-cicd-service && sls deploy
  post_build:
    commands:
      - echo Build completed on `date`

今回はCodeBuildのコンテナ起動時にserverless frameworkをインストールし、CodeCommitからダウンロードしてきたファイルをデプロイする処理を記載しています。なお、今回は簡易的にデプロイするため直接serverless frameworkをインストールしていますが、実運用する場合はyarnなどでモジュールのバージョンを固定した方が良いです。

CodePipeline実行

demo-repo直下で以下のコマンドを実行し、CodeCommitにコードをpushします。

$ git add .
$ git commit -m "Add Serverless Framework service"
[master a110d04] Add Serverless Framework service
 4 files changed, 92 insertions(+)
 create mode 100644 buildspec.yml
 create mode 100644 demo-cicd-service/.gitignore
 create mode 100644 demo-cicd-service/handler.py
 create mode 100644 demo-cicd-service/serverless.yml
$ git push origin master
Counting objects: 7, done.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 1.36 KiB | 698.00 KiB/s, done.
Total 7 (delta 0), reused 0 (delta 0)
To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/demo-repo
   12fe16f..a110d04  master -> master

CodeCommitの変更を検知しCodePipelineが起動します。

しばらく待つとCodePipelineが正常に終了します。「詳細」をクリックしビルドの状況を確認してみます。

ビルド状況のサマリ、各フェーズの詳細を確認することができます。

また、CodeBuild実行時のログも確認することができます。ちゃんとserverless frameworkのデプロイが実施できています。

アプリケーション動作確認

最後にアプリケーションが正常にデプロイされたことを確認します。 初期状態ではDynamoDBには項目が入っていないので、以下のコマンドにて項目を追加します。

$ aws dynamodb put-item --table-name demo-sls-person --item '{"person_id": {"S": "001"}, "name": {"S": "tanaka"}}' --region ap-northeast-1
$ aws dynamodb put-item --table-name demo-sls-person --item '{"person_id": {"S": "002"}, "name": {"S": "suzuki"}}' --region ap-northeast-1
$ aws dynamodb put-item --table-name demo-sls-person --item '{"person_id": {"S": "003"}, "name": {"S": "yamada"}}' --region ap-northeast-1

CodeBuildのログからendpointをコピーします。

上記のエンドポイントに対しGetリクエストを送信します。

$ curl https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev?person_id=001
{"person_id": "001", "name": "tanaka"}
$ curl https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev?person_id=002
{"person_id": "002", "name": "suzuki"}
$ curl https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev
[{"person_id": "001", "name": "tanaka"}, {"person_id": "003", "name": "yamada"}, {"person_id": "002", "name": "suzuki"}]

想定通りの結果となりました。

さいごに

Serverless FrameworkとCodeシリーズを利用し、サーバーレスアプリケーションの簡易的なCICD環境を構築しました。実運用するためには、以下のようにまだまだ考慮すべき点はありますが、サーバーレスアプリケーション開発全体の理解は深まったのではないでしょうか。

考慮事項

  • リリースサイクルの異なるリソースの管理方法(LambdaはServerless Frameworkで管理し、DynamoDBはCFnで管理するなど)
  • Gitのブランチ運用
  • etc

みなさま良きサーバーレスライフを!!

おまけ

現在サーバーレス開発部では一緒に働くメンバーを募集中です!!ご興味がある方は採用フォームからお問い合わせください!

私が所属しているAWS事業本部コンサルティング部でもサーバーレス案件に携われます。AWSインフラに軸足を置きつつサーバーレスのスキルまで身についちゃいます!!