# 機能設計書 71-Pod Admission制御

## 概要

本ドキュメントは、Kubelet側でのPod受け入れ判定（Pod Admission制御）機能の設計を記述する。Kubeletが新しいPodを受け入れる際に、ノードのリソース状況、Taint/Toleration、OS互換性、AppArmor、フィーチャー互換性などの観点から受け入れ可否を判定するメカニズムを定義する。

### 本機能の処理概要

**業務上の目的・背景**：Kubernetesクラスターにおいて、スケジューラーがPodをノードに割り当てた後でも、実際にKubeletがPodを実行する際にノードの現在の状況（リソース残量、カーネル機能のサポート状況、セキュリティポリシー等）を再確認する必要がある。これにより、スケジューリング時点と実行時点の間に発生した状況変化（他Podの起動によるリソース消費等）に対応し、ノードの安定性を保つことができる。

**機能の利用シーン**：KubeletのSync Loopにおいて、新しいPodがノードに割り当てられた際に自動的に呼び出される。静的Pod、DaemonSet Pod、通常のPodすべてが対象となる。

**主要な処理内容**：
1. PodAdmitHandlerインターフェースに基づく複数のAdmitハンドラーのチェーン実行
2. PredicateAdmitHandlerによるリソース（CPU、メモリ、エフェメラルストレージ、Pod数）の充足判定
3. NodeAffinityおよびTaint/Tolerationに基づくノード適合性チェック
4. OS互換性（kubernetes.io/osラベル、Pod.Spec.OS）の検証
5. AppArmorプロファイルの検証
6. Pod機能要件（PodLevelResources、SupplementalGroupsPolicy等）の互換性チェック
7. DeclaredFeaturesに基づくノードフィーチャー要件の検証

**関連システム・外部連携**：スケジューラーフレームワークのAdmissionCheck関数を内部的に利用し、NodeAffinity、TaintTolerationプラグインの判定ロジックを再利用する。

**権限による制御**：静的PodはTaint/Tolerationチェックが免除される。ノードクリティカルPodには特別な扱いがある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | Kubelet内部処理のため、直接の画面関連はなし |

## 機能種別

バリデーション / 内部制御処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Pod | *v1.Pod | Yes | 受け入れ判定対象のPod | Podオブジェクトが有効であること |
| OtherPods | []*v1.Pod | Yes | 同じノードにバインド済みの他のPod一覧 | - |

### 入力データソース

- API Server経由で取得されたPodオブジェクト
- Kubelet内部のPodキャッシュから取得した既存Pod一覧
- ノード情報（getNodeAnyWayFunc経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Admit | bool | Podが受け入れ可能かどうか |
| Reason | string | 拒否理由のCamelCase短縮名 |
| Message | string | 拒否理由の詳細メッセージ |

### 出力先

Kubelet内部のPodライフサイクル管理機構に返却され、拒否された場合はPodのステータスに反映される。

## 処理フロー

### 処理シーケンス

```
1. PodAdmitHandlersリストを順次実行
   └─ 各ハンドラーのAdmitメソッドを呼び出し
2. predicateAdmitHandler.Admit
   ├─ ノード情報の取得（getNodeAnyWayFunc）
   ├─ OS互換性チェック（OSSelector、OSField）
   ├─ SupplementalGroupsPolicyチェック
   ├─ プラグインリソース更新
   ├─ 拡張リソースのフィルタリング（DRA対応）
   └─ generalFilterによるスケジューラー判定の再利用
       ├─ AdmissionCheck（CPU、メモリ、ストレージ、Pod数）
       └─ TaintToleration チェック（静的Pod以外）
3. appArmorAdmitHandler.Admit
   └─ AppArmorプロファイルの検証
4. podFeaturesAdmitHandler.Admit
   └─ PodLevelResourcesサポートの確認
5. declaredFeaturesAdmitHandler.Admit
   └─ ノードのフィーチャーセットとPod要件のマッチング
```

### フローチャート

