# 通知設計書 7-BackOff

## 概要

本ドキュメントは、Kubernetesのkubeletがコンテナ起動のバックオフ（再起動待機）を検出した際に発行する「BackOff」イベント通知の設計を記述する。

### 本通知の処理概要

kubeletのコンテナランタイムマネージャがコンテナの再起動を試みた際に、バックオフ期間中であることを検出した場合にKubernetes Event APIを用いて「BackOff」イベントを記録する通知である。CrashLoopBackOff状態の検出を示す。

**業務上の目的・背景**：コンテナが繰り返しクラッシュし再起動される状況（CrashLoopBackOff）は、アプリケーションに根本的な問題があることを示す。この通知により、運用者はコンテナがバックオフ状態に入ったことを検知でき、アプリケーションのログ確認や設定の見直しを促される。CrashLoopBackOffはKubernetes運用で最も一般的なトラブルシューティング対象の一つである。

**通知の送信タイミング**：`doBackOff`関数内で、コンテナの再起動がバックオフ期間中であると判定された場合に発行される（`kuberuntime_manager.go` 1843行目）。具体的には、前回のコンテナ終了時刻からバックオフ期間が経過していない場合に発行される。

**通知の受信者**：Kubernetes Event APIを通じて記録されるため、kubectl eventsやモニタリングツールを利用するクラスタ管理者が受信者となる。Warning Eventであるため監視アラート対象となる。

**通知内容の概要**：イベントにはEventType（Warning）、Reason（BackOff）、およびメッセージ"Back-off restarting failed container {コンテナ名} in pod {Pod名}"が含まれる。

**期待されるアクション**：運用者はコンテナのログ（kubectl logs）を確認し、クラッシュの原因を調査する。一般的な原因として、設定ミス、依存サービスの未起動、リソース不足、アプリケーションバグ等がある。

## 通知種別

Kubernetes Eventオブジェクト（API内部通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（Event APIへの書き込み） |
| 優先度 | 高（Warning Event） |
| リトライ | Event API書き込み失敗時はkubelet内部でリトライ |

### 送信先決定ロジック

バックオフ中のコンテナの参照（ObjectReference）をGenerateContainerRefで生成し、Kubernetes Event APIサーバへ送信する。

## 通知テンプレート

### メール通知の場合

本通知はKubernetes Event APIオブジェクトとして発行されるため、メール通知は該当しない。

### 本文テンプレート

```
Back-off restarting failed container {コンテナ名} in pod {Pod名}
```

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| コンテナ名 | バックオフ中のコンテナ名 | container.Name | Yes |
| Pod名 | 対象Podの名前 | format.Pod(pod) | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| kubelet内部 | コンテナ再起動判定 | backOff.IsInBackOffSinceがtrueを返す | 前回終了からバックオフ期間が未経過 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| バックオフ期間外 | バックオフ期間が経過済みの場合はイベント発行されず、コンテナの再起動が許可される |
| ObjectReference生成失敗 | GenerateContainerRefがエラーを返した場合はイベントスキップ |
| コンテナステータスなし | 前回のコンテナステータスが存在しない場合はdoBackOff自体がスキップ |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[SyncPod - コンテナ起動判定] --> B[doBackOff呼び出し]
    B --> C[前回終了時刻取得]
    C --> D{バックオフ期間中?}
    D -->|いいえ| E[backOff.Next: 次のバックオフ期間設定]
    E --> F[コンテナ再起動許可]
    D -->|はい| G[GenerateContainerRef]
    G --> H{参照生成成功?}
    H -->|成功| I[recorder.Eventf: BackOff]
    H -->|失敗| J[イベントスキップ]
    I --> K[CrashLoopBackOffエラー返却]
    J --> K
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| etcd（Podオブジェクト） | Podメタデータ参照 | kube-apiserver経由 |
| kubelet内部キャッシュ | コンテナステータスの前回終了時刻 | PodStatusから取得 |

### テーブル別参照項目詳細

#### コンテナステータス

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| FinishedAt | バックオフ計算の起点時刻 | 最新の終了したコンテナステータス |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| etcd（Eventオブジェクト） | INSERT | BackOffイベントオブジェクトの作成 |

