はじめに
Cassandra を運用中、以下の障害に遭遇しました。
- seedノードを含む複数ノード停止
- 非seedノードを再起動
-
nodetool statusが失敗
再現確認で、シードノードだけ再起動した場合は失敗せず、普通のノードだけ失敗しました。
知識不足も相まって、解決に時間がかかってしまったので、この事象を通して、Cassandraの内部動作(Gossip / Failure Detector / Snitch)を整理しながら、障害を明確に理解しようと思います。
目次
- はじめに
- 目次
- 発端
- 結論(先に)
- Cassandraの構成
- Cassandraクラスタの成立条件
- ① Gossip(状態共有)
- ② Failure Detector(生死判定)
- ③ Snitch(トポロジー認識)
- なぜ nodetool が失敗したのか
- seedノードについてのイメージの変化
- 全体まとめ(重要)
- 参考
- 学び
発端
Cassandraのヘルスチェック通知のチャンネルに以下のアラートがなりました。
# 実行
nodetool status
# 結果
nodetool: Failed to connect to '127.0.0.1:7199' - ConnectException: 'Connection refused (Connection refused)'.
基本的にテストで出ることが多いのですが、今回は本番で大慌て。。。
結論(先に)
seed不在
↓
Gossip初期化不可
↓
クラスタ状態が存在しない
↓
nodetoolが失敗
Cassandraの構成
今回の環境は以下の構成です。
| 項目 | 内容 |
|---|---|
| ノード数 | 3台 |
| seedノード | 2台(Node A / Node B) |
| DC | 1つ |
| Rack | 3つ(各ノードを別Rackに配置) |
Cassandraクラスタの成立条件
クラスタは次の3つで成立しています:
| 要素 | 役割 | 一言で言うと |
|---|---|---|
| Gossip | ノード間で互いの状態(UP/DOWN/Token情報など)を定期的に交換し合う仕組み | クラスタの「口コミ伝達」 |
| Failure Detector | Gossipで届くHeartbeatの間隔をもとに、ノードが生きているかを確率的に判定する仕組み | クラスタの「生死判定」 |
| Snitch | 各ノードがどのDC・Rackに属するかのトポロジー情報を管理し、レプリカ配置の最適化に使う仕組み | クラスタの「地図」 |
この3つは独立して動いているのではなく、Gossipが動かないと残り2つも機能しないという依存関係があります。
① Gossip(状態共有)
● 役割
ノード間で状態を共有する仕組み
● 持っている情報
Gossip通信で共有される主な情報は以下の通りです。
| 情報 | 内容 |
|---|---|
| ノードの状態 | UP / DOWN / JOINING など |
| Token情報 | そのノードが担当するデータ範囲 |
| Schema Version | テーブル定義のバージョン(不一致を検知するため) |
| Load情報 | ノードが保持しているデータ量 |
| Rack / DC情報 | Snitchと連携したトポロジー情報 |
各ノードがこの情報を持つので、クラスタ全体の状態をどのノードからでも確認できます。
● 正常時の流れ
● 異常時(今回)
起動時に参照できるseedがなく、少なくとも今回の再現環境ではクラスタ参加に必要な情報を取得できず、Cassandraプロセスが正常に立ち上がりきらない状態になっていました。
② Failure Detector(生死判定)
● 役割
ノードが生きているかを確率で判断します。
Gossipで届くHeartbeatの到着間隔を統計的に分析し、Phi(φ)値として異常度を数値化します。
「統計的に分析する」とは?
各ノードは定期的にHeartbeat(生存確認の信号)を送り合っています。
Failure Detectorはその到着間隔の履歴を蓄積し、「普段はだいたいこの間隔で届く」という正常パターンを学習しているみたいです。
過去の到着間隔の平均・分散を計算
↓
「今の遅延」が正常範囲からどれだけズレているかを算出
↓
その乖離度 = Phi値
つまり、単純に「一定時間応答なし → DOWN」と判断するのではなく、ノードごとの正常な遅延を学習した上で、それと比較して異常かどうかを判断する仕組みです。
Phi = 0 → ほぼ正常(直前にHeartbeatが届いた)
Phi = 1〜7 → 徐々に怪しい
Phi ≧ 8 → DOWN判定(デフォルト閾値)
数値が上がるほど「Heartbeatが届いていない時間が、正常範囲と比べて長すぎる」ことを意味します。
| 項目 | 内容 |
|---|---|
| 判定の基準 | Gossipで届くHeartbeatの間隔 |
| 異常度の表現 | Phi値(数値が高いほど異常) |
| DOWN判定の閾値 | デフォルト phi_convict_threshold = 8(設定可能) |
| 判定の特徴 | 二値(生/死)ではなく確率的に判定する |
● イメージ
● 判定ロジック(Phi)
Phi値 ↑ = 異常度 ↑
低い → 正常
高い → 怪しい
閾値超え → DOWN
③ Snitch(トポロジー認識)
● 役割
ノードの物理配置(DC / Rack)を管理し、レプリカをどこに配置するかの判断に使われます。
| 項目 | 内容 |
|---|---|
| 管理する情報 | 各ノードのDC名・Rack名 |
| 主な用途 | レプリカ配置の最適化、読み書き経路の選択 |
| 代表的な種類 |
SimpleSnitch(DC/Rack区別なし)/ GossipingPropertyFileSnitch(設定ファイルで定義) |
| 今回の構成 |
GossipingPropertyFileSnitch(DC×1、Rack×3) |
● イメージ
なぜ nodetool が失敗したのか
とはまぁ、長々とCassandraにおけるゴシップ通信についてみてきたのですが、結論は以下になります。
まず nodetool status は、ローカルまたはリモートのCassandraノードにJMX経由で接続してクラスタ情報を表示するコマンドです。
そのため、今回出ていた以下のエラーそのものは、127.0.0.1:7199 のJMXポートに接続できなかったことを示しています。
nodetool: Failed to connect to '127.0.0.1:7199' - ConnectException: 'Connection refused (Connection refused)'.
つまり直接的には「nodetoolがGossipに失敗した」というより、CassandraプロセスまたはJMXが正常に待ち受けていないため、nodetoolが接続できなかったという状態です。
そのうえで、今回の背景としては、非seedノードの再起動時に参照できるseedノードがなく、Gossipの初期接続先を見つけられなかったことが大きいと考えています。
少し細かくすると、以下のようになります。
今回の場合:
今回疑問に思ったきっかけが、再現性確認でシードノードで再確認したのですが、シードノードではnodetool statusで失敗することはなかったです。
それは
seedノード自身は、seedリスト上の接点として扱われるため、同じ条件でもクラスタ参加の初期化に成功しやすかったからです。
通常のノードはGossip開始時に、クラスタ内のノードを見つけるための接点としてseedを参照します。
しかしseedノードは、自分自身がその接点の一つになるため、他のseedが不在でも今回の環境では起動できました。
【通常ノードの起動】
再起動 → seedに接続 → Gossip開始 → クラスタ参加
【seedノードの起動】
再起動 → seed接点として起動 → Gossip開始 → クラスタ参加
そのため、seedノード単独での再起動では nodetool status が成功し、
非seedノードの再起動ではseedが不在のためクラスタ参加まで進めず、結果として nodetool status のJMX接続も失敗した、というわけです。
seedノードについてのイメージの変化
今回の障害があって、シードノードのイメージが明確に変わりました。
今まではクラスターの中心でなんとなく重要程度に思っていましたが、結論、ノード同士が互いを見つけてリングのトポロジーを学ぶための入り口や灯台として機能するものだったのですね。
みんなの目印になっていて、各ノードが迷わないようにしているということ。
そういう人間になりたいものです。
全体まとめ(重要)
参考
- Apache Cassandra Documentation: cassandra.yaml
seed_provider - Apache Cassandra Documentation:
nodetool status - Apache Cassandra Documentation: Dynamo architecture
学び
今回は、実際に起きた障害のエラー調査とその周辺知識を勉強した内容として、Gossip通信では他のノードのバージョンやノードの状態、それが持つ情報などをやり取りしており、また、その情報をもとにFailure Detectorで生死判断をしていること、Snitchがレプリカ配置や経路選択に使われるということがわかりました。
ついでに、迷わない人間とノードはとにかく強いということを学びました。Cassandraのシードノードのようにはなれませんが、でも、迷っているからこそ人間は深みが出るのかもしれません。なんてね