flynnを使ったオートスケーリングシステム | サイバーエージェント 公式エンジニアブログ
はじめに

はじめまして。
新卒2年目(そろそろ3年目)エンジニアの向井といいます。
業務ではアメブロのサーバサイドを担当しています。

さて、今回の記事のネタは「flynnというオープンソースを使ってオートスケーリングシステムを構築してみた」というお話です。

flynnの導入から実際にオートスケーリングさせてみた結果までを綴っていきます。

オートスケーリングとは?

そもそもオートスケーリングとはなんでしょうか
オートスケーリングとは、サーバの負荷に応じて自動的にサーバの台数を増減させることです。
AWSではAuto Scalingとして提供されている機能です。

flynnとは?

flynnとはなんなのでしょうか
どうやらアプリケーションのデプロイ、そしてアプリケーションとデータベースのスケーリングを取り扱ってくれるPaaSのようです。
Herokuのオープンソース版のようなものだと思えばいいのかな。
アプリケーションのスケーリングというところに惹かれます。
オートスケーリングに使えそうな気配がしてきました。

flynnを紹介してらっしゃる方や使ってみたという記事を書いてらっしゃる方もいます。
flynnのインストール

基本的には公式サイトを参考にしました。

OSはUbuntu 14.04です。
公式サイトのInstallationに書いてあるスクリプトを実行するとflynnで使用するコマンドがインストールされます。
$ curl -fsSL -o /tmp/install-flynn https://dl.flynn.io/install-flynn... take a look at the contents of /tmp/install-flynn ...$ sudo bash /tmp/install-flynn});

社内環境の問題で外に出られるポートが制限されていて、上記install-flynnを実行した時にkeyserver.ubuntu.comとの通信ができませんでした。
どうやらURLをちょっと変えれば80ポートで通信できるようでした。
インストールが完了するとflynnやflynn-hostといったflynn関連のコマンドが使えるようになります。
インストールが済んだら以下のようにしてflynnを起動させます。
公式のやり方だとうまく動かなかったのでそちらとは若干異なります。

$ sudo flynn init
$ sudo flynn daemon

かなりログが出てきてなにやら始まります。
ここでこのコンソールは放っておいて別のコンソールで作業をつづけます。

$ sudo CLUSTER_DOMAIN=test.localflynn.com flynn-host bootstrap /etc/flynn/bootstrap-manifest.json

上記コマンドでflynnの各サブシステムが稼働し始めます。
コマンドが完了するとflynnのクラスタを登録するためのコマンドが出力されますので、そのままコピペして実行します。

$ sudo flynn cluster add -g test.localflynn.com:2222 -p GUhOzIhavtZoqbJr0zykUvJKyaOYLPvT6wrABF29GwY= default https://controller.test.localflynn.com dd3e7f0a438a69f715a0a660f5d1ebc1

flynn clusterコマンドによって現在登録されているクラスタ一覧が出力されます。
さきほどのコマンドでクラスタをdefaultという名前で登録したのでそのように登録されているはずです。

$ sudo flynn 
cluster NAME URL
default https://controller.test.localflynn.com (default)

次git pushするための鍵を登録します。
flynnではgitreceivedというサブシステムに対してgit pushすることでアプリケーションがデプロイされます。
そのときに使う鍵です。
ちなみに、~/.ssh/id_rsa.pubの内容が登録されますので、事前にssh-keygenで生成しておきましょう。

$ sudo flynn key add
Key ab:fd:f5:2a:13:a1:66:2d:ho:ge:b3:2d:8e:29:9c:63 added.

次にいよいよアプリケーションをデプロイしてみましょう。
アプリケーションはflynnの公式ページで用意されているものを使います。

$ git clone https://github.com/flynn-examples/nodejs-flynn-example
$ cd nodejs-flynn-example$ sudo flynn create example //flynnにリポジトリを登録
There is already a git remote called flynn //既にリポジトリが登録されている場合はメッセージが出る。
Are you sure you want to replace it? (yes/no): yesCreated example$ git push flynn master

ここまでやればアプリケーションのデプロイが始まるはずです。
さて、稼働したアプリケーションには特定のURLでアクセスすることができます。
今回でいうとexampleという名前のアプリケーションが動いており、
http://example.test.localflynn.com
でアクセスできます。ただしhostsファイルの設定が必要になります。
デプロイしたアプリケーションにアクセスすると、下記のようにコンテナのIDが出力されるページが表示されます。


オートスケーリングシステムの構築

本題です。

オートスケーリングシステムの構成要素

オートスケーリングシステムを構築するにあたって必要なものがいくつかあります。
それらを列挙していきつつ具体的に使ったツールについて説明します。
以下、”役割 / 使ったツール”の形式で書いていきます。

■ サービスディスカバリ / flynn discoverd
起動したアプリケーションの発見

■ Load Balancer / flynn router
アプリケーションが複数稼働している場合、それらにリクエストを分散させるLoad Balancer

