Rebuild A Podcast by Tatsuhiko Miyagawa. Talking about Tech, Software Development and Gadgets.

Nov 07
2013

25: Immutable Infrastructure (Naoya Ito, Gosuke Miyashita)

収録時間: 48:04 | Download MP3 (23.5MB)

伊藤直也さん、宮下剛輔さんをゲストに迎えて、Immutable Infrastructure, Docker, Packer, Serf などについて話しました。

0:00

miyagawa: 前回の、エピソード14のときに出てもらったお二人で、naoyaさんと mizzy さんに出てもらうことになりました。お願いします。

naoya: よろしくお願いします。

gosukenator: お願いします。

miyagawa: 前回 Docker っていうツールとか、あと mizzy さんが作ってる Serverspec とかの話でちょっと盛り上がったんですけども。それを配信したのが6月22日なんですけども、ちょうどそれの次の日の23日に、Chad Fowler さんっていう、昔 Living Social で VP of Engineering をやっていて、6Wunderkinder っていう Wunderlist っていう TODO アプリとかをそういうのを作ってるドイツの会社だと思うんですが、そこの人がブログポストを書いてて、"Immutable Infrastructure" っていうブログポストだったんですけども。

その辺りから結構この単語ですね、Immutable Infrastructure とか、Docker とかも色々バージョンアップしたり似たようなツールがどんどん出てきて盛り上がっているのを見ていて。naoyaさんがブログで、「ブログに書こうと思っている」っていうのを Twitter に書いてたりとか、mizzy さんがいいまとめの記事を書いてもらってたんで。この辺の話をちょっとしようかな、と思っております。

naoya: は~い。

gosukenator: はい。

naoya: Chad Fowler さんってあれですよね、「情熱プログラマー」の。

miyagawa: そうですね、Passionate Programer っていう、Rails 界隈では結構有名な人で。

naoya: あれっすよね、皇居の周りを一緒にマラソンする OO マラソンっていうのがあって。

miyagawa: Rubykaigi のときとか?

naoya: そうっすね。Chad Fowler さんが走りながらオブジェクト指向の話をするってのがあって。結構有名人らしいっすね。

miyagawa: うん。Railsconf とかに僕も去年、今年と行ったんですけど、去年まで Railsconf の chair みたいなのもやってて。結構 Ruby 関係では人気者という感じですね。ただ、この DevOps 関係ではそういう界隈の人ではなかったんですけど、このブログポストからそういう話題が盛り上がってきたので。引き合いに出されることが最近はちょっと多いですね。

naoya: Agile とかそっち方面の人かな、と思ってたら突然この人がこういうこと言い始めてちょっとびっくり、みたいな。

2:25

miyagawa: mizzy さんのこのポスト、結構よくまとまってたんで。

gosukenator: そうですね、はい。

miyagawa: この辺りから話を始めてみようと思ってるんですけども。

gosukenator: まず、この辺りの話をするときに、ブログポストに書いたように、プロビジョニングを3つのレイヤーに分けるとわかりやすいかなっていうのがあって。その辺りの説明をさせてもらっていいですかね?

miyagawa: そうですね。

gosukenator: はい、じゃあ、まずそこからなんですけど、これは別にプロビジョニングのレイヤーと言っても僕が考えたものじゃなくて、2010年の Velocity での Lee Thompson さんっていう方のプレゼンにあった資料から引っ張ってきてるものなんですけれども。一口にプロビジョニングと言っても、まず一番下のレイヤーで Bootstrapping といって OS インストールする領域。それから、次のレイヤーとして Configuration といって、いわゆる Puppet や Chef がやるようなミドルウェアのインストールとか設定とかそういった領域があって、更にその上に Fabric とか Capistrano を使ったようなアプリケーションのデプロイだったりロードバランサーの設定だったりとか、システムを有機的に結合するためのレイヤーみたいな。

そういった3つのレイヤーに分けられますよ、みたいな話をしてたのがそのプレゼンの内容ですね。で、特に Configuration と Orchestration って結構分離しにくいというか、どっからどこまでが Configuration でどっからどこまでが Orchestration なのかっていうのが割とわかりにくいんですけども。Configuration はスタティックな領域で、Orchestration はダイナミックな領域っていう風に考えると整理しやすいのかな、って考えてます。

miyagawa: なんか、僕はnaoyaさんの Chef 本を読んで、自分の個人的なサービスとかをデプロイするのに使ってたんですけど、Chef だと Orchestration っていう部分がアトリビュートとかノードのロールとか、色んなやり方があって。

naoya: はいはい。

miyagawa: 結構その辺が、初めてやろうとするとやり方がありすぎてわかりづらいってことを Twitter とかで文句言ってたんですけど。

gosukenator: ありますね、まさに。そこはもう向いてない領域ですよね、このレイヤーの分け方から見ても。

miyagawa: うん。

naoya: あれですかね、Orchestration って言った時のスコープ、入る範囲って道具も入るんですかね?例えば Chef だと Knife-solo とか、あるいは Chef-Server だとサーバー・クライアントみたいなモデルあるけど。そこまで含めて Orchestration なんですかね。

gosukenator: どうなんでしょうねぇ。

naoya: Serf が Orchestration ツールって言ってるけど、Chef で書いたコンフィグレーションをまいたりするのは Orchestration なのかそこは別の名前なのかちょっとわかってないんですけど。

gosukenator: そこは割と境目くらいの領域な感じもしますし、どっちに入るかって難しいですね。

miyagawa: このブログポストだと Fabric とか Capistrano が Orchestration っていう風に書いてあるんですけど、僕のイメージは Capistrano ってすごくアプリケーションとか Rails とか Web サーバー、アプリケーションのレイヤーにのったコードをまく、みたいなイメージがあるので、あんまり Orchestration 的な印象を僕は持ってないんですけども。mizzy さんのこれを見た時に Orchestration っていってるのは、どの辺の側面になるんですかね?

