2016-12-25こんばんは。インフラエンジニアやってます。2016の遅刻投稿です。何を書くかリリースツールを0から作る時に、どんな要求を受けてどう育っていくかを自分の経験を元にまとめていきたいと思います。これによってリリースツールを初めて扱う人や、もう一段階成長させたい時に参考になれば良いと思っています。リリースツールとは言語によらず、プログラミングしたソースコードを本番・開発環境で動かすまでのプロセスを自動化するツールの事を本ブログでは指します。会社によってはリリースをデプロイと呼ぶ事もあるかも知れないので、適宜読み替えて下さい。リリースプロセスプロセスは大抵の場合以下のステップで表現する事が出来ると思います。(大元はMavenのGoalが参考になっています。)1.Build/Compile・各言語毎に存在するCompile等のフェーズ。・各環境で動く様にする為の処理を行います。Package・一般的には幾つかのサーバーで動く筈なので、配布に適した形にします。・また、配布に適した場所に置く事もあります。Distribute・大抵の場合、リリースツールを要する場合は複数のサーバーが存在すると思います。そのサーバーへ配布し、アプリケーションが起動可能な状態まで準備します。Switch・実際に動くフォルダに3.で配布したアプリケーションを配置します。Restart/Reload・アプリケーションを最新バージョンで起動します。5.については1.の手前と5.の後ろでStop/Startで表現する場合があるかもしれないです。これらは次に書いた内容で進化させることができます。シンプルリリースまず最初は、アプリケーションを停止しても何をしてもいいから自動化されたプロセスでリリースをしたいという要望から始めましょう。シンプルなのはアプリケーションを停止しBuild/Compileを行いDistributeしSwitchしアプリケーションを起動するこのステップを一つのShellスクリプト等で実装して安定させましょう。このリリース方式のいい所は、どのステップにおいてイレギュラーな事が起きてもサービスが止まっているのでユーザー影響が出ない事です。シンプルなので初めての言語や初めてのツールを使った場合の基礎ケースとして実装するには最も扱いやすいです。Webサービスであろうが、社内サービスであろうが、ダウンタイムが減る方がいいと考えるのは自然だと思います。手をかけずに実現するには、順序を並び替えて実装するのが良いと思います。Build/Compileを行いDistributeしアプリケーションを停止しSwitchしアプリケーションを起動するアプリケーションの停止が切り替えの直前になるだけです。このタイミングではSwitchの実装が少し変更になります。おいては、起動中のプロセスがある状態で、次のバージョンのアプリケーションをサーバーに配布しなければいけないので、このタイミングで複数バージョンがフォルダ上に存在可能な実装に変える必要があります。フォルダが変わる場合は起動スクリプト等も合わせて対応を進めましょう。実際にバージョン毎のフォルダにパスを向けるのは手間が多いので、シンボリックリンクを使うのが適していると思います。して、起動スクリプトやらなんやらはここを見させる。/opt/app/version/my_app/version1_app/opt/app/version/my_app/version2_appの様に別フォルダに名前を変えて配置するのが適切です。シンボリックリンクの切り替えはSwitchのステップで行います。どちらが先に要望されるかはわからないですが、大抵の場合はほぼ同時に求められると思います。シンプルリリースには特に書いていませんでしが、処理を直列で実行している場合、サーバーが増えるにつれて処理時間が長くなっていくので高速化を期待される事になると思います。その場合は可能な限り並列処理化を進めていくのが良いでしょう。Build/Compileの部分以外は全て可能です。多重化する事も考えられます。(ちなみにWindowsでもPowerShellを使えば対応可能(面倒だが)であるので是非チャレンジしてみて下さい。等の並列実行をサポートしているツールに乗り換えるのもいいタイミングかもしれないです。教えてもらったので是非使ってみたい。私は、金融向けSIで働いた後にWeb系の会社へ転向しています。SIにいた頃は、ミスなく安定してリリースされる事が最も重要であり、それが守られるのであれば効率性や多様性を取る必要がありませんでした。リリースツールにおいては、大体このステップくらいまでを実装しておけば安定運用が開始され、また自分のできる責務を全うしたとみなされていたし、それ以上は過剰コストだと思われていました。Web系に来てみると視点が一つ変わりましたね・・・。この後に提案するリリース手法についてはSIだろうがWebだろうが是非取り組んで欲しいと思います。この取り組みによってより柔軟に、よりハイスピードでサービスを提供できると思います。よってダウンタイムは1~2分まで減ったと思います。ノーダウンタイムリリースというもう一つ上のステップが存在します。リリースのタイミング(実施時刻や曜日)を意識しなくて良くなる。いうメリットを得る事ができます。不具合修正や新機能はいつでも本番に出せる様になります。SIにいた頃は週末を待たねばならず、ユーザーは1週間不具合と付き合うかまたは週の途中にサービス断を受け入れてリリースをするしかありませんでした。いずれにしろユーザーが不利益を受ける状態だったのです。実際にどう実現するか、幾つかの例をあげていこうと思います。WebアプリケーションノーダウンタイムリリースはWebアプリケーションが圧倒的に相性が良いと思います。ノーダウンタイムにおいても、旧プロセスの停止と新プロセスの起動、ユーザーからのコネクションを新プロセスに向ける。この作業は不可避であるが、Webアプリケーションの場合、ミドルウェアでこの辺りを吸収する事ができます。アプリケーション側に実装があまりいらないのが良いところですね。Nginxを例にして記載します。RoRの場合はUnicornやPassengerをアプリケーションサーバーとして起動し、その手前にNginxをWebサーバーとして配置する事が多いとでしょう。restartを提供しています。Unicornの場合、以下の感じでRestartが可能です。メモリ上にロードして、リクエストを捌きます。済んだりもするので楽ちんです。NginxRoRの様な元からWebアプリケーションに特化した言語はいいよなぁ。思う方もこんな方法でも実現できます。今回のサンプルはJavaWebアプリケーションをJettyで起動し、その手前にNginxがいる構成を例にします。restartをサポートしていないです。Javaの実装内部でシグナルを受けたらプロセスをリロードする。muchな実装だと思うので他の方法を提案してみます。2台のサーバー又は2並列でアプリケーションを起動しておいて、1つづつ最新かする事で対応できます。Nginxにロードバランシング機能があるので、Nginxで1,2のプロセスに常時振り分けを行います。リリースの際は1つ目のJettyを停止してSwitchしてJettyを起動します。これにより1台は最新になります。同じ要領で2つ目のJettyを対応すれば良いです。Nginxのロードバランシングの設定では、リクエストを送って落ちていたらもう一台に振りなおしをしてくれる機能があるので、ロストする事なく1つづつ切り替えていく事ができます。Nginxのconfのサンプルは以下の感じです。30秒間に3回つながらないと30秒間切り離される。つながらなかった場合はNginxが別のサーバへ飛ばしなおしてくれるので1台でも生きていればエラーになる事はない。2台のサーバを想定したconfだが、1台で2プロセスあげる場合は同じホストでポート番号を分けるといいと思います。ロードバランサーを間において、ロードバランサーの先に2台のマシンを配置しておくことで実現できそうです。念の為、アプリケーション側ではリトライ処理を入れておくといいと思います。アプリケーション側に複数の接続先情報を書いておくでもいいと思います。1つ目がダメになったら2つ目にアクセスする様な実装を入れれば実現できそうです。取り組んでいるとそこそこ早いリリースが組めたかと思われますがそれでもやはり、サーバー台数が100台を超えてきたり、配布物が重くなると遅さを感じる様になると思います。のを本項目に書きます。素早いリリースで現実的に可能な範囲でリリース処理は高速化されているとします。可能な限り並列化を行い、サーバースペックも高くなっていても、台数が100台を超えると遅くなってきたと感じるのではないでしょうか。体感時間を減らす事で対応ができます。Deploymentsの考えそのままです。通常、リリースというのはGithub等のソースコードリポジトリにコミット/プッシュした後から作業が始まります。担当者はコミット/プッシュが終わった事を確認して、ビルドボタンを押して、リリースが終わったらテストをして、終わったら、本番のビルドボタンを押す。いう運用をしている事が多いです。Distributeまでしてしまう。Switchの手前まで作業が進んでいる。いう状況を作る事で、作業者はテストを終えた後、Switchだけを投げればいいのでリリースが一瞬で終わる様に体感させる事ができます。Distributeを行う様にWebhookで連携するだけでも、非常にスピード感が出ます。人を介すとそれほど、時間がかかったり、手間がかかったり、忘れられたりするのでそれがなくなるだけでも運用は手離れしていきます。部分リリースだいぶ長くなってきました。残り3項目はまだ実装が甘いので記述も甘くなる事が想定されるので、さらっと書いていきます。今までやってきた様な仕組みを普通に捉える組織は非常にリリースが活発な組織だと想像されます。いう要望が出てくるだろうし、あれば便利です。Webサーバー1台だけ配布するオプションを用意しておくと良いと思います。まで自動で動く様にしています。開発者からは常にテスト環境がリポジトリと同じになるというのは「今、環境ってどんな状態だっけ?」というのが忘れられて楽だそうです。仕込むことが出来れば運用は非常に楽になりました。等も組む事が出来れば柔軟な運用につながると思います。あとがきだらだらと書いてしまいましたが、リリースツールも突き詰めていくとまだまだ出来ることがあるし、新しく取り組むと、もっとこうしたいと課題がでるもんだなと思いました。(小並感)リリースツールが優秀な組織は変化に強く、変化のスピードが早い組織に慣れると信じているのでより一層がんばっていきたいと思います。本当はBlue/Greenデプロイメントも書きたかったが、今回はアプリケーションレイヤーだけの話に止めたかったので書くのをやめた。