# 通知設計書 91-FailedCreate

## 概要

本ドキュメントは、CronJobコントローラがJobの作成に失敗した際に発行されるKubernetesイベント通知「FailedCreate」の設計を記述する。

### 本通知の処理概要

CronJobコントローラがスケジュールに従ってJobリソースを作成しようとした際に、API Serverへの作成リクエストが失敗した場合にWarningイベントとして発行される通知である。

**業務上の目的・背景**：CronJobは定期的にJobを作成して実行するKubernetesリソースであるが、Namespaceの終了中やリソースクォータ超過、RBACの権限不足など様々な理由でJob作成が失敗する可能性がある。この通知は、CronJobが期待通りに動作していないことをクラスタ管理者やアプリケーション運用者に迅速に通知し、問題の早期発見と対処を可能にする。

**通知の送信タイミング**：CronJobコントローラの`syncCronJob`メソッドにおいて、`jobControl.CreateJob`がエラーを返し、かつそのエラーがNamespaceTerminatingやAlreadyExistsでない場合に発行される。具体的には、CronJobのスケジュール時刻に到達し、Job作成処理が実行されたタイミングである。

**通知の受信者**：Kubernetesイベントとして該当CronJobオブジェクトに記録される。`kubectl get events`や`kubectl describe cronjob`で確認可能であり、イベントウォッチャーやモニタリングツール（Prometheus、Datadog等）を通じてクラスタ管理者に通知される。

**通知内容の概要**：EventTypeはWarning、Reasonは「FailedCreate」、メッセージにはJob作成時に発生したエラーの詳細が含まれる。フォーマットは「Error creating job: {エラー内容}」である。

**期待されるアクション**：受信者はエラー内容を確認し、Job作成が失敗した原因を特定して修正する。一般的な原因としては、リソースクォータ超過、RBAC権限不足、Namespace削除中、JobTemplateの設定不備などが考えられ、それぞれに応じた対処が必要となる。

## 通知種別

Kubernetesイベント（Event API リソース）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（syncCronJob処理内で即座に発行） |
| 優先度 | 高（Jobが作成されないためCronJobの目的を果たせない） |
| リトライ | CronJobコントローラのワークキューにより自動リトライされる（rate limited requeue） |

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

CronJobコントローラの`recorder.Eventf`メソッドにより、対象のCronJobオブジェクトに対してイベントが記録される。送信先は当該CronJobオブジェクトのNamespace/Name配下のイベントリソースとして保存される。

## 通知テンプレート

### メール通知の場合

本通知はKubernetesイベントであり、メール送信は行わない。イベントの構造は以下の通りである。

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | N/A（Kubernetesイベント） |
| 送信元名称 | cronjob-controller |
| 件名 | N/A |
| 形式 | Kubernetesイベントリソース |

### 本文テンプレート

```
Error creating job: %v
```

変数`%v`にはJob作成時に返されたエラーオブジェクトの文字列表現が挿入される。

### 添付ファイル

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

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| err | Job作成時のエラー内容 | jobControl.CreateJob戻り値 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| コントローラ同期 | CronJobのスケジュール時刻到達 | jobControl.CreateJobがエラーを返し、かつNamespaceTerminatingでもAlreadyExistsでもない場合 | syncCronJobメソッド内のJob作成失敗時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| Namespaceが終了中 | HasStatusCause(err, NamespaceTerminatingCause)がtrueの場合はこのイベントではなく、別のエラー処理パスに入る |
| Jobが既に存在 | errors.IsAlreadyExists(err)がtrueの場合は既存Jobの再利用処理に入る |
| CronJobがSuspend中 | Spec.Suspendがtrueの場合はJob作成自体が行われない |
| タイムゾーン不正 | Spec.TimeZoneが無効な場合はUnknownTimeZoneイベントが発行される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[CronJob同期処理開始] --> B[スケジュール時刻チェック]
    B -->|時刻到達| C[ConcurrencyPolicy確認]
    B -->|未到達| Z[次回スケジュールでリキュー]
    C --> D[JobTemplateからJob生成]
    D --> E[jobControl.CreateJob実行]
    E --> F{作成結果}
    F -->|成功| G[SuccessfulCreateイベント発行]
    F -->|AlreadyExists| H[既存Job再利用処理]
    F -->|NamespaceTerminating| I[エラー返却]
    F -->|その他エラー| J[FailedCreateイベント発行]
    J --> K[エラー返却・リキュー]
    G --> L[ActiveList更新]
    Z --> M[終了]
    L --> M
    K --> M
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| CronJob | スケジュール情報、JobTemplate取得 | API Server経由 |
| Job | 既存Job一覧取得 | Informerキャッシュ経由 |

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

#### CronJob

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| Spec.Schedule | スケジュール判定 | cronJobLister経由 |
| Spec.JobTemplate | Job生成テンプレート | cronJobLister経由 |
| Spec.ConcurrencyPolicy | 並行実行ポリシー | cronJobLister経由 |
| Spec.Suspend | 停止状態確認 | cronJobLister経由 |
| Spec.TimeZone | タイムゾーン | cronJobLister経由 |
| Status.Active | アクティブJob一覧 | cronJobLister経由 |
| Status.LastScheduleTime | 最終スケジュール時刻 | cronJobLister経由 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| Event | INSERT | FailedCreateイベント作成 |

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

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | Event.Type | Warning | イベント種別 |
| INSERT | Event.Reason | FailedCreate | イベント理由 |
| INSERT | Event.Message | Error creating job: {err} | エラーメッセージ |
| INSERT | Event.Source.Component | cronjob-controller | 発行元コンポーネント |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| リソースクォータ超過 | Namespace内のリソース制限に達した場合 | クォータの引き上げまたは不要リソースの削除 |
| RBAC権限不足 | CronJobコントローラのServiceAccountにJob作成権限がない場合 | ClusterRole/RoleBindingの修正 |
| バリデーションエラー | JobTemplateの仕様が不正な場合 | CronJobのspec.jobTemplateを修正 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | ワークキューのrate limitedリトライ（指数バックオフ） |
| リトライ間隔 | 初回5ms、最大1000秒（デフォルトRateLimiter設定） |
| リトライ対象エラー | syncCronJob関数がerrorを返すすべてのケース |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | Kubernetesイベントのデフォルト集約ルールに従う |
| 1日あたり上限 | 特に制限なし（ただしイベントTTLのデフォルトは1時間） |

