# 機能設計書 97-Service公開（expose）

## 概要

本ドキュメントは、kubectl exposeコマンドによるKubernetes Serviceリソースの作成機能の設計を記述する。

### 本機能の処理概要

kubectl exposeコマンドは、既存のDeployment、ReplicaSet、ReplicationController、Pod、Serviceをベースに新しいKubernetes Serviceリソースを作成するCLI機能である。

**業務上の目的・背景**：アプリケーションをネットワーク経由でアクセス可能にするため、Pod群を論理的にグルーピングし、安定したエンドポイント（Service）を提供する。手動でYAMLを書くことなく、既存リソースから自動的にServiceを生成できる。

**機能の利用シーン**：Deploymentの外部公開、内部サービス間通信のためのClusterIP Service作成、LoadBalancerによる外部公開、NodePortによる開発環境アクセス。

**主要な処理内容**：
1. コマンドライン引数からターゲットリソース情報を取得
2. ターゲットリソースからセレクタ、ポート、ラベル等を自動抽出
3. Serviceオブジェクトを生成（createService）
4. Override適用後にAPI Serverに作成

**関連システム・外部連携**：kube-proxyがService定義に基づいてiptables/IPVSルールを設定。LoadBalancer型の場合はCloud Controllerが外部LBをプロビジョニング。

**権限による制御**：Serviceリソースのcreate権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | kubectl expose | 主機能 | Serviceリソースの作成 |

## 機能種別

CRUD操作（Create） / Serviceリソース自動生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| TYPE NAME | string | Yes | ターゲットリソースタイプと名前 | pod/service/replicationcontroller/deployment/replicaset |
| --port | string | No | Serviceのポート番号 | 有効なポート番号 |
| --target-port | string | No | コンテナ側のポート番号/名前 | ポート番号または名前 |
| --protocol | string | No | プロトコル（TCP/UDP/SCTP） | TCP/UDP/SCTP |
| --type | string | No | Service型（ClusterIP/NodePort/LoadBalancer/ExternalName） | 有効なService型 |
| --name | string | No | Service名（デフォルトはターゲット名） | DNS-1035形式 |
| --selector | string | No | ラベルセレクタ | 有効なラベルセレクタ |
| --labels / -l | string | No | Serviceに付与するラベル | 有効なラベル形式 |
| --external-ip | string | No | 外部IPアドレス | 有効なIPアドレス |
| --load-balancer-ip | string | No | ロードバランサIP | 有効なIPアドレス |
| --session-affinity | string | No | セッションアフィニティ（None/ClientIP） | None/ClientIP |
| --cluster-ip | string | No | ClusterIP（Noneでheadless） | 有効なIPまたは"None" |
| --dry-run | string | No | dry-run戦略 | none/client/server |
| -f / --filename | string | No | リソース定義ファイル | 有効なファイルパス |

### 入力データソース

CLI引数、kubeconfig

### 対応リソースタイプ

| リソース | 省略形 |
|---------|--------|
| pod | po |
| service | svc |
| replicationcontroller | rc |
| deployment | deploy |
| replicaset | rs |

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 作成結果 | string | "service/xxx exposed" メッセージ |
| Serviceオブジェクト | Object | --output指定時のService詳細 |

### 出力先

標準出力（stdout）

## 処理フロー

### 処理シーケンス

