ServerlessFrameworkで始めるAWS構築!サーバーレスの価値を体験しましょう😎

ServerlessFrameworkで始めるAWS構築!サーバーレスの価値を体験しましょう😎

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは!

本記事は、「Serverless Framework での AWS 構築を通じてサーバーレスの価値を体験」を目的に、スタートガイドを公開します。

これからサーバーレスをはじめたい、Amplify の自動開発をやめて自前でのインフラ構築に取り組みたい方は必見です。

想定する読者

  • サーバーレスをはじめたいヒト
  • Amplify 開発から脱却したいヒト
  • Serverless Framework に興味のあるヒト

Serverless Framework とは

AWS Lambda をはじめとした、AWS サーバーレス製品のデプロイ・モニタリング・CI.CD に対応するオールインワン開発フレームワークです。

Serverless Framework は複数の AWS 以外のクラウドベンダー(GCP 等々)にも対応しているため、マルチクラウドの環境づくりにも最適です。

では、早速 Serverless Framework でサーバーレスを体験してみましょう!

Serverless Framework を始める

Serverless Framework の最もわかりやすい価値として、「API 構築の自動化」が挙げられます。

まずはサーバーレスで構成された REST API をすばやくデプロイ・起動・実行してみましょう。

STEP.1 AWS アカウントを作成する

まずはデプロイする場所(AWS アカウント)が必要になります。

サーバーレス開発は、アプリケーションを可能な限り迅速に Web に移行するためにクラウドベンダー(LaaS)に依存しており、最も広く使用されているベンダーが AWS(Amazon Web Service)です。

AWS アカウントを既にお持ちの場合は、この項目はスキップしてください。

お持ちでない場合は、AWSアカウント作成ページに移動しアカウントを作成してください。

STEP.2 Serverless Framework のインストール

Serverless Framework のインストールはとても簡単です。

NPM モジュールであるため、Node と NPM さえあれば、インストールすることができます。

以下のコマンドで Serverless Framework をグローバルインストールしてください。

$ npm install -g serverless

STEP.3 新しいサービスを作成する

開始するには空のフォルダーにて、CLI で次のコマンドを実行するだけです。

$ serverless

たったこれだけでプロセスが開始され、スターターキットとしてテンプレートの選択も可能です。これは新しいサービスを実行するのに役立ちます。

引用元:https://www.serverless.com/blog/getting-started-with-serverless-framework

「サーバーレス」コマンドの使用

最初のオプションは、サービスのベースにするテンプレートタイプの設定です。(初めに設定する必要はありますが、後ほど変更することもできます)

  1. 「AWS-Node.js-HTTP API」オプションを選択
  2. 任意の名前を付けるか、「Enter」を押してデフォルトの aws-node-http-api-project を選択
  3. 手順2と同じ名前の新しいフォルダが作成され、選択したテンプレートがプルされる
  4. サーバーレスダッシュボードにログインするか登録するかを確認するメッセージが表示される

サーバーレスダッシュボードとは一体何か?

サーバーレスダッシュボードは、Serverless Framework が提供するツールであり、AWS への接続の管理を容易にし、サービスの構成データ、モニタリング機能、Lambda 関数のログを読み取る機能などを提供してくれます。

ダッシュボードは、無料で使用できます。
ダッシュボードを使用すると、実行するデプロイで AWS アカウントへの接続を非常に簡単に管理できます。

Y を選択して(または Enter キーを押して)、ダッシュボードを設定します。これにより、ブラウザにウィンドウが開きます。

下部にある[Register]をクリックして、GiHub、Google、または自分のメールアドレスとパスワードを使用してアカウントを作成しましょう。

[Register]をクリックし、ユーザー名の入力を求められたら、先に進み、数字と小文字のみを含むユーザー名を入力します。

アカウントが作成されると、CLI は次の2つのいずれかを実行します。

  • 何らかの理由でデバイスにすでに AWS 認証情報がある場合は、それらの認証情報を使用して AWS アカウントにデプロイするように求められます。
    この場合に no を選択して、次のステップ「Setting up provider manually」(プロバイダーを手動で設定する)で確認することをお勧めします。
  • デバイスに AWS 認証情報がない場合、CLI は「AWS Access Role」(AWS アクセスロール)または「Local AWS Keys」(ローカル AWS キー)を設定するかどうかを尋ねてきます。
    そのまま続行するために、AWS アクセスロールを選択しましょう。
引用元:https://www.serverless.com/blog/getting-started-with-serverless-framework

「AWS Access Role」を選択すると、別のブラウザウィンドウが開きます。(そうでない場合は、CLI がウィンドウを手動で開くために使用するリンクを提供します)ダッシュボードアカウント内でプロバイダを設定します。

引用元:https://www.serverless.com/blog/getting-started-with-serverless-framework

次のステップで、必ず「Simple」オプションを選択し、「Connect AWS provider」(AWS プロバイダーに接続)をクリックしてください。

これにより、「Quick create stack」(クイック作成スタック)というタイトルの AWS アカウントのページが開きます。