gosukenator: 先程も言ったように、僕のは大雑把に、スタティックとダイナミックっていう風に考えていて、アプリケーションとかは更新頻度とかも多いんで、ダイナミックの方に入るから上のほうかな、って考えてます。

6:02

miyagawa: 僕、今仕事で Capistrano とか使ってデプロイはするんですけども、サーバーのリストとかは動的に変わるものなので、Capistrano の設定ファイルに IP アドレスとかを直書きするわけにはいかなくて。

gosukenator: はいはい。

miyagawa: で、使ってるツールが、EC2 のインスタンスにタグをつけるツールを使って、アプリケーションのサーバーの一覧をデプロイするときに取ってきて、動的にホストのリストとかを組み立ててデプロイしてるので。多分そういう風にツールと組み合わせると Capistrano がやってることが Orchestration、サーバーのリストとかを動的に更新していく、ってとこに当てはまっていく感じなんですかね。

gosukenator: あぁ、そうですね、そういうイメージですね。

naoya: そうすると、そもそも Orchestration っていうのは、サーバーのリストとかサーバー全体のなかで持ってる動的な状態を管理する部分が Orchestration って感じなんですかね。

gosukenator: そんな感じになると思います。

naoya: なんか、Orchestration って馴染みがあんまりない言葉っていうのと、大規模インフラを運用してないといまいちピンとこない領域ではありますよね。

gosukenator: そうですね。なので、Configuration はすごくわかりやすいんですけれども。最初に「境目があいまい」って言ったのはそういうのもあったりとか。僕自身も Orchestration の定義ってはっきりわかってるわけじゃなくて。このレイヤーの分け方を見て、おそらくそういうことなのかな、っていう考えを持ってるって感じですね。

naoya: 僕、Orchestration って、Ansible ってツールのドキュメントで初めてその言葉を見て。

gosukenator: あぁ、なるほど。

naoya: あれがその、いわゆる「デプロイ」というか、実行のことを「オーケストなんとか~」とか言ってるんですよね。そもそも。あの辺から始まった言葉なのか、そもそもそれより前からずっと DevOps 界隈で使われた言葉なのか、いまいちよくわかってないけど。ほんと最近聞くようになって、抽象的な言葉だなぁ、と思って聞いてはいましたね。

miyagawa: 前回のポッドキャストでは結構 Docker が出始めだったこともあって、VM に代わるというか、Vagrant とかで VM を作っていちいち毎回プロビジョニングするというよりも、Docker みたいな lightweight なツールを使って、例えば CI をやるときに早くしたりだとか、Serverspec みたいなものをテストするときに既に動いてる VM を使うんじゃなくて1個1個スナップショットを取った状態から Docker を使って Serverspec のテストをする、とかいうような使い方があるよね、みたいな話でちょっと盛り上がったと思うんですけど。つまり VM の軽量な代替品のような形で話を結構してたと思うんですよね。

ただ、この Chad さんの Immutable Infrastructure とかの話とか、あるいは Docker 界隈も色んなエコシステムみたいなのが出来てきて。結構、Docker で作ったコンテナそのままデプロイすればいいんじゃないの!?みたいな感じの考え方もあって。それをやってるよ、みたいなブログポストもポツポツ見るようになってきたなぁ、ていう印象があるんですけど。その辺の考え方ってこないだ話してた時と変わりました?見方とか。

09:20

naoya: もう1つブログのポストで、「Immutable Infrastructure について」っていう、apatheia.info っていうブログの人が書いているんだけども。Immutable Infrastructure って…あっ、Immutable Infrastructure の話をそもそもまだしてない。

miyagawa: そうね、そこの話をまずしましょうかね。

naoya: Immutable Infrastructure っていうのは、まず Immutable っていうので「不変なインフラストラクチャ」っていう意味なんだけど。文字どおり「サーバーを不変にする」って意味ではなくて、オペレーションを不変にして1回プロビジョニング、セットアップしてしまったサーバーは2度とそこに変更を加えないっていう前提でインフラを運用していくって話で。

で、なんでそんなことをするのかって言うと、冪等性とかと関係があって。Chef とか Puppet とかって、サーバーの状態が色々変わってくっての前提にツールがあるけど、そもそもその状態が固定化されてるんだったら、冪等性とか管理する必要ないよね、って。で、その前提で全体を管理できれば運用負荷が下がったりとか、もっと簡単に障害やサーバーを増やしたりとか対応できたりとか。直感的には、サーバーが変わらなければ横にサーバーをコピーしていくのとかすごい簡単だし。みんな理解できると思うんだけど。それを実際にやったらどうなるかっていうのをみんなコンセプトに合わせて色々やってるってかんじですよね。

miyagawa: うん。

naoya: で、その Immutable Infrastructure をどうやるかっていうなかに、この Blue Green Deployment っていうテクニックがあって。Blue Green Deployment もあんまり有名じゃないのかな。

miyagawa: 名前はあんまり聞いたことないですけどね。

naoya: これ、僕は Amazon Re:Invent で Amazon の CTO の人が「1時間に1000回デプロイしてる」みたいな話をしたことがあって。去年かな。そのときに知ったんですけど。要するに、サーバーに新しくソフトウェアをデプロイするときに Capistrano とかを使って今あるサーバーに上書きするんじゃなくて、クラウドなんだから今動いてるのとまったく同じコピーをどかーんと立ち上げちゃって。で、そっちであれこれやって全部準備が済んだらロードバランサーとかをかちゃっと切り替えて、これでデプロイ完了にしちゃえば、例えばそのデプロイが失敗してたら1つ前の環境にロードバランサー戻せばすぐ戻せるし、そうやって同時並行で立ち上げちゃうんで、途中でサーバーの状態が中途半端になってるとかなくなるから、絶対こっちのほうがいいよね、って話があったんですよ。

