Kubernetesのレジリエンス:Chaos Meshでクラスターを堅牢化する

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

回避できたはずの午前2時の呼び出し

夜中の2時、枕元のスマートフォンが震えます。PagerDutyが致命的なサービス停止を知らせるアラートを鳴らしています。霞む目をこすりながらログインすると、そこには惨状が広がっていました。1つのPodがクラッシュし、それがリトライの嵐を引き起こしてデータベースを過負荷にし、イングレスコントローラーまでオフラインにしてしまったのです。スタック全体が機能停止しています。

私たちの多くが、このような悪夢を経験したことがあります。レプリカやヘルスチェックがあるからシステムは弾力的(レジリエント)だと思い込みがちですが、本番環境は私たちが見逃したエッジケースを容赦なく暴き出します。ここで登場するのが「カオスエンジニアリング」です。真夜中に災害が降りかかるのを待つのではなく、午後2時のコントロールされた状況下で自ら障害を引き起こすのです。私の経験上、Chaos Meshはこの作業において最も精密なツールです。

クイックスタート:300秒で最初のPodを壊す

Chaos Meshは、Kubernetes上で直接障害をオーケストレーションするクラウドネイティブなプラットフォームです。Custom Resource Definitions (CRDs) を使用しており、Deploymentを定義するのと同じくらい簡単に障害を定義できます。さっそくセットアップして、最初の実験を実行してみましょう。

1. Chaos Meshのインストール

最も早いインストール方法は Helm を使うことです。 クラスターの準備が整っており、kubectl が設定されていることを前提とします。

helm repo add chaos-mesh https://charts.chaos-mesh.org
kubectl create ns chaos-mesh
helm install chaos-mesh chaos-mesh/chaos-mesh -n chaos-mesh --set dashboard.create=true

kubectl get po -n chaos-mesh で進捗を確認してください。Podが実行されたら、いよいよ「破壊」の準備完了です。

2. Pod障害実験の定義

よくある悩みの種をシミュレートしてみましょう。本番環境のネームスペースにある特定のPodが突然停止するケースです。pod-kill.yaml という名前のファイルを作成します。

apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
  name: pod-failure-example
  namespace: default
spec:
  action: pod-kill
  mode: one
  selector:
    namespaces:
      - app-production
    labelSelectors:
      "app": "web-server"
  scheduler:
    cron: "@every 1m"

3. 実験の実行

設定を適用してカオスを開始します。

kubectl apply -f pod-kill.yaml

60秒以内に、Chaos Meshは web-server というラベルの付いたPodを強制終了させます。ここで、モニタリングツールを確認してください。ロードバランサーは502エラーを適切に処理していますか? KubernetesはSLAを維持するのに十分な速さで代替Podを起動していますか? もしユーザーがラグを感じたなら、それは緊急事態になる前に弱点を見つけられたということです。

カオスの仕組み

Chaos Meshは単にプロセスを停止させるだけではありません。Linuxカーネルを活用して、複雑な障害をシミュレートします。そのアーキテクチャは主に3つのコンポーネントで構成されています。

  • Chaos Dashboard: YAMLを直接触らずに実験を管理できるビジュアルコマンドセンター。
  • Chaos Controller Manager: カオスオブジェクトのスケジュールとライフサイクルを管理する頭脳。
  • Chaos Daemon: すべてのノードで実行される特権デーモンセット。eBPFやcgroupsを使用して、ネットワークスタックやファイルシステムを操作します。

この設計により、クロックスキューやカーネルパニックなど、手動ではシミュレーションがほぼ不可能な障害を注入できます。手動スクリプトとは異なり, Chaos Meshは自己修復機能を備えています。実験が終了するかCRDを削除すれば、システムは即座に元の状態に戻ります。不要なiptablesルールや壊れた設定が残ることはありません。

主な障害タイプ

  1. PodChaos: Podやコンテナのクラッシュ、および「Pending」状態をシミュレートします。
  2. NetworkChaos: 遅延、パケットロス、データの破損を注入します。これはマイクロサービスの「死の連鎖(デススパイラル)」の主な原因です。
  3. IOChaos: ディスクパフォーマンスの低下やファイルシステムエラーを模倣します。
  4. StressChaos: CPUやメモリを限界まで消費させ、Horizontal Pod Autoscaler (HPA) の応答性をテストします。

応用編:不安定なマイクロサービスのシミュレーション

Podを停止させるのは基本のテストに過ぎません。真の価値は、特定の2つのサービス間のネットワーク劣化をシミュレートすることにあります。サービスAがサービスBを呼び出していると仮定しましょう。接続に突然200msの遅延が発生した場合、何が起こるかを知る必要があります。

ネットワーク遅延の注入

network-latency.yaml ファイルを作成します。

apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
  name: network-latency-test
spec:
  action: delay
  mode: all
  selector:
    namespaces:
      - app-production
    labelSelectors:
      "app": "service-a"
  delay:
    latency: "200ms"
    jitter: "50ms"
  direction: to
  target:
    selector:
      labelSelectors:
        "app": "service-b"
    namespaces:
      - app-production

この実験は、サービスAからサービスBへ向かうトラフィックのみをターゲットにします。クラスターの他の部分は影響を受けません。この精密な制御は、ステージング環境全体をダウンさせることなく、サーキットブレーカーやタイムアウトロジックをテストするために不可欠です。

現場で得た貴重な教訓

カオス実験は、無計画に行うと危険を伴います。生産的な実験にするために、私が守っているルールをいくつか紹介します。

1. ベースラインを確立する

監視していないものは測定できません。何かを壊す前に、Grafanaなどのダッシュボードで「定常状態(ステディステート)」、つまり通常のエラー率やp99レイテンシを確認してください。オブザーバビリティが整っていない場合は、まずそれを構築することから始めてください。

2. 爆発半径(ブラスト半径)を制御する

最初から本番クラスター全体で実験を行ってはいけません。まずは専用のQAネームスペースから始めましょう。自信がついたら、本番のトラフィックを再現したステージング環境へ移行します。実際の稼働環境でのスケジュールされた「ゲームデー(避難訓練)」を検討するのは、その次です。

3. カオスを自動化する

レジリエンスは一度確認すれば終わりではありません。新しいコードをリリースするたびに、新しい脆弱性が生まれる可能性があります。CI/CDパイプラインに統合しましょう。例えば、結合テスト環境へのデプロイごとに PodKill 実験を実行します。テストに失敗すれば、そのコードはまだ実戦投入の準備ができていないということです。

4. 緊急停止スイッチを用意しておく

Chaos Meshはクリーンアップに優れていますが、常に手動での中止プランを持っておくべきです。YAMLオブジェクトを削除すれば、障害は即座に停止します。

kubectl delete -f pod-kill.yaml

まとめ

信頼性は構築する「機能」ではなく、維持し続ける「習慣」です。Chaos Meshを使用して能動的に弱点を探し出すことで、問題発見の負担を顧客からチームへと移すことができます。日曜日の朝にバグで叩き起こされるより、火曜日の午後にタイムアウトのバグを修正する方がはるかにマシです。今日からシステムを壊し始めましょう。あなたの睡眠スケジュールが、将来のあなたに感謝することでしょう。

Share: