# 画面設計書 18-kubectl taint

## 概要

本ドキュメントは、Kubernetes CLIツール `kubectl taint` コマンドの画面設計書である。ノードにTaint（汚染マーク）を追加・削除し、Podのスケジューリングを制御するコマンドの仕様を記載する。

### 本画面の処理概要

`kubectl taint` コマンドは、ノードにTaintを設定することで、特定のTolerationを持たないPodがそのノードにスケジュールされることを防止する。Taintはkey=value:effect の形式で指定し、effect にはNoSchedule、PreferNoSchedule、NoExecuteの3種類がある。

**業務上の目的・背景**：クラスタ内の特定ノードを専用ワークロード向けに予約したり、GPU搭載ノードなど特殊なハードウェアを持つノードに適切なPodのみを配置したりするため、TaintとTolerationの仕組みが用いられる。本コマンドによりノードのTaint設定を動的に管理できる。

**画面へのアクセス方法**：ターミナル上で `kubectl taint nodes <ノード名> <key=value:effect>` を実行する。

**主要な操作・処理内容**：
1. Taintの追加：`kubectl taint nodes <name> key=value:effect`
2. Taintの削除：`kubectl taint nodes <name> key:effect-`（末尾のハイフン）
3. キー指定の全Taint削除：`kubectl taint nodes <name> key-`
4. 既存Taintの上書き：`--overwrite` フラグ

**画面遷移**：本コマンドは単独実行のCLIコマンドである。NoExecute Taint追加後、Taint Evictionコントローラーが該当Podを自動退避する。

**権限による表示制御**：nodeリソースに対するget/patch/update権限が必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 94 | Taint管理（taint） | 主機能 | ノードにTaintを追加・削除する主処理 |
| 32 | Taint Evictionコントローラー | API連携 | NoExecute Taint追加後にTaint EvictionコントローラーがPod退避を実行する |

## 画面種別

CLI コマンド（リソース更新）

## URL/ルーティング

```
kubectl taint NODE NAME KEY_1=VAL_1:TAINT_EFFECT_1 ... KEY_N=VAL_N:TAINT_EFFECT_N
```

## 入出力項目

### 入力項目

| 項目名 | フラグ | 型 | 必須 | デフォルト | 説明 |
|--------|--------|------|------|-----------|------|
| リソース種別 | 位置引数 | string | Yes | - | "node"（またはnodes） |
| ノード名 | 位置引数 | string | Yes(*) | - | Taint対象のノード名 |
| Taint指定 | 位置引数 | string[] | Yes | - | key=value:effect 形式（追加）またはkey:effect-（削除） |
| 上書き | --overwrite | bool | No | false | 既存Taintの上書きを許可 |
| 全ノード | --all | bool | No | false | 全ノードにTaintを適用 |
| ラベルセレクタ | -l, --selector | string | No | "" | ラベルによるノード選択 |
| Dry Run | --dry-run | string | No | "none" | "none" / "client" / "server" |
| フィールドマネージャ | --field-manager | string | No | "kubectl-taint" | フィールドマネージャ名 |

(*) --allまたは--selector指定時は不要

### 出力項目

| 項目名 | 説明 |
|--------|------|
| 処理結果メッセージ | `node/<name> tainted` |

## 表示項目

| 項目 | 形式 | 説明 |
|------|------|------|
| ノード名 | `node/<name>` | 対象ノード |
| 操作結果 | `tainted` / `untainted` / `modified` | Taint追加/削除/変更の結果 |

## イベント仕様

### 1-taint実行

1. コマンドライン引数を解析しTaintOptionsを初期化する（`Complete`、taint.go L132-207）
   - リソース引数とTaint引数を分離する（L156-171）
   - Taint文字列をパースしてtaintsToAdd/taintsToRemoveに分類する（L185）
2. バリデーションを実行する（`Validate`、L227-260）
   - リソース種別がNodeであることを確認する（L239）
   - 同一キーの追加と削除が同時指定されていないか確認する（L244-258）
   - --allとselectorの排他チェック（`validateFlags`、L210-224）
3. Builderで対象ノードを取得する（`RunTaint`、L263-351）
4. 各ノードに対してTaintを更新する（`updateTaints`、L355-371）
   - 既存Taintとの重複チェック（--overwrite未指定時はエラー）
   - `reorganizeTaints`でTaintリストを再構成
5. Strategic Merge Patchを計算してAPI Serverに送信する（L288-345）
6. 結果を表示する

## データベース更新仕様

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

| 操作（イベント） | 対象リソース | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| taint追加 | Node | PATCH | spec.taintsにTaintエントリを追加 |
| taint削除 | Node | PATCH | spec.taintsからTaintエントリを削除 |

### テーブル別更新項目詳細

#### Node

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| PATCH | spec.taints[] | Taintの追加・削除・変更 | Strategic Merge Patchで更新 |

## メッセージ仕様

| 種別 | メッセージ | 条件 |
|------|-----------|------|
| 成功 | `node/<name> tainted` | Taint追加成功 |
| 成功 | `node/<name> untainted` | Taint削除成功 |
| 成功 | `node/<name> modified` | Taint変更成功 |
| エラー | `one or more resources must be specified as <resource> <name>` | リソース未指定 |
| エラー | `at least one taint update is required` | Taint引数未指定 |
| エラー | `invalid resource type %s, only node types are supported` | Node以外のリソース指定 |
| エラー | `node %s already has %v taint(s) with same effect(s) and --overwrite is false` | 既存Taint重複（上書き不可） |
| エラー | `can not both modify and remove the following taint(s) in the same command: %s` | 同一Taintの追加と削除の同時指定 |
| エラー | `all resources must be specified before taint changes: %s` | リソースとTaint引数の順序エラー |
| エラー | `setting 'all' parameter with a non empty selector is prohibited` | --allとselectorの同時指定 |

