ServerlessでLambdaをVPC内にデプロイする


## 追記（2016/12/03 18:38）

[v1.3.0](https://github.com/serverless/serverless/releases/tag/v1.3.0)から[LambdaファンクションとIAM Roleの依存関係を解決してくれるようになり](https://github.com/serverless/serverless/pull/2743)、下記のバグは解消されました:tada:


## 概要

ServerlessからVPC内にLambdaをデプロイするための設定方法と、その際にハマったServerlessのバグについて

## 環境

Node.js v4.3.2
Serverless v1.0.3


## VPCの登録

providerもしくはfunction単位でvpcの設定ができます。
VPC内に立てるためにElastic Network Interface(ENI)を利用しているので、以下のようにvpcの設定と一緒にiamRoleStatementも設定する必要があります。


```yaml:serverless.yml
provider:
  name: aws
  runtime: nodejs4.3
  stage: dev
  region: ap-northeast-1
  vpc:
    securityGroupIds:
      - sg-xxxxxxxx
    subnetIds:
      - subnet-xxxxxxxx
      - subnet-xxxxxxxx
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "ec2:CreateNetworkInterface"
        - "ec2:DescribeNetworkInterfaces"
        - "ec2:DeleteNetworkInterface"
      Resource:
        - "*"
```

### IAM Roleを設定しないと

Roleを設定せずにdeployをすると以下のようにENIの設定ができない旨のエラーが返されます。

```sh
$ serverless deploy
.
.
.

Serverless: Deployment failed!

  Serverless Error ---------------------------------------

     An error occurred while provisioning your stack: GetEndpointsLambdaFunction
     - Your access has been denied by EC2, please make sure
     your function execution role have permission to CreateNetworkInterface.
     EC2 Error Code: UnauthorizedOperation. EC2 Error Message:
     You are not authorized to perform this operation..
```

## Serverlessのバグ？

上記の設定をし、いざ`serverless deploy`をしてもIAM Roleを設定していない状態と同様のエラーが返されてしまいます。

```sh:デプロイエラー
$ serverless deploy
.
.
.

Serverless: Deployment failed!

  Serverless Error ---------------------------------------

     An error occurred while provisioning your stack: GetEndpointsLambdaFunction
     - Your access has been denied by EC2, please make sure
     your function execution role have permission to CreateNetworkInterface.
     EC2 Error Code: UnauthorizedOperation. EC2 Error Message:
     You are not authorized to perform this operation..
```

おそらく、IAM Roleの設定がされずにLambdaを作成しようとしていると思われます。
この件についてはIssueにも上がっている模様です。
[VPC not created correctly in 1.0.0-beta · Issue #1786 · serverless/serverless](https://github.com/serverless/serverless/issues/1786)

### ワークアラウンド

正しくデプロイするにはIAM Roleの設定が反映されている状態である必要があります。
なので、始めにvpcの設定を外した状態でデプロイしてIAM Role設定を反映し、その後vpc設定を入れた状態で再デプロイすればエラーは起きません

#### 1. VPC設定を外してデプロイ

```yaml:serverless.yml（VPC設定を外す）
provider:
  name: aws
  runtime: nodejs4.3
  stage: dev
  region: ap-northeast-1
  # vpc:
  #   securityGroupIds:
  #     - sg-xxxxxxxx
  #   subnetIds:
  #     - subnet-xxxxxxxx
  #     - subnet-xxxxxxxx
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "ec2:CreateNetworkInterface"
        - "ec2:DescribeNetworkInterfaces"
        - "ec2:DeleteNetworkInterface"
      Resource:
        - "*"
```

```sh:VPC設定を外した状態でデプロイ
$ sls deploy
Serverless: Packaging service…
Serverless: Uploading CloudFormation file to S3…
Serverless: Uploading service .zip file to S3…
Serverless: Updating Stack…
Serverless: Checking Stack update progress…
.....
Serverless: Stack update finished…
```

#### 2. VPC設定を戻して再デプロイ

```yaml:serverless.yml（VPC設定を戻す）
provider:
  name: aws
  runtime: nodejs4.3
  stage: dev
  region: ap-northeast-1
  vpc:
    securityGroupIds:
      - sg-xxxxxxxx
    subnetIds:
      - subnet-xxxxxxxx
      - subnet-xxxxxxxx
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "ec2:CreateNetworkInterface"
        - "ec2:DescribeNetworkInterfaces"
        - "ec2:DeleteNetworkInterface"
      Resource:
        - "*"
```

```sh:VPC設定を戻して再デプロイ
$ sls deploy
Serverless: Packaging service…
Serverless: Uploading CloudFormation file to S3…
Serverless: Uploading service .zip file to S3…
Serverless: Updating Stack…
Serverless: Checking Stack update progress…
.....
Serverless: Stack update finished…
```


## 参考

- [Configuring your functions to run in a VPC - Serverless Documentation](https://serverless.com/framework/docs/providers/aws/vpc/#configuring-your-functions-to-run-in-a-vpc)
- [[Serverless Framework]Lambda FunctionをVPCの中に入れる](http://dev.classmethod.jp/etc/serverless-framework-lambda-function-run-in-vpc/)