# 機能設計書 139-Service管理

## 概要

本ドキュメントは、Kubernetes における Service 管理機能の設計を記述する。ClusterIP、NodePort、LoadBalancer、ExternalName 各タイプの Service の CRUD 操作および関連するリソース割り当て（IP、ポート）の管理を行う。

### 本機能の処理概要

**業務上の目的・背景**：Service はKubernetesの中核的なネットワーキング抽象であり、Pod 群への安定したアクセスポイントを提供する。動的に変化する Pod のIPアドレスに対して、固定的なClusterIPやDNS名を通じたアクセスを可能にする。

**機能の利用シーン**：マイクロサービスアーキテクチャにおけるサービス間通信、外部からのアクセスポイントの公開（NodePort, LoadBalancer）、外部サービスへの参照（ExternalName）等。

**主要な処理内容**：
1. Service オブジェクトの CRUD 操作
2. ClusterIP/ClusterIPs の自動割り当てと管理
3. NodePort の自動割り当てと管理
4. HealthCheckNodePort の管理
5. Service タイプ変更時のフィールド自動クリーンアップ
6. IPFamily/IPFamilyPolicy の管理（デュアルスタック対応）
7. Status サブリソースの管理（LoadBalancer 情報）

**関連システム・外部連携**：kube-proxy（実際のルーティング実装）、cloud-controller-manager（LoadBalancer プロビジョニング）、CoreDNS（サービスディスカバリ）、ipallocator（IP割り当て）、portallocator（ポート割り当て）

**権限による制御**：RBAC により Service の CRUD が制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | kubectl や API を通じて操作 |

## 機能種別

ネットワークリソース管理（API リソースの CRUD + リソース割り当て）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| metadata.name | string | Yes | Service 名 | DNS ラベル準拠 |
| metadata.namespace | string | Yes | 対象 Namespace | 有効な Namespace 名 |
| spec.type | ServiceType | No | Service タイプ | ClusterIP, NodePort, LoadBalancer, ExternalName |
| spec.clusterIP | string | No | 固定 ClusterIP | 有効な IP アドレスまたは "None" |
| spec.clusterIPs | []string | No | 固定 ClusterIP リスト（デュアルスタック） | 有効な IP アドレスリスト |
| spec.ports | []ServicePort | Yes | ポート定義 | ポート番号、プロトコル |
| spec.selector | map[string]string | No | Pod セレクタ | ラベルセレクタ |
| spec.externalTrafficPolicy | ExternalTrafficPolicy | No | 外部トラフィックポリシー | Cluster, Local |
| spec.ipFamilyPolicy | IPFamilyPolicy | No | IP ファミリーポリシー | SingleStack, PreferDualStack, RequireDualStack |
| spec.loadBalancerClass | *string | No | LoadBalancer クラス | 有効なクラス名 |
| spec.allocateLoadBalancerNodePorts | *bool | No | LB NodePort 自動割り当て | true/false |

### 入力データソース

- Kubernetes REST API

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| spec.clusterIP | string | 割り当てられた ClusterIP |
| spec.clusterIPs | []string | 割り当てられた ClusterIP リスト |
| spec.ports[].nodePort | int32 | 割り当てられた NodePort |
| spec.healthCheckNodePort | int32 | 割り当てられた HealthCheck NodePort |
| status.loadBalancer | LoadBalancerStatus | LoadBalancer 情報 |

### 出力先

- etcd（永続化）
- REST API レスポンス

## 処理フロー

### 処理シーケンス

```
1. Create リクエスト受信
   └─ PrepareForCreate: Status クリア、dropServiceDisabledFields
2. バリデーション
   └─ ValidateServiceCreate
3. IP/ポート割り当て（REST.Create 内）
   └─ ClusterIP 割り当て、NodePort 割り当て、HealthCheckNodePort 割り当て
4. etcd への永続化
5. Update リクエスト受信
   └─ PrepareForUpdate: Status保持、dropServiceDisabledFields、dropTypeDependentFields
6. タイプ変更時の自動クリーンアップ
   └─ 不要になったフィールド（ClusterIP, NodePort, HealthCheckNodePort等）の自動クリア
```

### フローチャート

