1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kubernetesを学ぶ9日間 - Day 9: Chaos Engineering 入門

1
Last updated at Posted at 2025-12-18

はじめに

「ジャンルなしオンラインもくもく会 Advent Calendar 2025」の18日目の記事です。

今日は、意図的に障害を起こすカオスエンジニアリングを実践します。「本番環境で障害が起きる前に、障害を起こして耐障害性を検証する」というアプローチです。

本シリーズの全体構成

前回までのおさらい

カオスエンジニアリングとは?

定義

本番環境に近い状況で意図的に障害を注入し、システムの耐障害性を検証する手法

なぜ生まれたのか?

従来のテスト カオスエンジニアリング
正常系のテスト 異常系のテスト
正しく動くか? 壊れても大丈夫か?
理想的な環境 現実的な環境
ユニットテスト、結合テスト 本番環境での検証

現実

  • ネットワークは必ず遅延する
  • Podは予期せず落ちる
  • ディスクI/Oは突然遅くなる
  • メモリ不足は突然起きる

Netflixの事例: Chaos Monkey

Netflixが開発した本番環境でランダムにサーバーを停止するツール

  • ✅ 障害に強いアーキテクチャを実現
  • ✅ 障害発生時の復旧時間を短縮
  • ✅ エンジニアの障害対応スキル向上

Chaos Mesh とは?

特徴

  • CNCFプロジェクト(現在Incubating)
  • Kubernetes Native(CRDベース)
  • 豊富な障害シナリオ(Network, Pod, Stress, I/O, Time など)
  • WebベースのUI(Chaos Dashboard)
  • 定期的な障害注入(Workflow, Schedule)

サポートする障害タイプ(代表的なものを抜粋)

障害タイプ 説明 用途
PodChaos Pod削除/強制終了 再起動耐性検証
NetworkChaos 遅延/パケットロス/帯域制限 ネットワーク障害検証
StressChaos CPU/メモリ負荷 リソース枯渇検証
IOChaos I/O遅延/エラー ディスク障害検証
TimeChaos 時刻ずれ タイムスタンプ依存処理検証
DNSChaos DNS解決失敗/遅延 外部サービス依存検証
HTTPChaos HTTPエラー/遅延 API障害検証

Chaos Meshインストール

1. Helm

# Helm Repositoryを追加
helm repo add chaos-mesh https://charts.chaos-mesh.org
helm repo update

# インストール(Talos Linux + containerd環境)
helm install chaos-mesh chaos-mesh/chaos-mesh \
  -n chaos-mesh --create-namespace \
  --set chaosDaemon.runtime=containerd \
  --set chaosDaemon.socketPath=/run/containerd/containerd.sock

# PodSecurity を privileged に設定(chaos-daemonに必要)
kubectl label namespace chaos-mesh pod-security.kubernetes.io/enforce=privileged

# Pod起動確認
kubectl get pods -n chaos-mesh -o wide
NAME                                       READY   STATUS    RESTARTS   AGE
chaos-controller-manager-f864656b8-9k66w   1/1     Running   0          2m
chaos-daemon-jpndf                         1/1     Running   0          2m   # Worker-03
chaos-daemon-px7dv                         1/1     Running   0          2m   # Worker-02
chaos-daemon-q42tp                         1/1     Running   0          2m   # Worker-01
chaos-dashboard-696c7d7796-94gk6           1/1     Running   0          2m
chaos-dns-server-7449ff89-whh67            1/1     Running   0          2m

ポイント: chaos-daemon は DaemonSet で全ノードに配置。これが実際に障害を注入するエージェント。

2. Chaos Dashboard アクセス

# Ingress経由でアクセス
https://chaos.homelab.local

3. Dashboard 認証(RBAC トークン)

Dashboard にアクセスすると、RBAC トークンの入力を求められます。

Dashboard ログイン画面
ServiceAccount とトークンを作成します