そういうのが前段としてあって。で、じゃあ Blue Green Deployment を自分でやろうと思った時に「そこを自動化してなんたらかんたら」って考えると、あんまり現実的じゃないなぁ、と思ってたのが、Docker とかだとコンテナが一瞬で立ち上がるし、mizzy さんも書いてたけど、ローカルで動かしたコンテナをそのままチョクで転送して立ち上げるだけで動いてくれるから、そういうのをやるのに現実的だよねっと思って。もしかしたらこれプロダクションに使えるかもな、みたいな感じでしたね。

12:28

gosukenator: そうですね。この辺は、今は Immutable Infrastructure って言ってるのって Amazon の話だったりとかのように「VM を別に立ち上げてロードバランサーで向きを切り替える」みたいなやり方が主流で、コンテナの話ってまだそんなに見つからなくてですね。コンテナとかデプロイで検索すると、Java の話ばっかり出てきて。まだ「コンテナデプロイ」ってのはまだそれほど実際やってるとことかないのかな、っていうイメージですね。で、VM で切り替えるやり方は、資料をあさってみると2011年に Netflix の人が発表した資料とかでも既に触れられたりとかしてて。

naoya: あぁ、そうそうそうそう。

gosukenator: そうですよね。Netflix はその辺先進的な取り組みをしているなぁ、という感じはありますね。

naoya: Amazon の Elastic Beanstalk に、ロードバランサーを切り替えるんじゃなくて、コンテナをバコッと立ち上げといてそのコンテナの準備が済んだら、「ここの URL はこっちのコンテナに割り振る」みたいなことが設定で出来る項目があるんすよ。Environment って言って。

gosukenator: へぇ~。

naoya: だから、それを使うとコンテナベースで git push するだけで立ち上げられて、カジュアルに新しいインフラを作れて、しかもトラフィックの向き先をIPアドレスとかロードバランサーみたいな大げさな仕組みじゃなくて設定でかちゃっと切り替える、ことが出来るようになってるんすよね。2011年に Netflix が言ってた時ってのは、やっぱり VM ベースで頑張ってて、多分浮動IPとか使って切り替えましょって話なんだけど。それをもっとプログラマブルにやるにはやっぱりコンテナが後ろにあってもっとカジュアルに上げ下げできて、っていうのが必要なんじゃないかなっていうのが最近の感覚って感じはしますね。

miyagawa: うん。やっぱ、Elastic Beanstalk とかも「AWS がやってる PaaS でしょ」みたいな印象が多分あったと思うんすけど。PaaS 固有の制限というか、Heroku とか僕がいた dotCloud とかみたいに、やってることって git push したらコード取ってきて Capistrano deploy のようなことをして、依存性を解決して立ち上げるサーバーのプロセスを決めて Linux コンテナーを立ち上げてロードバランサーの向き先を変える、っていうのがほとんどやってることなんですけど。

それと従来のデプロイ方法とのギャップを埋めるツールが今まであんまりなかったんで、手動で AMI を作ってシコシコやってロードバランサー切り替えたりとかいうのをやってたりしたんですけど。そこのギャップを埋めるツールとしての Docker とかが出てきてるっていうのは、Docker って元々 dotCloud の基盤であったような LXC のツールとかをオープンソース化したものっていう印象が強いんで、そこにちょうどフィットする形にはなってるのかなぁ、っていう印象はありますね。

naoya: そうですね、うん。大体そういう感じです。だから、テストとかだけじゃなくて本番にも使うっていう人がちょこちょこ出てくるっていうのは必然的な流れかもしれないですね。

15:38

miyagawa: なんか、自分がいたときにあんまり気づかなかったような、Platform as a Service で作ってるとどうしてもコンテナが毎回破棄されちゃうんでデバッグがしづらいとか、ログファイルとかは全部外に出さないといけないとか、ローカルのファイルシステム触っても次デプロイすると消えちゃうとか。そういうのが Platform as a Service の制約だなぁ、っていう風に思いながらやってて、それのために使えないツールとかも結構あったんですけど。

それが逆にむしろ強みというか、そういう制約のなかでアプリケーション、インフラをデザインしていくことによって、Chad さんのブログポストのもう1個のタイトルは "Immutable Infrastructure and Disposable Components" っていう、使い捨てのコンポーネントっていう側面っていうのが、そういう制約があることによっていい意味で強制されちゃうっていう。そういう気がしましたね。

naoya: そうなんですよね。そこがかなり大事で。要するに Travis とかはそういうのを使って、使い捨ての環境っていうのに自分たちの行動が制限されるっていうのが逆に快適っていう部分があるじゃないですか。テストにあんまり状態を持たせないで1回でサーバーが破棄されるなかでテストサイクルを完成させると、そもそもアプリケーションがその前提に乗ってるとポータブルになる、みたいな。そもそも自分たちのシステムをそういうものにしてしまって、全体の Agility を上げましょうっていう話だと思うんですよね。

miyagawa: うん。結局 Jenkins とかもね、僕が今見てる環境だとそういう使い捨てまでは行ってないので。EC2 とかの上で動いてるんですけど、毎回立ち上げて破棄して、とかはやってないから。「このサーバーの Jenkins だけコケる」とかいうのが大体あるんですよ。

naoya: あー、そうそう。あるんですよ。

miyagawa: このテストをプッシュすると Jenkins の02だけコケる、とかいって。だからこいつを1回リブートして、とか言ってるんで。そういうのが毎回立ち上げ直せばいらないよね、っていうのが1つだし、かと言って毎回立ち上げてるとビルドするための時間とかコストとかがバカにならないんで、スナップショットをとって Docker みたいなのでローカルで作ったものを転送して動かす、みたいなことをすると、ツール的な部分で効率がちょっとよくなるっていう。そういうメリットがありそうですよ。