## 例外処理

| 例外条件 | 動作 |
|---------|------|
| Node以外のリソース種別を指定 | エラーメッセージを表示して終了 |
| 既存Taintとの重複（--overwrite未指定） | エラーメッセージを表示して終了 |
| 同一キーの追加と削除を同時指定 | エラーメッセージを表示して終了 |
| ノードが存在しない | NotFoundエラーを表示して終了 |
| パッチ計算失敗 | Replace操作にフォールバック（L341-345） |

## 備考

- Taintのeffectは `NoSchedule`、`PreferNoSchedule`、`NoExecute` の3種類のみ有効
- key長の最大値はDNS1123SubdomainMaxLength（253文字）、value長の最大値はLabelValueMaxLength（63文字）（L111）
- 引数の順序制約：リソース引数（node名）はTaint引数の前に全て指定する必要がある（L168-170）
- Strategic Merge Patchの計算に失敗した場合はReplace操作にフォールバックする（L341-345）
- dry-run=clientの場合はパッチ結果をローカルでマージして表示する（L298-326）
- `--all`と`--selector`は排他的であり、同時指定はできない（L212-213）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | taint.go | `staging/src/k8s.io/kubectl/pkg/cmd/taint/taint.go` | TaintOptions構造体（L47-68）：taintsToAdd/taintsToRemoveフィールド |
| 1-2 | types.go | `staging/src/k8s.io/api/core/v1/types.go` | v1.Taint型：Key/Value/Effect/TimeAddedフィールド |

**読解のコツ**: TaintOptionsのtaintsToAddとtaintsToRemoveが追加と削除を分離管理する。引数解析時にTaint文字列がパースされてこれらに分類される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | taint.go | `staging/src/k8s.io/kubectl/pkg/cmd/taint/taint.go` | NewCmdTaint関数（L99-129）：コマンド定義とフラグ登録 |

**主要処理フロー**:
1. **L105**: validArgsで"node"のみを許可
2. **L114-118**: Complete -> Validate -> RunTaintの実行チェーン
3. **L122-127**: --overwrite, --all, --field-manager等のフラグ登録

#### Step 3: 引数解析とバリデーション

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | taint.go | `staging/src/k8s.io/kubectl/pkg/cmd/taint/taint.go` | Complete（L132-207）：引数分離とTaintパース |
| 3-2 | taint.go | `staging/src/k8s.io/kubectl/pkg/cmd/taint/taint.go` | Validate（L227-260）：Node種別確認と矛盾チェック |

**主要処理フロー**:
- **L156-171**: 引数をリソースとTaintに分離（`=`/`:`含有でTaint判定）
- **L185**: parseTaintsでTaint文字列をv1.Taintに変換
- **L228-241**: リソース種別がNodeであることを確認
- **L244-258**: 同一キーの追加・削除の矛盾チェック

#### Step 4: Taint更新処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | taint.go | `staging/src/k8s.io/kubectl/pkg/cmd/taint/taint.go` | RunTaint（L263-351）：パッチ計算とAPI呼び出し |
| 4-2 | taint.go | `staging/src/k8s.io/kubectl/pkg/cmd/taint/taint.go` | updateTaints（L355-371）：Taintリストの再構成 |

**主要処理フロー**:
- **L274-288**: 旧データのマーシャル、updateTaints呼び出し、新データのマーシャル
- **L288**: Strategic Merge Patchの計算
- **L341-345**: パッチ失敗時のReplace操作フォールバック

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

```
NewCmdTaint (L99)
    |
    +-- Complete (L132)
    |       +-- 引数分離（リソース/Taint）
    |       +-- parseTaints()
    |       +-- f.NewBuilder()
    |
    +-- Validate (L227)
    |       +-- SplitAndParseResourceRequest()
    |       +-- Mapper.KindFor()
    |       +-- validateFlags()
    |
    +-- RunTaint (L263)
            +-- builder.Do().Visit()
                    +-- updateTaints (L355)
                    |       +-- checkIfTaintsAlreadyExists()
                    |       +-- reorganizeTaints()
                    +-- strategicpatch.CreateTwoWayMergePatch()
                    +-- helper.Patch() / helper.Replace()
                    +-- printer.PrintObj()
```

### データフロー図

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

nodes <name>            Complete()
  key=val:effect       --> 引数分離 ----------------+
  key:effect-          --> parseTaints() ----------->|
                                                     |
                       Validate()                    |
                       --> Node種別確認 ------------>|
                       --> 矛盾チェック ------------>|
                                                     |
                       RunTaint()                    |
                       --> ノード取得 -------------->+---> API Server
                       --> updateTaints() ---------->|
                       --> Patchバイト計算 --------->|
                       --> helper.Patch() ---------->+---> API Server
                                                     |     (Node Patch)
                                                     +---> stdout
                                                           "tainted"
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| taint.go | `staging/src/k8s.io/kubectl/pkg/cmd/taint/taint.go` | ソース | taintコマンドのメイン実装 |
| utils.go | `staging/src/k8s.io/kubectl/pkg/cmd/taint/utils.go` | ソース | parseTaints, reorganizeTaints等のユーティリティ |
| taint_test.go | `staging/src/k8s.io/kubectl/pkg/cmd/taint/taint_test.go` | テスト | taintコマンドのユニットテスト |