```mermaid
flowchart TD
    A[Pod受け入れリクエスト] --> B{OS互換性チェック}
    B -->|不一致| R1[拒否: PodOSSelectorNodeLabelDoesNotMatch]
    B -->|一致| C{OSフィールドチェック}
    C -->|不一致| R2[拒否: PodOSNotSupported]
    C -->|一致| D{SupplementalGroupsPolicy}
    D -->|非対応| R3[拒否: SupplementalGroupsPolicyNotSupported]
    D -->|OK| E[リソース充足判定]
    E --> F{generalFilter}
    F -->|不足| G{AdmissionFailureHandler}
    G -->|回復不可| R4[拒否: OutOfXxx]
    G -->|回復| H[許可]
    F -->|OK| H
    H --> I{AppArmor検証}
    I -->|失敗| R5[拒否: AppArmor]
    I -->|OK| J{PodFeatures検証}
    J -->|非対応| R6[拒否: PodLevelResourcesNotSupported]
    J -->|OK| K{DeclaredFeatures検証}
    K -->|不一致| R7[拒否: PodFeatureUnsupported]
    K -->|OK| L[許可: Admit=true]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-71-01 | OS互換性 | Pod のkubernetes.io/osラベルがノードのOSと一致すること | Podにkubernetes.io/osラベルが付与されている場合 |
| BR-71-02 | OSフィールド互換性 | Pod.Spec.OS.Nameがノードのruntime.GOOSと一致すること | Pod.Spec.OSが設定されている場合 |
| BR-71-03 | リソース充足 | CPU、メモリ、エフェメラルストレージ、Pod数がノード容量内であること | 全Pod |
| BR-71-04 | TaintToleration | NoExecute Taintに対するTolerationが存在すること | 静的Pod以外 |
| BR-71-05 | AppArmor | ノードがPodの要求するAppArmorプロファイルをサポートすること | Pod.Status.PhaseがPending |
| BR-71-06 | SupplementalGroupsPolicy | Strict指定時にノードが対応していること | Beta以上のフィーチャーゲートが有効な場合 |
| BR-71-07 | 拡張リソースフィルタ | ノードに存在しない拡張リソース要求は無視される | DRAまたはクラスターレベルリソース使用時 |

### 計算ロジック

リソース充足判定はスケジューラーの`AdmissionCheck`関数を再利用し、各リソースの`Requested + Used <= Capacity`を確認する。

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベースへの直接操作はなし。API Serverとの通信のみ |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| InvalidNodeInfo | 情報取得エラー | ノード情報が取得できない場合 | Pod拒否。Kubeletの再起動やAPI Server接続を確認 |
| OutOfcpu | リソース不足 | CPU要求がノード容量を超過 | 他Podの退避またはリソース追加 |
| OutOfmemory | リソース不足 | メモリ要求がノード容量を超過 | 他Podの退避またはリソース追加 |
| OutOfephemeral-storage | リソース不足 | エフェメラルストレージ不足 | ディスク空き容量確保 |
| OutOfpods | リソース不足 | Pod数上限到達 | maxPods設定の見直し |
| PodOSSelectorNodeLabelDoesNotMatch | 互換性エラー | OS不一致 | 正しいノードセレクターを設定 |
| PodOSNotSupported | 互換性エラー | OSフィールド不一致 | 適切なノードに配置 |
| AppArmor | セキュリティエラー | AppArmorプロファイル未対応 | ノードへのプロファイルインストール |

### リトライ仕様

NodeAffinityによる拒否の場合のみ、キャッシュではなく最新のノード情報を再取得して再判定する。

## トランザクション仕様

トランザクションの概念はなし。各Admitハンドラーは独立して判定を行い、1つでも拒否があればPod全体が拒否される。

## パフォーマンス要件

- 各Admitハンドラーは即座に結果を返すことが期待される
- generalFilterはスケジューラーの判定ロジックを再利用しており、O(N)（Nは既存Pod数）の計算量

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

- AppArmorプロファイルの検証により、セキュリティポリシー違反のPodが実行されることを防止
- SupplementalGroupsPolicyのStrictモードにより、意図しないグループ権限のエスカレーションを防止
- 静的PodはTaintチェックが免除されるため、ノード管理者の責任範囲となる

## 備考

- `DRAExtendedResource`フィーチャーゲートが有効な場合、DRAでバックアップされた拡張リソースはAdmissionCheckから除外される
- 手動バインドされた静的Podでノードレベルの拡張リソースが不足している場合、誤って許可される既知の問題がある

---

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

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

### 推奨読解順序

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

まず、PodAdmission制御で使用されるインターフェースとデータ型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | interfaces.go | `pkg/kubelet/lifecycle/interfaces.go` | PodAdmitHandler, PodAdmitAttributes, PodAdmitResultの定義 |

**読解のコツ**: `PodAdmitHandler`インターフェースはChain of Responsibilityパターンで使用される。`PodAdmitHandlers`型（スライス）に複数のハンドラーが登録され、順次実行される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | predicate.go | `pkg/kubelet/lifecycle/predicate.go` | predicateAdmitHandlerのAdmitメソッド |

**主要処理フロー**:
1. **119-250行目**: `predicateAdmitHandler.Admit`メソッド - メインのAdmission判定ロジック
2. **124行目**: `getNodeAnyWayFunc`でノード情報を取得
3. **136行目**: `rejectPodAdmissionBasedOnOSSelector`でOS互換性チェック
4. **143行目**: `rejectPodAdmissionBasedOnOSField`でOSフィールドチェック
5. **151行目**: `rejectPodAdmissionBasedOnSupplementalGroupsPolicy`でセキュリティポリシーチェック
6. **185行目**: `removeMissingExtendedResources`で拡張リソースフィルタリング
7. **187行目**: `generalFilter`でスケジューラー判定再利用

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | predicate.go | `pkg/kubelet/lifecycle/predicate.go` | generalFilter関数（435-463行目） |

**主要処理フロー**:
- **436行目**: `scheduler.AdmissionCheck`を呼び出してリソース充足を確認
- **452-460行目**: 静的Pod以外に対してTaint/Tolerationチェックを実施

#### Step 4: AppArmorおよびFeatures Admitハンドラーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | handlers.go | `pkg/kubelet/lifecycle/handlers.go` | AppArmor検証（188-215行目）、PodFeatures検証（228-292行目） |

**主要処理フロー**:
- **200-215行目**: `appArmorAdmitHandler.Admit` - Pendingフェーズのみ検証
- **236-238行目**: `podFeaturesAdmitHandler.Admit` - PodLevelResourcesサポート確認
- **257-292行目**: `declaredFeaturesAdmitHandler.Admit` - ノードフィーチャーマッチング

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

```
Kubelet SyncLoop
    |
    +-- PodAdmitHandlers (順次実行)
           |
           +-- predicateAdmitHandler.Admit
           |       +-- getNodeAnyWayFunc (ノード情報取得)
           |       +-- rejectPodAdmissionBasedOnOSSelector
           |       +-- rejectPodAdmissionBasedOnOSField
           |       +-- rejectPodAdmissionBasedOnSupplementalGroupsPolicy
           |       +-- pluginResourceUpdateFunc
           |       +-- removeMissingExtendedResources
           |       +-- generalFilter
           |              +-- scheduler.AdmissionCheck
           |              +-- corev1.FindMatchingUntoleratedTaint
           |
           +-- appArmorAdmitHandler.Admit
           |       +-- apparmor.Validator.Validate
           |
           +-- podFeaturesAdmitHandler.Admit
           |       +-- isPodLevelResourcesSupported
           |
           +-- declaredFeaturesAdmitHandler.Admit
                   +-- ndf.Framework.InferForPodScheduling
                   +-- ndf.MatchNodeFeatureSet
```

### データフロー図

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

Pod (API Server) ------> predicateAdmitHandler ---------> PodAdmitResult
                            |                               {Admit, Reason, Message}
Node Info (Cache) ------> appArmorAdmitHandler
                            |
OtherPods (Cache) ------> podFeaturesAdmitHandler
                            |
                          declaredFeaturesAdmitHandler
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| interfaces.go | `pkg/kubelet/lifecycle/interfaces.go` | ソース | PodAdmitHandler等のインターフェース定義 |
| predicate.go | `pkg/kubelet/lifecycle/predicate.go` | ソース | predicateAdmitHandlerとリソース/Taint判定ロジック |
| handlers.go | `pkg/kubelet/lifecycle/handlers.go` | ソース | AppArmor、PodFeatures、DeclaredFeatures Admitハンドラー |
| admission_failure_handler_stub.go | `pkg/kubelet/lifecycle/admission_failure_handler_stub.go` | ソース | AdmissionFailureHandlerのスタブ実装 |
| features_linux.go | `pkg/kubelet/lifecycle/features_linux.go` | ソース | Linux固有のPodLevelResources判定 |
| doc.go | `pkg/kubelet/lifecycle/doc.go` | ソース | パッケージドキュメント |
