# 機能設計書 143-Cloud Controller Manager

## 概要

本ドキュメントは、Kubernetes Cloud Controller Manager（CCM）の設計について記述する。CCMはクラウドプロバイダー固有のコントローラーループを実行し、ノード管理、ルーティング、ロードバランサー管理などのクラウド依存機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：Kubernetesをマルチクラウド環境で運用するために、クラウドプロバイダー固有のロジックをコアコンポーネントから分離する必要がある。CCMはこの分離を実現し、各クラウドプロバイダーが独自のコントローラーを実装・配布できるアーキテクチャを提供する。これにより、Kubernetesコアのリリースサイクルからクラウドプロバイダー固有コードを独立させることが可能となる。

**機能の利用シーン**：AWS、GCP、Azureなどのクラウド環境でKubernetesクラスターを運用する際に使用される。ノードの初期化（ProviderID設定、ゾーンラベル付与）、LoadBalancerタイプServiceのプロビジョニング、ノードのライフサイクル管理（インスタンス削除検知）などに利用される。

**主要な処理内容**：
1. クラウドプロバイダーの初期化とInterface実装の取得
2. cloud-nodeコントローラー: ノードのProviderID設定、アドレス・ゾーン情報の同期
3. cloud-node-lifecycleコントローラー: クラウドインスタンスの存在確認とノード削除
4. cloud-routeコントローラー: Pod CIDRに対応するクラウドルートの管理
5. cloud-serviceコントローラー: LoadBalancerタイプServiceのプロビジョニング
6. オプショナルなNodeIPAMコントローラーの統合

**関連システム・外部連携**：クラウドプロバイダーAPI（AWS EC2/ELB、GCP Compute Engine、Azure VMなど）、API Server、kubelet

**権限による制御**：CCMは専用のServiceAccountで動作し、ClusterRoleBinding経由でノード、Service、Routeリソースへのアクセス権限が付与される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | kubectl get nodes | 参照画面 | CCMがProviderIDやゾーン情報を設定したノード情報の確認 |
| - | kubectl get svc | 参照画面 | LoadBalancerタイプServiceの外部IP確認 |

## 機能種別

コントローラー / クラウド連携 / リソースライフサイクル管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --cloud-provider | string | Yes | クラウドプロバイダー名 | 登録済みプロバイダー名 |
| --cloud-config | string | No | クラウドプロバイダー設定ファイルパス | 有効なファイルパス |
| --controllers | []string | No | 有効にするコントローラーのリスト | 有効なコントローラー名 |
| --allow-untagged-cloud | bool | No | ClusterIDなしのクラウドを許可 | true/false |
| --configure-cloud-routes | bool | No | クラウドルートの設定を有効化 | true/false |

### 入力データソース

- Kubernetes API Server（Watch経由でNode、Service、Endpointリソースを監視）
- クラウドプロバイダーAPI（インスタンス情報、ロードバランサー状態等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Node.spec.providerID | string | クラウドプロバイダーのインスタンスID |
| Node.metadata.labels | map | topology.kubernetes.io/zone、topology.kubernetes.io/region等 |
| Node.status.addresses | []NodeAddress | クラウドから取得したノードアドレス |
| Service.status.loadBalancer | LoadBalancerStatus | ロードバランサーのIngress情報 |

### 出力先

Kubernetes API Server（リソースの更新）、クラウドプロバイダーAPI（ロードバランサー作成等）

## 処理フロー

### 処理シーケンス

```
1. CCM起動
   └─ コマンドラインオプションの解析、クラウドプロバイダーの初期化
2. クラウドプロバイダーInterface取得
   └─ cloudprovider.InitCloudProvider()でプロバイダー実装をロード
3. ClusterID検証
   └─ HasClusterID()でクラスターIDの存在を確認
4. コントローラー初期化・起動
   └─ DefaultInitFuncConstructorsに基づき各コントローラーを初期化
5. 各コントローラーが定期的にreconcileループを実行
   └─ Node sync、Service sync、Route sync
```

### フローチャート

