# 通知設計書 132-CertificateOverdueForRefresh

## 概要

本ドキュメントは、KubernetesのPod証明書（PodCertificate）のリフレッシュが遅延している場合に発行されるWarningイベント「CertificateOverdueForRefresh」の通知設計について記載する。

### 本通知の処理概要

本通知は、kubeletのPodCertificateManagerが管理するPod証明書のリフレッシュが、予定時刻から一定時間（10分）を超えて遅延した際に発行されるWarningイベントである。証明書のライフサイクル管理における異常状態の早期検知を目的とする。

**業務上の目的・背景**：Pod証明書はPodCertificateProjection機能を使用して、PodにX.509証明書を自動配布する仕組みである。証明書には有効期限があり、期限前にリフレッシュ（更新）が必要である。リフレッシュが遅延している場合、証明書が期限切れとなりPodのサービスに影響が出る可能性があるため、早期に管理者に通知する必要がある。

**通知の送信タイミング**：PodCertificateManagerのhandleProjection処理において、credStateFreshまたはcredStateWaitRefresh状態で、現在時刻がbeginRefreshAtから10分（refreshOverdueDuration）を超過した場合にイベントが発行される。1つのPodCertificateProjectionにつき1回のみ発行される（eventEmittedForOverdueForRefreshフラグで制御）。

**通知の受信者**：対象Podに紐付くKubernetesイベントとして記録されるため、kubectl describe pod等でPodを参照するクラスタ管理者やアプリケーション開発者が受信者となる。

**通知内容の概要**：Pod証明書のリフレッシュが遅延している旨を示す警告メッセージ「PodCertificate refresh overdue」。

**期待されるアクション**：受信者はPodCertificateRequestの状態を確認し、証明書署名者（Signer）が正常に動作しているか、PodCertificateRequestが適切に処理されているかを調査する。必要に応じてPodの再起動やSignerの修復を行う。

## 通知種別

Kubernetesイベント（Event API）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（kubelet内のPodCertificateManager ワークキュー経由） |
| 優先度 | 高 |
| リトライ | 有・projectionQueueのRateLimitingQueue による自動リトライ |

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

イベントは対象PodのObjectReferenceに紐付けて記録される。PodCertificateProjectionのprojectionKeyから対応するPodを特定し、そのPodに対してイベントが発行される。

## 通知テンプレート

### Kubernetesイベント

| 項目 | 内容 |
|-----|------|
| EventType | Warning |
| Reason | CertificateOverdueForRefresh |
| Component | kubelet podcertificate manager |

### 本文テンプレート

