# 機能設計書 35-Bootstrapコントローラー

## 概要

本ドキュメントは、Kubernetes kube-controller-managerに含まれるBootstrapコントローラー群（Bootstrap Signer/Token Cleaner）の機能設計を記述する。クラスターブートストラップ用のトークン管理とConfigMap署名を担当する。

### 本機能の処理概要

**業務上の目的・背景**：Kubernetesクラスターへのノード参加（kubeadm join）時に使用するBootstrapトークンの管理機能を提供する。Bootstrap Signerは`cluster-info` ConfigMapにトークンベースのJWS署名を付与し、新規ノードがクラスター情報を安全に検証できるようにする。Token Cleanerは期限切れのBootstrapトークンSecretを自動削除する。

**機能の利用シーン**：
- kubeadm joinでノードをクラスターに参加させる際、Bootstrap Signerが付与した署名でcluster-info ConfigMapの正当性を検証する
- Bootstrapトークンの有効期限切れ後、Token Cleanerが自動的にSecretを削除する

**主要な処理内容**：

**Bootstrap Signer**:
1. `kube-public`名前空間の`cluster-info` ConfigMapの変更を監視する
2. `kube-system`名前空間のBootstrapトークンSecretの変更を監視する
3. 有効なトークンごとにJWS（JSON Web Signature）を計算する
4. ConfigMapのDataフィールドに`jws-kubeconfig-{tokenID}`キーで署名を格納する
5. トークンの追加・削除・変更に応じて署名を更新する

**Token Cleaner**:
1. `kube-system`名前空間のBootstrapトークンSecretの変更を監視する
2. 期限切れトークンを検出し、Secretを削除する
3. 期限切れ前のトークンについては、TTL後に再チェックをスケジュールする

**関連システム・外部連携**：kubeadm、cluster-bootstrap API、JWS（JSON Web Signature）ライブラリ

**権限による制御**：ConfigMap（kube-public）とSecret（kube-system、type=bootstrap.kubernetes.io/token）に対する権限。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | kubeadm token | 主機能 | Bootstrapトークンの作成・管理 |
| - | kubeadm join | 関連機能 | クラスター参加時にSigner署名を検証 |

## 機能種別

トークン管理（作成・削除） / ConfigMap署名操作

## 入力仕様

### 入力パラメータ（Bootstrap Signer）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ConfigMapNamespace | string | Yes | ConfigMapの名前空間 | デフォルト: kube-public |
| ConfigMapName | string | Yes | ConfigMap名 | デフォルト: cluster-info |
| TokenSecretNamespace | string | Yes | Secret名前空間 | デフォルト: kube-system |

### 入力パラメータ（Token Cleaner）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| TokenSecretNamespace | string | Yes | Secret名前空間 | デフォルト: kube-system |
| SecretResync | time.Duration | No | Secret再同期期間 | デフォルト: 0（遅延最大） |

### 入力データソース

- ConfigMap Informer: cluster-info ConfigMapの変更イベント（Signerのみ）
- Secret Informer: Bootstrapトークン型Secretの変更イベント

## 出力仕様

### 出力データ（Bootstrap Signer）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ConfigMap.Data["jws-kubeconfig-{tokenID}"] | string | JWS署名文字列 |

### 出力データ（Token Cleaner）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Secret削除 | - | 期限切れBootstrapトークンSecretの削除 |

### 出力先

- Kubernetes API Server（ConfigMap更新、Secret削除）

## 処理フロー

### Bootstrap Signer 処理シーケンス

```
1. ConfigMapまたはSecret変更イベントを受信
   └─ pokeConfigMapSync()でキューにエンキュー
2. serviceConfigMapQueue()がキューからデキュー
3. signConfigMap()が署名を計算
   └─ ConfigMapのkubeconfig内容を取得
   └─ 既存のJWS署名を収集・削除
   └─ 有効なトークンを取得（getTokens）
   └─ 各トークンでJWS署名を計算
   └─ 新旧署名を比較し、変更がある場合のみ更新
```