ここでは変更する必要はありませんので、ページの下部にある確認ボックスをオンにするために下にスクロールして、[Create Stack](スタックの作成)をクリックします。

引用元:https://www.serverless.com/blog/getting-started-with-serverless-framework

この時点で、AWS が必要なものを作成するまで数秒待つ必要があります。ステータスが「CREATE_COMPLETE」になると、左側のリストの更新ボタンをクリックできるようになります。

引用元:https://www.serverless.com/blog/getting-started-with-serverless-framework

完了したらタブを閉じて、ダッシュボードのプロバイダ作成ページに戻ることができます。

ダッシュボードは、プロバイダが正常に作成されたことを自動的に検出し、CLI も同様に検出します。

展開に関する質問に「Y」と返信し、新しいサービスが展開されるまで数分待ちましょう!

プロバイダを手動で設定する

デバイスにすでに AWS 認証情報があり、デプロイするかどうかを尋ねられたときに「No」を選択した場合でも、プロバイダーをセットアップする必要があります。

ありがたいことに、セットアップはとても簡単で、app.serverless.com にアクセスして、上記で説明したようにアカウントを登録するだけです。

次に、アプリのリストページに移動したら、左側の[org]をクリックし、[providers]タブを選択して、最後に[add]を選択します。プロバイダの追加は上記とまったく同じであり、完了したら、CLI でサービスに戻ることができます。

また、必ず cd で services フォルダに移動してから「serverlessdeploy」を実行してください

ローカルの AWS 認証情報を使用する

ダッシュボードアカウントでプロバイダを設定したくない場合は、自分のデバイスでローカルの認証情報の設定を使用できます。

これには、適切な権限を持つユーザーを作成し、デバイスに認証情報を追加することが含まれます。

一体何をしたのか?

デプロイが成功すると、ダッシュボードまたは CLI のいずれかで、呼び出すことができる HTTP エンドポイントがあることがわかります。また、お気に入りの IDE またはテキストエディタで作成したばかりのサービスを開き、serverless.yml のコンテンツを確認すると、サービスのほとんどすべてを制御することができます。

持っている関数があるセクションにイベントとそれらが繋がったことがわかるでしょう。

また、この HTTP エンドポイントが呼び出されたときに実行されるコードは、handler.js ファイルの「hello」という関数で定義されていることに注意してください。

このファイルを編集してから「サーバーレスデプロイ」を実行すると、変更が AWS アカウントにプッシュされ、次にブラウザまたは curl を使用してそのエンドポイントを呼び出すと、変更が反映されていることがわかります。

$ curl {your_endpoint_URL}

新しい Web API エンドポイントを作成しましょう

いくつかの基本事項がわかったので、これをさらに拡張して、いくつかの有用なエンドポイントを追加しましょう。

データベースに新しいレコードを追加できるように、POST エンドポイントがあると便利です。

これを行うために、DynamoDB と呼ばれる AWS サービスを使用します。これにより、Lambda 関数のデータストアをすばやく簡単に作成できます。

DynamoDB データベースの追加

これを行うには、serverless.yml を開き、ファイルの最後に以下を貼り付けます。

resources:
  Resources:
    CustomerTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
          - AttributeName: primary_key
            AttributeType: S
        BillingMode: PAY_PER_REQUEST
        KeySchema:
          - AttributeName: primary_key
            KeyType: HASH
        TableName: ${self:service}-customerTable-${sls:stage}

そして、createCustomer.js という serverless.yml と同じフォルダに新しいファイルを作成し、それに次のコードを追加しましょう。

'use strict'
const AWS = require('aws-sdk')

module.exports.createCustomer = async (event) => {
  const body = JSON.parse(Buffer.from(event.body, 'base64').toString())
  const dynamoDb = new AWS.DynamoDB.DocumentClient()
  const putParams = {
    TableName: process.env.DYNAMODB_CUSTOMER_TABLE,
    Item: {
      primary_key: body.name,
      email: body.email
    }
  }
  await dynamoDb.put(putParams).promise()

  return {
    statusCode: 201
  }
}

AWS との通信に役立つ npm モジュールが含まれていることに気付いたかもしれません。そのため、次のコマンドを使用して、サービスの一部としてこの必要な npm モジュールをインストールしてください。

$ npm install –save aws-sdk

注:このプロジェクト全体をクローンの参照として使用する場合は、GitHub で見つけることができます。ただ、デプロイする前に、サーバーレスダッシュボードアカウントに接続するために独自の組織名とアプリ名を serverless.yml に追加することを忘れないでください。

データベーステーブル名を関数で使用できるようにする

関数がどのテーブルにアクセスするかを知るためには、その名前が使用可能である必要があります。
Lambda には環境変数の概念があります。

serverless.yml に環境変数を設定して、コードで関数にアクセスできるようにすることができます。 serverless.yml のプロバイダセクションに以下を追加します。

provider:
  environment:
    DYNAMODB_CUSTOMER_TABLE: ${self:service}-customerTable-${sls:stage}

関数コードでは、`process.env.DYNAMODB_CUSTOMER_TABLE`ようにこの環境変数にアクセスしていることに気付いたかもしれません。

