Serverless Frameworkで運用しているAWSアプリケーションのデプロイをGithub Actionで管理する方法


概要

Serverless Frameworkを使用する時、ローカルからデプロイするだけで特にCIを回していなかったのでGithub Actionで開発フローを組もうと思い調べてみたので設定手順をまとめておきたいと思います。

この記事でセットアップする開発フローは、Github Pushトリガーによって、Serverless Serviceをデプロイするアクションを起動する非常にシンプルなものです。

目次

  • 構成
  • 運用フロー
  • 準備
  • 設定
    • Serverless Framework
    • Github Action
  • 動作確認
  • 参考URL

構成


Lambdaのトリガーとして設定するAPI Gatewayには、開発用(dev)・本番用(prod)の2つのステージを用意し、Functionを起動した際はそれぞれのステージのLambdaが実行されるようにします。

開発用Lambda(dev)
Latestバージョンを常に参照します。LatestバージョンはAWSによって、デプロイ毎にデフォルトで割り当てられる最新のバージョンの事です。

本番用Lambda(prod)
指定したバージョンを切り替える事で、本番用にバージョニング設定する事が出来ます。

運用フロー

GithubのマスターブランチへのPushをトリガーに、Serverless Serviceをデプロイするアクションが実行されるようにします。

トリガー

1.開発環境(開発用Lambda)へのデプロイ
GithubのマスターブランチへのPushをトリガーとします。

2.本番環境(本番用Lambda)へのデプロイ
Githubのマスターブランチへタグ付きのPushをトリガーとします。

準備

  • Serverless Frameworkのインストール
npm install -g serverless
  • プロバイダーセットアップ

今回はAWSアプリケーションを作成するので、Serverless FrameworkのプロバイダーとしてAWSを設定します。Serverless Frameworkに、AWSの機能権限を与えたIAMユーザーを割り当てるために下記を実行する必要があります。

1.AWSでServerless用のIAMユーザを発行。

2.IAMユーザにAdministratorAccessの管理ポリシーを与える。

設定

Serverless Framwork

1.サービス(Serverless Frameworkにおける実行環境の単位)の作成

serverless create --template aws-nodejs --name greeting-service --path greeting-service

2.環境変数の設定(env.yml)

prod:
  appName: "Serverless App"
default:
  appName: "DEV Serverless APP"

3.サービス全体の設定(serviceless.yml)

今回はLambdaとAPI Gatewayで構成するアプリケーションです。serverless.ymlに諸々のAWSに関する設定を記述していきます。

  • サービス内のLambdaファンクション群

Getリクエストで、挨拶を返すHiファンクションの定義。

  • Lambdaファンクションごとのトリガーとなるイベントの定義

Functionのトリガーとして、Getリクエストを定義。

  • 環境変数の定義

serverless.yml内で使用する変数を定義。
Function内で使用する変数を定義。

  • providerの設定

AWSの地域設定。

変数の中身は、GithubのPushトリガーで設定出来るように定義します。この変数がServerlessのデプロイ先をルーティングする役割を担当します。

service: greeting-service
frameworkVersion: '2'

//自身で定義した変数 => serviceless.ymlで参照
custom:
  defaultStage: dev
  // 開発環境へのデプロイ → prod.appName変数が参照される。
  // 本番環境へのデプロイ → default.appName変数が参照される。
  environment: ${file(env.yml):${self:provider.stage}, file(env.yml):default}

provider:
  name: aws
  runtime: nodejs12.x
  lambdaHashingVersion: 20201221
  stage: ${opt:stage, self:custom.defaultStage}
  // lambdaで使用する変数
  environment:
    appName: ${self:custom.environment.appName}
  // 地域の指定
  region: ap-northeast-1

functions:
  greeting:
    handler: handler.greeting
    events:
      - http:
          path: /
          method: get

4.Lambda functionの設定

'use strict';