```
1. ToOptions: フラグからオプションへ変換
2. Complete: ファクトリからの依存注入
3. RunExpose: Service作成実行
   ├─ resource.Builderでターゲットリソース取得
   ├─ CanBeExposed: リソースがexpose可能か確認
   ├─ MapBasedSelectorForObject: セレクタ自動抽出
   ├─ PortsForObject: ポート自動抽出
   ├─ ProtocolsForObject: プロトコル自動抽出
   ├─ Labels自動抽出
   ├─ createService: Serviceオブジェクト生成
   ├─ Override適用
   └─ API ServerにCreate
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[ToOptions: フラグ→オプション変換]
    B --> C[Complete: 依存注入]
    C --> D[RunExpose: ターゲットリソース取得]
    D --> E[CanBeExposed チェック]
    E --> F{expose可能?}
    F -->|No| G[エラー終了]
    F -->|Yes| H[セレクタ・ポート・ラベル自動抽出]
    H --> I[createService: Serviceオブジェクト生成]
    I --> J[Override適用]
    J --> K{dry-run client?}
    K -->|Yes| L[オブジェクト出力のみ]
    K -->|No| M[API Server CREATE]
    M --> N[結果出力]
    L --> N
    N --> O[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-97-01 | 名前長制限 | Service名はDNS1035LabelMaxLength（63文字）に制限 | 常時 |
| BR-97-02 | セレクタ自動抽出 | --selector未指定時はターゲットリソースのセレクタを使用 | selector未指定時 |
| BR-97-03 | ポート自動抽出 | --port未指定時はターゲットリソースのポート定義を使用。複数ポートは全て含まれる | port未指定時 |
| BR-97-04 | プロトコルデフォルト | --protocol未指定時はTCPがデフォルト | protocol未指定時 |
| BR-97-05 | ラベル自動抽出 | --labels未指定時はターゲットリソースのラベルを流用 | labels未指定時 |
| BR-97-06 | TargetPortデフォルト | --target-port未指定時はService Portと同値を設定 | target-port未指定時 |
| BR-97-07 | headless Service | --cluster-ip=NoneでheadlessService。ポートなしでもOK | cluster-ip=None時 |
| BR-97-08 | マルチポート名生成 | 複数ポート時はport-1, port-2...の名前を自動生成 | 複数ポート時 |
| BR-97-09 | マルチプロトコル | 同一ポートに複数プロトコルがある場合、port-{n}-{protocol}形式で個別ポートを生成 | マルチプロトコル時 |

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| Create | Service | CREATE | Serviceリソースを新規作成 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | expose不可エラー | リソースタイプがexpose対象外 | 対応リソースを使用 |
| - | セレクタ取得エラー | セレクタが自動取得できず--selectorも未指定 | --selectorを指定 |
| - | ポート取得エラー | ポートが自動取得できず--portも未指定（headless以外） | --portを指定 |
| - | セッションアフィニティエラー | 無効なsession-affinity値 | None/ClientIPを指定 |
| - | セレクタ必須エラー | セレクタが空 | --selectorを指定 |

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

API Serverのatomic create操作。

## パフォーマンス要件

単一API呼び出し。ターゲットリソースの取得とService作成の2回のAPI呼び出し。

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

- Serviceリソースのcreate権限が必要
- LoadBalancer型は外部公開となるため注意
- external-ipの不適切な設定に注意

## 備考

- Deploymentのセレクタがservice-compatibleでない場合（matchExpressions使用時等）はexposeできない
- Service名は元のリソース名から自動的に63文字に切り詰められる
- --overridesオプションで生成されたServiceオブジェクトをカスタマイズ可能

---

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | expose.go | `staging/src/k8s.io/kubectl/pkg/cmd/expose/expose.go` | **90-135行目**: ExposeServiceOptions構造体でコマンドの全オプションを確認 |
| 1-2 | expose.go | `staging/src/k8s.io/kubectl/pkg/cmd/expose/expose.go` | **138-160行目**: ExposeServiceFlags構造体でCLI入力フラグを確認 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | expose.go | `staging/src/k8s.io/kubectl/pkg/cmd/expose/expose.go` | **173-199行目**: NewCmdExposeService関数。validArgsをexposeResourcesから動的に生成 |

#### Step 3: Service生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | expose.go | `staging/src/k8s.io/kubectl/pkg/cmd/expose/expose.go` | **296-428行目**: RunExpose関数で、ターゲットリソースからServiceを生成する全体フロー |
| 3-2 | expose.go | `staging/src/k8s.io/kubectl/pkg/cmd/expose/expose.go` | **316-317行目**: CanBeExposedでリソースタイプのexpose可否チェック |
| 3-3 | expose.go | `staging/src/k8s.io/kubectl/pkg/cmd/expose/expose.go` | **328-334行目**: セレクタの自動抽出（MapBasedSelectorForObject） |
| 3-4 | expose.go | `staging/src/k8s.io/kubectl/pkg/cmd/expose/expose.go` | **340-355行目**: ポートの自動抽出。headless時はポートなしでもOK |
| 3-5 | expose.go | `staging/src/k8s.io/kubectl/pkg/cmd/expose/expose.go` | **430-575行目**: createService関数でServiceオブジェクトの構築 |
| 3-6 | expose.go | `staging/src/k8s.io/kubectl/pkg/cmd/expose/expose.go` | **472-521行目**: ポート・プロトコルのマッピング。マルチプロトコル対応ロジック |
| 3-7 | expose.go | `staging/src/k8s.io/kubectl/pkg/cmd/expose/expose.go` | **533-547行目**: TargetPort設定。未指定時はServicePortと同値 |

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

```
NewCmdExposeService
    │
    ├─ ExposeServiceFlags.ToOptions
    │      ├─ GetDryRunStrategy
    │      ├─ PrintFlags.ToPrinter
    │      └─ RecordFlags.ToRecorder
    │
    ├─ Complete
    │      ├─ f.NewBuilder()
    │      ├─ f.ClientForMapping
    │      ├─ polymorphichelpers (CanBeExposed, MapBasedSelector, Ports, Protocols)
    │      └─ f.ToRESTMapper()
    │
    └─ RunExpose
           ├─ builder.Do() → r.Visit()
           │      ├─ CanBeExposed(GVK)
           │      ├─ MapBasedSelectorForObject()
           │      ├─ PortsForObject()
           │      ├─ ProtocolsForObject()
           │      └─ meta.NewAccessor().Labels()
           ├─ createService()
           │      ├─ parseLabels(selector)
           │      ├─ parseLabels(labels)
           │      ├─ parseProtocols(protocols)
           │      └─ corev1.Service構築
           ├─ overrider.Apply()
           ├─ resource.NewHelper().Create()  ───▶ API Server
           └─ PrintObj()
```

### データフロー図

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

CLI引数                 ───▶ ToOptions → Complete
 (TYPE NAME --port)           │
                              ▼
kubeconfig              ───▶ RunExpose
ターゲットリソース  ◀──── Builder.Do()         ◀─── API Server (GET)
                         ├─ セレクタ抽出
                         ├─ ポート抽出
                         ├─ プロトコル抽出
                         ├─ ラベル抽出
                         ├─ createService()
                         ├─ overrider.Apply()
                         ├─ NewHelper().Create() ───▶ API Server (CREATE Service)
                         └─ PrintObj()           ───▶ stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| expose.go | `staging/src/k8s.io/kubectl/pkg/cmd/expose/expose.go` | ソース | exposeコマンドのメイン実装（630行） |
| polymorphichelpers | `staging/src/k8s.io/kubectl/pkg/polymorphichelpers/` | ソース | CanBeExposed, MapBasedSelector, Ports, Protocols関数群 |
