nanapiをDocker + CoreOS化する際に学んだこと

Shigu エンジニアリング
docker_coreos

こんにちは、AWS大好き大西です。

今回はnanapiをCoreOS + Dockerで運用することができましたので報告とノウハウをお伝えできればと思います。
コンテナは最近AWSでもECSが正式リリースされたりRocketがシェアを上げてきたりと中々熱い技術になっています。

Docker化する経緯

Yahoo砲が頻繁にありELBのAutoScalingでは間に合わないので最初からサーバを多めに用意してました。
急激なアクセスに耐えるために自前でAutoScalingを構築することがそもそもの経緯です。

そしてスケールフローが変更されることにより、デプロイフローも変更されるので思い切ってDockerに挑戦してみました。
今後主流になると予想される Immutable InfrastructureBlue-Green Deployment を導入しました。

メンバー構成

メンバーはVexus2と私の二人でした。
最初はお互いDockerについてよくわかっていなかったのですが、役割分担は綺麗にできたと思ってます。

ImageをpullしてきてDocker環境でサービスを動かすまでがVexus2、動いた状態から分散、切り替え、監視などを担当するのが私でした。

失敗

私達はインフラについてそこまで知識があるわけでなく、なんとなく触ってきていたということを思い知らされました。
そのため、よくわかっていないのに色々技術を欲張りすぎたため、エラーの原因特定に時間がかかりました。
コンテナになってシンプルになる、なんてことはなく基礎の知識から必要でした。

CoreOS

Dockerって言えばCoreOSだよねって程度でCoreOSに手を付けました。
ここは自分達の技量と経験では不足している代物でした。

DockerはubuntuでもCentOSでもAmazonLinuxでも対応していますが、私達はいきなりCoreOS + Dockerに手を付けました。
何かエラーがあるたびに、CoreOSのエラーなのかDockerのエラーなのかわからなくなり、無駄に時間を使っていました。

今後Dockerを導入される方には、まず使い慣れたOSでのテストをおすすめします。
Dockerはイメージをそのまま別のOSに持っていけるので、すぐに別のOSでも動き出すでしょう。

OSの思想に縛られすぎた

CoreOSでのデプロイは etcd + fleet という概念が強いのですが実際に使ってみると中々運用が難しかったです。

デプロイするまでは問題はないのですが、障害時にetcdが停止することにより復旧のフローが非常面倒になることが課題に上がりました。
その辺りの理由としてetcdのCluster sizeに問題がありました。

Optimal etcd Cluster Size

リンク先で説明されていますが、簡単に説明するとetcdを立ち上げているサーバを半分以下するとetcdが正常に動作しなくなります。
etcdが再起動されたとしてもそれは復旧しないため、再度Clusterを作り直す必要があります。

確かにfleetのetcdの組み合わせは強力ですが、リカバリ方法が煩雑になることは避けました。
また日本での運用のノウハウがあまりなかったのと、当時etcdのバージョンがv1.0未満だったため実装は完了しましたが断念しました。

機能は独立させ、構成は小さく

テストも含めるとやることが膨大になりスケジュールが全然立てれなくなりました。
そこでそもそもの目的を達成するために機能を絞りました。

  • やりたいこと
    • Docker
    • AutoScalingの高速化
    • Blue-Green Deployment

Dockerは別として、AutoScalingとBlue-Green Deploymentさえできれば問題ないということだけを考えるようにしました。

そのために必要なものを整理しました。

  • 必要なもの
    • 一つのOSにコンテナを二つ立てて両方が正常に動く
    • そしてその二つを切り替えるスイッチがあればいい
    • スケールアウトした時にコンテナが正常に立ち上がり、自動的にサービスインされる
    • 高速に立ち上がるサーバ

出来上がった構成

二つのポートを切り替えてBlue-Greenにしてます。
FrontProxyサーバが常に下についているコンテナにヘルスチェックをかけて、変更があればreloadされます。
AWSのタグフィルターでサーバを立ち上げれば自動的にFrontProxyサーバのチェック対象に加わります。

デプロイ方法はCapistranoを使ってsystemdからコンテナを起動しています。
またポートの切り替えをするのもCapistranoで行っています。
安全機構として、誰かがデプロイして動作確認中はデプロイロックがかかり、デプロイやコンテナ削除はBlue側にしか絶対行われません。
懸念点としては安全なデプロイができるが、デプロイの頻度が下がってしまっていることです。
弊社では デプロイ頻度 < 安全なデプロイ なためこちらの構成になっています。

それぞれの機能が独立しているため、今後etcdとfleet入れたい!kubernetes入れたい!となった時でも他の機能に影響を出さないように設計してあります。
コンテナ側の詳細についてはこちらの記事になります。

まだAutoScalingの高速化ができていない

まだAutoScalingの高速化ができていないので現在も絶賛開発中です。
まずYahoo砲と同等の攻撃を可能にするツールを作成中です。
またスケールアウトの方法としてはAWSのCloud Design Patternの Job Observer パターン を参考にしたいと思っています。

所感

運用する上で問題ないと感じています。
DockerとCoreOSだから起きた障害は1ヶ月ほど運用してみましたがありません。

そもそもコンテナの一部が落ちたとかでサービスダウンするのであればSPOF考慮してないとか設計レベルの問題なのでDockerは関係ありません。
ただ、現状はまだありませんが、なんらかの理由でコンテナが落ちる可能性を考慮してモニタリングなりすることは必須です。
ここは今まで通りで監視方法が変わっただけですね。

CoreOSらしい運用できていないのが少し気になっていますが、etcdとfleetがなくてもCoreOSを使うメリットは十分ありました。

  • メリット
    • 立ち上がりが早い
    • OSのアップデートがサービスに影響しない(コンテナ内は別)
    • AMIが必要なくなった

開発面では効率も上がり安心したデプロイを行えるようになったので、開発者にもお財布にも優しい状態です。
まだDockerは安定してないからなーって言葉をよく聞きますがコンテナ時代の幕は既に開いてると思っています。

最後に

nanapiでは最近CakePHP → Ruby on Rails になったり Docker + CoreOS になったりと大幅に環境を変更しました。
今回fleetとetcdを選ばなかったことにも繋がるのですが、今CoreOSのベストプラクティスを目指しても1年後に私達は別のアプローチをしていると思います。

どれだけ今頑張って素晴らしい技術で組んだとしても、構成変更に弱かったり属人化してしまったりすると負債になりかねません。
技術が進化し、もっと便利なツールが出てきても置き換えることができなくなったりします。
技術を追求することは非常に大切ですが、目的を忘れず、できるだけ早く、使いやすく常に安定したサービスを提供するのが私の仕事です。

今回のnanapi.jpの運用がコンテナ界に少しでも貢献できればと思います。