# 通知設計書 4-Failed (StartContainer)

## 概要

本ドキュメントは、Kubernetesのkubeletがコンテナの起動に失敗した際に発行する「Failed」イベント通知（StartContainer）の設計を記述する。

### 本通知の処理概要

kubeletのコンテナランタイムマネージャがCRIのStartContainer RPCを呼び出した結果、エラーが返却された場合、またはPreStartContainerフックが失敗した場合に、Kubernetes Event APIを用いて「Failed」イベントを記録する通知である。

**業務上の目的・背景**：コンテナの起動失敗は、作成には成功したがプロセスの開始ができなかったことを意味する。これは設定の問題（エントリポイントの不正、権限問題等）やリソースの競合などに起因する。運用者がこの通知を受け取ることで、コンテナのライフサイクルのどの段階で失敗したかを正確に把握でき、適切な対処を行える。

**通知の送信タイミング**：`startContainer`関数内でCRI StartContainer RPCがエラーを返した場合（294行目）、またはPreStartContainerフックが失敗した場合（285行目）に発行される。

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

**通知内容の概要**：イベントにはコンテナの参照情報、EventType（Warning）、Reason（Failed）、およびエラーの詳細メッセージが含まれる。

**期待されるアクション**：運用者はコンテナのエントリポイントや環境変数の設定を確認し、コンテナランタイムのログを調査する。セキュリティコンテキストの設定ミスやcgroupの問題なども原因として考えられる。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

kubeletが管理するPodに属するコンテナの参照（ObjectReference）を生成し、Kubernetes Event APIサーバへ送信する。

## 通知テンプレート

### メール通知の場合

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

### 本文テンプレート

```
Error: {gRPCエラーメッセージ}
```

または

```
Internal PreStartContainer hook failed: {gRPCエラーメッセージ}
```

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| Pod名 | 対象Podの名前 | Pod.ObjectMeta.Name | Yes |
| Namespace | 対象PodのNamespace | Pod.ObjectMeta.Namespace | Yes |
| コンテナ名 | 対象コンテナの名前 | Container.Name | Yes |
| コンテナID | CRIから返却されたコンテナID | CreateContainer RPC応答 | Yes |
| エラーメッセージ | gRPCステータスのメッセージ | grpcstatus.FromError(err).Message() | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API（CRI） | PreStartContainerフック失敗 | internalLifecycle.PreStartContainer戻り値がエラー | コンテナ起動前の内部フック処理の失敗 |
| API（CRI） | StartContainer RPC失敗 | runtimeService.StartContainer戻り値がエラー | コンテナランタイムでの起動失敗 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 起動成功 | コンテナ起動が正常に完了した場合はStartedイベントが発行される |
| コンテナ作成段階で失敗 | 作成段階で失敗した場合はFailedToCreateContainerのイベントとなる |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[コンテナ作成成功] --> B[PreStartContainerフック]
    B --> B1{フック成功?}
    B1 -->|失敗| Z[recordContainerEvent: Failed]
    B1 -->|成功| C[recordContainerEvent: Created]
    C --> D[CRI StartContainer RPC]
    D --> D1{起動成功?}
    D1 -->|失敗| Z
    D1 -->|成功| E[recordContainerEvent: Started]
    Z --> Y[エラーメッセージ返却]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| etcd（Podオブジェクト） | Pod・コンテナのメタデータ参照 | kube-apiserver経由 |

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

#### Podオブジェクト

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| ObjectMeta.Name | イベントの対象Pod特定 | kubeletが管理するPod |
| ObjectMeta.Namespace | イベントの記録先Namespace | kubeletが管理するPod |

### 更新テーブル一覧

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

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

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | Event.Reason | "Failed" | イベント理由 |
| INSERT | Event.Type | "Warning" | 警告イベント |
| INSERT | Event.Message | "Error: {詳細}" | エラーメッセージ |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| PreStartContainerフック失敗 | 内部フック処理エラー | プラグインの設定確認 |
| CRI StartContainer RPC失敗 | コンテナランタイムでの起動エラー | ランタイムログ確認、エントリポイント確認 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | kubeletのsyncPodループにより自動リトライ |
| リトライ間隔 | Pod同期間隔に依存 |
| リトライ対象エラー | すべてのコンテナ起動エラー |

## 配信設定

### レート制限

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

### 配信時間帯

制限なし。

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

- エラーメッセージにコンテナランタイムのgRPCエラー詳細が含まれるため、内部情報が露出する可能性がある。
- `recordContainerEvent`関数内でcontainerIDをコンテナ名に置換する処理が行われる。

## 備考

- 本イベントのReasonは"Failed"であり、No.3のFailedToCreateContainerと同一のReason値を使用する。メッセージ内容（"Error:" vs "Internal PreStartContainer hook failed:"）で区別が可能。
- イベント定数は`pkg/kubelet/events/event.go` 24行目で`FailedToStartContainer = "Failed"`として定義されている。

---

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

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

### 推奨読解順序

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

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

**読解のコツ**: FailedToStartContainerはFailedToCreateContainerと同じ"Failed"という値を持つ。コード内の使用箇所で両者を区別する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kuberuntime_container.go | `pkg/kubelet/kuberuntime/kuberuntime_container.go` | 282-297行目: PreStartContainerフックとStartContainer RPC |

**主要処理フロー**:
1. **282行目**: PreStartContainerフック実行
2. **283-286行目**: フック失敗時のFailedイベント発行（"Internal PreStartContainer hook failed:"）
3. **291行目**: CRI StartContainer RPC呼び出し
4. **292-295行目**: RPC失敗時のFailedイベント発行（"Error:"）

#### Step 3: イベント記録関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kuberuntime_container.go | `pkg/kubelet/kuberuntime/kuberuntime_container.go` | 84行目: `recordContainerEvent`関数 |

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

```
kubeGenericRuntimeManager.SyncPod()
    |
    +-- startContainer()                              [kuberuntime_container.go:199]
           |
           +-- runtimeService.CreateContainer()        [CRI RPC - 作成成功]
           +-- internalLifecycle.PreStartContainer()
           |      +-- [失敗] recordContainerEvent(Failed)  [行285]
           |
           +-- recordContainerEvent(Created)            [行288]
           +-- runtimeService.StartContainer()          [CRI RPC]
                  +-- [失敗] recordContainerEvent(Failed)  [行294]
```

### データフロー図

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

コンテナID        ------>  startContainer()               ------>  Kubernetes Event
(作成済み)                   |                                      (Type: Warning,
                             +-- CRI StartContainer                Reason: Failed,
                             +-- grpcstatus.FromError()             Message: "Error: {詳細}")
                             +-- recordContainerEvent()
                             |
gRPC Error        <------  CRI Response
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| event.go | `pkg/kubelet/events/event.go` | ソース | イベント理由定数の定義 |
| kuberuntime_container.go | `pkg/kubelet/kuberuntime/kuberuntime_container.go` | ソース | コンテナ起動処理およびFailedイベント記録 |
| kuberuntime_manager.go | `pkg/kubelet/kuberuntime/kuberuntime_manager.go` | ソース | Pod同期処理の全体管理 |