■ リソース管理 / なし
flynnを複数台のサーバで動かしてクラスタを組んでいてflynn上のアプリケーションの数を増やしたとき、どのサーバ上でアプリケーションを起動させるかを決定します。
今回は単一ホスト上で動かしているので使用していません。

■ 仮想マシン / libvirt
flynnがアプリケーションやDBを起動するとデフォルトでlibvirtを使って起動します。
サブシステムやアプリケーションと仮想マシンは1対1の関係です。

■ 仮想マシンの生成/廃棄のイベント検知 / Flynn cli, 自作スクリプト
仮想マシンの生成/廃棄時にflynnが特定の文字列を標準出力に出力するため、それを自作スクリプトで検知します。
それからZabbixで負荷監視をしている都合上、仮想マシンが起動したときにZabbixへ登録しています。
逆に仮想マシンが廃棄されたときにZabbixから登録抹消しています。

■ リソース監視 / Zabbix
flynn上で稼働するアプリケーションにかかる負荷を監視し、負荷に応じてスケールアウト/インを行うスクリプトを実行します。

オートスケーリングシステム動作説明

オートスケーリングシステムの全体図です。

図中の番号と対応させながら説明していきます。
① クライアントからのアクセスはflynn routerを通じて各web appにルーティングされます。
②, ③ Zabbixで監視されている仮想マシンの負荷の平均が上昇してくるとZabbixからflynn_scaleout.shが実行され、追加で仮想マシン(web app)が起動します。
④ 具体的には flynn scale というコマンドを使っていて、web appの個数を自由に指定できます。今回はflynn_scaleout.shを起動すると1つweb appを増やします。
⑤ 新たにweb appが起動するとZabbixにもホストの追加します。
⑥ また、flynn discoverdがweb appを発見して自動的にルーティングの対象に加えてくれます。新たにweb appが加わることで全体としての負荷は落ち着く(はずです。)

②, ③, ④ 負荷が下がってくると flynn_scalein.shが実行され web appが1台廃棄されます。
⑤ Zabbixからホスト情報の削除を行います。
⑥ そしてflynn discoverdが自動的に廃棄したweb appをルーティング対象から除外してくれます。

実験

では、実際にオートスケーリングを動かしてみましょう。
実験では1台のマシンのうえに複数台の仮想マシンを起動させました。
flynnの機能的には複数台のマシンでクラスタを組み、マシンをまたがってflynnを動作させることも可能なようです。

実験内容

web appに対してhttpリクエストを投げまくって負荷をコントロールして、負荷に応じてweb appの数が増減するかを確認します。
まず、web app用の仮想マシンを1台立ち上げた状態でZabbixに監視登録したところからスタートです。
Zabbixには, 各仮想マシンのCPU負荷の平均が30%以上になったらflynn_scaleout.shを実行させ、10%以下になったらflynn_scalein.shを実行させる設定をしています。

実験結果

結果は以下のグラフになります。
上のグラフが各仮想マシンのCPUの使用率の平均で、下のグラフが仮想マシン(web app)の台数を表しています。横軸は時間で、上下ともに同じ時間のグラフです。
何度か故意に負荷を上げたり下げたりしています。
手動で負荷を操作した箇所は「負荷追加」と「負荷削減」で、オレンジ色でラベリングしています。
下のグラフの仮想マシンの台数に関してはすべて自動的に増減しています。

オートスケーリングシステムグラフ
グラフをよく見てみると、負荷追加したときにオートスケーリングシステムが反応してapp追加が行われています。app追加によってCPUの平均使用率が減少しています。負荷削減したときには、app廃棄が行われ、CPU平均使用率が上昇しています。

いずれにしても自動的にCPU平均使用率が10%~30%に収まるようにappの追加/廃棄が行われていることが確認できました。

おわりに

過去にApache Mesosというオープンソースを使ってオートスケーリングシステムを作ってみたことがあり、そのときはLoad BalancerにHAProxyを使ったりdocker eventというdockerの機能を使って仮想マシンの生成/廃棄のイベント検知を行ったりといろいろなツールを組み合わせていました。
そのときに比べると必要なツールが少なくて楽でした

参考:http://hogepiyo.hatenablog.jp/entry/2014/07/06/172217

flynnはたまに起動しなくてもう一回手順を最初からやり直すとうまくいくとか不安定なところがあってこれからに期待です。
最初は複数マシン上でflynnを動かそうとしてましたが、途中で単体マシン上でしか動かなくなり諦めました・・。
それにしてもrouterとdiscoverdはよかったです。
自分ですると結構めんどくさい部分だったので自動的によきに計らってくれるというのはかなり楽でした。
アプリケーションの個数をコマンド一発で変えられるのもよい感じでした。なんといっても楽。
欲を言えば負荷計測機能が欲しいところです。今後に期待。

ということでflynnを使ってオートスケーリングシステムをつくってみたお話でした。
楽しんでいただけたら幸いです。


付録

オートスケーリングシステムをつくるにあたっての自作スクリプトのソースコードはこちら
https://github.com/marshi/autoscaling
(以前別の機会で作ったapache Mesos + docker用のスクリプトも入っています)