LoginSignup
14
8

More than 5 years have passed since last update.

edeliverとconsulを使ったphoenix applicationのdeploy

Last updated at Posted at 2016-12-13

Elixir Advent Calendar 2016 14日目です。

現在開発しているphoenixのプロジェクトで使用しているedeliverとconsul+strecherを使ったdeploy構成を簡単に紹介したいと思います。

edeliver

edeliverはelixir/erlangで使えるbuild&deployツールです。

build部分はexrmやdistilleryをwrapして、gitを使ったAuto Versioningやupgrade buildサポート機能を提供してくれます。
deploy部分は、buildしたpackageをリリースタイプを指定することで、ローカル保存、S3にアップロード、stagingまたはproduction環境へのdeployなどの動作を実行することができます。
興味が出たらwikiにいろいろ書いてあるのでそちらを見るのがいいと思います。

deploy部分はコードを見ると結構思い切りがいい書き方がされているので(褒め言葉)、build部分だけ利用してconsulと組み合わせることでdeployすることにしました。

Versioningは基本的にstop/startやblue/greenで運用しているような環境ではversion更新が問題になることはないのですが、upgradeを実施しようとするとincrementalなVersioningが必要になってきます。
applicationのversionは基本はmix.exsの中に記載して更新しますが、細かいreleaseを何回も行うような環境だと、release branchにマージするたびにversionを更新しないといけません。

edeliverではgitのcommit-countやrevisionを利用して、バージョニングのルールに違反しないようなバージョン番号を発行してbuildに含めてくれます。(このあたりのルールを使用)
現在自分たちの環境で使用しているAUTO_VERSIONの設定は

AUTO_VERSION="git-commit-count-branch+git-revision"

(git-commit-countとgit-commit-count-branchは別物なので注意)

また、upgrade buildを作成するためにはupgrade前のbuildが必要になるのですが、以前の作成時のrevision番号を指定するだけで、2回build作成が走るので時間はかかりますがクリーンな環境からでもupgrade buildを行うことができます。

distilleryを使う場合にmix release.initで前もってrel/config.exsを作っておく必要があります。
upgrade buildを作成するためにはその内部に

environment :plan do
  set include_erts: true
  set cookie: :"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
end

で、include_ertstrueにしておく必要があります。

consul + stretcher

consulのイベント検出を利用してpull型の配送を行うための組み合わせになります。
詳しく知りたい方は本家の記事を参照していただければと思います。

build + deployの流れ

build処理とdeploy処理にわけて実行しています。

build処理はおおざっぱに言うと、buildして精製物をS3に置く処理になっていて、

  1. edeliver用のconfigをビルド環境用のものに取り替える
    • edeliverが.deliver/configが直接読むので、環境ごとに切り替える必要があった
  2. S3上にlockを取得する
  3. S3上からcurrent_relaseを取得する
    • current_releaseは現在deployされて動いているbuildの情報を記載してあるyml
    • 存在しない場合はbuild releaseを実行する
    • 存在する場合はbuild upgradeを実行する
  4. 作成したビルドをS3にアップロード
  5. stretcher用のmanifestファイルを作成してS3に配置
    • start_manifest, restart_manifest, (upgrade_manifest)の3つを前もって作成しておく
  6. 作成したビルドのバージョン等をlatest_buildに記載してS3上にupload
  7. S3上のlockを解放

上記の処理を実行しています。

deploy処理は最新のbuildをappサーバに配布する処理で、start|restart|upgradeのリリースタイプを指定しています

  1. S3上のcurrent_releaselatest_buildとリリースタイプの組み合わせから整合性をチェック
    • release buildに対してupgradeじゃないかとか、release_buildとversionが変わらないなど...
  2. S3上にlockを取得する
  3. consulにeventを発行
    • リリースタイプに対応するmanifestを一緒に渡してstretcherの挙動を制御しています
  4. current_releaseを更新
  5. S3上のlockを解放

上記のような仕組みでdeployを実行しています。

開発ステージごとにいくつかの共有環境があるので、buildや管理用のファイルはbucketやパスで分離されており、自分の反映したい環境にslackで実行依頼を投げてhubotを介して、jenkins内のdocker containerでbuildとdeployを実行しています

なんでこんな構成にしたのか

APIをメインとしたリクエストのみの場合、containerを使ったdeployの仕組みをとったほうが容易だと思います。
ただphoenixの一つの魅力であるphoenix channelのsocket接続を切断せずに継続的デプロイを実施したいと考えていて、とりあえず試行錯誤している段階です。

hot deployはやはりまだ試行錯誤している段階で、安定しているとは言えていない状況です。
ただもう少しノウハウ等がたまってきたらまた共有していきたいなと思っています。

14
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
8