```mermaid
flowchart TD
    A[Update リクエスト] --> B[PrepareForUpdate]
    B --> C[Status 保持]
    C --> D[dropServiceDisabledFields]
    D --> E[dropTypeDependentFields]
    E --> F{タイプ変更?}
    F -->|ClusterIP→ExternalName| G[ClusterIP/ClusterIPs/IPFamilies クリア]
    F -->|NodePort→ClusterIP| H[NodePort クリア]
    F -->|LB→非LB| I[HealthCheckNodePort/AllocateNodePorts/LBClass クリア]
    F -->|No change| J[バリデーション]
    G --> J
    H --> J
    I --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-139-01 | Namespace スコープ | Service は Namespace スコープのリソース | 常時 |
| BR-139-02 | Status 保護 | 作成時に Status クリア。更新時に Status は旧値保持 | Create/Update |
| BR-139-03 | タイプ依存フィールド自動クリア | タイプ変更時に不要なフィールドを自動クリア | Update 時 |
| BR-139-04 | ClusterIP→ExternalName 変更 | ClusterIP/ClusterIPs がユーザー変更なしの場合のみクリア | タイプ変更時 |
| BR-139-05 | NodePort 保持判定 | 新しいNodePortが追加されていない場合のみクリア | タイプ変更時 |
| BR-139-06 | HealthCheckNodePort 保持判定 | 値が変更されていない場合のみクリア | タイプ変更時 |
| BR-139-07 | LB Status クリア | 非LBタイプへの変更時にLBステータスをクリア | タイプ変更時 |
| BR-139-08 | AllowCreateOnUpdate | true - Update で新規作成を許可 | Update 時 |
| BR-139-09 | ExternalTrafficPolicy 自動クリア | 外部アクセス不可タイプへの変更時にクリア | タイプ変更時 |

### 計算ロジック

- SelectableFields: `spec.clusterIP` と `spec.type` でフィルタリング可能

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

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

| 操作 | 対象リソース | 操作種別 | 概要 |
|-----|-------------|---------|------|
| Create | Service | INSERT | IP/ポート割り当て付きで作成 |
| Update | Service | UPDATE | Spec 更新（タイプ依存フィールド自動クリア含む） |
| Status Update | Service | UPDATE | LB ステータス更新（Spec 保持） |
| Delete | Service | DELETE | IP/ポート解放付きで削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | BadRequest | バリデーションエラー | エラーメッセージと共に拒否 |
| 409 | Conflict | IP/ポート割り当て競合 | リトライを促す |
| 422 | UnprocessableEntity | 不正な設定 | エラーメッセージと共に拒否 |

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

Service の作成・削除時には IP/ポートの割り当て・解放が伴い、REST.Create/Delete 内で処理される。割り当て失敗時はロールバックされる。

## パフォーマンス要件

通常の Kubernetes API オブジェクト操作と同等。IP/ポートの割り当ては ipallocator/portallocator 経由で行われる。

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

- RBAC による Service の管理権限制御
- Status 更新時の IP 警告チェック（GetWarningsForIP）
- LoadBalancer Status の IP 検証
- dropServiceDisabledFields/dropServiceStatusDisabledFields でフィーチャーゲート未対応フィールドをクリア

## 備考

- Service は Kubernetes の discriminated union パターンの典型例（typeフィールドが判別子）
- タイプ変更時の自動クリーンアップはプール割り当てリソースの解放に必要
- ProxyREST によるサービスプロキシもサポート

---

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

### 推奨読解順序

#### Step 1: Strategy パターン

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | strategy.go | `pkg/registry/core/service/strategy.go` | svcStrategy 構造体（42-45行目） |
| 1-2 | strategy.go | 同上 | PrepareForCreate()（69-74行目）: Status クリア + dropServiceDisabledFields |
| 1-3 | strategy.go | 同上 | PrepareForUpdate()（77-84行目）: Status 保持 + dropServiceDisabledFields + dropTypeDependentFields |

#### Step 2: タイプ依存フィールドのクリーンアップ

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | strategy.go | 同上 | dropTypeDependentFields()（240-317行目）: **最も重要な処理**。タイプ変更時の自動クリーンアップの全ロジック |
| 2-2 | strategy.go | 同上 | needsClusterIP()（319-324行目）: ExternalName 以外は ClusterIP が必要 |
| 2-3 | strategy.go | 同上 | needsNodePort()（347-352行目）: NodePort/LoadBalancer タイプで NodePort が必要 |
| 2-4 | strategy.go | 同上 | needsHCNodePort()（374-382行目）: LB + Local トラフィックポリシーで HCNodePort が必要 |

**読解のコツ**: dropTypeDependentFields は「ユーザーが変更していない場合のみクリア」という原則を守るため、same*() ヘルパー関数で旧値との比較を行っている。

#### Step 3: Storage レイヤー

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | storage.go | `pkg/registry/core/service/storage/storage.go` | REST 構造体（60-68行目）: ipallocator, portallocator を保持 |
| 3-2 | storage.go | 同上 | NewREST()（79-100行目）: Store 初期化。IP/ポートアロケータの統合 |

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

```
REST API リクエスト
    │
    ├─ Create → REST.Create()
    │      ├─ Strategy.PrepareForCreate()
    │      │      ├─ Status クリア
    │      │      └─ dropServiceDisabledFields()
    │      ├─ Strategy.Validate() → ValidateServiceCreate()
    │      ├─ Allocators.allocate() [ClusterIP/NodePort/HCNodePort]
    │      └─ etcd store
    │
    ├─ Update → REST.Update()
    │      ├─ Strategy.PrepareForUpdate()
    │      │      ├─ Status 保持
    │      │      ├─ dropServiceDisabledFields()
    │      │      └─ dropTypeDependentFields()
    │      ├─ Strategy.ValidateUpdate() → ValidateServiceUpdate()
    │      └─ Allocators.update() [IP/ポート再割り当て]
    │
    └─ Status Update → StatusREST
           ├─ serviceStatusStrategy.PrepareForUpdate() [Spec 保持]
           └─ serviceStatusStrategy.ValidateUpdate()
```

### データフロー図

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

API Request         ──▶ PrepareForCreate/Update   ──▶ sanitized Service
  (Service)              dropTypeDependentFields

sanitized Service   ──▶ Allocators                ──▶ Service with allocated
                         ipallocator                    ClusterIP/NodePort
                         portallocator

allocated Service   ──▶ etcd store                ──▶ persisted Service
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| strategy.go | `pkg/registry/core/service/strategy.go` | ソース | Create/Update 戦略、タイプ依存クリーンアップ |
| storage/storage.go | `pkg/registry/core/service/storage/storage.go` | ソース | REST ストレージ、IP/ポートアロケータ統合 |
| storage/alloc.go | `pkg/registry/core/service/storage/alloc.go` | ソース | IP/ポートの割り当てロジック |
| ipallocator/ | `pkg/registry/core/service/ipallocator/` | ソース | IP アドレス割り当て |
| portallocator/ | `pkg/registry/core/service/portallocator/` | ソース | ポート割り当て |
| proxy.go | `pkg/registry/core/service/proxy.go` | ソース | サービスプロキシ |
