# 通知設計書 32-Shutdown

## 概要

本ドキュメントは、Kubernetesクラスタにおいてノードのシャットダウンが検知された際に発行されるShutdownイベント通知の設計を記述する。kubeletのNode Shutdown Manager（nodeshutdown）がOS レベルのシャットダウンシグナルを検知し、Graceful Node Shutdownプロセスを開始する際にこの通知が発行される。

### 本通知の処理概要

Shutdown通知は、kubeletのNode Shutdown Managerがsystemd（Linux）またはWindows Service（Windows）からのシャットダウンシグナルを検知した際に発行されるNormalイベントである。シャットダウン検知時とシャットダウンキャンセル検知時の両方でこのイベントが発行され、それぞれ異なるメッセージが記録される。

**業務上の目的・背景**：ノードのシャットダウンはクラスタの可用性に直接影響するため、シャットダウンの開始をリアルタイムに通知する必要がある。GracefulNodeShutdown機能により、シャットダウン前にPodを安全に終了させるプロセスが開始され、この通知はそのプロセスの開始を示すマーカーとなる。計画的なメンテナンスや予期しないシャットダウンの追跡に使用される。

**通知の送信タイミング**：Linux環境ではsystemdのInhibitメカニズムを通じてシャットダウンシグナルがD-Bus経由で受信された時点、Windows環境ではWindowsサービスのPreshutdown通知を受信した時点で発行される。また、シャットダウンがキャンセルされた場合にも別メッセージでイベントが発行される。

**通知の受信者**：Kubernetes APIサーバを通じてイベントが記録され、ノードオブジェクトに紐づけられる。クラスタ管理者、モニタリングシステム、およびkubectl get eventsを使用するユーザが受信者となる。

**通知内容の概要**：シャットダウン検知時は「Shutdown manager detected shutdown event」、シャットダウンキャンセル時は「Shutdown manager detected shutdown cancellation」というメッセージが記録される。

**期待されるアクション**：クラスタ管理者はシャットダウンイベントを確認し、ノード上のPodが他のノードに正常にリスケジュールされていることを確認する。シャットダウンが計画外の場合は原因調査を行う。

## 通知種別

Kubernetes Event（Normal）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（D-Bus/Windowsサービスのイベント監視ループ内で発行） |
| 優先度 | 中（Normal EventType） |
| リトライ | EventRecorderの内部キュー機構に依存 |

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

イベントはkubeletが管理するノードオブジェクト（nodeRef）に対して記録される。送信先はKubernetes APIサーバであり、イベントオブジェクトとして永続化される。

## 通知テンプレート

### メール通知の場合

本通知はKubernetes Eventとして発行されるため、メール通知は直接行わない。

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

### 本文テンプレート

```
# シャットダウン検知時
Shutdown manager detected shutdown event

# シャットダウンキャンセル時
Shutdown manager detected shutdown cancellation
```

### 添付ファイル

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

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| isShuttingDown | シャットダウン状態フラグ | D-Bus MonitorShutdown / Windows Service通知 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| OSシグナル（Linux） | systemd D-Bus PrepareForShutdown信号 | GracefulNodeShutdown機能が有効 | systemdのInhibitメカニズムを使用 |
| OSシグナル（Windows） | Windows Preshutdown通知 | WindowsGracefulNodeShutdown機能が有効 | Windowsサービスフレームワークを使用 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| Feature Gate無効 | GracefulNodeShutdown（Linux）/WindowsGracefulNodeShutdown（Windows）が無効の場合、Manager自体がstubとなり通知は発行されない |
| ShutdownGracePeriod未設定 | shutdownGracePeriodByPodPriorityが空の場合、Managerが無効化される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[OS シャットダウンシグナル受信] --> B{isShuttingDown?}
    B -->|true| C[Shutdown eventをイベント記録]
    B -->|false| D[Shutdown cancellation eventをイベント記録]
    C --> E[nodeShuttingDownNow = true]
    E --> F[syncNodeStatus実行]
    F --> G[processShutdownEvent開始]
    G --> H[Pod優先度順にGraceful Shutdown]
    H --> I[InhibitLock解放]
    I --> J[終了]
    D --> K[nodeShuttingDownNow = false]
    K --> L[InhibitLock再取得]
    L --> J
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| Pod一覧 | シャットダウン時の終了対象Pod取得 | getPods() ActivePodsFunc経由 |

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

#### Pod一覧

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| Pod.Spec.Priority | Pod終了の優先順位決定 | アクティブなPodすべて |
| Pod.Spec.TerminationGracePeriodSeconds | 終了猶予期間 | アクティブなPodすべて |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| Events | INSERT | Shutdownイベントの記録 |
| Node.Status | UPDATE | nodeShuttingDownNow状態の同期 |
| localStorage | UPDATE | Graceful Shutdownの開始時刻/終了時刻記録 |

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

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | Event.Reason | "Shutdown" | Kubernetes Eventオブジェクト |
| INSERT | Event.Type | "Normal" | EventTypeNormal |
| INSERT | Event.Message | "Shutdown manager detected shutdown event" または "...shutdown cancellation" | メッセージは状態に依存 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| D-Bus接続失敗 | systemdとの接続が確立できない場合 | 1秒間隔で再接続（dbusReconnectPeriod） |
| InhibitLock取得失敗 | シャットダウン抑止ロックの取得エラー | エラーログ出力、処理継続 |
| ローカルストレージ書き込み失敗 | 状態ファイルへの書き込みエラー | エラーログ出力、処理継続 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | D-Bus再接続: 無限（1秒間隔） |
| リトライ間隔 | 1秒（dbusReconnectPeriod） |
| リトライ対象エラー | D-Bus接続エラー |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（シャットダウンイベントの発生頻度に依存） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