```mermaid
flowchart TD
    A[CCM起動] --> B[CloudProvider初期化]
    B --> C{ClusterID存在?}
    C -->|Yes| D[コントローラー初期化]
    C -->|No/UntaggedAllowed| D
    C -->|No/UntaggedNotAllowed| E[Fatal終了]
    D --> F[cloud-nodeコントローラー]
    D --> G[cloud-node-lifecycleコントローラー]
    D --> H[cloud-routeコントローラー]
    D --> I[cloud-serviceコントローラー]
    F --> J[ノードProviderID/ゾーン設定]
    G --> K[インスタンス存在確認]
    H --> L[クラウドルート管理]
    I --> M[LoadBalancer管理]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-143-01 | プロバイダーインターフェース | cloudprovider.Interfaceを実装する必要がある | 常時 |
| BR-143-02 | ClusterID必須 | ClusterIDが必須（allow-untagged-cloudで緩和可能） | CCM起動時 |
| BR-143-03 | コントローラー選択 | DefaultInitFuncConstructorsから不要なコントローラーを削除可能 | CCMカスタマイズ時 |
| BR-143-04 | InstancesV2優先 | InstancesV2が実装されている場合、Zones interfaceは呼ばれない | ノード情報取得時 |

### 計算ロジック

LoadBalancer名の計算: "a" + Service.UID（ハイフン除去、32文字制限）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ノード更新 | etcd /registry/nodes/{name} | UPDATE | ProviderID、ゾーンラベル、アドレス情報の更新 |
| ノード削除 | etcd /registry/nodes/{name} | DELETE | クラウドインスタンスが存在しないノードの削除 |
| Service更新 | etcd /registry/services/{ns}/{name} | UPDATE | LoadBalancer Statusの更新 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Fatal | クラウドプロバイダー初期化失敗 | クラウド設定を確認 |
| - | Fatal | ClusterIDが存在せず、allow-untagged-cloud=false | クラスタータグを設定 |
| - | InstanceNotFound | クラウドインスタンスが存在しない | ノードが自動削除される |
| - | NotImplemented | プロバイダーが機能未実装 | 該当コントローラーを無効化 |

### リトライ仕様

各コントローラーはreconcileループで動作し、エラー発生時は指数バックオフで再試行する。

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

API Serverへのリソース更新は楽観的並行制御に基づく。クラウドプロバイダーAPIとの操作はべき等性を持つよう設計される。

## パフォーマンス要件

コントローラーのreconcile間隔はデフォルト設定に準拠。大規模クラスター（数千ノード）においても線形にスケールするよう、Informerキャッシュを利用した効率的なリソース監視を行う。

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

- CCMにはクラウドプロバイダーの認証情報が必要であり、Secretとして安全に管理する必要がある
- CCMのServiceAccountには最小権限の原則に基づくRBAC設定が必要
- クラウドAPIへの通信はTLSで暗号化される

## 備考

- CCMはKubernetesコアから外部化されたコンポーネントであり、各クラウドプロバイダーが独自にビルド・配布する
- サンプル実装として `k8s.io/cloud-provider/sample/basic_main.go` が提供されている

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cloud.go | `staging/src/k8s.io/cloud-provider/cloud.go` | cloudprovider.Interface -- クラウドプロバイダーが実装すべきインターフェース全体 |

**読解のコツ**: Interface内の各メソッド（LoadBalancer(), Instances(), InstancesV2(), Zones(), Routes()）がそれぞれ対応するサブインターフェースを返す。`(T, bool)`のパターンで機能サポートの有無を示す。

**主要処理フロー**:
- **43-69行目**: Interface定義 -- Initialize, LoadBalancer, Instances, InstancesV2, Zones, Clusters, Routes
- **122-173行目**: LoadBalancerインターフェース -- GetLoadBalancer, EnsureLoadBalancer, UpdateLoadBalancer, EnsureLoadBalancerDeleted
- **176-205行目**: Instancesインターフェース -- NodeAddresses, InstanceID, InstanceType
- **207-223行目**: InstancesV2インターフェース -- InstanceExists, InstanceShutdown, InstanceMetadata
- **246-256行目**: Routesインターフェース -- ListRoutes, CreateRoute, DeleteRoute
- **298-335行目**: InstanceMetadata構造体 -- ProviderID, InstanceType, NodeAddresses, Zone, Region

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | main.go | `cmd/cloud-controller-manager/main.go` | CCMのmain関数とコントローラー初期化 |

**主要処理フロー**:
- **46-79行目**: main関数 -- ccmOptions作成、controllerInitializers取得、コマンド生成・実行
- **52行目**: DefaultInitFuncConstructorsで標準コントローラー一覧を取得
- **62-75行目**: NodeIpamControllerの追加例
- **77行目**: NewCloudControllerManagerCommandでコマンドを作成
- **82-102行目**: cloudInitializer -- クラウドプロバイダーの初期化とClusterID検証

#### Step 3: コントローラー実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | controllermanager.go | `staging/src/k8s.io/cloud-provider/app/controllermanager.go` | コントローラーマネージャーの起動ロジック |
| 3-2 | core.go | `staging/src/k8s.io/cloud-provider/app/core.go` | 各コントローラーの初期化関数 |

#### Step 4: 個別コントローラーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | node controller | `staging/src/k8s.io/cloud-provider/controllers/node/` | ノードコントローラー実装 |
| 4-2 | node lifecycle | `staging/src/k8s.io/cloud-provider/controllers/nodelifecycle/` | ノードライフサイクルコントローラー |
| 4-3 | route controller | `staging/src/k8s.io/cloud-provider/controllers/route/` | ルートコントローラー |
| 4-4 | service controller | `staging/src/k8s.io/cloud-provider/controllers/service/` | サービスコントローラー |

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

```
main()
    |
    +-- options.NewCloudControllerManagerOptions()
    +-- app.DefaultInitFuncConstructors (コントローラー一覧)
    +-- app.NewCloudControllerManagerCommand()
    |       |
    |       +-- cloudInitializer()
    |       |       +-- cloudprovider.InitCloudProvider()
    |       |       +-- cloud.HasClusterID()
    |       |
    |       +-- controllermanager.Run()
    |               +-- cloud-node controller
    |               |       +-- cloud.InstancesV2() / cloud.Instances()
    |               +-- cloud-node-lifecycle controller
    |               |       +-- cloud.InstanceExists() / InstanceShutdown()
    |               +-- cloud-route controller
    |               |       +-- cloud.Routes()
    |               +-- cloud-service controller
    |                       +-- cloud.LoadBalancer()
    |                               +-- EnsureLoadBalancer()
    |                               +-- UpdateLoadBalancer()
    |                               +-- EnsureLoadBalancerDeleted()