```
PodCertificate refresh overdue
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | Kubernetesイベントのため添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| なし | メッセージは固定文字列 | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 定期リフレッシュ | runRefreshPass（1分間隔） | credStateFresh状態でnow > beginRefreshAt + 10分 | リフレッシュ遅延検出（Fresh状態） |
| PCR更新 | PodCertificateRequest Informerイベント | credStateWaitRefresh状態でnow > beginRefreshAt + 10分 | リフレッシュ遅延検出（WaitRefresh状態） |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| イベント発行済み | eventEmittedForOverdueForRefreshフラグがtrueの場合、同一Projectionに対する重複発行を抑止 |
| 証明書未発行 | credStateInitialまたはcredStateWaitの場合は対象外（まだ初回発行が完了していない） |
| 証明書拒否/失敗 | credStateDeniedまたはcredStateFailedの場合は対象外 |
| beginRefreshAt未到達 | 現在時刻がbeginRefreshAtより前の場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[runRefreshPass / PCR Informerイベント] --> B[projectionQueueにProjectionを追加]
    B --> C[handleProjection]
    C --> D{credState判定}
    D -->|credStateFresh| E{now > beginRefreshAt?}
    D -->|credStateWaitRefresh| F{PCR Terminal状態?}
    E -->|No| G[終了]
    E -->|Yes| H{now > beginRefreshAt + 10分?}
    H -->|No| I[新PCR作成 → credStateWaitRefresh]
    H -->|Yes| J{eventEmittedForOverdueForRefresh?}
    J -->|Yes| I
    J -->|No| K[CertificateOverdueForRefreshイベント発行]
    K --> L[eventEmittedForOverdueForRefreshをtrueに設定]
    L --> I
    F -->|Issued| M[credStateFreshへ遷移]
    F -->|Pending| N{now > beginRefreshAt + 10分?}
    N -->|Yes| O{eventEmittedForOverdueForRefresh?}
    O -->|No| P[CertificateOverdueForRefreshイベント発行]
    P --> G
    O -->|Yes| G
    N -->|No| G
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| Pod | 対象Pod情報の取得 | PodManager経由 |
| PodCertificateRequest | PCRの状態確認 | Informerキャッシュ（pcrLister）経由 |
| ServiceAccount | サービスアカウントUID取得 | API直接アクセス |
| Node | ノードUID取得 | Informerキャッシュ（nodeLister）経由 |

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

#### PodCertificateRequest

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| Status.Conditions | PCRの最終状態（Issued/Denied/Failed） | PCR名で取得 |
| Status.BeginRefreshAt | リフレッシュ開始予定時刻 | PCR名で取得 |
| Status.NotAfter | 証明書有効期限 | PCR名で取得 |
| Status.CertificateChain | 発行された証明書チェーン | PCR名で取得 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| Event | INSERT | 警告イベントの記録 |

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

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | Type | Warning | イベントタイプ |
| INSERT | Reason | CertificateOverdueForRefresh | イベント理由 |
| INSERT | Message | PodCertificate refresh overdue | 固定メッセージ |
| INSERT | Source.Component | kubelet | イベントソース |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| Pod未検出 | PodManagerでPodが見つからない | credStoreをクリーンアップ |
| PCR取得失敗 | pcrListerからPCRが取得できない | ワークキューでリトライ |
| ServiceAccount取得失敗 | API ServerからSA取得失敗 | ワークキューでリトライ |
| PCR削除検知 | PCRがabandon時間を超過して見つからない | credStateInitialに戻り新PCRを作成 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 無制限（RateLimitingQueue） |
| リトライ間隔 | 指数バックオフ（DefaultTypedControllerRateLimiter） |
| リトライ対象エラー | handleProjection関数が非nilエラーを返した場合 |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | Kubernetes Event APIのデフォルトレート制限に従う |
| 1日あたり上限 | 制限なし（ただしProjectionあたり1回のみ） |

### 配信時間帯

時間帯制限なし。kubeletが稼働中かつリフレッシュ遅延を検出した時点で発行される。定期リフレッシュパスは1分間隔で実行される。

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

- 証明書のリフレッシュ遅延は、TLS通信の中断やサービス停止につながる可能性があるため、高優先度で対応が必要
- PodCertificateRequestにはPodUID、ServiceAccountUID、NodeUIDなどの情報が含まれるが、イベントメッセージ自体には機密情報は含まれない
- 証明書の秘密鍵はcredStore内にメモリ上でのみ保持され、再起動時には消去される

## 備考

- refreshOverdueDurationは10分間のハードコード値（定数refreshOverdueDuration）
- beginRefreshAtにはjitterDuration（0-5分のランダム遅延）が加算される
- credStateが遷移してもeventEmittedForOverdueForRefreshフラグは引き継がれる（credStateFresh→credStateWaitRefresh遷移時）
- PodCertificateManager機能はPodCertificateProjection機能ゲートに依存する

---

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

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

### 推奨読解順序

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

PodCertificateManagerの状態遷移モデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | podcertificatemanager.go | `pkg/kubelet/podcertificate/podcertificatemanager.go` | projectionKey構造体（132-138行目）、projectionRecord構造体（140-155行目）、credState各実装（158-266行目） |

**読解のコツ**: 状態マシンは credStateInitial → credStateWait → credStateFresh → credStateWaitRefresh のサイクルで遷移する。credStateFreshとcredStateWaitRefreshにeventEmittedForOverdueForRefreshフラグが存在する。

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

IssuingManagerの初期化と実行ループを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | podcertificatemanager.go | `pkg/kubelet/podcertificate/podcertificatemanager.go` | NewIssuingManager関数（270-309行目）、Run関数（339-353行目） |

**主要処理フロー**:
1. **270-309行目**: NewIssuingManagerでPCR InformerのイベントハンドラとprojectionQueueを初期化
2. **339-353行目**: RunでキャッシュSync待ちの後、runRefreshPass（1分間隔）とrunProjectionProcessorを起動

#### Step 3: リフレッシュ遅延検出ロジックを理解する

handleProjection内のcredStateFreshおよびcredStateWaitRefresh処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | podcertificatemanager.go | `pkg/kubelet/podcertificate/podcertificatemanager.go` | handleProjection関数内のcredStateFreshケース（542-609行目）、credStateWaitRefreshケース（611-689行目） |

**主要処理フロー**:
- **546-548行目**: beginRefreshAt前なら何もしない
- **554-558行目**: credStateFresh状態でbeginRefreshAt + 10分を超過した場合にCertificateOverdueForRefreshイベントを発行
- **677-681行目**: credStateWaitRefresh状態でbeginRefreshAt + 10分を超過した場合にCertificateOverdueForRefreshイベントを発行

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

```
IssuingManager.Run (339行目)
    |
    +-- runRefreshPass (704行目) [1分間隔]
    |      |
    |      +-- queueAllProjectionsForPod (311行目) [全Pod]
    |
    +-- runProjectionProcessor (355行目) [常時]
           |
           +-- processNextProjection (360行目)
                  |
                  +-- handleProjection (378行目)
                         |
                         +-- [credStateFresh] (542行目)
                         |      |
                         |      +-- clock.Now().After(beginRefreshAt + 10min) (554行目)
                         |      +-- recorder.Eventf "CertificateOverdueForRefresh" (556行目)
                         |      +-- createPodCertificateRequest (580行目)
                         |
                         +-- [credStateWaitRefresh] (611行目)
                                |
                                +-- clock.Now().After(beginRefreshAt + 10min) (677行目)
                                +-- recorder.Eventf "CertificateOverdueForRefresh" (679行目)
```

### データフロー図

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

runRefreshPass --------+
(1分間隔タイマー)       |
                       |
PCR Informer ----------+----> handleProjection ---+
(Add/Update/Delete)    |                          |
                       |                          +---> Kubernetes Event
TrackPod (kubelet) ----+                          |     (CertificateOverdueForRefresh)
                       |                          |
                       v                          +---> credStore更新
                  projectionQueue                       (eventEmittedフラグ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| podcertificatemanager.go | `pkg/kubelet/podcertificate/podcertificatemanager.go` | ソース | PodCertificateManager本体。状態管理、イベント発行 |
| podcertificatemanager_test.go | `pkg/kubelet/podcertificate/podcertificatemanager_test.go` | テスト | PodCertificateManagerのユニットテスト |
| podcertificate_metrics.go | `pkg/kubelet/metrics/collectors/podcertificate_metrics.go` | ソース | PodCertificateのPrometheusメトリクス収集 |
| kubelet.go | `pkg/kubelet/kubelet.go` | ソース | kubeletからのPodCertificateManager初期化・呼び出し |
| types.go | `staging/src/k8s.io/api/certificates/v1beta1/types.go` | ソース | PodCertificateRequest API型定義 |
| projected.go | `pkg/volume/projected/projected.go` | ソース | Projected Volumeプラグイン（証明書配布） |