naoya: ありますね。

18:01

miyagawa: 実際問題、本番環境に向けて作る、そういう disposable なものを考えた時に、出来るのって今の時点だとアプリケーションサーバーくらいかなぁ、っていう。

naoya: まあそうでしょうね、現時点だと。要するに、データベースみたいにストレージ持っててそっちに状態がある、みたいな感じだとこういう管理が結構難しいし。あと memcached とかね、デプロイして捨てられたら困っちゃうみたいなこともあるし。

miyagawa: でも、memcached はちゃんと使ってればキャッシュは消えても大丈夫なはずだから。

naoya: (笑)まあ、それはそもそも memcached をそういう使い方してるのが間違いっていうのがあるんだけども。

miyagawa: そうそうそう。要は memcached とか Cassandra とかみたいに、もとから分散されることが前提のプロトコルだと割とノードを動的に追加して削除してってのがしやすいとは思うので。普通のリレーショナルデータベースとかに比べるとしやすいから。あるノードを殺してまたデプロイして、みたいなのがしやすいかなとは思うんですけど。

naoya: 本来はそういう話なんですけどね。そこで Serf ってことですか、次。

miyagawa: そういうことなのかな。

naoya: Serf の話はもうしちゃっていいのかな。

19:18

miyagawa: そうですね、ちょっとペースが速いですけど。Serf も Hashicorp という、Vagrant を作ってる Mitchell Hashimoto さんがやってるビジネスなんですけども、そこがオープンソースで出してるツールが3つあって、Vagrant と Packer と Serf。最後のが最近出たやつですね。

で、僕が見た感じ Packer は結構 Docker とレイヤーがカブるツールかな、って印象なんですけども。あまり詳しく見たわけではないので。

naoya: Packer、僕の印象では、要するに VM の初期設定みたいなコンフィグレーションを JSON に落としこんで Vagrant みたいにポータブルに扱いましょうって感じですよね。目的としては VM を立ち上げるまでを全部自動化するためのツールなんですけど。そこはただ、これまでも AWS だと AMI を自動作成するツールとかそういうのもあったんで、そんなに珍しい領域ではなかったんですよね。

ただ、僕は Serf が出てきて Hashimoto さんが本当に考えてたことがよくわかった、みたいなのがあって。あれも要するに、VM ベースの Immutable Infrastructure を実現するためのツールとして Packer を彼は作っていて、Serf ってのはそれをコンテナベースで実現するために必要な部品として作ってるよっていう。そういう全体の構想があの会社にはある感じなんですよね。

miyagawa: mizzy さん ブログポストでこの Packer についても触れてますけど。

gosukenator: そうですね。Packer は VM 作るツールなんで、Docker との関係でいうと、Packer で作った VM イメージをそのまま Docker で動かしたりとか出来るんじゃないかなぁ、とか考えてはいますね。まだ試してはいないし、KVM のイメージとかって Packer が対応したのって昨日一昨日とかにマージされたコードで出来るようになったって感じなので。僕は、最初の VM 作るときに「どうしよう」って感じがあるので、そこは Packer をうまく使うといいのかなって考えてはいますね。

miyagawa: 基本的にはこれは、抽象化のレイヤーが、レイヤーにレイヤーを重ねていくみたいなイメージで、また Packer が Vagrant の上に、いや並列?

naoya: Vagrant と Packer ね、ちょっとレイヤーが違ってて、実際には多分 Vagrant と組み合わせると Packer の方が下になるんですよね。Packer が作った VM イメージを Vagrant で立ち上げる、みたいなのが VM の場合だから。

miyagawa: なるほど。それは EC2 とか Vagrant とかをちょっと抽象化して下のレイヤーで Packer で作れるって感じですかね。

naoya: そうなんすよね。で、Packer が目指してるのは、相手が EC2 だろうか Rackspace だろうが VirtualBox だろうが、同じ手続きで VM の状態を定義できるっていうのが Packer のユニバーサルなインターフェースなんで。それの吐き先が Docker コンテナってことになれば、「Docker に対応する」ってことになるし、それは多分今も出来るかもしれないけど、普通に考えてそうですよね。

gosukenator: そうですね。

naoya: そうすると、Dockerfile を使わずに、Packer で Docker イメージを作り出すとか出来るようになるってことかな。

gosukenator: あー、はいはい。

22:46

miyagawa: この辺の、ベースイメージを持ってきたあとどうやってプロビジョニングしていくかっていうのが、Chef みたいなコンフィグレーションマネージメントツールを使って冪等性とかを考慮しながら色んなものをアプライしていく従来のツールと、使い捨て前提で Dockerfile みたいに順番に上からコマンドをずらずらかいていって、差分とかがあれば diff を当ててとか新しいファイルをコピーする、みたいな単純なツールと。毎回使い捨てでやるってことが前提になると、Chef みたいな言ってしまえば「大げさ」なツールはいらなくて、上からコマンド流していって出来たバイナリを放り投げるほうが楽じゃん、みたいな考え方はありますよね。

naoya: ありますね。ただ、僕の個人的な感覚で言うと、Chef の冪等性を担保するみたいな部分は、使い捨てベースになるとオーバースペックなんだけど、Chef が重要なのってそこだけじゃなくて、インフラのプロビジョニングを全部にコードにして GitHub とかで管理できるってのがものすごく大きいわけですよね。

