# 通知設計書 22-InspectFailed

## 概要

本ドキュメントは、Kubernetesクラスタにおいてコンテナイメージの検査（inspect）に失敗した際に発行されるイベント通知「InspectFailed」の設計を定義する。

### 本通知の処理概要

コンテナイメージのプル前チェック処理において、ローカルのイメージ参照情報の取得に失敗した場合に、kubeletのimageManagerがWarningイベントとしてKubernetes Event APIに記録する通知である。

**業務上の目的・背景**：イメージのinspect処理はPullIfNotPresentやPullNeverポリシーにおいて、ローカルにイメージが存在するかどうかを判定するために必要な前処理である。この処理が失敗する場合、CRIランタイムとの通信障害やイメージストアの破損などが疑われるため、運用者への早期通知が重要である。

**通知の送信タイミング**：kubeletがimageService.GetImageRef()を呼び出してローカルイメージの参照情報を取得する際にエラーが発生した時点、またはapplyDefaultImageTag()でイメージ名の解析に失敗した時点で発行される。

**通知の受信者**：Kubernetes Event APIを通じて、対象PodのObjectReferenceに紐づくイベントとして記録される。kubectl describe pod等で確認可能であり、外部通知システムを通じてクラスタ管理者に伝達される。

**通知内容の概要**：失敗したイメージ名とエラー詳細を含むメッセージが通知される。メッセージ形式は「Failed to inspect image "イメージ名": エラー詳細」または「Failed to apply default image tag "イメージ名": エラー詳細」となる。

**期待されるアクション**：受信者は(1)CRIランタイムの状態を確認、(2)イメージストアの健全性を確認、(3)イメージ名の形式が正しいか確認、(4)ノードのディスク状態を確認、などの対応を行う。

## 通知種別

Kubernetes Event（APIリソース）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（イメージプル前チェック処理内で即時実行） |
| 優先度 | 高（EventType: Warning） |
| リトライ | イベント記録自体のリトライはEventRecorderの内部実装に依存 |

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

対象PodのObjectReference（`*v1.ObjectReference`）に対してイベントが記録される。ObjectReferenceがnilの場合はklogへのWarningログ出力のみとなる。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | N/A（Kubernetes Event） |
| 送信元名称 | kubelet |
| 件名 | N/A |
| 形式 | テキスト |

### 本文テンプレート

パターン1（GetImageRef失敗時）:
```
Failed to inspect image "{イメージ参照}": {エラー詳細}
```

