# 通知設計書 5-Killing

## 概要

本ドキュメントは、Kubernetesのkubeletがコンテナを強制終了する際に発行する「Killing」イベント通知の設計を記述する。

### 本通知の処理概要

kubeletのコンテナランタイムマネージャがコンテナの停止処理を開始する際に、Kubernetes Event APIを用いて「Killing」イベントを記録する通知である。コンテナのGraceful Shutdownの開始を示す。

**業務上の目的・背景**：コンテナの停止はPodの削除、ローリングアップデート、エビクション、ヘルスチェック失敗など多様な理由で発生する。この通知により、運用者はコンテナがいつ停止処理に入ったかを追跡でき、停止理由をメッセージから把握できる。特にデバッグ時に、予期しない停止の原因分析に不可欠である。

**通知の送信タイミング**：`killContainer`関数の冒頭で、実際のSIGTERMシグナル送信やPreStopフック実行の前に発行される。コンテナの停止処理開始を示すマーカーイベントである（`kuberuntime_container.go` 864行目）。

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

**通知内容の概要**：イベントにはEventType（Normal）、Reason（Killing）、および停止理由を示すメッセージが含まれる。デフォルトメッセージは"Stopping container {コンテナ名}"であるが、呼び出し元から具体的な停止理由が渡される場合もある。

**期待されるアクション**：通常のPod削除やアップデートに伴う場合はアクション不要。予期しない停止の場合は、メッセージに含まれる停止理由を確認し、ヘルスチェック設定やリソース制限を見直す。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

停止対象のPodに属するコンテナの参照（ObjectReference）を生成し、Kubernetes Event APIサーバへ送信する。

## 通知テンプレート

### メール通知の場合

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

### 本文テンプレート

```
Stopping container {コンテナ名}
```

または呼び出し元が理由を指定した場合：

```
{停止理由メッセージ}
```

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| Pod名 | 対象Podの名前 | Pod.ObjectMeta.Name | Yes |
| Namespace | 対象PodのNamespace | Pod.ObjectMeta.Namespace | Yes |
| コンテナ名 | 対象コンテナの名前 | containerSpec.Name | Yes |
| コンテナID | 停止対象のコンテナID | containerID.ID | Yes |
| メッセージ | 停止理由 | 呼び出し元から渡されるmessage引数 | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API操作 | Pod削除 | kubeletがPod削除を処理 | ユーザによるPod削除 |
| コントローラ | ローリングアップデート | Deployment更新によるPod入れ替え | 古いPodのコンテナ停止 |
| kubelet | ヘルスチェック失敗 | LivenessProbe失敗 | コンテナの再起動 |
| kubelet | エビクション | リソース逼迫 | Podのエビクション |
| kubelet | PreStopフック前 | コンテナ停止処理開始 | すべてのコンテナ停止処理 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ObjectReference生成失敗 | containerSpecが取得できない場合、関数がエラーを返す |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[killContainer呼び出し] --> B[containerSpec取得]
    B --> B1{取得成功?}
    B1 -->|失敗| Z[エラー返却]
    B1 -->|成功| C[gracePeriod計算]
    C --> D[メッセージ生成]
    D --> E[recordContainerEvent: Killing]
    E --> F{PreStopフックあり?}
    F -->|あり| G[PreStopフック実行]
    F -->|なし| H[terminationOrdering待機]
    G --> H
    H --> I[CRI StopContainer RPC]