で、Dockerfile とか使ってると、あれはただのシェルスクリプトに相当してるから、全然スクリプトも構造化できてなくて。コード書いててほんとに、昔インフラでやってた、ただの自動化のスクリプト書いてるだけじゃん、っていう感覚があってかなり後戻りしてる感じがあるんですよ。だからそこの間を埋める道具が出てくるか、Chef とか Puppet をそういうことに使うかどっちかだな、と思ってますね。だから Dockerfile 直で書くっていうのは、ほんとにプロダクションでやるときは僕はやらないと思いますね。

gosukenator: 僕も、Dockerfile と Chef/Puppet みたいなものの間みたいなツールが出てくるんじゃないかな、と思っていて、それが Immutable ってことを前提にすることでそういうツールが作れるんじゃないかな、と思っていて。Immutable ってこと前提にすると、先ほどから出てる冪等性とか、あと Puppet を使っていてすごく困るのが、依存関係を定義してあげないと、「先をこっちに入れて次にこれを順番でいれないと入らない」ってところは自分で定義してあげないといけなくて、その辺の制御っていうのがすごく面倒だったりするんですね。でも、Immutable なもの前提にして、まっさらな状態から当てるだけって考えれば、当てる順番だけ制御できればいいんでその辺は楽になるのかなってところとか。

あと、Chef/Puppet って削除するのが苦手だと思うんですよね。一時的に必要で入れたものとかを後からいらなくなったから削除、みたいなのが結構やりづらいというか、そこの管理がすごくしづらいなってのあるんですけど。Immutable を前提にしてまっさらなところからやることで、その辺を考えなくてもよくなるってメリットはあるかな、と。

naoya: そうっすね。だから、そういう新しいプロビジョニングのなんかが出てくるかもしれないし、Chef とか Puppet からそういう機能削ったもっと lightweight な、コードは一緒だけどもっと簡単に使えるよってものを誰かが作るかもしれないし。

gosukenator: そうですね。

naoya: 多分そういう感じです。コンテナベースがほんとに未来になるならっていう。

miyagawa: なんか Chef はコードっぽさはあるんだけども、コードっぽさが行き過ぎてる感はちょっとあって。GitHub とかで Chef のレシピ、Cookbook を拾ってくると、設定するアトリビュートとかやたら山のようにあって。

naoya: そうそうそう。

miyagawa: 「俺はただこのコマンドを入れたいだけなんだぞ」っていう。

naoya: それはありますよね。

miyagawa: すごいイラつきますよね。

naoya: 僕、Chef の Cookbook はコミュニティのやつほぼ使わないですからね。大体冗長だから。

miyagawa: 大体いちから書いちゃうわけでしょ?

naoya: そうそう。ただ、いちから書くっていうときに、それを僕はやってるから、なおのことプロビジョニングフレームワークみたいなのがないとちょっとやってらんないな、って感じはありますね。要するに、対象のディストリビューションが apt なのか yum なのかとかで区別してスクリプト書いたりとかもうやりたくないし。パッケージコマンドで書きたいし、とかね。色々ありますよね。

26:50

miyagawa: Serf の話はちょろちょろ名前は出てきてますけどあんまりちゃんと話してないんで、ちょっと話をしてみたいんですけど。これはどういうツールですかね?

naoya: これはどっちが喋ったらいいかな?

gosukenator: これは僕は naoya さんが喋るべきだと思います。

miyagawa: (笑)

naoya: (笑)一応ね、ひと通り触ったんで。Serfは、僕も最初よくわかんなかったんですよ。Packer とか Vagrant ってすごくわかりやすいじゃないですか、動かすと VM が出来るとか。そういうのではなくて、さっき冒頭にあがった Orchestration の一番わかりづらいところを面倒見るツールで。Serf 自体が持ってるツールっていうのは、クラスタを構成するクラスタリングの仕組みと、そのクラスタのなかに命令というか、イベントを発行してそれを全クラスタに伝搬させるっていうその2つしか機能がないんですよね。

で、それだけ聞くと「何に使えるの?」って感じなんですけど、例えばロードバランサーの下にぶら下がってる Web サーバー郡っていうのを、Serf でクラスタにしておいて、その Web クラスタにマシンが1個追加された、障害で落ちたとかいうイベントを Serf は拾うことができる。そうすると、ロードバランサー自身がマシンの一覧を自分で管理しなくても、Serf 側で「クラスタにノードが追加された、削除された」っていう情報を感知して自分自身のマシン一覧みたいなのをアップデートできるようになって自律して動けるようになるわけですよ。

で、今まではロードバランサーとかにマシンリストみたいなのが組み込まれてて、マシンが増減するとデプロイツールとか使ってその設定を書き換えてたわけですよね。それがロードバランサーだけじゃなくて色んなところにあって、例えば memcached のサーバーリストとか、あるいは LVS とか keepalived が監視してるノード一覧とか munin とかが監視してるノード一覧とか。そういう、マシンが増減するたびにデプロイツールを動かさなきゃいけない、みたいなのがあって、それがいわゆる Immutable Infrastructure とものすごく相性が悪いんですよね。サーバーのなかに状態があるから、それを書き換えるために Chef を動かさなきゃいけなくて、そのために冪等性が必要だったりとか。

だから、そこを全部取り除いちゃえば状態を持ってるサーバーが減るので、コンテナをまるっと作って捨てるみたいなことがやりやすくなるよね、っていうのが多分 Serf のコンセプトですね。

miyagawa: もし Chef とか Puppet とかでやろうと思うと、サーバーが増えたらサーバーを管理してるノードのバリューとかを追加してデプロイ全部しなおしとか、そういうことになっちゃうのを避けようっていうことですね。

29:40