時間帯の制限なし。OSレベルのシャットダウンシグナルが検知された時点で即時発行される。

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

- シャットダウンイベントは機密情報を含まない
- D-Bus通信はローカルシステムバスを使用し、リモートアクセスは不可
- イベントはKubernetes RBACにより閲覧権限が制御される

## 備考

- GracefulNodeShutdown機能はLinuxとWindowsの両方で利用可能だが、実装メカニズムが異なる
- Linux: systemdのInhibit Delay パターンを使用
- Windows: Windows Serviceの Preshutdown通知を使用
- シャットダウンキャンセルも同じイベントReasonで記録されるが、メッセージ内容が異なる
- Pod終了順序はPriority値に基づいて決定される（GracefulNodeShutdownBasedOnPodPriority機能）

---

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

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

### 推奨読解順序

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

まず、イベント定数とShutdown Manager の設定構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | event.go | `pkg/kubelet/events/event.go` | 75行目: `NodeShutdown = "Shutdown"` 定数定義 |
| 1-2 | nodeshutdown_manager.go | `pkg/kubelet/nodeshutdown/nodeshutdown_manager.go` | Config構造体とManager インターフェースの定義 |

**読解のコツ**: nodeshutdownパッケージはLinux（_linux.go）とWindows（_windows.go）で別実装を持つ。ビルドタグに注目すること。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | nodeshutdown_manager_linux.go | `pkg/kubelet/nodeshutdown/nodeshutdown_manager_linux.go` | 79-106行目: NewManager関数でManagerの初期化 |
| 2-2 | nodeshutdown_manager_linux.go | `pkg/kubelet/nodeshutdown/nodeshutdown_manager_linux.go` | 248-285行目: シャットダウンイベント監視ループ |

**主要処理フロー**:
1. **80行目**: Feature Gate `GracefulNodeShutdown` の有効チェック
2. **265-268行目**: isShuttingDownフラグに基づいてイベントメッセージを切り替え
3. **266行目**: `m.recorder.Event(m.nodeRef, v1.EventTypeNormal, kubeletevents.NodeShutdown, "Shutdown manager detected shutdown event")`
4. **279行目**: `m.processShutdownEvent()` でGraceful Shutdown処理を開始

#### Step 3: Graceful Shutdown処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | nodeshutdown_manager_linux.go | `pkg/kubelet/nodeshutdown/nodeshutdown_manager_linux.go` | 312行目以降: processShutdownEvent関数 |

**主要処理フロー**:
- **312行目**: `processShutdownEvent()` - アクティブなPodを取得し優先度順にGraceful Shutdownを実行
- **317行目**: defer でInhibitLockを解放

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

```
kubelet.Run()
    |
    +-- nodeshutdown.NewManager(conf)
           |
           +-- managerImpl.start()
                  |
                  +-- dbusCon.MonitorShutdown() [Linux]
                  |   |
                  |   +-- D-Bus PrepareForShutdown監視
                  |
                  +-- イベント監視ループ
                         |
                         +-- recorder.Event(nodeRef, Normal, "Shutdown", message)
                         |
                         +-- processShutdownEvent()
                                |
                                +-- getPods()
                                +-- podManager.killPods() [優先度順]
                                +-- dbusCon.ReleaseInhibitLock()
```

### データフロー図

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

systemd D-Bus                 nodeshutdown.managerImpl             Kubernetes Event
PrepareForShutdown   ----->   イベント監視ループ             ----> (Reason: "Shutdown",
シグナル                       (nodeshutdown_manager_              Type: Normal)
                               linux.go:248-285)              |
                                                              +--> Node Status更新
                                                              |
                                                              +--> Pod Graceful
                                                                   Shutdown実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| event.go | `pkg/kubelet/events/event.go` | ソース | イベント定数定義（NodeShutdown） |
| nodeshutdown_manager_linux.go | `pkg/kubelet/nodeshutdown/nodeshutdown_manager_linux.go` | ソース | Linux版Shutdown Manager実装 |
| nodeshutdown_manager_windows.go | `pkg/kubelet/nodeshutdown/nodeshutdown_manager_windows.go` | ソース | Windows版Shutdown Manager実装 |
| nodeshutdown_manager.go | `pkg/kubelet/nodeshutdown/nodeshutdown_manager.go` | ソース | Manager インターフェースと共通型定義 |
| inhibit_linux.go | `pkg/kubelet/nodeshutdown/systemd/inhibit_linux.go` | ソース | systemd D-Bus Inhibitメカニズム |
| kubelet.go | `pkg/kubelet/kubelet.go` | ソース | Shutdown Managerの初期化呼び出し |
| nodeshutdown_manager_linux_test.go | `pkg/kubelet/nodeshutdown/nodeshutdown_manager_linux_test.go` | テスト | Linux版テストケース |