#### 送信ログテーブル

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | Event.Reason | "BackOff" | イベント理由 |
| INSERT | Event.Type | "Warning" | 警告イベント |
| INSERT | Event.Message | "Back-off restarting failed container..." | バックオフメッセージ |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ObjectReference生成失敗 | コンテナ参照の生成エラー | イベント記録スキップ、バックオフエラーは正常返却 |
| Event API書き込み失敗 | kube-apiserverとの通信障害 | EventRecorderによる自動リトライ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | バックオフ期間経過後に次回のsyncPodで再評価 |
| リトライ間隔 | 指数バックオフ（初期値に対してGet(key)で取得） |
| リトライ対象エラー | CrashLoopBackOff |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | EventRecorderのバースト制限に依存 |
| 1日あたり上限 | 明示的な上限なし（同一イベントは集約） |

### 配信時間帯

制限なし。

## セキュリティ考慮事項

- メッセージにはコンテナ名とPod名のみが含まれ、機密情報は含まれない。

## 備考

- 本イベントはkubelet内の`kubeGenericRuntimeManager.doBackOff`関数（`kuberuntime_manager.go` 1843行目）で発行される。
- イベント定数は`pkg/kubelet/events/event.go` 27行目で`BackOffStartContainer = "BackOff"`として定義されている。
- バックオフは指数的に増加する。backOff.Get(key)でバックオフ期間を取得し、NewBackoffErrorでErrCrashLoopBackOffエラーを返す（1849行目）。
- バックオフの起点時刻はコンテナの最新の終了時刻（cStatus.FinishedAt）である（1838行目）。
- バックオフキーはGetBackoffKey(pod, container)で生成される（1840行目）。

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | event.go | `pkg/kubelet/events/event.go` | 27行目: `BackOffStartContainer = "BackOff"` の定数定義 |

**読解のコツ**: BackOffStartContainerはContainer event reason listに含まれるが、実際にはコンテナの再起動バックオフ全般に使用される。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kuberuntime_manager.go | `pkg/kubelet/kuberuntime/kuberuntime_manager.go` | 1836-1854行目: `doBackOff`関数 |

**主要処理フロー**:
1. **1836行目**: バックオフチェック開始のログ出力
2. **1838行目**: cStatus.FinishedAtで前回終了時刻取得
3. **1840行目**: GetBackoffKey(pod, container)でバックオフキー生成
4. **1841行目**: backOff.IsInBackOffSinceで判定
5. **1842行目**: GenerateContainerRefでObjectReference生成
6. **1843-1844行目**: recorder.EventfでBackOffイベント発行
7. **1846行目**: backOff.Get(key)でバックオフ期間取得
8. **1849行目**: NewBackoffError(ErrCrashLoopBackOff)でエラー返却
9. **1852行目**: バックオフ期間外の場合はbackOff.Nextで次の期間を設定

#### Step 3: SyncPodからの呼び出しを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kuberuntime_manager.go | `pkg/kubelet/kuberuntime/kuberuntime_manager.go` | SyncPod内のコンテナ起動判定でdoBackOffが呼ばれる |

### プログラム呼び出し階層図

```
kubeGenericRuntimeManager.SyncPod()
    |
    +-- computePodActions()
    |      +-- doBackOff()                          [kuberuntime_manager.go:1836]
    |             |
    |             +-- backOff.IsInBackOffSince()
    |             +-- GenerateContainerRef()
    |             +-- recorder.Eventf(BackOff)       [行1843]
    |             +-- backOff.Get() / backOff.Next()
    |             +-- NewBackoffError(ErrCrashLoopBackOff)
    |
    +-- startContainer() [バックオフ外の場合]
```

### データフロー図

```
[入力]                              [処理]                              [出力]

コンテナステータス  ------>  doBackOff()                     ------>  Kubernetes Event
(FinishedAt)                 |                                        (Type: Warning,
                             +-- IsInBackOffSince()                   Reason: BackOff,
バックオフ状態     ------>   +-- backOff.Get()                        Message: "Back-off restarting...")
(内部キャッシュ)              +-- recorder.Eventf()                    |
                                                                ------>  BackoffError
                                                                         (ErrCrashLoopBackOff)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| event.go | `pkg/kubelet/events/event.go` | ソース | イベント理由定数の定義 |
| kuberuntime_manager.go | `pkg/kubelet/kuberuntime/kuberuntime_manager.go` | ソース | doBackOff関数およびBackOffイベント記録 |
| kubelet.go | `pkg/kubelet/kubelet.go` | ソース | Pod同期のトリガー |
