Lambda & Serverless Frameworkあれこれ(ざっくりとした概要やコマンド)

## 前書き
最近業務でAWSのLambdaとServerless Frameworkを使うことが多いです。
業務の流れが早く、次から次へと新しいツールを触ってすべて忘れていきそうなので、個人的なまとめとして、記事を作成します。
正確性よりも、概要というかざっくりとした全体像みたいなものを把握することを目的としています。
>Done is better than perfect


## Lambdaとは？
「サーバーレス」という種類に属する「サーバー」です(え笑)。
公式(https://aws.amazon.com/jp/lambda/) には、
> AWS Lambda を使用することで、サーバーのプロビジョニングや管理をすることなく、コードを実行できます。料金は、コンピューティングに使用した時間に対してのみ発生します。

と記載されています。
感覚で説明すると、「設定や管理が不要で、プログラムをLambdaの"関数"としてデプロイしておき、そのエンドポイント(URL)にアクセスする、もしくは、関数の実行条件(トリガー）を設定しておくと、プログラム(関数)を実行させることができるサーバー」といった感じです。

はい。「サーバーレス」ですが、結局サーバーです。

参考:
サーバーレスとは？ 簡単な事例をまじえてわかりやすく解説！
https://blog.qbist.co.jp/?p=2654



## Serverless Frameworkとは？
Lambdaを扱うための便利ツールです（え笑)
公式(https://www.serverless.com/) には

>zero-friction serverless development
easily build apps that auto-scale on low cost, next-gen cloud infrastructure.

とデカデカと掲げてあって、
> Serverless Framework はServerless Applicationを構成管理デプロイするためのツールです。 
Serverless Frameworkの使い方まとめ
https://qiita.com/horike37/items/b295a91908fcfd4033a2


と説明されていたりします。

なので、冒頭間違っていますが、「Lambda」というAWSのサーバーレスサービスに限らず、GCPやAzureなど、他のクラウドサービスのサーバーレス的サービスにも使えるんだと思います(ほんとかよ)

Lambdaとセットでしか使ったことのない私にとっては、「Lambdaを扱うためのめっちゃ便利ツール」といった感じです。

具体的には、コマンド一発で、Lambdaへのデプロイや、Lambdaの形式に併せて関数や設定ファイルを作ることができます。

ちなみに、日本語で喋っていると、サーバーレスのことを、「サーバーレス」と言いますし、「Serverless Framework」のことも「サーバーレス」と言うので、若干混乱します笑

## インストール
npmのモジュールとして公開されていますので、インストールします。
```npm install -g serverless```
バージョン確認は、
```serverless --version```です。

## アプリケーション(サービス)の作成
TypeScriptで作る場合、

```
sls create -t aws-nodejs-typescript -p sls-test
```
です。```-t```は```--template```、```-p```は```--path```の略です。
テンプレートとは、どの言語でアプリケーションを作りたいか、ということで、他にもテンプレートが用意されています。
上記コマンドを実行すると、sls-testというディレクトリに、handler.tsやserverless.tsが作成されます。
serverless.tsは設定ファイルで、handler.tsには、デフォルトでhelloという関数が作られています。
必要なモジュールをインストールするために、```npm install```しておきます。

## AWS CLI
AWSのコマンドラインツール(CLI)です。
インストール(Mac)
```brew install awscli``` or ```brew install awscli```
```aws configure --profile user1```というコマンドで、AWSにアクセスするための設定を行います。
AWS Access Key IDやAWS Secret Access Key、Default region name、Default output formatを設定します。Default output formatはjsonを指定します。
```aws configure list```や```aws configure list --profile user1```でプロファイルの設定を確認できます。
このプロファイルを、デプロイ時にオプションで指定することで、デプロイ先のAWSアカウントを切り替えることができます。
また、serverless.tsに、デフォルトで使用するプロファイルを設定することができます。

参考: AWS-CLIの初期設定のメモ
https://qiita.com/reflet/items/e4225435fe692663b705


## 初期設定
serverless.tsにオブジェクト形式で設定が記載されています。
providerという項目に、regionとprofileという項目を追加します
(設定しなかった場合、リージョンはオハイオ、プロファイルはdefault
(```aws configure```で```--profile```オプションを付けなかった場合に作成されるプロファイル)が使用されます。

```typescript:serverless.ts
provider: {
    name: 'aws',
    runtime: 'nodejs12.x',
    profile: 'user1', // プロファイル名
    region: 'ap-northeast-1',
    apiGateway: {
      minimumCompressionSize: 1024,
    },
    environment: {
      AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1',
    },
  },
```
これで、指定のAWSアカウントの指定のリージョンのLambdaにデプロイされるようになります。

## serverless.tsのfunctionとhandler.ts
```sls create```で作成されたserverless.tsとhandler.tsには以下のような記載があります。

```ts:serverless.ts
functions: {
    hello: {
      handler: 'handler.hello',
      events: [
        {
          http: {
            method: 'get',
            path: 'hello',
          }
        }
      ]
    }
  }
```
helloは関数を識別するラベルで自由に設定できます。
handlerの欄にはルートディレクトリからの相対パスでファイル名.関数名を記載。
eventsには、関数が実行される条件(トリガー)を記載します。
HTTPリクエストのGETメソッドで関数のエンドポイント(URL)にアクセスすると、hello関数が実行されます。
エンドポイント(URL)の末尾はpathで指定されているhelloになります。
エンドポイントは、デプロイ後にターミナルで表示される他、Lambdaのコンソール画面で確認することができます。


```ts:handler.ts
export const hello: APIGatewayProxyHandler = async (event, _context) => {
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!',
      input: event,
    }, null, 2),
  };
}
```
hello関数が定義されています。returnで、HTTPレスポンスを返します。
eventオブジェクトにはリクエストヘッダーやボディが格納されていて、関数内でオブジェクト形式で取り出すことができます。

参考：
AWS Lambdaメモ -ハンドラの引数eventの中身-
http://tk5-21.hatenablog.com/entry/2018/01/12/003751



## デプロイ
```sls deploy```
コンソールでLambdaにアクセスすると、関数の一覧に、sls-test-dev-helloと関数が登録されているのがわかります。
また、```--stage```オプションをつけることで、環境を切り替えてデプロイすることができます。

> Serverlessのデプロイにはstageという概念が導入されています。いわゆる本番環境とテスト環境といった環境をstageという単位で切り分けています。
引用元: Serverless Frameworkの使い方まとめ(https://qiita.com/horike37/items/b295a91908fcfd4033a2)

```
sls deploy --stage stg
→ sls-test-stg-helloという名前で関数がデプロイされる。
```

なお、```--stage```の後のstage名はstgやprd、betaなど開発者側で自由に決められます。

## 環境変数の外部ファイル化
> serverless.yml内で自身で定義した変数を参照させることも出来ます。${self:someProperty}というシンタックスで定義可能です。
(中略)
serverless.ymlとは別で定義したファイルを読み込んで、その変数を参照することも出来ます。${file(../myFile.yml):someProperty}というシンタックスでserverless.ymlに定義してください。
引用元: Serverless Frameworkの使い方まとめ(https://qiita.com/horike37/items/b295a91908fcfd4033a2)

serverless.tsに記載のオブジェクト内に、変数を定義して、それを参照できることと、別ファイルを参照できることも利用して、関数内で使用する環境変数を外部ファイル化することができます。

詳しくは下記記事が非常にわかりやすいです。

参考：
Serverless Frameworkで環境変数を外部ファイルから読み込み、環境毎に自動で切り替えてみる
https://dev.classmethod.jp/articles/serverless-framework-conf-change/

(順番が前後しましたが、environmentという項目に環境変数を設定することができます。関数ごとに設定することもできます。)

## 後書き
まとめていると、よくわかってないところがどんどん出てきて、永遠に終わらないですね笑
eventオブジェクトとかイベントソースとか特に。
一旦、こんな感じで終わらせていただきます。