Wantedlyインフラチームの @koudaiii です。
まずインフラチームでは、「Code wins Arguments」を支えるインフラ = 変化に強いインフラ作りに取り組んでいます。
Code wins Argumentsについては、こちらのインタビューを参照してください。
チームで1時間ミーティングするならコードをかこうという考え方のもと、エンジニアであれば、仮説を考えてあれこれ考えるよりも、プロトタイプを作って検証することや、営業であれば、エンジニアに頼む前に企画書を書いて5社程度の確約をとってきて、これなら行けると思ったらエンジニアに依頼する
Docker を Production で使うのはなぜ?
Wantedly では、 2014夏頃よりProduction で Docker を使っています。元々 Heroku からサービスをスタートしているので、コンテナ自体はずっと利用してきており、AWS に移行する際に私たちは Heroku に近い形でインフラを構築してきました。
結論として、私たちが Docker を Production で使うのは Heroku に近いインフラを用意することで変化に強いインフラ作りが出来ると考えているからです。
起動の速さ
VM を起動するのは通常数分かかります。一方 Docker では数秒でサービスがリクエストを捌ける状態まで立ち上げることが出来ます。
リクエストが急増する時は、数分待っていたら間に合わないということも多いのですが、この起動の速さの差により、安全を期して余裕をもたせすぎた構成にする必要がなくなります。もちろん予備のマシンを用意して置く必要はありますが、それはサービス間で共有できるので、トータルで用意しなければならない予備のマシンの数は減らすことが出来ます。
Middlewareを試しやすい/入れやすい
例えば Elasticsearchを試したい場合、 `docker pull elasticsearch:2.3.3` とするだけで Elasticsearch が入ったコンテナを用意することが出来きます。
少し独自の plugin 等を含んだ構成にしたい時も、簡単な Linux コマンドを Dockerfile に書くだけで実現できます。
Chef や Ansible でも、これと同様なことは実現できますが、1年ぐらい経つと同じインストール方法ではインストールできなくなってしまったりして、設定ファイルのメンテナンスが必要になってしまいます。これに対し Dockerfile なら、たとえその方法でインストールができなくなっていたとしてもイメージになっているので起動させ続けることが出来ます。
必要な場合はローカルで利用するときも Production で使っているのと同じ Docker イメージを使うことが出来ます。VM だと Production で使用するインフラ系のツールや監視設定も同伴されているので、ローカルで使う時にそれらを除外するのが手間だったりしますが、Application が入っているだけのコンテナに絞って手元で用意できるのはローカルのPCに対しても負荷が少ないですし、気にする部分が減ります。
XaaS/オンプレミスに縛られない
一つの image として保存されているため、 AWS で動いているものをGCP に移動させることが可能です。
また、PaaS では日本に提供されていなかったり、独自のサービス、ElasticsearchなどのMiddlewareが建てられなかったりします。
Heroku の場合、 npm や mecab 入りの Railsとかが建てられなかったり、建てられたとしても buildpack をカスタマイズする必要があります。
この工数から結局 Dockerfile を書くのと同じかそれ以上かかってしまいます。
シンプルな構成になり、一つ一つを管理しやすい
Docker では、 Dockerfile というファイルでコンテナの build を行います。
この Dockerfile から出来るコンテナは一個のプロセスだけを動かすシンプルな構成を推奨しています。
そのため、一つのサービスで複数のプロセスが必要な場合、シンプルな構成で作られたコンテナを組み合わせて利用することになり、より疎結合で変更がしやすくなります。
この方法論については Twelve-Factor App をご参照ください。
これにより大きな物が出来る「Unixという考え方」に近いことを実現出来ます。
コンテナ(Docker) vs VM
コンテナ(Docker)と VM では、仮想化の粒度が大きく異なります。
・VMの場合は、マシン単位で取り扱う
・コンテナの場合はプロセス単位で取り扱う
簡単な例として、Ruby の version up をしたいと考えた場合にどうやってデリバリーしていくのかを取り扱いたいと思います。
以下の前提条件から比較していきたいと思います。
・なるべくマシンで作業しない
・ダウンタイムなしで入れ替えたい
作業範囲
VM の場合、一つのマシンとして取り扱うため、その他の Logging や Monitoring tool またはそれ以外の Application で影響を及ぼさないか注意しなければなりません。
コンテナの場合、一つのコンテナとして閉じているため、そのコンテナ内だけに集中して作業することが出来ます。
リリースのしやすさ
VM の場合、 instance をまるごと入れ替えるため、 instance の起動を待ってから、入れ替える形になります。一度にたくさんのinstance を作ったり消したりする際に、非常に大掛かりな作業になります。
コンテナの場合、そのコンテナに絞って入れ替えるだけになるので、普段の deploy プロセスと同じ方法で入れ替えることが出来ます。普段から利用しているプロセスをそのまま使えるのは作業者も、安心してリリースすることができます。
ローカル上での開発のしやすさ
VMは一式マシンを用意する考えなので、一部のみ置き換えるのが難しく、Production で必要となる Logging や Monitoring tool その他の Application を含めてローカル環境で組む必要があります。
また開発する際に Chef や Packer や Ansible 等の Provisioning Tool を使うことが多いと思いますが、何度も実行して試したい場合に、複数回 VM の立ち上げ直しと Provisioning の実行が必要になり、手間が多いです。
コンテナの場合、そのコンテナ内に閉じられるため、影響範囲が少なく、対象の Dockerfile に集中して version up に取り組むことが出来ます。
また何度も実行して試したい場合に、そのコンテナに絞って build と run を実行できるため、VM に比べて手間が少ないです。
そのために、Dev 側のエンジニアも Middleware 追加、 plugin 追加、 version up などが出来るようにすることで、Dev 側のチームが主体となって変化を作ることが可能です。
Wantedly ではどこまで Docker を使っているか?
現在 Wantedly では、稼働しているすべてのインフラが CoreOS + Docker の構成になっています。
マシン側で直接何か処理をすることはなく、Docker のコンテナが仕事をする構成です。
これにより、ホストマシン間の違いがなくなり、instance レベルで気にすることはだいぶ減り、質の悪い instance は積極的に terminate して作り直しています。
Docker を使い続けるのはなぜなのか?
Docker で使い続けているのは、この Dev 側でも積極的に試しやすいという点と入れ替えやすいという点が大きな要因になっています。
Dev 側でも積極的に試しやすい点
Dockerfile という一枚のシンプルなファイルを扱うことで、分岐が多くなった Provisioning Tool を Dev 側が見に行く必要がなくなります。
最近では Dev 側から Dockerfile を書いてリリースしたいと言う場面がでてきました。
コンテナの構築部分が Dev 側で行われることでインフラチームはより次の新しいPlatform 準備や Tool 開発に集中することが出来ます。
今も Provisioning Tool を使い続けてたら Ruby の version を上げたい場合、 いつまでもインフラチームの作業のままです。
入れ替えやすい点
また、 Docker になることでマシンの部分についてより意識しなくてもよくなってきています。
以前まで マシンに直接インストールをしていた Middleware があり、そのちょっとした Middleware の変更のためだけに VM image を入れ替えるのは工数的に行いにくい状況でした。Docker に置き換えたことで、よりその Middleware も最新を使うようになりました。
Wantedly では実際にどのくらいやりたいことを実現できているのか?
既存で動いていた部分については、Docker で実現されている
上述の通り Dockerfile の作成について、インフラチーム以外の Dev 側のエンジニアで作成されたりしています。
例えば、Elasticsearch や 小さな module となる Service などは、インフラチームではなく Dev 側のエンジニアが主体で書かれています。
新しくサービスをリリースするところまではできていない
しかし、まだ instance を用意したり、DNS をつけたり、ELB を用意するといった部分については、インフラチームが行っている状況です。
今後
Kubernetes のようなクラスタリングする仕組みを作ることで現在できていない部分が解決出来ると思っています。
各サービス毎に instance を用意したり、ELB を用意したりも要らなくなります。
DNS の部分は、既に Terraform を使っていますが、単純に使う頻度が少ないので、インフラチームから Pull Request を出すことが多いですが、
現環境からより、試しやすい、入れやすい が整うことで、 より Dev 側から Pull Request が来る機会が増えると感じます。
これからもDocker を使い続けるのか?
Wantedly インフラチームは、「変化に強いインフラ」作りに取り組んでいます。
インフラ環境をDev側がより意識せず、簡単に作って壊せる、試しやすい 環境を提供しようと努力しています。
そのために、クラスタリングという一つの大きなインフラを作ることで、達成出来るのではないかと考えています。
そのクラスタリングが作りやすいのは今のところ Docker だから私たちは使い続けると思います。
クラスタリングは Docker swam だったり Kubernetes で実現できます。
逆に、何があったら Docker をやめるのか?
インフラを全く意識しない環境が低コストかつ、一瞬で用意することができればいつでも乗り換えると思います。あくまでも Docker が目的ではなく、手段であり、Docker を使う事自体が目的ではないからです。
ただ、現状 Docker よりもそれが実現可能そうなものは現れていないと考えています。
まとめ
変化に強いインフラ実現するための手段として、Wantedly では Docker を Production で利用しています。
とはいえ、 Docker だから変化に強いインフラがすべて実現かというとそうではありません。今でも新しくサービスをリリースする時はどうしてもインフラチームが作業することが多々あり、まだ完全に実現ができている状態ではありません。
インフラチームでは、この変化に強いインフラを作るために日々改善に取り組んでいます。