環境変数は、必要な構成の詳細を Lambda 関数に渡すための非常に強力な方法になります。

機能権限の設定

先に進んで変更を既にデプロイすることはできますが(「serverless deploy」コマンドを使用して自由にデプロイできます)、コードがデータベースと通信できるようにするために、もう1つ追加する必要があります。

デフォルトでは、セキュリティ上の理由から、AWS では Lambda 関数が他の AWS サービスにアクセスできるようにするための明示的なアクセス許可を追加する必要があります。

これには、serverless.yml にいくつかの構成を追加する必要があります。

serverless.yml の「provider」ブロック内に、次のものがあることを確認してください。

provider:
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "dynamodb:PutItem"
        - "dynamodb:Get*"
        - "dynamodb:Scan*"
        - "dynamodb:UpdateItem"
        - "dynamodb:DeleteItem"
      Resource: arn:aws:dynamodb:${aws:region}:${aws:accountId}:table/${self:service}-customerTable-${sls:stage}

これらのパーミッションは、DynamoDB に接続できるようデプロイされたときに、Lambda 関数に適用されるようになります。

エンドポイントの追加

データベースの構成を追加し、データベースと通信するためのコードを記述しましたが、現時点では記述したコードをトリガーする方法はありません。一旦修正しましょう。

serverless.yml で、functions ブロック内に次のブロックを貼り付けます。

functions:
  createCustomer:
    handler: src/createCustomer.createCustomer
    events:
      - http: 
          method: POST
          path: /
  1. 最初の行では、特定の関数に名前を付けることができます。この場合は「createCustomer」です。
  2. 次のインデントされた行は、この関数のコードが存在する場所を定義します。
    「createCustomer.createCustomer」は、ピリオドの前のファイル名とピリオドの後のファイルの関数名に分類されます。必要に応じて、パス全体を指定することもできます。
    createCustomer.js ファイルを「src」という別のフォルダに移動した場合、ハンドラープロパティは「handler:src/createCustomer.createCustomer」になります。
  3. 次に、関数コードをトリガーするイベントを定義する必要があります。その際は複数形にしてください。
    同じコードに複数のトリガーを設定できますが、まずは1つだけを使用しましょう。
  4. 残りのコードは標準の HTTP 構成です。 POST リクエストとしてルート URL「/」が呼び出されます。

エンドポイントのテスト

「serverless deploy」(サーバーレスデプロイ)を実行してみましょう。数秒後、デプロイしたすべての変更が AWS アカウントにプッシュされ、デプロイ後の概要でエンドポイントについて必要な情報が提供されます。

デプロイしたら、エンドポイントをテストします。API の HTTP エンドポイントをテストするための方法は、どれでも使用可能ですが、CLI で curl を素早く使用することができます。

curl -X POST -d '{"name":"Gareth Mc Cumskey","email":"gareth@mccumskey.com"}' --url https://[insert your url here]/

GET エンドポイントの追加

API にデータを挿入できるようになったので、クイックエンドポイントをまとめてすべての顧客を取得しましょう。まず、次の関数構成を serverless.yml に挿入します。

getCustomers:
    handler: getCustomers.getCustomers
    events: 
      - httpApi:
          path: /
          method: get

次に、getCustomers.js というファイルを作成し、getCustomers 関数に次のコードをドロップする必要があります。

'use strict'
const AWS = require('aws-sdk')

module.exports.getCustomers = async (event) => {
  const scanParams = {
    TableName: process.env.DYNAMODB_CUSTOMER_TABLE
  }

  const dynamodb = new AWS.DynamoDB.DocumentClient()
  const result = await dynamodb.scan(scanParams).promise()

  if (result.Count === 0) {
    return {
      statusCode: 404
    }
  }

  return {
    statusCode: 200,
    body: JSON.stringify({
      total: result.Count,
      items: await result.Items.map(customer => {
        return {
          name: customer.primary_key,
          email: customer.email
          }
        })
    })
  }
}

ここで実際に注意する必要があるのは、その環境変数を再利用して DynamoDB テーブルにアクセスすることと、DynamoDB のスキャンメソッドを使用してすべてのレコードを取得することです。

プロジェクトの最終バージョンで、デフォルトの関数定義と handler.js ファイルを削除したことに気付いたかもしれません。必要に応じて、今すぐ実行してください。

「serverless deploy」(サーバーレスデプロイ)の後、新しいエンドポイントができました。そして、それに対してcurl コマンドを実行し、前に挿入したアイテムを取得する必要があります。

curl –url {insert_URL_here}

まとめ

本記事のように Serverless Framework を使用すると、エンドポイントの起動を非常に高速に行うことができます。

スムーズに行けば30分もかからないでしょう。

これで、実際には本番環境に対応した2つのエンドポイントができました。 AWS では多くのサーバーレス製品は3つのアベイラビリティーゾーンにわたって完全に冗長化されており、負荷分散されていますので可用性の点も安心です。

私たちは通常時 Serverless Framework でインフラ構築を行い、最短工数でお客様のサービスインをサポートいたします。

サーバーレスの開発は、お気軽にご相談ください。