ApexとLamveryの比較

# 前置き
ちょっと前から[Lamvery](https://github.com/marcy-terui/lamvery)というAWS Lambdaのデプロイや管理を簡単にするツール（OSS）を作っていて、[Qiitaでも紹介](http://qiita.com/marcy-terui/items/1617ab4e20e3339d1930)させてもらったりしていたのですが、結構便利に使えるようになってきてはいるものの、最近出てきた[Apex](https://github.com/apex/apex)の注目度 [^1] が非常に高くて嫉妬したので比較記事を書いてみることにしました。

`Lamvery`の説明についてはこちらをご確認ください。
http://qiita.com/marcy-terui/items/1617ab4e20e3339d1930
https://github.com/marcy-terui/lamvery/blob/master/README.md

`Apex`はwikiを見るとなんとなく雰囲気がつかめるかと思います。
https://github.com/apex/apex/wiki

一方が自作なので、できるだけ公平を期したいとは思っていますが、Lamvery側に寄ってしまっていたらお察しください。また、作者としての解説と見解も載せさせていただきます。ご参考までに。

あと、Apexは対抗心から色々把握してるつもりですが、誤りなどあればご指摘いただけれると助かります。

下記、2016年1月29日現在の比較です。

# 基本部分の比較
| 項目                     | Apex                    | Lamvery       |
|--------------------------|-------------------------|---------------|
| 実装言語                 | Go                  | Python            |
| インストール方法          | バイナリダウンロード    | PyPi,rpm,deb    |
| 対応ランタイム(Lambda)    | Go, Python, Node.js | Python, Node.js   |
| 管理対象                | Project単位            | Function単位     |
| 設定ファイルフォーマット | JSON                    | YAML + jinja2   |

## 解説と見解

### 実装言語
好みの問題ですね。

### インストール方法
#### Apex
インストール方法はGoゆえに依存ごとバイナリ化されていて、ダウンロードして置くだけの`Apex`が強いでしょうか。
#### Lamvery
`Python` + `pip`環境のセットアップが必要。そこから先は`pip`で、依存ごとまとめて１コマンドでインストールできます。[^2]
また、CI環境などで使うためにPythonまで含めて完全に独立した環境を作れるyumとdebのパッケージも提供してます。
https://github.com/marcy-terui/lamvery#installation

### 対応ランタイム(Lambda)
#### Apex
`Apex`はLambdaが公式では対応していない`Golang`に対応しているのが特徴です。他にもBabel等のAltJS系に対応しているようです[^3]
#### Lamvery
`Lamvery`では特に要望がなければ`Go`をサポートするつもりはないです。[^4]
`Node.js`は自分が`Python`メインなので今のところ試験的なサポートです。[^4]

公式が`Go`対応するのはそう遠くない未来だと思ってるんですがどうでしょうね？
みんなそんなに非公式な方法でもいいから使いたいものなのかな・・・？

### 管理対象
#### Apex  
`Apex`は複数のLambda Functionを一つのProjectでまとめて管理でき、Projectに適用する設定ファイルと個々のFunctionに適用する設定ファイルとがあります。
#### Lamvery
`Lamvery`はFunction単位でしか管理できません。ここは今後どうするか考えている所です。
ただ、Function単位であるため、Python限定ではありますが`virtaulenv`[^5]仮想環境内でそのFunctionが使用するライブラリのみをインストールしておけば、それを自動的に格納効率を考慮して収集し、アップロードするようにしています。これは、`Apex`はただ特定のディレクトリ以下を全てアップロードするだけなので、[Lambdaのソースコード容量に制限がある](http://ijin.github.io/blog/2016/01/14/monitor-lambda-capacity/)ことを考えれば大きな違いなのではないでしょうか。Python限定ですが。。。[^6]

### 設定ファイルフォーマット
#### Apex  
ただの`JSON`です。
#### Lamvery  
`YAML`ですが、テンプレートエンジンである[jinja2](http://jinja.pocoo.org/docs/dev/)を被せています。
つまり、変数埋め込みや動的な記述をサポートしています。

# 機能比較
| 項目                               | Apex  | Lamvery |
|------------------------------------|-------|---------|
| Deploy                            | ○     | ○       |
| Rollback                          | △     | ○       |
| 任意のAliasの設定                   | ☓    | ○       |
| 実行(Invoke)                       | ○     | ○      |
| 除外リスト                          | ○     | ○      |
| 機密情報受け渡し                    | ○      | ◎      |
| CloudWatch Events(スケジュール実行) | ☓[^8] | ○      |
| CloudWatch Logs(実行ログの閲覧)     | ○     | ○       |
| CloudWatch Metrics(起動時間など)    | ○     | ☓ [^7] |

## 解説と見解
両方にある機能の中で、特徴的な違いがある部分のみ記載します。

### Deploy & Rollback
Lambdaの特殊なバージョニングの仕様は以下が分かりやすいので目を通しておくと良いかと思います↓
http://dev.classmethod.jp/cloud/aws/lambda-versioning/

#### Apex  
バージョニング[^9]が必須です。Deploy時に `current` というAliasを設定し、Rollback時には最新の一つ前のバージョンに`current`を付け替えることで実施します。
ですが、この`Apex`の手法はAliasの付け替えをdeploy,rollback以外で行うと破綻します。それだけならまだ良いのですが、deploy,rollbackを二度繰り返しても破綻します（下記参照）
![apex_rollback.png](https://qiita-image-store.s3.amazonaws.com/0/57327/fbe208ee-0f07-d987-3724-ab6dcbe25bc0.png)
最後は「2」に戻って欲しいのにFailしてしまうことが分かっている「3」に戻ってしまいます。一応、Rollback時に任意のバージョンを指定するオプションは用意されていますが、バージョン番号を人間が覚えておかないといけないというのはナンセンスだと思います。

#### Lamvery  
`Lamvery`では、上記の問題があるため、別の方式を採用しています。
簡単に言うと、Deploy時に前のバージョンにも別のAliasを付けておき、そこに対してRollbackします。一時的に2つ以上前のバージョンに巻き戻したりするような運用を可能とするためです。

また、任意のAliasを付ける機能もあるので、組み合わせて使用することで柔軟なバージョン管理ができます。
Apexと同じようにシンプルに使いたければ、バージョニングを有効にしたままDeployとRollbackだけを使えば良いだけです。  
Rollbackを使用する場合はバージョニングが必須ですが、使用しない場合は設定ファイルでオフにできます。また、デプロイ時に設定するAliasも任意に設定できます。
これも、先にも述べた[Lambdaの容量に制限があること](http://ijin.github.io/blog/2016/01/14/monitor-lambda-capacity/)を踏まえれば必要なオプションだと思っています。軽微な修正ではオフにしておいて、必要な時にオンにしてロールバックできるようにするということもできます。  

### 実行(Invoke)
#### Apex
単発起動と、標準入力から入力を次々受け付けて(Streaming)、連続で同期実行[^10]することができる。
#### Lamvery
単発実行のみ。Streamingは非同期実行[^10]して、ClouodWatch Logsをtailするような形で形でサポートしたいと思ってます。

### 機密情報の受け渡し
#### Apex
Deploy時に環境変数として指定します。バージョン管理[^11]に含めることはできません。
ソースやWikiを見る限りPythonが対応していないような・・・？
#### Lamvery  
[KMS](https://aws.amazon.com/jp/kms/)を利用し、暗号化した機密情報を設定ファイルに含めてバージョン管理[^10]できます。
~~現状はPythonのみのサポートですが、近いうちにNode.jsにも対応したいと思っています。~~
Node.jsも対応しました（2015.02.03）

# 所感とまとめ
今のところ、全体的には一長一短という感じかと思います。
ただ、ロールバックの仕様とCloudWatch Events対応は大きな違いだと思うので、日本語サポート可能[^12]という点も踏まえて`Apex`だけではなく、`Lamvery`にも目を向けていただければ幸いです :-) [^13]

https://github.com/marcy-terui/lamvery




[^1]: GitHubのスター数、[Apexの日本語記事](https://osdn.jp/magazine/16/01/20/160000)と[LamveryのQiita記事](http://qiita.com/marcy-terui/items/1617ab4e20e3339d1930)のはてブ数を比べると。。。
[^2]: `pip`はRubyで言う所の`gem`, Node.jsで言う所の`npm`です。`pyenv`でPythonをインストールすると標準で入ってるし、Linux系ならデフォルトのパッケージマネージャから入れられることが多いです
[^3]: Node.jsからGoのバイナリを子プロセスとして立ち上げて、標準入出力を使ってやり取りするような方式で対応している
[^4]: まさにユーザが少ないゆえの悩み。。。
[^5]: ライブラリ等を共有しない独立したPython実行環境を作ることができるPythonライブラリ
[^6]: 自分がPythonメインで使っているからで、Node.jsに詳しい方がアイデアだけでもいただければ対応はしたい
[^7]: 近日対応予定
[^8]: 対応予定？[Issue](https://github.com/apex/apex/issues/147)にて議論中
[^9]: Lambda的には`publish`オプション
[^10]: https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/API_Invoke.html#API_Invoke_RequestSyntax
[^11]: LambdaのじゃなくてGitとかの方
[^12]: というか日本語の方が助かる
[^13]: 「Apexを超えてやる！」って思ってるけど、あまりにも見向きされないとモチベーションが続かないかもしれないｗ