### 配信時間帯

制限なし。CronJobのスケジュール時刻に応じて任意の時間帯で発行される。

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

エラーメッセージにはAPI Serverからのエラー詳細が含まれるため、内部的なリソース名やNamespace名が露出する可能性がある。ただし、Kubernetesイベントへのアクセスは通常RBACで制御されているため、適切なアクセス制御が設定されていれば問題はない。

## 備考

- 本イベントはCronJobコントローラv2（`cronjob_controllerv2.go`）で実装されている
- EventSourceのComponentは「cronjob-controller」（行97で設定）
- Job作成後のステータス更新が失敗した場合は別のエラーパスとなる

---

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

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

### 推奨読解順序

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

CronJobとJobのAPI型定義を理解することが最初のステップである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.go | `staging/src/k8s.io/api/batch/v1/types.go` | CronJob構造体のSpec（Schedule, JobTemplate, ConcurrencyPolicy等）とStatus（Active, LastScheduleTime等）を理解する |
| 1-2 | injection.go | `pkg/controller/cronjob/injection.go` | jobControlInterface（GetJob, CreateJob, DeleteJob）とcjControlInterface（UpdateStatus, GetCronJob）を理解する |

**読解のコツ**: CronJob.Spec.JobTemplateがJob生成のテンプレートとなる点が重要。

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

CronJobコントローラの同期ループの起点を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cronjob_controllerv2.go | `pkg/controller/cronjob/cronjob_controllerv2.go` | ControllerV2構造体とNewControllerV2関数（行84-131）でコントローラの初期化を理解する |

**主要処理フロー**:
1. **行97**: EventRecorderの生成。Component名は「cronjob-controller」
2. **行134-162**: Run関数でワーカー起動
3. **行169-186**: processNextWorkItem関数でキューからキーを取得しsync関数を呼出
4. **行188-235**: sync関数でCronJobオブジェクト取得、関連Job取得、syncCronJob呼出

#### Step 3: 同期処理の詳細を理解する

syncCronJobメソッドがJob作成の中核ロジックである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cronjob_controllerv2.go | `pkg/controller/cronjob/cronjob_controllerv2.go` | syncCronJob関数（行426-674）の処理フロー全体を理解する。特に行609-642のJob作成部分が本通知の発行箇所 |

**主要処理フロー**:
- **行604**: getJobFromTemplate2でJobオブジェクト生成
- **行609**: jobControl.CreateJobでAPI Serverに作成リクエスト
- **行611-614**: NamespaceTerminatingエラーの場合はイベント発行せず返却
- **行615-637**: AlreadyExistsエラーの場合は既存Job再利用
- **行638-641**: その他エラーの場合に`FailedCreate`イベント発行

#### Step 4: Job生成ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | utils.go | `pkg/controller/cronjob/utils.go` | getJobFromTemplate2関数（行244-267）でCronJobのJobTemplateからJobオブジェクトを生成する処理を理解する |

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

```
ControllerV2.Run (行134)
    |
    +-- worker (行164)
         |
         +-- processNextWorkItem (行169)
              |
              +-- sync (行188)
                   |
                   +-- cronJobLister.CronJobs().Get (行194)
                   +-- getJobsToBeReconciled (行205, 258)
                   +-- cleanupFinishedJobs (行214, 682)
                   +-- syncCronJob (行216, 426)
                        |
                        +-- time.LoadLocation (行507) -- UnknownTimeZone
                        +-- parsers.ParseCronScheduleWithPanicRecovery (行519)
                        +-- nextScheduleTime (行528)
                        +-- getJobFromTemplate2 (行604)
                        +-- jobControl.CreateJob (行609)
                        |    |
                        |    +-- 成功 -> SuccessfulCreate (行649)
                        |    +-- AlreadyExists -> 既存Job再利用
                        |    +-- NamespaceTerminating -> エラー返却
                        |    +-- その他エラー -> FailedCreate (行640) ★本通知
                        |
                        +-- recorder.Eventf (行640)
```

### データフロー図

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

CronJob Spec       --> syncCronJob                  --> FailedCreate Event
  .Schedule             |                                (Warning)
  .JobTemplate          +-- getJobFromTemplate2
  .ConcurrencyPolicy    +-- jobControl.CreateJob
  .TimeZone             +-- recorder.Eventf
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cronjob_controllerv2.go | `pkg/controller/cronjob/cronjob_controllerv2.go` | ソース | CronJobコントローラのメインロジック。FailedCreateイベント発行箇所（行640） |
| utils.go | `pkg/controller/cronjob/utils.go` | ソース | Job生成、スケジュール計算ユーティリティ |
| injection.go | `pkg/controller/cronjob/injection.go` | ソース | jobControlInterface、cjControlInterfaceの定義と実装 |
| types.go | `staging/src/k8s.io/api/batch/v1/types.go` | ソース | CronJob、Job等のAPI型定義 |
| parsers.go | `pkg/util/parsers/parsers.go` | ソース | Cronスケジュール解析ユーティリティ |