### Token Cleaner 処理シーケンス

```
1. Secret変更イベントを受信
   └─ enqueueSecrets()でキューにエンキュー
2. worker()がキューからデキュー
3. syncFunc()がキーを処理
   └─ Secretを取得
   └─ evalSecret()で期限を評価
      ├─ 期限切れ → Secretを削除
      └─ TTL > 0 → TTL後にキューに再追加
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-35-01 | JWS署名生成 | 有効なBootstrapトークンごとにDetached JWS署名を生成する | ConfigMap/Secret変更時 |
| BR-35-02 | トークン検証 | Secret名のtokenIDとData内のtokenIDが一致すること | 署名対象トークン選定時 |
| BR-35-03 | 署名用途確認 | `usage-bootstrap-signing`が"true"のトークンのみ署名対象 | 署名対象トークン選定時 |
| BR-35-04 | 期限切れ除外 | 期限切れトークンは署名対象から除外する | 署名対象トークン選定時 |
| BR-35-05 | 差分更新 | 署名に変更がない場合はConfigMap更新をスキップする | 署名計算後 |
| BR-35-06 | TTLベース削除 | Token Cleanerは`expiration`フィールドに基づき期限切れSecretを削除する | Secret評価時 |
| BR-35-07 | UID前提条件 | Secret削除時にUIDプレコンディションを設定し、別オブジェクトの誤削除を防止する | Secret削除時 |

### 計算ロジック

- JWS署名: `jws.ComputeDetachedSignature(content, tokenID, tokenSecret)` - Detached JWS署名を計算
- 有効期限: `bootstrapsecretutil.GetExpiration(secret, time.Now())` - TTLと期限切れ状態を取得

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 署名更新 | ConfigMap (kube-public/cluster-info) | UPDATE | JWS署名データの更新 |
| Secret削除 | Secret (kube-system) | DELETE | 期限切れBootstrapトークンの削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NotFound | ConfigMap不在 | cluster-info ConfigMapが存在しない | スキップ（resyncで再試行） |
| NotFound | Secret不在 | 既に削除されたSecret | 正常終了扱い |
| Conflict | 競合エラー | ConfigMap同時更新 | エラーログ出力（次回resyncで再試行） |

### リトライ仕様

- Bootstrap Signer: ワークキューのレートリミッタによるリトライ（キュー名: bootstrap_signer_queue）
- Token Cleaner: ワークキューのレートリミッタによるリトライ（キュー名: token_cleaner）

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

ConfigMap更新は単一API呼び出し。Secret削除もUIDプレコンディション付きの単一API呼び出し。

## パフォーマンス要件

- Signer: 単一キューアイテム（ConfigMapキー）で合体・直列化
- Cleaner: 10秒間隔でワーカー実行

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

- Bootstrapトークンは機密情報であり、kube-system名前空間のSecretとして保管される
- JWS署名によりクラスター情報の完全性を検証可能
- トークンの使用目的（signing, authentication）をフィールドで制御
- 期限切れトークンの自動削除で不正利用リスクを低減

## 備考

- Bootstrap Signerはcluster-info ConfigMapに対して1つのキューアイテムのみ保持するため、短時間の複数変更が合体される
- Token Cleanerはrequeue機構（AddAfter）でTTL後の再チェックを実現する

---

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | bootstrapsigner.go | `pkg/controller/bootstrap/bootstrapsigner.go` | SignerOptions（46-63行目）とSigner構造体（75-93行目） |
| 1-2 | tokencleaner.go | `pkg/controller/bootstrap/tokencleaner.go` | TokenCleanerOptions（43-50行目）とTokenCleaner構造体（61-73行目） |

#### Step 2: Bootstrap Signerの処理フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bootstrapsigner.go | `pkg/controller/bootstrap/bootstrapsigner.go` | NewSigner（96-155行目）でInformer設定 |
| 2-2 | bootstrapsigner.go | `pkg/controller/bootstrap/bootstrapsigner.go` | signConfigMap（197-254行目）で署名計算の中核ロジック |

**主要処理フロー**:
- **115-132行目**: ConfigMap FilteringResourceEventHandler - 対象ConfigMapのみフィルタ
- **134-152行目**: Secret FilteringResourceEventHandler - BootstrapToken型Secretのみフィルタ
- **211-215行目**: kubeconfigキーの取得
- **229-243行目**: 各トークンのJWS署名計算と差分検出

#### Step 3: Token Cleanerの処理フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | tokencleaner.go | `pkg/controller/bootstrap/tokencleaner.go` | NewTokenCleaner（76-110行目）でInformer設定 |
| 3-2 | tokencleaner.go | `pkg/controller/bootstrap/tokencleaner.go` | evalSecret（197-221行目）で期限評価と削除 |

**主要処理フロー**:
- **200行目**: GetExpirationでTTLと期限切れ状態を取得
- **201-212行目**: 期限切れの場合、UIDプレコンディション付きで削除
- **213-219行目**: TTL > 0の場合、AddAfterでrequeue

#### Step 4: ユーティリティ関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | util.go | `pkg/controller/bootstrap/util.go` | validateSecretForSigning（30-69行目）でトークン検証 |

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

```
[Bootstrap Signer]
NewSigner (96行目)
    ├─ ConfigMap Handler → pokeConfigMapSync (181行目)
    └─ Secret Handler → pokeConfigMapSync (181行目)