module.exports.greeting = async (event) => {
  console.log(process.env.appName);
  console.log(event.requestContext.stage);

  let html = `
    <p>Hi!</p>
  `;

  return {
    statusCode: 200,
    headers: {
      'Content-Type':'text/html'
    },
    body: html
  };
};

Github Action

1.AWSのシークレットキーと環境変数をGithubで設定する。

2.workflowの設定

  • dev workflow

マスターPushをトリガーにしたワークフローを記述します。このワークフローが走ることで、1.開発環境(開発用Lambda)へのデプロイが実行されます。

name: Deploy Dev Lambda Function by Serverless Framework
on:
  push:
    branches:
      - master
jobs:
  deploy-dev:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - uses: actions/setup-node@v1
      with:
        node-version: '12.x'
    - name: Install Serverless Framework
      run: npm install -g serverless
    - name: Serverless AWS authentication
      run: sls config credentials --provider aws --key ${{ secrets.AWS_KEY }} --secret ${{ secrets.AWS_SECRET }}
    - name: Create env file
      run: |
        cat > env.yml << EOF
        ${{ secrets.ENV }}
        EOF
    - name: Install NPM dependencies
      run: npm install
    - name: Deploy Lambda functions
      // ステージを開発環境に指定し、デプロイ
      run: sls deploy -s dev
  • prod workflow

タグ付きのマスターPushをトリガーにしたワークフローを記述。このワークフローが走ることで、2.本番環境(本番用Lambda)へのデプロイが実行されます。

name: Deploy Production Lambda Function by Serverless Framework
on:
  push:
    tags: # Deploy tag (e.g. v1.0) to production
      - 'v**'
jobs:
  deploy-prod:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - uses: actions/setup-node@v1
      with:
        node-version: '12.x'
    - name: Install Serverless Framework
      run: npm install -g serverless
    - name: Serverless AWS authentication
      run: sls config credentials --provider aws --key ${{ secrets.AWS_KEY }} --secret ${{ secrets.AWS_SECRET }}
    - name: Create env file
      run: |
        cat > env.yml << EOF
        ${{ secrets.ENV }}
        EOF
    - name: Install NPM dependencies
      run: npm install
     // ステージを本番環境に指定し、デプロイ
    - name: Deploy Lambda functions
      run: sls deploy -s prod

動作確認

設定したGithub Actionで、Serverless Applicationのデプロイが実行されるか確認したいと思います。まずは開発環境にデプロイします。

git push origin master

Actions画面で確認してみると、開発ステージにデプロイされた事が確認出来ます。

curlコマンドでも確認してみます。
開発環境(https://***.execute-api.***.amazonaws.com/dev)

curl https://***.execute-api.***.amazonaws.com/dev/
<p>Hi!</p>

開発環境にアプリケーションがデプロイされている事が確認出来ました。

続いて、タグを切って本番環境にデプロイしてみます。差分を確認するために、Function関数を変更します。

'use strict';
module.exports.greeting = async (event) => {
  console.log(process.env.appName);
  console.log(event.requestContext.stage);

  let html = `
    <p>Chao!</p>
  `;

  return {
    statusCode: 200,
    headers: {
      'Content-Type':'text/html'
    },
    body: html
  };
};
git push origin Tag<version>

こちらもcurlコマンドでも確認してみます。
本番環境(https://***.execute-api.***.amazonaws.com/prod)

curl https://***.execute-api.***.amazonaws.com/prod/
<p>Chao!</p>

本番環境にアプリケーションがデプロイされている事が確認出来ました。

まとめ

Serverless Frameworkを使えば、AWSアプリケーションの構築管理が便利に出来ますが環境の切り替えをActionに任せる事でよりサービスの運用が楽になる事が分かりました。

今回の運用フローでは、AWS Lambda関数を、開発用と本番用の2つに分けていますが、エイリアスでバージョニングを行えば1つの関数で環境をスイッチング出来るみたいなのでそちらの方法も試してみたいと思います。

参考URL

Serverless Frameworkの使い方まとめ
How to deploy Serverless applications using Github Actions
APIGateway+Lambdaによるアプリサーバをバージョン管理する