naoya: あぁ、そうそう。でその Serf のクラスタを構成するプロトコル で Gossip Protocol ってのが Cassandra とかでも使われてて、memcached にある consistent hashing とかああいうのがやってるユースケースと似てて。プロトコルの内容は全然違うんだけど、要するに decentralized で中央集権なサーバーが1個もなくて、マシン追加すると Gossip Protocol なら一定の確率で「クラスタに入れましたよ」ってのを伝搬することで、全クラスタが「どこに誰がいるか」がわかるっていうプロトコルなんですけど。それを使うことによって、中央集権なサーバーもなければ、イベントだけで全部が管理できるというか、そういう感じになってるんすよ。

ただ、ロードバランサーが、とかいったらちょっと大げさだけど、antipop さんがこないだ面白いの作ってて、自分のネットワークにあるホスト一覧みたいなのを DNS で使わないでホスト名だけでアクセスできるようにするっていうのを書いてて。要は Serf で自分の扱ってるマシン全部をクラスタにしといて、マシンが入るたびに自分のIPアドレスとホスト名を各サーバーが自分自身の /etc/hosts みたいのに書き込む、みたいな。そういうのを、Perl のスクリプトで10行くらいで書いてたけど。そういうことを簡単に出来るようにするのが Serf っていうツールですね。

gosukenator: 僕、その Serf によって、最初に話したプロビジョニングのレイヤー分けがすごくわかりやすくなるんじゃないかなぁ、と思っていて。Immutable な部分を作るのが Configuration Management の領域で、Serf でやれるところが Orchestration の領域っていう風にきれいに分けることができるんじゃないかなぁ、っていう風に考えていて。そこがすごくやりやすくなるんじゃないかな、って。

naoya さんの話にあったように動的に変わる部分で、例えばサーバー増やして nagios や munin の監視対象に入れる、みたいなところも、今うちだと新しいサービスだと自動で EC2 の API 使ってとかやってるところもあるんだけど、古いサービスだとそんなにサーバーもしょっちゅう増減するわけじゃないんで、もう Puppet とかでその辺のファイルも管理して、新しくサーバーが増えたら Puppet で管理してるファイル書き換えて Puppet 流し込むみたいなことをやってるんですけども。

その辺も実際は Orchestration の領域になるんで、あんまり Puppet や Chef でやるような領域じゃないと思っていて。そこは Serf によってすごくやりやすくなって、そっちに任せることによって Puppet や Chef の Manifest やレシピもより運用しやすく管理しやすくなっていくんじゃないかな、っていう風には考えてますね。

32:15

miyagawa: なんか、似たようなツールに Zookeeper とかあると思うんですけど、どういう違いがあるんですかね?

naoya: 僕あんま Zookeeper 詳しくないんだけど、書いてましたね Zookeeper vs Serf って。

miyagawa: ページはありますね。

gosukenator: はい。etcd とか。

miyagawa: レイヤーとしては同じっていう認識でいいんですかね?

naoya: 一応 "vs" って言ってるくらいだから同じなのかなぁ(笑)

gosukenator: (笑)比較ページ見た感じだと、Zookeeper とかは中央集権型みたいな。

naoya: そうだ、そんなこと書いてあった。

gosukenator: そういう違いはあるみたいなことは書いてあって。で Serf は分散・協調して eventually consistent で、みたいなそんな話が書いてありますね。

naoya: 結局、中央集権システムみたいなの作っちゃうと、当然そこが Single Point of Failure になっちゃうっていう問題もあるし、あとはそこが状態を管理してるに等しいんで、結局 Immutable じゃないじゃん、っていう話なんですよね。だから、Immutable Infrastructure をやるには、decentralized な管理システムってのが大前提になってくるんで、そういう意味でも Serf ってのは Zookeeper とは違うんだ、ってことは言いたいんでしょうね。

miyagawa: なるほど。てことは実際に Serf とかを使って運用するとかってなった時に、実際のサーバーのコンフィグレーションであったりとか、memcached の一覧を Serf とかで管理したりして、アプリケーションからのつなぎ先を動的に変えるみたいなインテグレーションみたいなのはどういう形になるんすかね?

naoya: えーっとね、実際にそれを書こうと思ったら、Serf って起動するときにシェルスクリプトのパスを1本渡せるんですよ。そこにイベントの名前が普通にただの標準入力でテキストで渡ってくるんですよね。それを Perl とか Ruby とかで読んで、正規表現でマッチさせて自分のアクション書く、みたいな感じですけど。そう、Serf はそういうツールとのインテグレーションのところまでは面倒見ないですよね、今のところは。

ただ、mizzy さんも書いてたけど、プラグインの仕組みとかを今後用意するって Serf のプロジェクトロードマップに書いてるんで、だからそこのプラグインディレクトリに Serf-memcached とか Serf-HAproxy とか、そういうのがいっぱい追加されてコミュニティの人が書いた robust なテスト済みのイベントハンドラーみたいなのがあるから、それを使えばコード書くのが嫌な人も Serf で簡単に管理できるよ、って将来なるんじゃないかな、と。

miyagawa: うーん。

naoya: 実際書いてますね。"serf plugin install haproxy" とかいうコマンドを提供するつもり。

gosukenator: あ、もうあるんですね。

naoya: いや、まだないです。そういうコマンドを提供するつもりだよってロードマップに書いてるんで。実際これでそういうことが出来るようになるんじゃないかな、と。

miyagawa: あれですね、Heroku とかでアドオンとかを使って memcached とか Redis みたいなのを使おうとすると、大体アドオンが勝手に設定されて Redis の URL とかホスト名とかパスワードとかが環境変数に渡ってきた状態でコンテナが起動する、みたいなのが普通なんで。多分その考え方、パラダイムと結構相性がいいかな、と思って。Serf とかでイベント受けとったら環境変数を変えて立ち上げ直す、とか。そういう風にするだけでほとんどアプリケーション側のことはいじらなくてもいい、みたいな運用の仕方がもしかしたら出来る感じなのかな、っていう感じがします。

35:48

