AWS Lambda with VPCでのトラブルシュート事始め

#はじめに
AWS Lambdaが2016年2月11日に待望のVPCアクセスをサポートしてから1ヶ月とちょっと経ったわけですが、その特性や気をつける点については以前[こちら](http://qiita.com/Keisuke69/items/1d84684f0511a062e968)で簡単にまとめました。今回は実際にVPCアクセスを利用しようとして上手く行っていない場合にチェックすべきポイントについて簡単にまとめます。
といっても**基本的にはAWS Lambda固有の話ではなく、VPC周りの確認が主になります**。

なお、VPCの件以外にもAWS Lambdaの挙動などハマりがちなポイント、確認すべきポイントについて先日のJAWS DAYS 2016で登壇した際にまとめたので[こちら](http://www.slideshare.net/keisuke69/building-scalable-application-on-the-cloud)も合わせて参照ください。

**本投稿は個人によるものであり、所属する企業や団体に関係するものでも代表するものでもありません**

#AWS Lambdaにおけるネットワーク的な制限
まず、AWS LambdaでVPCアクセスを有効にしたにも関わらず上手くアクセスできないという場合、その原因は十中八九ネットワーク的な設定の問題です。そういった意味ではいわゆるネットワーク系の問題解決に利用する一般的なツール、pingやtracerouteといったものを問題切り分けのため利用したいところなのですが、これらをLambdaファンクションから実行することは許可されていません。正確に言うと、AWS Lambdaの基盤実行環境のベースはAmazon Linuxなんですが、本来Amazon Linuxに用意されているネットワーク系のコマンドがAWS Lambdaの実行環境ではomitされています。また、**利用可能なプロトコルとしてもTCP/IPのみが許可されており、UDPやICMPといったプロトコルは許可されていません**。従って現実的にLambdaファンクションからの経路調査等のネットワーク的な調査はかなり制限されると言えます。

#ポイントその1
まず、最初に全くアクセスできないのではなく、ある一定の負荷を越えた場合にVPCアクセス周りが不安定になるという場合はキャパシティ不足が疑われます。具体的にはLambdaファンクションがリクエストをさばく上で必要となるENI数もしくはIPアドレス数が十分でないことが挙げられます。こちらについては現時点ではCloudWatch Logsなどにはエラーとして出力されないため、注意が必要です。IPアドレス数についてはLambdaファンクションに割当てたサブネットそのものサイズ、およびEC2インスタンスなどその他のリソースも同じサブネットで動いている場合はそれらが使用する数も考慮する必要があります。なお、必要なENIのキャパシティについては以下の計算式でおおよその数が算出可能です。
```
Projected peak concurrent executions * (Memory in GB / 1.5GB)
```
この式の各パラメータは次のような意味になります。

* Projected peak concurrent execution – 許可されている同時実行数
* Memory – Lambdaファンクションに設定したメモリサイズ

また、Lambdaファンクションに割り当てるサブネットを複数割り当てることも有効です。その場合はアベイラビリティゾーンを分けるとより可用性は高まると言えます。

#ポイントその2
最初に大抵の問題はVPC周りの設定の問題がほとんどであると言いました。というわけでそもそもVPCの構成的にLambdaファンクションに割り当てたサブネットが目的のリソースに対して通信可能であることが大前提です。従って、手っ取り早く確認するには同じサブネット上にEC2インスタンスを起動して、それにログインした上でAWS Lambdaでは制限されているネットワーク系のコマンドを利用して確認するというものです。もちろんその際は同一サブネットだけでなくセキュリティグループに関しても同様のものを利用してください。ただし、Lambdaファンクションと同一のものだとSSHを許可されていないでしょうから、Lambdaファンクションに割り当てているセキュリティグループに対して一時的にSSHを許可するか、SSH以外のルールを全く同じにしたセキュリティグループを利用するのがいいと思います。

#ポイントその3
EC2インスタンスからのテストでもやはりNGな場合、以下のあたりの設定を確認してみてください。

##ルートテーブル
そもそもLambdaファンクションに割り当てたサブネットが目的リソースの所属するネットワークに対してルーティングされているかを確認してください。これはマネージメントコンソールからだとVPCを選択した上で、左側のペインより「Subnets」をクリックし、右上ペインから対象サブネットを選択し、右下ペインに表示される情報の「Route Table」を確認します。

![Screen_Shot_2016-03-22_at_6_20_45_PM.png](https://qiita-image-store.s3.amazonaws.com/0/30135/3af70831-f43e-77c5-4f46-973150f04b57.png)

##セキュリティグループ
同様にLambdaファンクション割り当てるサブネットもしくはセキュリティグループからの通信がアクセス対象のリソースに割り当てられているセキュリティグループで許可されているかを確認してください。大抵はインバウンドルールとして許可する通信のルールのみ定義されているはずです。従って、割り当てたサブネットもしくはセキュリティグループをソースとした通信がその許可ルールに含まれている、もしくは別エントリとしてそれらをソースとした宛先ポートへの通信を許可するルールが追加されていることを確認してください。

##ネットワークACL
これも前2つと同様、目的とした通信が許可されていることを確認します。inbound/outboundともにALLOWの範囲に含まれているか確認してください。

##ENIの作成権限
そもそもなんですが、AWS LambdaのVPCアクセスにはENIが利用されています。このENIはユーザに代わってAWS Lambdaが自動的に作成・削除を行うためあらかじめそのLambdaファンクションに割り当てるIAM Roleに対してENIの作成・削除を許可するポリシーを設定しておく必要があります。これには事前に用意されている「AWSLambdaVPCAccessExecutionRole」というポリシーをアタッチするか手動で以下を追加します。

```
ec2:CreateNetworkInterface
ec2:DescribeNetworkInterfaces
ec2:DeleteNetworkInterface
```

# まとめ
というわけでAWS Lambdaを使ってVPCアクセスする場合に確認すべきポイントを簡単にまとめました。この辺りを確認した上でやはり問題が継続する場合はサポートに問い合わせるのがいいでしょう。
他にも思いつくことがあったら随時追加していきます。


なお、しつこいですが**本投稿は個人によるものであり、所属する企業や団体に関係するものでも代表するものでもありません**。