Run (158行目)
    └─ serviceConfigMapQueue (185行目)
        └─ signConfigMap (197行目)
            ├─ getConfigMap (264行目)
            ├─ getTokens (297行目)
            │   ├─ listSecrets (279行目)
            │   └─ validateSecretForSigning (util.go:30行目)
            ├─ jws.ComputeDetachedSignature
            └─ updateConfigMap (256行目)

[Token Cleaner]
NewTokenCleaner (76行目)
    └─ Secret Handler → enqueueSecrets (136行目)

Run (113行目)
    └─ worker (146行目)
        └─ processNextWorkItem (152行目)
            └─ syncFunc (169行目)
                └─ evalSecret (197行目)
                    ├─ bootstrapsecretutil.GetExpiration
                    ├─ Secrets().Delete (UIDプレコンディション付き)
                    └─ queue.AddAfter (TTL後requeue)
```

### データフロー図

```
[Bootstrap Signer]
cluster-info ConfigMap ──▶ pokeConfigMapSync ──▶ signConfigMap ──▶ ConfigMap更新
Bootstrap Secrets     ──▶ pokeConfigMapSync       │                (JWS署名付き)
                                                   ├─ getTokens
                                                   └─ ComputeDetachedSignature

[Token Cleaner]
Bootstrap Secrets ──▶ enqueueSecrets ──▶ syncFunc ──▶ Secret削除
                                             │         (期限切れ)
                                             └── AddAfter (TTL後requeue)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bootstrapsigner.go | `pkg/controller/bootstrap/bootstrapsigner.go` | ソース | Bootstrap Signer本体 |
| tokencleaner.go | `pkg/controller/bootstrap/tokencleaner.go` | ソース | Token Cleaner本体 |
| util.go | `pkg/controller/bootstrap/util.go` | ソース | トークン検証ユーティリティ |
| jws | `k8s.io/cluster-bootstrap/token/jws/` | 外部ライブラリ | JWS署名計算 |
| bootstrapapi | `k8s.io/cluster-bootstrap/token/api/` | 外部ライブラリ | Bootstrap API定数定義 |
| bootstrapsecretutil | `k8s.io/cluster-bootstrap/util/secrets/` | 外部ライブラリ | Secret操作ユーティリティ |
