AWS CodeBuildでサーバーレス環境をビルドしてみる

# CodeBuildが発表されました！

AWSのre:Invent2016が先日開催され、また多くのサービスが発表されました。
まだ全てのサービスを追いきれてないのですが、なんとなく気になったのでCodeBuildを触ってみました。

[AWS CodeBuild ― フルマネージドのビルドサービス](https://aws.amazon.com/jp/blogs/news/aws-codebuild-fully-managed-build-service/)

最近serverless frameworkでLambdaやAPI Gatewayを作成することを覚えたので、今回はこのCodeBuildを使ってserverlessのビルドを行ってみようと思います。

# 構成
構成は以下のとおりです。

![構成.png](https://qiita-image-store.s3.amazonaws.com/0/40136/c82b89fa-6452-f4b3-803b-433e276e226f.png)

１．serverless frameworkのコードを変更
２．CodeCommitにpush
３．pushイベントをトリガーにLambda起動
４．LambdaからCodeBuildのProjectをスタート
５．CodeBuildでserverless frameworkのデプロイ

# CodeCommitの設定

## リポジトリの設定
今回CodeCommitの設定については説明しませんが、以下のような情報を参考にCodeCommitにPushできるところまで設定して下さい。

[サルでもできるCodeCommit ssh接続でgit cloneするまで](http://qiita.com/shojimotio/items/8e5f9e0616bb5a67275d)


# Serverless Frameworkサービスの作成
事前に以下のような情報を参考にサービスを作成しておく必要があります。
これをCodeCommitにPushしておいて下さい。

[Hello World Node.js Example](https://serverless.com/framework/docs/providers/aws/examples/hello-world/node/)

# CodeBuildの設定

## IAMロールの作成
CodeBuild用のポリシーは以下のとおりです。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:logs:us-east-1:000000000000:log-group:/aws/codebuild/serverless_deploy",
                "arn:aws:logs:us-east-1:000000000000:log-group:/aws/codebuild/serverless_deploy:*"
            ],
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ]
        },
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::codepipeline-us-east-1-*"
            ],
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:GetObjectVersion"
            ]
        },
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:codecommit:us-east-1:000000000000:serverless_frameworks"
            ],
            "Action": [
                "codecommit:GitPull"
            ]
        }
    ]
}
```

これに加えて、serverless deploy時に必要なポリシー（LambdaやAPI Gatewayの作成など）の追加が必要となるので適宜追加して下さい。
※今回はAdministratorAccessを追加しています。すみません！

## ビルド定義
ビルドの定義はbuildspec.ymlにて行います。
今回は「serverless frameworkをインストール後、sls deployを実行する」という定義を行っています。

```yaml:buildspec.yml
version: 0.1

phases:
  install:
    commands:
      - echo update started on `date`
      - apt-get update -y
      - echo install started on `date`
      - npm install -g serverless
  build:
    commands:
      - echo build started on `date`
      - sls deploy
```

これをCodeCommitのルートディレクトリに配置する必要があります。
配置後、CodeCommitの状態は以下のようになりました。

![スクリーンショット 2016-12-04 9.02.50.png](https://qiita-image-store.s3.amazonaws.com/0/40136/a9b2aa61-909f-8e64-4b45-f68412453528.png)

## Project作成
実際にProjectを作成してみます。

**Create project**ボタンをクリック
![スクリーンショット 2016-12-04 9.04.37.png](https://qiita-image-store.s3.amazonaws.com/0/40136/562952e3-5d76-3ee7-db58-9cdaf59bcd7e.png)

設定値は以下のようにします。

**Project name**：serverless_deploy
**Source provider**：AWS CodeCommit
**Repository**：（CodeCommitのリポジトリを選択）
**Environment image**：Use an image managed by AWS CodeBuild
**Oprerating system**：Ubuntu
**version**：aws/codebuild/nodejs:4.3.2
**Build specification**：Use the buildspec.yml in the source code root directory
**Artifacts type**：No artifacts
**Role namem**：（作成したIAMロールを選択）


![スクリーンショット 2016-12-04 9.05.33.png](https://qiita-image-store.s3.amazonaws.com/0/40136/57c8364a-6a7c-9cf2-891c-d97525b1fc45.png)

その後、**Continue**→**Save**で作成します。



# Lambdaの設定

## IAMロールの作成
以下ポリシーにてLambdaファンクション用のIAMロールを作成します。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1480757677000",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "codebuild:StartBuild"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```

