# 通知設計書 3-Failed (CreateContainer)

## 概要

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

### 本通知の処理概要

kubeletのコンテナランタイムマネージャがコンテナの作成プロセスにおいてエラーが発生した場合に、Kubernetes Event APIを用いて「Failed」イベント（Reason: Failed）を記録する通知である。コンテナ作成の複数段階（イメージプル後のCRI呼び出し、設定生成、PreCreateContainerフック等）で失敗が検出された場合に発行される。

**業務上の目的・背景**：コンテナの作成失敗はPodの正常起動を妨げる重大な問題である。この通知により、運用者はコンテナの作成段階で何が問題だったのかを迅速に特定できる。イメージの不一致、リソース不足、設定エラーなど多様な原因がありうるため、エラーメッセージと併せて障害の根本原因の分析に利用される。

**通知の送信タイミング**：`startContainer`関数内のコンテナ作成処理の各段階でエラーが発生した際に発行される。具体的には以下の箇所：イメージプル失敗後（217行目）、ターゲットID取得失敗時（249行目）、コンテナ設定生成失敗時（259行目）、リソース設定失敗時（265行目）、PreCreateContainerフック失敗時（272行目）、CRI CreateContainer RPC失敗時（279行目）である。

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

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

**期待されるアクション**：運用者はエラーメッセージを確認し、以下の対応を行う。イメージ関連のエラーであればイメージの存在確認やレジストリの接続確認、設定エラーであればPod Specの見直し、リソース関連であればノードのリソース状況を確認する。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

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

## 通知テンプレート

### メール通知の場合

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

### 本文テンプレート

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

または

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

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| Pod名 | 対象Podの名前 | Pod.ObjectMeta.Name | Yes |
| Namespace | 対象PodのNamespace | Pod.ObjectMeta.Namespace | Yes |
| コンテナ名 | 対象コンテナの名前 | Container.Name | Yes |
| エラーメッセージ | gRPCステータスのメッセージ | grpcstatus.FromError(err).Message() | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API（CRI） | イメージプル失敗 | EnsureImageExists戻り値がエラー | イメージの取得に失敗した場合 |
| API（CRI） | ターゲットID取得失敗 | getTargetID戻り値がエラー | EphemeralContainer等のターゲット解決失敗 |
| API（CRI） | コンテナ設定生成失敗 | generateContainerConfig戻り値がエラー | コンテナの設定生成に失敗 |
| API（CRI） | リソース設定失敗 | setActuatedContainerResources戻り値がエラー | コンテナリソースの設定に失敗 |
| API（CRI） | PreCreateContainerフック失敗 | internalLifecycle.PreCreateContainer戻り値がエラー | 内部フック処理の失敗 |
| API（CRI） | CreateContainer RPC失敗 | runtimeService.CreateContainer戻り値がエラー | コンテナランタイムでの作成失敗 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 作成成功 | コンテナ作成が正常に完了した場合はCreatedイベントが発行される |
| ObjectReference生成失敗 | コンテナの参照生成に失敗した場合はイベントが記録されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[startContainer呼び出し] --> B[イメージプル]
    B --> B1{プル成功?}
    B1 -->|失敗| Z[recordContainerEvent: Failed]
    B1 -->|成功| C[ターゲットID取得]
    C --> C1{取得成功?}
    C1 -->|失敗| Z
    C1 -->|成功| D[コンテナ設定生成]
    D --> D1{生成成功?}
    D1 -->|失敗| Z
    D1 -->|成功| E[リソース設定]
    E --> E1{設定成功?}
    E1 -->|失敗| Z
    E1 -->|成功| F[PreCreateContainerフック]
    F --> F1{フック成功?}
    F1 -->|失敗| Z
    F1 -->|成功| G[CRI CreateContainer RPC]
    G --> G1{作成成功?}
    G1 -->|失敗| Z
    G1 -->|成功| H[recordContainerEvent: Created]
    Z --> Y[エラーメッセージ返却]