```

### データフロー図

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

API Server ────────> CCM Informers ────> Nodeコントローラー ────> Node更新
(Node/Service Watch)                                              (ProviderID, Zone)
                                   ────> Serviceコントローラー ──> Service更新
                                                                   (LB Status)
Cloud API ─────────> CCM ────────────> Routeコントローラー ────> クラウドルート
(Instance/LB情報)                                                  (作成/削除)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| main.go | `cmd/cloud-controller-manager/main.go` | ソース | CCMエントリーポイント |
| cloud.go | `staging/src/k8s.io/cloud-provider/cloud.go` | ソース | クラウドプロバイダーインターフェース定義 |
| controllermanager.go | `staging/src/k8s.io/cloud-provider/app/controllermanager.go` | ソース | コントローラーマネージャー |
| core.go | `staging/src/k8s.io/cloud-provider/app/core.go` | ソース | コアコントローラー初期化 |
| node/ | `staging/src/k8s.io/cloud-provider/controllers/node/` | ソース | ノードコントローラー |
| nodelifecycle/ | `staging/src/k8s.io/cloud-provider/controllers/nodelifecycle/` | ソース | ノードライフサイクルコントローラー |
| route/ | `staging/src/k8s.io/cloud-provider/controllers/route/` | ソース | ルートコントローラー |
| service/ | `staging/src/k8s.io/cloud-provider/controllers/service/` | ソース | サービスコントローラー |
| providers.go | `cmd/cloud-controller-manager/providers.go` | ソース | プロバイダー登録 |
| nodeipamcontroller.go | `cmd/cloud-controller-manager/nodeipamcontroller.go` | ソース | NodeIPAMコントローラー統合 |