naoya: Serf ちょっと面白いのが、Gossip Protocol とイベントハンドラーをコマンドで渡すっていうだけなんで、全然 DevOps とかじゃない分野にも色々遊びで使えるんじゃないかとちょっと思ってて。昨日知り合いと話してたんですけど、勤怠管理システムってあるじゃないですか。会社に来た時に WiFi につないだら出社したことになる、とかいうハックをしてる人たちがいるんだけれど、Serf もね、クラスタがどっかにジョインしたらそれが「ジョインした」っていうイベントがとれるから、例えば会社のネットワークに Serf のエージェントでジョインするようにしといて、Serf ジョインしたらスクリプト動かして「出勤しました」ってことにするとか。

とにかく、複数のノードがあってそこに参加とか、そっから抜けたみたいなイベントを取ってなんかしたいみたいなアプリケーションに。多分何にでも応用できるんですよね。そういうすごい薄い仕組みになってるっていうのがすごくいいなぁと思って。面白かったですね。

miyagawa: これも Go で書かれてるんですよね。

naoya: これも Go ですね。

miyagawa: 最近 Mitchell さんは Packer とかほとんど全部 Go で書いてるみたいですね。

naoya: そうそう。この DevOps 界隈での Go ブームっていうのが来てるっぽいっすね。

miyagawa: やっぱりそういうところと相性がすごく良さそうですよね。シェルスクリプトで書くよりももっと堅牢に書けるし。

naoya: そうですね。あと、ポータブルですからね。クロスコンパイルである程度サポートできるんで。

miyagawa: そうですよね。Go の話は先週のエピソード24で話してるので、聞き逃してる方はそれも聞いてみてください。

37:30

naoya: ただ、今まで Immutable Infrastructure とかコンテナベースのが、ってのを語ってきましたけど、実際にやろうとするとまだまだ課題はたくさんあってですね。Docker でやってる人もいるって言うけど、結構アグレッシブだな、っていうのが僕の印象で。例えば Docker って、プロセス立ち上げるとなかで普通の Linux サーバーで動いてるようなプロセスが一切動いてないじゃないですか。

で、自分が指定したプロセスだけが立ち上がるっていう。ほんとにそれで長時間サーバーを動かし続けて問題ないのかとか、まだまだよくわからないし。あと、Docker 自身がすごく API が変わりまくってるんで、そういうのに追従していくるのどうするんだ、とか。Serf でやるのいいけどそのイベントハンドラーのスクリプト誰が書くんだ、とか。まだまだ結構あるんですよね、いろんなのが。

gosukenator: プロセス自体は /sbin/init とかも起動できるんで、同じようにすることも出来るっちゃできますね。

naoya: でも、そういうの含め、「詳しい人しか触るの危険」みたいな状態ではあります。

gosukenator: ありますね。あと、結構ハマりどころも多くて。一見普通の VM のように見えるんだけど、やっぱりコンテナ型と Hypervisor 型って全然動きが違うんで、同じように考えてるとものすごくハマりますね。

naoya: そうっすね。その辺含めてまだノウハウないし、色々やんなきゃいけないことあるな、と。ただ、全体としてはそっちの方向にみんな向かっていってるっていうのがこの半年くらいの流れで、これが止まることはないから「将来的にはこういうことになるんだろうな」っていうくらいの感じで見てますね。

39:05

miyagawa: Docker はこないだ会社名が元々 dotCloud だったのを Docker に変えたみたいで、そっちに主軸を置いてやっていくっていうピボットをしたみたいなんですけど。こないだも話しましたけど、やっぱりすごくそういう流れにピッタリあった時にツールを出してきたってイメージがあるので。LXC のラッパーみたいなもんじゃん、っていう考え方もできるんですけど、こういう統一的なツールとかエコシステムを構築するっていうのは黎明期においてはすごく重要なんで。そこをうまいタイミングだったな、と思いますね。

naoya: それはありますね。で、エンドユーザーから見た場合に、コンテナベースでとか Immutable Infrastructure とか言ってるけどそれ Heroku 使えばそれでいいんじゃないの?、みたいな(笑)

gosukenator: (笑)

miyagawa: そうそうそう(笑)

naoya: そういうとこちょっとあって、そことの住み分けをどういう風にしてくんだろうな、とか。要するに、オンプレミスとか大規模すぎて AWS とかに全部任せらんないみたいな人たちがこういうのやるなら嬉しいかもしれないけど、個人ユーザーみたいな小規模なシステムの面倒みてる人にとっては「大げさな話しかない」みたいなところもあるんで。そういうのを、もっとツールがカジュアルに色んなものを提供して、「自分でこういうのやっても結構いいよ」っていう状態になるまでもう少し時間かかりそうだな、っていう風には見てますね。

miyagawa: Platform as a Service のサービス側を運用している方の問題点としては、個人がパパっと作ったものをデプロイするのに Heroku とかはものすごくいい環境なんですけど、サービスがスケールしていくにつれて、卒業していって自分で EC2 とかで運用する、みたいな方に行ってしまうっていうのが結構あったんですけども。

そういう意味でも、Heroku とかに向けて作るには制約とかが出てきて、毎回毎回インスタンスが破棄されるとかそういう特性をうまく引き継いだままスケールさせるってところに Docker の面白いとこもあるかな、っていう気はするんですけどね。

naoya: だから、逆のパターンがあるかもしれないですね。Docker とかでローカルで作っておいて、Docker 対応の PaaS にボコっと乗せて。本番の運用のときは自分たちの Docker を使わずにどっかから、いや、「どっか」って洒落じゃないですけど(笑)

gosukenator: (笑)

miyagawa: (笑)

naoya: どこかでやってる Docker ベースのサービスにデプロイしちゃう、みたいな。そういうのが一番 Win-Win なモデルって感じがしますね。