パターン2（デフォルトタグ適用失敗時）:
```
Failed to apply default image tag "{イメージ名}": {エラー詳細}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| N/A | - | - | Kubernetes Eventのため添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| imageRef / requestedImage | 検査対象のイメージ名またはイメージ参照 | EnsureImageExists引数 / GetImageRef返却値 | Yes |
| err | inspect失敗時のエラー詳細 | imageService.GetImageRef()の返却エラー | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 内部処理 | imageService.GetImageRef()のエラー | pullPolicyがPullIfNotPresentまたはPullNeverの場合 | imagePullPrecheck内の122-126行目 |
| 内部処理 | applyDefaultImageTag()のエラー | 常に（イメージ名解析失敗） | EnsureImageExists内の176-181行目 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| pullPolicyがPullAlways | PullAlwaysの場合はGetImageRefが呼ばれないため本イベントは発行されない |
| ObjectReferenceがnil | klogへのWarningログ出力のみ |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[EnsureImageExists呼び出し] --> B[applyDefaultImageTag]
    B -->|失敗| C[InspectFailedイベント発行]
    B -->|成功| D[imagePullPrecheck呼び出し]
    D --> E{pullPolicyチェック}
    E -->|PullAlways| F[inspect不要、プルへ]
    E -->|PullIfNotPresent/PullNever| G[GetImageRef呼び出し]
    G -->|失敗| H[InspectFailedイベント発行]
    G -->|成功| I[イメージ存在判定]
    C --> J[ErrInvalidImageName返却]
    H --> K[ErrImageInspect返却]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| N/A | - | CRIランタイムのイメージストアを参照 |

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

本通知はデータベースを直接参照しない。CRI APIを通じてローカルイメージストアを参照する。

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| Event APIリソース（etcd） | INSERT | Warningイベントの記録 |

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

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | Type | Warning | EventType |
| INSERT | Reason | InspectFailed | イベント理由 |
| INSERT | Message | "Failed to inspect image..." | エラー詳細を含むメッセージ |
| INSERT | InvolvedObject | Pod ObjectReference | 対象Pod |
| INSERT | Source.Component | kubelet | 発行元コンポーネント |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ErrImageInspect | GetImageRefがエラーを返す | CRIランタイムの状態確認、ノードの再起動 |
| ErrInvalidImageName | イメージ名の解析に失敗 | Pod specのイメージ名の形式を修正 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Pod起動リトライの一部として間接的にリトライされる |
| リトライ間隔 | kubeletのPod同期間隔に依存 |
| リトライ対象エラー | ErrImageInspect, ErrInvalidImageName |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | EventRecorderのバースト設定に依存 |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（24時間365日）

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

- CRIランタイムからのエラーメッセージがそのまま記録されるため、内部情報が露出する可能性がある
- RBACによるEventリソースへのアクセス制御が適用される

## 備考

- InspectFailedはイメージプル処理の前段階で発生するエラーであり、イメージプルそのものは実行されない
- PullAlwaysの場合はinspect処理がスキップされるため、本イベントはapplyDefaultImageTag失敗時のみ発行される可能性がある

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.go | `pkg/kubelet/images/types.go` | ErrImageInspect, ErrInvalidImageNameのエラー定義（32-41行目） |
| 1-2 | event.go | `pkg/kubelet/events/event.go` | FailedToInspectImage = "InspectFailed" 定数定義（50行目） |

**読解のコツ**: InspectFailedイベント理由はFailedToInspectImage定数として定義されている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | image_manager.go | `pkg/kubelet/images/image_manager.go` | EnsureImageExists関数内のapplyDefaultImageTag呼び出し（176-181行目） |

**主要処理フロー**:
1. **176行目**: applyDefaultImageTag呼び出し
2. **177-181行目**: 失敗時にInspectFailedイベント発行、ErrInvalidImageName返却

#### Step 3: inspect処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | image_manager.go | `pkg/kubelet/images/image_manager.go` | imagePullPrecheck関数（109-136行目） |

**主要処理フロー**:
- **120-127行目**: PullIfNotPresent/PullNeverの場合にGetImageRefを呼び出し
- **122-126行目**: GetImageRef失敗時にInspectFailedイベント発行、ErrImageInspect返却

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

```
kuberuntime_manager.go: startContainer()
    |
    +-- imagePuller.EnsureImageExists()         [image_manager.go:164]
            |
            +-- applyDefaultImageTag()           [image_manager.go:417]
            |       +-- logIt() --> InspectFailed [image_manager.go:179] (解析失敗時)
            |
            +-- imagePullPrecheck()              [image_manager.go:109]
                    |
                    +-- imageService.GetImageRef() (CRI API呼び出し)
                    +-- logIt() --> InspectFailed [image_manager.go:124] (GetImageRef失敗時)
```

### データフロー図

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

Pod spec               --> EnsureImageExists()          --> ErrInvalidImageName
  requestedImage            |                               ErrImageInspect
  pullPolicy                +-- applyDefaultImageTag()
                            +-- imagePullPrecheck()
                                |
CRIランタイム           <-- imageService.GetImageRef()
  (containerd/CRI-O)        |
                            +-- error
                                |
                            +-- logIt()                 --> Kubernetes Event API
                                recorder.Event()            (Warning/InspectFailed)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| event.go | `pkg/kubelet/events/event.go` | ソース | FailedToInspectImage定数定義 |
| types.go | `pkg/kubelet/images/types.go` | ソース | ErrImageInspect, ErrInvalidImageName定義 |
| image_manager.go | `pkg/kubelet/images/image_manager.go` | ソース | inspect処理実装、InspectFailedイベント発行 |
| image_manager_test.go | `pkg/kubelet/images/image_manager_test.go` | テスト | InspectFailedシナリオのテスト |