## 設定値
Lambdaファンクション用の設定値は以下のようにしました。

**Runtime**：Node.js 4.3
**Handler**：serverlessDeploy.deploy
**Role**：（作成したIAMロール）
**Memory**：128MB
**Timeout**：10sec

また、環境変数には以下を設定して下さい。

**PROJECT_NAME**：**serverless_deploy**

## コード
コードは以下のとおりです。

```js:serverlessDeploy.js
'use strict';

const AWS = require('aws-sdk');

module.exports.deploy = (event, context, callback) => {

  const codebuild = new AWS.CodeBuild();

  const params = {
    projectName: process.env.PROJECT_NAME,
    sourceVersion: event.Records[0].codecommit.references[0].commit
  };

  codebuild.startBuild(params, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred
    else     console.log(data);           // successful response
  });
};
```

このコードを以下のようにserverlessDeployディレクトリに配置し、「npm install --save aws-sdk」でaws-sdkをインストールして下さい。
その後、serverlessDeployディレクトリをzipにしてアップロードして下さい。

```zsh
➜  serverlessDeploy tree -L 1
.
├── node_modules
├── package.json
└── serverlessDeploy.js
```

※おそらくもう少し経てば上記コードを直接Lambdaの設定画面で貼り付けていけると思いますが、現在は最新のaws-sdkモジュールでないとCodeBuildが動かないためzipにしてアップロードしています。

# CodeCommitのトリガー設定

CodeCommitにPushした際にLambdaが起動するように設定します。

## トリガーの設定
CodeCommitのトリガーから**Create trigger**をクリックします。

![スクリーンショット 2016-12-04 9.22.03.png](https://qiita-image-store.s3.amazonaws.com/0/40136/98cfae89-8e52-68bc-0242-67a8e3972d56.png)

設定画面で以下を入力します。

**Trigger name**：build
**Events**：Push to existing branch
**Branch names**：All branches
**Send to**：AWS Lambda
**Lambda Function**：（作成したLambdaファンクション）

![スクリーンショット 2016-12-04 9.24.01.png](https://qiita-image-store.s3.amazonaws.com/0/40136/36bc15ad-e618-8c13-2f93-db441c5558d5.png)

その後、**Create**ボタンをクリックするとトリガーの作成は完了です。

## 権限付与

CodeCommmitからLambdaを呼び出すにはAdd permittionする必要があります。
以下を参考にLambdaファンクションに権限を与えて下さい。

[CodeCommitにTriggersが追加されてた？ので触ってみた【cloudpack大阪ブログ】](http://qiita.com/shinichi-takahashi/items/4f817fb348fa6ba94bbd)


## 実際に試してみる

設定は以上で完了なので、実際にCodeCommitにPushしてみたいと思います。

Serverless Frameworkのコードを変更し以下のようにCodeCommitにPushします。

```zsh
➜  serverless_frameworks git:(develop) git push origin develop
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 294 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 1 (delta 0)
remote:
To ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/serverless_frameworks
   9a85375..088a243  develop -> develop
```

しばらく経つとCodeBuildが動き始め、

![AWS_CodeBuild_Management.png](https://qiita-image-store.s3.amazonaws.com/0/40136/3cd971cf-bf77-2419-f502-29e2575adee8.png)

Buildが完了します。

![AWS_CodeBuild_Management 4.png](https://qiita-image-store.s3.amazonaws.com/0/40136/b642a036-449c-f09e-2eef-1f9eeda2cf7a.png)

CloudWatch Logsを見てみると以下のようにきちんとログがはかれていました。

![CloudWatch_Management_Console.png](https://qiita-image-store.s3.amazonaws.com/0/40136/f71ae115-274d-202b-8e6d-21ac6ffd2e65.png)

以下のようにAPI GatewayやLambda、DynamoDBについてもServerless Frameworkのコード通りに作成されています。

![API_Gateway.png](https://qiita-image-store.s3.amazonaws.com/0/40136/9b31160f-72fa-b6f5-0fdb-b9e75e65239e.png)

# 以上

CodeBuildのお陰で、サーバーレス環境のコード管理とビルドが楽になりそうです。
他のサービスでも面白そうなものがいっぱいでているので、面白いものをどんどん作成していきます！