miyagawa: そうですよね。スケールアップ、dotCloud とか Heroku から自分のとこにスケールアップするのもありだし、スケールダウンさせるっていうのもありだと思うしね。

naoya: そうそうそう。とにかく、アプリケーションがポータブルになってインフラもポータブルになると、やれることが色々増えるわけだから。そこまで頑張ってみんな道具作りましょう、みたいなフェーズに来たのかな、と。

miyagawa: こないだのポッドキャストのときも Docker って話したときに、それが「Docker」なのか「どこか」なのかってわからん、っていうツッコミが結構ありました。

naoya: (笑)

miyagawa: だいぶ中身が濃い感じでやってきたんで、50分くらいでちょうどいい感じではありますけども。

naoya: インフラの話はしゃべり始めるとあっちこっちに話題が広がっていって話が止まんないっていう問題がありますね。

miyagawa: ありますね。今日紹介した URL とかリンクの一覧は、rebuild.fm/25 からリンクしてるので、そこをチェックしてください。

42:44

naoya: あ、Chaos Monkey の話をしてないな、そういえば。これもまた今度かな。

miyagawa: なんかね、データベースとかストレージが入ってくると難しいよね、って話さっきしたんですけど。Food Fight Show っていう DevOps のポッドキャストで Immutable Infrastructure の話をしてた回を聞いたら、MySQL でもあれをやってるぜ、っていう人がいて。

どうやってやるかというと、毎日スナップショットを取って、新しいノードを立ち上げてスナップショットをロードして、レプリケーションにオートジョインさせてマスターを Chaos Monkey 的な形で殺すと。でフェイルオーバーさせて、マスターの古いインスタンスは破棄して、新しくマスターに昇格したやつをマスターにして、っていう感じでやってたんで。Chaos Monkey 的な「いらないやつはどんどん殺していく、ランダムに殺していく」的なのと。うまく運用できればそういう考え方で出来るのかもしれないですね。

naoya: うん、それいいっすね。MySQL だから常にマスター殺しても昇格できるって状態がそれによって担保されるって。Chaos Monkey の本来の目的ですけど。それと Immutable Infrastructure 的なデプロイ簡単みたいなののうまいとこ取りしてて。すごくいいモデルですね。ただ、MySQL をそんなカジュアルに立ち上げたり新しくしたりして、キャッシュのウォームアップっていうんですか、そういうのは大丈夫なのかな、っていうのはちょっと気になったけど。ちっちゃいシステムだったら全部上に乗るかもしれないけど、そうじゃない場合そんなカジュアルに切り替えられないって問題ありますね。

miyagawa: そのエピソードで話してたのは、Chad さんはその辺はチートしていて、「DB サーバーは自分らで運用するのやめて Amazon の RDS を使うことにする」と。だからそこの問題はチートして回避するんだって言ってたんですけども。ただ、そうするにしてもしないにしても、DB とかを1個の巨大なマスターを持つんじゃなくて、Wunderlist の場合だと基本的には個人向けのツールなので、個人の ID があってその下に TODO リストが貼りついていると。

一応コラボレーション機能はあるんだけども、何人かのグループだけなんで、シャーディングみたいな感じで小さい DB のインスタンスをいっぱい持つように設計をしているので、カジュアルに殺していった時でも影響範囲やパフォーマンス的なことをそんなに真剣に考えなくてもいいっていう。そういうメリットがあるから、もしランダムに殺していくとかいうラディカルなことをしなくても、小さくまとめていくのは Immutable Infrastructure とか Disposable Component をやってく上では結構重要なアーキテクチャ設計だ、みたいなことを言ってましたね。

45:40

naoya: 確かにそれはあるんだよな。そうなんっすよ。結果、Docker でプロセスが全然立ち上がってないみたいな話さっきしたんですけど、例えば1コンテナのなかで立ち上げるデーモンとか1個とか、そういう考え方になってくじゃないですか。同じコンテナのなかにあれとこれ入れてそれを連携させて動かすってよりは、コンテナごとに1つの役割しか持たせずにそれをネットワークで連携させる、みたいな。アプリケーション側はミニマムにして設計し直すみたいな考え方は Immutable Infrastructure 前提になってくると必要になってくると思うんすけど。今のはそういう話ですよね。

miyagawa: そうなんですよ。Docker はデフォルトではそうじゃないんですけど、起動する endpoint っていうコマンドを指定するのが推奨されていて、コンテナでは1個のメインプロセス、Redis 立ち上げるなら Redis だし、Rails 立ち上げるなら Rails だし、みたいな。そういう決めを作ってコンテナをバンバン作って連携させるってのが推奨されてるやり方ですよね。

gosukenator: Docker の 0.6.5 の最新でも、コンテナ間のコミュニケーション機能みたいなのが出来てて。そういうの見越してるのかな、と。通信ポートを拾えるような感じになっていて。環境変数で渡されるようになってて。で、それで相手のポートを通信するみたいな機能が乗ってきてるんで。まさにそういうことイメージしてるのかな、っていうのはその機能見て感じましたね。

miyagawa: 確かに。まぁ、そんな感じですかね?

naoya: はい。

gosukenator: はい。

miyagawa: エピソードを Web サイトから聞いてもらってる人も結構いるんですけども、出来ればポッドキャストのクライアントを使って毎週聞いていただけるとありがたいです。

naoya: (笑)

miyagawa: サイトの上の方に RSS と iTunes のリンクがあるんで、iPhone とか iTunes 使ってる人は iTunes のリンクから、それ以外の Android とかの人は RSS ってリンクをクリックすると subscribe 出来るんでよろしくお願いします。あとは、iTunes のレビューの方もまだまだ募集してますんでお願いします。

naoya: ではでは。

gosukenator: ありがとうございましたー。


Transcribed by @harupong http://blog.harupong.com/