# ServiceAccount と ClusterRole を作成
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: chaos-admin
  namespace: chaos-mesh
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: chaos-admin
rules:
  - apiGroups: ["chaos-mesh.org"]
    resources: ["*"]
    verbs: ["*"]
  - apiGroups: [""]
    resources: ["pods", "namespaces"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: chaos-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: chaos-admin
subjects:
  - kind: ServiceAccount
    name: chaos-admin
    namespace: chaos-mesh
EOF

# トークン生成(有効期限: 1年)
kubectl create token chaos-admin -n chaos-mesh --duration=8760h

生成されたトークンを Dashboard に入力

  • Name: chaos-admin
  • Token: 生成されたJWTトークン

Dashboard メイン画面

補足: このトークンは ClusterRole なので、全 namespace で chaos 実験を実行可能。特定 namespace に制限する場合は Role + RoleBinding を使用。


実践1: PodChaos(Pod障害)

デモアプリのデプロイ

まず、カオス実験対象のアプリ(podinfo)をデプロイします。

# podinfo をデプロイ(3レプリカ)
helm install podinfo podinfo/podinfo \
  -n demo --create-namespace \
  --set replicaCount=3 \
  --set ui.message="Chaos Target App"

# Pod確認
kubectl get pods -n demo -o wide
NAME                       READY   STATUS    RESTARTS   AGE   NODE
podinfo-86cd999777-bj6rm   1/1     Running   0          13s   k8s-worker-01
podinfo-86cd999777-ld69k   1/1     Running   0          13s   k8s-worker-02
podinfo-86cd999777-whl58   1/1     Running   0          13s   k8s-worker-02

シナリオ: Podが突然落ちる

apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
  name: pod-kill-demo
  namespace: chaos-mesh
spec:
  action: pod-kill
  mode: one  # 1つだけ削除
  selector:
    namespaces:
      - demo
    labelSelectors:
      app.kubernetes.io/name: podinfo
  duration: "30s"
# PodChaos適用
kubectl apply -f podchaos-kill.yaml

# 実行確認
kubectl get podchaos -n chaos-mesh
NAME            AGE
pod-kill-demo   10s

# Podが強制終了される → 自動復旧
kubectl get pods -n demo -o wide
NAME                       READY   STATUS    RESTARTS   AGE   NODE
podinfo-86cd999777-bj6rm   1/1     Running   0          86s   k8s-worker-01
podinfo-86cd999777-r8vpf   1/1     Running   0          6s    k8s-worker-02  # ← 新規作成!
podinfo-86cd999777-whl58   1/1     Running   0          86s   k8s-worker-02

結果: ld69k が kill され、r8vpf が自動で作成された。ReplicaSet が即座に復旧。

検証ポイント

  • ReplicaSet: 自動的に新しいPodが作成されるか? → 即座に復旧
  • Service: トラフィックが正常なPodにルーティングされるか?
  • Graceful Shutdown: アプリケーションが安全に終了するか?

実践2: NetworkChaos(ネットワーク障害)

シナリオ1: ネットワーク遅延

apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
  name: network-delay-demo
  namespace: chaos-mesh
spec:
  action: delay
  mode: all
  selector:
    namespaces:
      - demo
    labelSelectors:
      app.kubernetes.io/name: podinfo
  delay:
    latency: "3000ms"     # 3秒遅延
    correlation: "100"    # 100%の確率で適用
    jitter: "500ms"       # ±500msの揺らぎ
  direction: to           # 受信トラフィックに遅延
  duration: "60s"
# NetworkChaos適用
kubectl apply -f networkchaos-delay.yaml

# Ingress経由でレスポンス時間を計測
curl -sk -w "Time: %{time_total}s\n" -o /dev/null \
  https://10.0.0.210 -H "Host: podinfo.homelab.local"

# 遅延注入中: Time: 2.899952s 〜 5.732055s
# 通常時:     Time: 0.259037s

結果: 3秒の遅延注入により、レスポンス時間が約 11〜22 倍に増加。体感でも明らかに遅い。

シナリオ2: パケットロス

apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
  name: network-loss
  namespace: chaos-mesh
spec:
  selector:
    namespaces:
      - demo
    labelSelectors:
      app: backend

  action: loss

  mode: all

  # パケットロス設定
  loss:
    loss: "30"          # 30%のパケットをロス
    correlation: "80"

  direction: to

  duration: "5m"

シナリオ3: 帯域制限

apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
  name: network-bandwidth
  namespace: chaos-mesh
spec:
  selector:
    namespaces:
      - demo
    labelSelectors:
      app: backend

  action: bandwidth

  mode: all

  # 帯域制限
  bandwidth:
    rate: "1mbps"      # 1Mbpsに制限
    limit: 20000       # バッファサイズ
    buffer: 10000

  direction: to

  duration: "5m"

検証ポイント

  • Timeout設定: タイムアウトは適切か?
  • Retry: リトライロジックは機能するか?
  • Circuit Breaker: サーキットブレーカーは動作するか?
  • Fallback: フォールバック処理は適切か?

実践3: StressChaos(リソース負荷)

シナリオ1: CPU負荷

apiVersion: chaos-mesh.org/v1alpha1
kind: StressChaos
metadata:
  name: stress-cpu
  namespace: chaos-mesh
spec:
  selector:
    namespaces:
      - demo
    labelSelectors:
      app: backend

  mode: one

  # CPU負荷
  stressors:
    cpu:
      workers: 4      # 4ワーカー
      load: 80        # 各ワーカーが80%負荷

  duration: "5m"

シナリオ2: メモリ負荷

apiVersion: chaos-mesh.org/v1alpha1
kind: StressChaos
metadata:
  name: stress-memory
  namespace: chaos-mesh
spec:
  selector:
    namespaces:
      - demo
    labelSelectors:
      app: backend

  mode: one

  # メモリ負荷
  stressors:
    memory:
      workers: 4
      size: "512MB"   # 各ワーカーが512MB消費

  duration: "5m"
# リソース使用量確認
kubectl top pod -n demo -l app=backend
NAME                       CPU(cores)   MEMORY(bytes)
backend-5d8b9d8d9f-xxxxx   3200m        2048Mi  # ← 負荷注入中
backend-5d8b9d8d9f-yyyyy   100m         256Mi
backend-5d8b9d8d9f-zzzzz   100m         256Mi

検証ポイント

  • HPA: Horizontal Pod Autoscalerは動作するか?
  • Resource Limits: Pod Evictionは適切に発生するか?
  • OOM Kill: Out Of Memoryでの再起動は正常か?

実践4: Workflow(複合障害シナリオ)

シナリオ: 段階的な障害注入

apiVersion: chaos-mesh.org/v1alpha1
kind: Workflow
metadata:
  name: demo-chaos-workflow
  namespace: chaos-mesh
spec:
  entry: entry
  templates:
    # エントリーポイント
    - name: entry
      templateType: Serial
      children:
        - network-delay
        - pod-kill
        - stress-cpu

    # Step 1: ネットワーク遅延(5分間)
    - name: network-delay
      templateType: NetworkChaos
      deadline: 5m
      networkChaos:
        selector:
          namespaces:
            - demo
          labelSelectors:
            app: backend
        action: delay
        mode: all
        delay:
          latency: "500ms"
        direction: to
        duration: "5m"

    # Step 2: Pod削除(1つ)
    - name: pod-kill
      templateType: PodChaos
      deadline: 1m
      podChaos:
        selector:
          namespaces:
            - demo
          labelSelectors:
            app: backend
        action: pod-kill
        mode: one
        duration: "30s"

    # Step 3: CPU負荷(5分間)
    - name: stress-cpu
      templateType: StressChaos
      deadline: 5m
      stressChaos:
        selector:
          namespaces:
            - demo
          labelSelectors:
            app: backend
        mode: one
        stressors:
          cpu:
            workers: 4
            load: 90
        duration: "5m"
# Workflow適用
kubectl apply -f workflow.yaml

# 実行状態確認
kubectl get workflow -n chaos-mesh
NAME                          AGE   PHASE
demo-chaos-workflow     2m    Running

# 詳細確認
kubectl describe workflow demo-chaos-workflow -n chaos-mesh

並列実行(Parallel)

apiVersion: chaos-mesh.org/v1alpha1
kind: Workflow
metadata:
  name: parallel-chaos
  namespace: chaos-mesh
spec:
  entry: entry
  templates:
    - name: entry
      templateType: Parallel  # 並列実行
      children:
        - network-delay
        - stress-cpu
        - io-delay

    # 同時に3つの障害を注入
    - name: network-delay
      # ...

    - name: stress-cpu
      # ...

    - name: io-delay
      # ...

実践5: Schedule(定期実行)

毎日10時にPodを1つ削除

apiVersion: chaos-mesh.org/v1alpha1
kind: Schedule
metadata:
  name: scheduled-pod-kill
  namespace: chaos-mesh
spec:
  # Cron形式
  schedule: "0 10 * * *"  # 毎日10時

  # 実行履歴を保持
  historyLimit: 5

  # 同時実行を許可しない
  concurrencyPolicy: Forbid

  type: PodChaos
  podChaos:
    selector:
      namespaces:
        - demo
      labelSelectors:
        app: backend
    action: pod-kill
    mode: one
    duration: "30s"
# Schedule適用
kubectl apply -f schedule.yaml

# 実行履歴確認
kubectl get schedule scheduled-pod-kill -n chaos-mesh -o yaml
status:
  active:
  - kind: PodChaos
    name: scheduled-pod-kill-xxxxx
    namespace: chaos-mesh
  lastScheduleTime: "2025-12-18T01:00:00Z"

Chaos Dashboard(Web UI)

機能

  1. Chaos実験作成: GUIで障害シナリオを作成
  2. 実行状況監視: リアルタイムで実験の進捗を確認
  3. 結果分析: メトリクス、ログ、イベントを統合表示
  4. アーカイブ: 過去の実験結果を保存

Dashboard での実験作成

1. New Experiment をクリック
2. 障害タイプを選択(PodChaos, NetworkChaos, etc.)
3. 対象Podをラベルセレクタで指定
4. パラメータを設定(遅延時間、削除モードなど)
5. Submit で実験開始

Chaos Meshで実現できること

障害シナリオ 検証内容
PodChaos 再起動耐性、ReplicaSetの動作
NetworkChaos タイムアウト、リトライ、Circuit Breaker
StressChaos HPA、Resource Limits、OOM対応
Workflow 複合障害シナリオ
Schedule 定期的な耐障害性検証

導入効果

  • 本番障害の事前検証: 障害が起きる前に対策
  • 復旧時間の短縮: 障害対応の練習
  • 自信: 「壊れても大丈夫」という確信
  • 継続的改善: 定期的な検証で劣化を防止

まとめ

所感

実際にホームラボ環境で Chaos Mesh を動かしてみて感じたこと

良かった点

  • 導入は簡単: Helmコマンドで導入完了
  • 即座に効果が見える: PodChaosでPodをkillすると、ReplicaSetが数秒で復旧する様子が確認できた
  • NetworkChaosが強力: 1秒未満だと体感としてわかりにくいが、3秒の遅延を注入するとレスポンス時間が11〜22倍に。ブラウザでも体感できるレベルの遅延がでてよかったです

今後試したいこと

  • カオス実験中はGrafanaでメトリクスを見ながら実施する仕組みをいれる
  • Scheduleを使った定期的な障害注入を行って慣れていきたい
  • Workflowで複合障害シナリオ(遅延 → Pod kill → CPU 負荷の順番で実行)、ただし自分の首を絞めない程度で

シリーズを通して

  • 取り上げたいがボリュームからできないものも多かったので、後日気になるものを継続していきたいと思います
  • 数年前と比べてかなりの頻度でバージョンも上がっていたり、機能も増えているので、開発者に感謝しつつ追いかけていきます
  • なぜ〇〇が実現できるの?がいくつかあったので深堀りをして理解に努めていきたいですね

さいごに

  • 今回アドベントカレンダーの場を作ってくれたサーバー管理者様に感謝して来年はもうちょいアウトプットをしていきたいと思います!

シリーズ完走

9日間のKubernetes学習シリーズ、お疲れさまでした!


参考リンク

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?