```

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

### 参照テーブル一覧

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

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

#### Podオブジェクト

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| ObjectMeta.Name | イベントの対象Pod特定 | kubeletが管理するPod |
| ObjectMeta.Namespace | イベントの記録先Namespace | kubeletが管理するPod |
| Spec.Containers[].Name | コンテナ参照生成 | startContainer呼び出し時 |

### 更新テーブル一覧

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

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

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| イメージプル失敗 | イメージの取得に失敗 | イメージ名の確認、レジストリ接続確認 |
| コンテナ設定生成失敗 | Pod Specに問題がある | Pod Specの修正 |
| CRI CreateContainer失敗 | コンテナランタイムエラー | ランタイムのログ確認、ノードの状態確認 |
| PreCreateContainerフック失敗 | 内部フック処理エラー | プラグインの設定確認 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし。

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

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

## 備考

- 本イベントのReasonは"Failed"であり、`FailedToCreateContainer`と`FailedToStartContainer`の両方が同じ"Failed"を使用する。メッセージ内容で区別する必要がある。
- イベント定数は`pkg/kubelet/events/event.go` 23行目で`FailedToCreateContainer = "Failed"`として定義されている。

---

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

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

### 推奨読解順序

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

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

**読解のコツ**: FailedToCreateContainerとFailedToStartContainerはどちらもReason値が"Failed"であることに注意。呼び出し箇所とメッセージで区別する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kuberuntime_container.go | `pkg/kubelet/kuberuntime/kuberuntime_container.go` | 199行目: `startContainer`関数の全体構造。特に217, 249, 259, 265, 272, 279行目のエラーパス |

**主要処理フロー**:
1. **217行目**: イメージプル失敗時のFailedイベント発行
2. **249行目**: ターゲットID取得失敗時のFailedイベント発行
3. **259行目**: コンテナ設定生成失敗時のFailedイベント発行
4. **265行目**: リソース設定失敗時のFailedイベント発行
5. **272行目**: PreCreateContainerフック失敗時のFailedイベント（メッセージが異なる）
6. **279行目**: CRI CreateContainer RPC失敗時のFailedイベント発行

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kuberuntime_manager.go | `pkg/kubelet/kuberuntime/kuberuntime_manager.go` | 1763行目: SyncPod内でのコンテナ作成失敗時のFailedイベント発行 |

**主要処理フロー**:
- **1763行目**: SyncPod内の並列コンテナ起動でも同様にFailedイベントが記録される

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

```
kubeGenericRuntimeManager.SyncPod()
    |
    +-- startContainer()                         [kuberuntime_container.go:199]
    |      |
    |      +-- imagePuller.EnsureImageExists()
    |      |      +-- [失敗] recordContainerEvent(Failed)  [行217]
    |      |
    |      +-- spec.getTargetID()
    |      |      +-- [失敗] recordContainerEvent(Failed)  [行249]
    |      |
    |      +-- generateContainerConfig()
    |      |      +-- [失敗] recordContainerEvent(Failed)  [行259]
    |      |
    |      +-- setActuatedContainerResources()
    |      |      +-- [失敗] recordContainerEvent(Failed)  [行265]
    |      |
    |      +-- internalLifecycle.PreCreateContainer()
    |      |      +-- [失敗] recordContainerEvent(Failed)  [行272]
    |      |
    |      +-- runtimeService.CreateContainer()
    |             +-- [失敗] recordContainerEvent(Failed)  [行279]
    |
    +-- [SyncPod内] recordContainerEvent(Failed)         [行1763]
```

### データフロー図

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

Pod Spec          ------>  startContainer()               ------>  Kubernetes Event
(Container定義)              |                                      (Type: Warning,
                             +-- 各段階のエラー検出                   Reason: Failed,
                             +-- grpcstatus.FromError()             Message: "Error: {詳細}")
                             +-- recordContainerEvent()
                             |
gRPC Error        <------  CRI Response / Internal Error
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| 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` | ソース | SyncPod内のコンテナ作成失敗ハンドリング |
