Docker を本番環境で4ヶ月運用して分かった HARD THINGS

Docker を本番環境で4ヶ月運用して分かった HARD THINGS

今年も残すところあと10日となりました。
Docker Advent Calendar 2015 22日目 山中です。

簡単に自己紹介

Advent Calendar 経由でお越しになった方もいらっしゃるかと思いますので簡単に自己紹介させて頂きます。

名前: 山中 悠 (@yuurelx)
経歴:
   -2009 バイトで検索エンジン開発&自宅データセンター
 2009-2014 株式会社HDE (Programmer/SE/PM/Infra. Engineer)
 2015   株式会社ペロリ (DevOps Engineer)
 2016-   INGoT合同会社 (CTO), Reactive Inc. (Core Engineer)
登壇歴:
 Docker Meetup Tokyo #5
 SCRIPTY #4
 Sensu deep talks #1,#2
 Fashion Tech meetup #1

今日のお話

以前、いくつかのイベントで Docker の本番利用についてお話させていただいたのですが、その後数ヶ月4ほど経ちましたので、その後どうなったかということを書こうかと思います。

Docker Meetup Tokyo #5 の LT で本当に伝えたかったこと
http://staycreative.jp/2015/08/docker-meetup-tokyo-5-lt/

MERY on Docker
http://slides.com/urelx/mery-on-docker

(ちなみに書籍の HARD THINGS とは全く関係ありません (^^;)

MERY における Docker デプロイの構成

前提知識として、構築した Docker デプロイのアーキテクチャについて簡単に紹介致します。

New deployment of MERY

基本的には Kubernetes や Amazon ECS 等のオーケストレーションツールは使わず、
Docker 単体で運用しています。

アプリケーションに機能追加した際のデプロイの流れは下記のとおりです。

  1. リリース担当のエンジニアがリリース用のブランチに Pull Request
  2. レビュー後、その PR をマージ (これ以降はすべて自動で処理される)
  3. CircleCI が動き、自動テスト後に Docker イメージのビルドと DockerHub への push
  4. CircleCI が API 経由で Rundeck(ジョブスケジューラ) のデプロイジョブを実行
  5. Rundeck が SSH 経由で各アプリケーションサーバにログインし、 Docker イメージを pull
  6. Nginx 内の upstream のパスを書き換えて新しいコンテナに向け、 Nginx を reload

本構成はクックパッドさんの構成を参考にしています。
http://techlife.cookpad.com/entry/2015/04/20/134758

本番環境に Docker を導入して得られたもの

1. AMI の管理が不要になった

MERY は時間帯によっての負荷の差が激しいので、コスト最適化のためにインスタンス数の動的な変更(オートスケーリング)を行っています。
オートスケーリングを行うためにはマスターとなるイメージが必要なので、それをデプロイの度に作る必要があり、そこが一つのルーチン作業になっていました。

Docker 採用後はコンテナイメージがアプリケーションのマスターイメージとなるため、オートスケーリング時には DockerHub から最新のイメージを pull して run するだけで済むようになります。

Pull Request マージによるワンクリックデプロイの実現にもこの成果が役立ちました。

2. アプリケーションの言語やミドルウェアが違っていても同じ方式でデプロイ出きるようになった

図のアプリケーションは Rails ですが、 Go + Circus をコンテナ化して運用しているプロジェクトがあったり、別途特別なライブラリを必要とするプロジェクトもあります。
これをコンテナという抽象化したレイヤーで包むことで、ほぼ同じような方式で運用・デプロイできるようになります。
複数のプロジェクトのインフラを支えるエンジニアにとって嬉しいメリットです。 :)

Docker を導入して発生したトラブル達

これでめでたしめでたしと行けば良かったのですが、枯れてない技術を導入するとやはり何らかのトラブルが発生しがちです。

1. CIやデプロイに時間がかかる

Docker にはファイルシステムのキャッシュ機構があるため、ローカル環境でのビルドは早いのですが、 CircleCI のキャッシュ機構と若干相性が悪いため比較的ビルドに時間がかかります。

Caching Docker layers
https://circleci.com/docs/docker#caching-docker-layers

また、 DockerHub への push もインターネット通信のため時間がかかります。
コンテナイメージのサイズをできる限り減らしたのですが、それでも +5分 程度 CI 時間が伸びました。

また、デプロイ時にも DockerHub からイメージを落とすためそこが遅くなる原因となります。

2. 障害時の切り戻しに時間がかかる

既存インスタンスに対する切り戻しは古いバージョンのコンテナをデプロイするだけで済むのですが、オートスケーリング用のインスタンスのためのイメージのロールバックは盲点でした。

先に書いたとおり、オートスケール時に Launch されたインスタンスは最新の Docker イメージを DockerHub から取得するのですが、そのためにはどのバージョン(tag)のイメージが“最新”かを指定しなければなりません。そして、ロールバック時にはそれを古いものに更新しなければなりません。

hoge/app:v114 (latest)
hoge/app:v113 ↓

バージョンの指定には Docker イメージの tag を用いていましたが、この tag を付け替える機能は DockerHub の API に無いため、一度ローカルに pull して付け替え、再度 push しなければなりません。これに数分の時間がかかります。

3. 外部サービスの安定性に依存する (CircleCI や DockerHub)

デプロイなりオートスケーリングなどで、日に何十回も Docker イメージを push/pull するようになって分かったことなのですが、特に DockerHub の安定性がよろしくなく、時々 5xx エラーで失敗します。これが現場の開発エンジニアに不信感を与えてしまいました。

4. 現場の運用エンジニアが Docker 運用に慣れるまで時間がかかる

オーケストレーションツールは使っておりませんが、それでも従来のサーバ上に生デプロイする構成と比べると複雑になります。

  • サーバに入ってログを見ようとしたらログが無い! (コンテナ内にある)
  • 障害時に Docker に起因する問題かそうでないかが分かり辛い
  • 特殊なオペレーションをしたいときに、経験者に都度確認する必要がある

リソースに若干の余裕のあるプロジェクトだと、徐々にノウハウをトランスファーして行け、ほぼ運用をお任せできたりするのですが、カツカツのプロジェクトだとそうもいかず。。。

Docker 構成から元の AMI + Capistrano 構成に戻したプロジェクトも有り

現在も本構成で元気に動いているシステムもあれば、残念ながら本番運用のクオリティに達していないという評価が為され、元の構成に戻すことになったシステムもあります。
CM 公開による高負荷対策が必要な忙しい時期に、構成変更が被ってしまったのも良くなかったかもしれません。

個別のトラブルは解決出来ないものではありませんが(DockerHub -> Amazon ECR 等)、その解決にリソースを割ける状況かという現実的な判断も必要です。

まとめ

  • 枯れていない技術を導入することにはリスクが伴う。場合によってはメリットを越える
  • Docker は可能性を持ったツールだが、決して簡単なツールではない。慣れが必要。意外なデメリットもある。
  • 枯れた技術で問題を解決出来ないかまず綿密に検討する。その上で、新技術を選択するのであれば早い段階から現場エンジニアへの相談・合意を得る

やや HARD な内容になりましたが、それでも僕は Docker は便利なツールだと思いますし、技術のトレンドとしてコンテナ仮想化は広まって行くと思っていますのでこの度の経験を反省点に、問題解決のツールの一つとして活用して行きたいと考えています


顧問インフラエンジニア 山中

サーバー1台から数百台まで。
AWS インフラ導入支援・運用コンサルやってます!

Related

Comments

No Comments Yet!

You can be first to comment this post!

Post Reply