EatSmartシステム部ブログ

ウェブサイトの開発や運営に関する情報です。

Docker Swarmの障害への対応

イートスマートでは、提供するサービスのフロントエンドで利用するミドルウェアをDockerコンテナ化し、Swarmモード上で稼働させています。 先日発生したDocker Swarmの障害と、それへの対応をまとめました。

アラート

サーバやコンテナの状態はZabbixを利用して監視しています。 9月30日の午後、syslogの監視から一通のアラートが飛んできました。 ログの内容は以下の通りでした。

Sep 30 17:14:47 docker01 dockerd[18844]: time="2019-09-30T17:14:47.363605167+09:00" level=error msg="error receiving response" error="rpc error: code = DeadlineExceeded desc = context deadline exceeded"

サービスへのアクセスは問題なくコンテナの死活監視なども異常が発生していないので、当時は大事になるとは思っていませんでした。 サーバにsshでログインしてDockerコンテナの状態を見ても問題が無かったのですが、ノードの状態を確認しようとした時に事の大きさに気づきました。

# docker node ls
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.

ここで、Docker Swarmで障害が発生していることに気づきました。 コンテナ間の通信にオーバーレイネットワークを構築しているのですが、Swarmモードが機能しないとオーバーレイネットワークへのコンテナを参加させることができなくなります。 具体的には、docker runやrestart時にエラーが発生し、コンテンが起動できません。

原因

各サーバのログを見る限り、クラスタの各ノードは以下の動きをしていました。

  1. リーダーがフォロワへ降格
  2. リーダーを喪失
  3. ノード間の通信にエラーが発生する
  4. ノードAがリーダーに立候補するが過半数を得られない
  5. ノードBがリーダーに立候補し過半数を獲得しリーダーになる
  6. ノードBへノードAから5の時点より新しいリクエストが来たため、ノードBはフォロワへ降格
  7. リーダーの選出が繰り返されるも、ノードBへ投票したノード群が否決を繰り返し誰も過半数を獲得出来ない

以前行った検証ではリーダーの喪失からリーダーの選出が行われクラスタが維持されることを確認したのですが、今回は過半数のノード群が否決を繰り返すようになったため、リーダーの選出する機能しなくなっていました。

検証

このままではコンテナの更新や再起動が出来ないので、Swarmモードを回復させなければなりません。 障害が発生した環境と同等のものを用意し、検証を行いました。 検証の方法としては、以下を行いました。

  1. ノードAとノードBの2台でSwarmモードを構築する
  2. ノードBで"docker swarm leave --force"で強制的に切り離す
  3. ノードAで"docker node ls"を実行すると同様のエラーが発生することを確認する
  4. ノードAで"docker swarm init --force-new-cluster"を実行して再構築する
  5. ノードAで作成したトークンでノードBを復帰させる
  6. コンテナを再起動する

以上の手順でオーバーレイネットワークが回復することを確認できました。

復旧

10月2日の早朝にメンテナンスを実施しました。 復旧にあたり、ノードAをリーダーへ選出するためノードBを含む否決を行うノードを切り離してみましたが、ノードの総数が更新されないため過半数を獲得出来ず失敗しました。 次に、検証で行ったようにノードA以外をを順次切り離し、クラスタの再構築を行いました。

まとめ

今回の復旧手順では、既存のクラスタから一度に全てのノードを切り離しを行った後に新しいクラスタの構築を行ったため一時的にサービスを停止が発生しました。 復旧後のふりかえりでは、既存のクラスタから1台ずつ切り離し新しいクラスタへ参加させればサービス停止が発生しないのではないかという話がありました。 今回は復旧まで十分な検討が出来ませんでしたが、次回以降は今回の経験を踏まえて対応したいと思います。