k8sに関してはArgo Rolloutsで以上!!!って感じのこの領域ですが、VMで動くソフトウェアを安全にリリースしたかったので開発しました。大まかな流れは下記のとおりです。
- GibHubのReleaseをポーリングする
- 最新のリリースがあれば、1台のみデプロイする
- 指定した時間、ヘルスチェックが通過すれば、残りの全台デプロイする
デプロイや、ロールバック、ヘルスチェックは利用者が任意のスクリプトや、コマンドを準備する必要があります。
例えばdebパッケージをインストールするスクリプトは下記のようになります。
#!/bin/bash
set -e -x
dpkg -i $ASSET_FILE
フックされるスクリプトには、アセットファイルが 環境変数ASSET_FILE
として渡ります。またタグはRELEASE_TAG
環境変数にセットされます。
ヘルスチェックについては下記のようにmackerelのpluginを利用したり、任意のコマンドでチェックすることが出来ます。
#!/bin/bash
set -e
check-tcp -p 80 -w 5 -c 10
check-tcp -p 443 -w 5 -c 10
check-log -p critical -f /var/log/nginx/error.log -w 3 -c 5
またヘルスチェックが失敗した場合は、任意のロールバックを実行できます。下記はdebパッケージをロールバックする例です。
#!/bin/bash
set -e -x
dpkg --force-downgrade -i $ASSET_FILE
この場合、ASSET_FILEは直近インストールされていたバージョンのアセットファイルのパスが環境変数経由で渡されます。
現在インストールされているバージョンを取得するのも任意のスクリプトで実装が可能です。
#!/bin/bash
set -e
echo v`dpkg-query -l yourpackage |grep -oP '(\d+\.\d+\.\d+)'`
このようなスクリプトを設定ファイルや環境変数、コマンドライン引数でパスを指定する必要があります。
# デプロイ時にコールされるスクリプト
deploy_command = "/var/lib/gacr/deploy"
# ロールバック時にコールされるスクリプト
rollback_command = "/var/lib/gacr/rollback"
# ヘルスチェック時のコールされるスクリプト
healthcheck_command = "/var/lib/gacr/healthcheck"
# 現在インストールされているバージョンを取得するスクリプト
version_command = "/var/lib/gacr/get_version"
# 監視するリポジトリ
repo = "STNS/STNS"
# ダウンロードするアセットファイルの正規表現パターン
package_name_pattern = "stns-v.*_amd64.jammy.deb"
# 10秒間でカナリアリリース判定
canary_rollout_window = "1m"
# ヘルスチェックは10秒ごとに実行
healthcheck_interval = "10s"
[redis]
host = "redis"
とりあえず動かして見たい場合、下記のようにdocker-composeで動かすことが出来ます。
$ git clone git@github.com:pyama86/git-assets-canary-releaser.git
$ cd git-assets-canary-releaser
$ GITHUB_TOKEN=xxx make run_example
上記を実行すると私が開発しているSTNSのサーバが自動でインストールされる様子を確認できます。
カナリアリリースの排他制御はRedisのSetNXを利用しています。最近いろんなソフトウェアでSetNX多用しており、こんなに便利で大丈夫???となってます。
最後に、それぞれスクリプトに自由度があるので、色々なところで使えると思います。ぜひアイディアの一つとして考えてみてください!