```

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

### 参照テーブル一覧

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

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

#### Podオブジェクト

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| ObjectMeta.Name | イベントの対象Pod特定 | kubeletが管理するPod |
| Spec.Containers[].Name | コンテナ参照生成 | killContainer呼び出し時 |
| Spec.TerminationGracePeriodSeconds | GracePeriod計算 | コンテナ停止時 |
| Spec.Containers[].Lifecycle.PreStop | PreStopフック有無判定 | コンテナ停止時 |

### 更新テーブル一覧

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

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

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | Event.Reason | "Killing" | イベント理由 |
| INSERT | Event.Type | "Normal" | 正常イベント |
| INSERT | Event.Message | "Stopping container {名前}" | デフォルトメッセージ |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| containerSpec取得失敗 | Pod情報からコンテナ仕様が見つからない | restoreSpecsFromContainerLabelsでコンテナラベルから復元を試行 |
| CRI StopContainer失敗 | コンテナランタイムでの停止失敗 | kubeletが再試行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | kubeletのPod同期ループによる自動リトライ |
| リトライ間隔 | Pod同期間隔に依存 |
| リトライ対象エラー | コンテナ停止エラー |

## 配信設定

### レート制限

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

### 配信時間帯

制限なし。

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

- メッセージには停止理由が含まれるが、機密情報は含まれない。
- `recordContainerEvent`関数内でcontainerIDをコンテナ名に置換する処理が行われる。

## 備考

- 本イベントはkubelet内の`kubeGenericRuntimeManager.killContainer`関数（`kuberuntime_container.go` 864行目）で発行される。
- イベント定数は`pkg/kubelet/events/event.go` 25行目で`KillingContainer = "Killing"`として定義されている。
- messageが空の場合はデフォルトメッセージ"Stopping container {名前}"が使用される（861-862行目）。
- Killingイベント発行後にPreStopフックの実行、terminationOrdering待機、実際のCRI StopContainer RPCが実行される。

---

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

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

### 推奨読解順序

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

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

**読解のコツ**: KillingContainerはContainer event reason listに含まれている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kuberuntime_container.go | `pkg/kubelet/kuberuntime/kuberuntime_container.go` | 841行目: `killContainer`関数の全体構造 |

**主要処理フロー**:
1. **844-856行目**: containerSpec取得（Pod情報またはコンテナラベルから復元）
2. **859行目**: GracePeriod計算（setTerminationGracePeriod）
3. **861-863行目**: デフォルトメッセージの設定
4. **864行目**: `recordContainerEvent`でKillingイベント発行
5. **873-875行目**: PreStopフック実行（存在する場合）
6. **879-882行目**: terminationOrdering待機

#### Step 3: killContainerの呼び出し元を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kuberuntime_manager.go | `pkg/kubelet/kuberuntime/kuberuntime_manager.go` | killContainerの呼び出し箇所。KillPod, SyncPod等から呼ばれる |

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

```
kubelet.syncPod() / kubelet.killPod()
    |
    +-- kubeGenericRuntimeManager.KillPod()
    |      |
    |      +-- killContainer()                       [kuberuntime_container.go:841]
    |             |
    |             +-- GetContainerSpec() / restoreSpecsFromContainerLabels()
    |             +-- setTerminationGracePeriod()
    |             +-- recordContainerEvent(Killing)    [行864]
    |             +-- executePreStopHook()              [行874]
    |             +-- ordering.waitForTurn()            [行881]
    |             +-- runtimeService.StopContainer()    [CRI RPC]
    |
    +-- kubeGenericRuntimeManager.SyncPod()
           +-- killContainer()  [コンテナ再起動時]
```

### データフロー図

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

Pod Spec          ------>  killContainer()                ------>  Kubernetes Event
(コンテナ停止要求)            |                                      (Type: Normal,
                             +-- containerSpec取得                   Reason: Killing,
停止理由メッセージ ------>   +-- recordContainerEvent()              Message: "Stopping container {名前}")
                             +-- PreStopフック実行
                             +-- CRI StopContainer
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| event.go | `pkg/kubelet/events/event.go` | ソース | イベント理由定数の定義 |
| kuberuntime_container.go | `pkg/kubelet/kuberuntime/kuberuntime_container.go` | ソース | コンテナ停止処理およびKillingイベント記録 |
| kuberuntime_manager.go | `pkg/kubelet/kuberuntime/kuberuntime_manager.go` | ソース | KillPod, SyncPod等の上位処理 |
| kubelet.go | `pkg/kubelet/kubelet.go` | ソース | Pod同期・停止のトリガー |
