Capistranoでデプロイした後にAMIを作って世代管理するプラグイン書いた

タイトルの通り、デプロイ後にAMIを作ってAMIの世代管理もできるCapistrano3向けのプラグインを作りました。
要件としては意外とありそうなのに、(自分で調べた限り)gemがなかったので、作ったという経緯です。AMIを作るだけならば、適当にaws-sdkをrequireしてタスクを一から書いてもよさそうですが、世代管理まで自前で書くのは面倒かと思う(というか自分で書いてみて面倒だった)ので、とりあえずバックアップとしてAMIは定期的に取得したいよねっていうときに使ってもらえるといいんじゃないかと思います。


使い方

基本的にREADMEに書いてある通りですが、日本語でも書いておきます。

インストール

https://rubygems.orgで公開しているので、いつもの通りにインストールできます。

$ gem install capistrano-ami

もちろん、Gemfileでも使えます。たぶんGemfileで指定するほうが多いでしょうね。

group :development do
  gem 'capistrano-ami' require: false
end

後は他のプラグインよろしく、Capfileに指定するとタスクが有効になります。

require 'capistrano/ami'

設定

後は config/deploy.rb に記述して各種設定が可能です。

set :aws_region, 'ap-northeast-1'
set :base_ami_name, 'web-role'
set :keep_amis, 5

base_ami_name は生成されるAMI名の一部です。実際に生成されるAMI名は「[設定した名前]_[インスタンスID]_[タイムスタンプ]」になります。未指定の場合、capistrano-ami が使用されます。keep_amis は管理する世代数で、未指定の場合、5世代まで残します。世代管理にはタグを利用しているので、インスタンスが変わらない限り、base_ami_name が変わっても1世代としてカウントされます。
aws_region はデプロイ先のリージョンで、未指定の場合タスクに失敗しますので必ず指定してください。また、代わりに環境変数 AWS_REGION を利用することもできます。

クレデンシャルの扱い

内部的にaws-sdkを利用するので、AWSのクレデンシャルを指定する必要があります。
プラグインでは可能な限り、複数のクレデンシャルプロバイダに対応できるように作成しています。

直接指定する場合

config/deploy.rb などで直接指定することが可能です。

set :aws_access_key_id, 'YOUR_AWS_ACCESS_KEY'
set :aws_access_secret_key, 'YOUR_AWS_SECRET_KEY'
環境変数を利用する場合

直接指定する方法は直感的ですが、ソースコードにセキュアな情報がプレーンテキストで記載されてしまうという問題があります。
代替案として一般的なのは環境変数で、こちらでも指定可能です。

$ export AWS_ACCESS_KEY_ID=YOUR_AWS_ACCESS_KEY
$ export AWS_ACCESS_SECRET_KEY=YOUR_AWS_SECRET_KEY

また、環境変数 AWS_REGION でリージョンの指定もできるので、リージョンを環境変数で指定して、他のクレデンシャル情報を環境変数、または別の方法で提供するようにすると、ソースコードがよりセキュアになります。個人的にはリージョンくらいはソースコードに明記されていてもいいんじゃないかと思いますが...

SharedCredentialsを利用する場合

プラグインでは ~/.aws/credentials ファイルによるSharedCredentialsに対応しています。
デフォルトの値を使用する場合には特に指定する必要はありませんが、特定のプロファイルを使用する場合には以下のように設定してください。

set :aws_credentials_profile_name, 'profile-name'

これによって、ひとつのファイルですべてのクレデンシャルを管理しつつ、ソースコードをセキュアに保つことができます。

IAMロールを利用する場合

IAMロールはAWSのクレデンシャルプロバイダの中で最もセキュアな方式で、本プラグインAWS上で動作する場合のみ利用可能です。IAMロールが設定されているインスタンス上で実行する場合には、特に設定を記述する必要はありません。

クレデンシャルの優先順位

各クレデンシャルは複数設定されている場合に以下の優先順位に従って適用されます。

  • 指定したプロファイルのSharedCredentials
  • 直接指定された値
  • 環境変数
  • デフォルトのSharedCredentials
  • IAMロール

使いドコロ

デプロイの度にAMIを作って、いつでもスケールアウトできるようにしたい!というときに便利だと思います。
後は、ひとつのマシンに対してAMIを作っていると、キャッシュが効くので、前回デプロイ時との差分が小さいほど作成の時間が短縮できます。ゴールデンイメージ方式特有のプロビジョニングに時間がかかりすぎる問題の解決策として効く、かもしれません。

最後に

Ruby初心者なので、リファクタリングから機能追加までIssue,PRお待ちしてます!
あと、RubocopとReekにはわかりやすいクソコードを排除していただき、大変助かりました。やっぱり継続的なLintって大事ですね。