こんにちは!MSA(Microservice Architecture)環境でサービスを運用していると、ヒヤリとする瞬間がありますよね。😵 数多くのサービスインスタンスのうちの1つが、突然正常に応答しなくなります。しかし、ロードバランサーはその事実を知らずに、ユーザーリクエストを不調なインスタンスに送り続け…結局、ユーザーは5xxエラー画面に遭遇するだけになります。
このような状況をどうすれば防げるでしょうか?Istioを使えば、非常に洗練された解決策があります。それがOutlier Detection(異常値検出)機能です!しかし、この機能がどのように動作するか正確にご存知ですか?もし「定期的にサーバーの状態をチェックする機能」だと思っていたなら、今日のこの記事をぜひ読んでみてください!重要な誤解を正し、サービス安定性を一段階引き上げることができるでしょう。

🤔 Outlier Detection、あなたの正体は?
IstioのOutlier Detectionは、サービスメッシュ内で異常に動作するサービスインスタンス(Pod)を自動的に見つけ出し、一時的にロードバランシングの対象から除外する機能です。
まるで団体徒競走でペースが落ちたり転んだりした選手を見つけ、一時的に休ませる賢い監督のようですね。🏃♂️💨 この機能のおかげで、特定のインスタンスの障害がサービス全体の障害に広がるのを防ぐことができます。
鍵となるのは、この「異常な動作を検出する方法」です。
🕵️♂️ 受動的(Passive)な監視者、Outlier Detection
結論から言うと、IstioのOutlier Detectionは受動的(Passive)なヘルスチェック方式です。
これはどういう意味でしょうか?Active(能動的)方式と比較すると簡単に理解できます。
- Passive(受動的)方式 🕵️♂️: 実際のサービスに入ってくるトラフィックの応答をじっと監視し、問題を把握します。例えば、特定のインスタンスへのリクエストで連続して5xxエラーが発生するのを検知すると、「ああ、こいつは今調子が悪いな!」と判断し、トラフィックプールから一時的に除外します。別途ヘルスチェック用のリクエストは送信しません。ひたすら「実戦トラフィック」の結果のみで判断します。
- Active(能動的)方式 🩺: 実際のサービストラフィックとは関係なく定期的に「元気かい?」と安否を問うヘルスチェック用のリクエストを送信します。私たちがよく知るKubernetesのLiveness/Readiness Probeが代表的な例ですね。/healthzのようなエンドポイントに定期的にリクエストを送り、決められた時間内に正常な応答(HTTP 200 OKなど)が来なければ、「こいつは不調だ!」と判断して対処します。
したがって、IstioのOutlier Detectionは、別途リクエストを送信せず、実際のトラフィックの流れの中で問題を検出するため、受動的(Passive)な方式であると言えます。
⚙️ Outlier Detectionの設定を見てみよう (YAML)
言葉だけで説明してもピンとこないですよね?実際のIstio DestinationRuleリソースでOutlier Detectionがどのように設定されるか、コードで確認してみましょう。
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: reviews-dr
spec:
host: reviews.prod.svc.cluster.local
trafficPolicy:
outlierDetection:
# 連続で5xxエラーが何回発生したら除外するか
consecutive5xxErrors: 3
# 監視周期(この周期ごとに状態をスキャン)
interval: 10s
# 一度除外されたら最低どれくらいの期間除外されるか
baseEjectionTime: 1m
# ロードバランシングプールから最大で除外できるインスタンスの割合
maxEjectionPercent: 50
上記のYAMLファイルのoutlierDetection設定を一つずつ見ていきましょう。
- consecutive5xxErrors: 3:
reviewsサービスの特定のインスタンスが連続で3回502、503、504のような5xxエラーを返すと… - interval: 10s: Istioは10秒ごとにこのような状況が発生したかスキャンし…
- baseEjectionTime: 1m: 問題が検出されたインスタンスを最低1分間トラフィック分散の対象から除外します。(実際の除外時間は
baseEjectionTime* 除外された回数で計算され、徐々に長くなります。) - maxEjectionPercent: 50: どんなに多くのインスタンスに問題が発生しても、サービス全体が麻痺するのを防ぐため、全インスタンスの50%までしか除外しません。
この設定のどこにも「/healthパスにリクエストを送れ」といったActive方式の設定は見当たりませんよね?実際のトラフィックの応答結果のみに基づいて動作することが明確にわかります。
💡 では、どちらが良いのでしょうか?
「じゃあActive方式は間違っていて、Passive方式だけを使うべきなの?」と思われるかもしれません。
答えは「いいえ、どちらも必要で、相互補完的です!」です。
| 区分 | Istio Outlier Detection (Passive) | Kubernetes Probes (Active) |
| 検出方式 | 実際のトラフィック応答監視 📊 | 定期的なヘルスチェックリクエスト送信 ピングポン ピングポン |
| 長所 | 実際のユーザーに影響を与える問題を即座に把握可能。負荷がない。 | トラフィックがない状態でもインスタンスの問題を事前に把握可能。 |
| 短所 | トラフィックがないと問題を検出できない。 | ヘルスチェックリクエスト自体がサービスに若干の負荷を与える可能性がある。 |
| 主な役割 | 一時的な過負荷や断続的なエラーからサービスを保護(トラフィック隔離) | アプリケーション自体がダウンしたり応答不能になった状態を検出(コンテナ再起動) |
ご覧のように、2つの方式は異なる種類の問題を解決します。
- K8s Probe (Active): コンテナが完全に停止したり、DBコネクションプールが満杯でこれ以上リクエストを処理できないなど、根本的な問題を検知し、コンテナを再起動させる役割を果たします。
- Istio Outlier Detection (Passive): コンテナは稼働しているものの、一時的なCPUスパイクやネットワーク遅延などで一時的に応答が不安定になったインスタンスを検知し、ユーザーからのトラフィックから一時的に隔離する役割を果たします。
✨ 結論:一緒に使ってもっと強力に!
結論として、IstioのOutlier Detectionは、実際のトラフィックを監視する受動的(Passive)なヘルスチェック方式です。これは、定期的にヘルスチェックリクエストを送信するKubernetesのLiveness/Readiness Probeのような能動的(Active)な方式とは明確に区別されます。
最も理想的な構成は、この2つを一緒に使用することです。🤝
- Readiness Probeでまだ準備ができていないPodにトラフィックが流れるのを防ぎ、
- Liveness Probeで完全に停止したPodを再起動させ、
- Outlier Detectionで一時的に調子が悪いPodをトラフィックプールから一時的に隔離することで、サービス安定性を最大限に高めることができます。
これで、IstioのOutlier Detectionがどのように動作するのか、そしてなぜ「受動的」方式なのかが明確に理解できたでしょうか?この概念を正確に理解し適用して、より堅牢で弾力的なマイクロサービスを構築してみてください!
コメントを残す