# 機能設計書 140-DNS

## 概要

本ドキュメントは、Kubernetes におけるクラスター内 DNS 名前解決機能の設計を記述する。Pod に対する DNS 設定の自動構成と、サービスディスカバリのための DNS 名前解決を提供する。

### 本機能の処理概要

**業務上の目的・背景**：Kubernetes クラスター内のサービスディスカバリの中核を担う機能。各 Pod に対して適切な DNS 設定（resolv.conf）を自動生成し、Service 名による名前解決を可能にする。これにより、Pod は Service の ClusterIP を知らなくてもサービス名でアクセスできる。

**機能の利用シーン**：Pod からの Service へのアクセス時、Pod から外部ドメインへのアクセス時、Pod の DNS ポリシー設定時に使用される。

**主要な処理内容**：
1. Pod の DNS ポリシー（ClusterFirst, Default, None）に基づく DNS 設定の決定
2. resolv.conf の動的生成（nameserver, search, options の構成）
3. クラスター DNS サーバーアドレスの注入
4. クラスタードメインに基づく検索サフィックスの構成
5. DNS 検索パスと文字数の制限チェック
6. ホストの DNS 設定との統合

**関連システム・外部連携**：CoreDNS（クラスター DNS サーバー）、kubelet（DNS Configurer）、CRI（コンテナランタイム）

**権限による制御**：Pod の dnsPolicy と dnsConfig フィールドにより、Pod 作成者が DNS 設定をカスタマイズ可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | Pod 作成時に kubelet が自動的に DNS 設定を構成 |

## 機能種別

ネットワーク設定管理（Pod DNS 構成）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| spec.dnsPolicy | DNSPolicy | No | DNS ポリシー | ClusterFirstWithHostNet, ClusterFirst, Default, None |
| spec.dnsConfig | PodDNSConfig | No | カスタム DNS 設定 | nameservers, searches, options |
| spec.dnsConfig.nameservers | []string | No | カスタム nameserver | 有効な IP アドレス |
| spec.dnsConfig.searches | []string | No | カスタム検索ドメイン | DNS サブドメイン準拠 |
| spec.dnsConfig.options | []PodDNSConfigOption | No | カスタム DNS オプション | name/value ペア |

### 入力データソース

- Pod Spec の dnsPolicy/dnsConfig フィールド
- kubelet の起動パラメータ（clusterDNS, clusterDomain, resolverConfig）
- ホストの /etc/resolv.conf（resolverConfig で指定）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| DNSConfig | runtimeapi.DNSConfig | CRI に渡される DNS 設定 |
| DNSConfig.Servers | []string | DNS サーバーアドレスリスト |
| DNSConfig.Searches | []string | DNS 検索ドメインリスト |
| DNSConfig.Options | []string | DNS オプションリスト |

### 出力先

- CRI (Container Runtime Interface) を通じてコンテナの /etc/resolv.conf に反映

## 処理フロー

### 処理シーケンス

```
1. Pod DNS タイプ判定
   └─ dnsPolicy に基づき podDNSCluster / podDNSHost / podDNSNone を決定
2. ベース DNS 設定の取得
   ├─ Cluster: clusterDNS アドレス + クラスタードメインベースの search
   ├─ Host: ホストの /etc/resolv.conf から読み取り
   └─ None: 空の設定
3. PodDNSConfig のマージ
   └─ ユーザー指定の nameservers/searches/options をベース設定にマージ
4. 制限チェック
   └─ 検索パス数（最大32）、検索リスト文字数（最大2048）のチェック
5. DNS 設定の返却
   └─ runtimeapi.DNSConfig として CRI に渡す
```

### フローチャート

```mermaid
flowchart TD
    A[Pod DNS 設定要求] --> B{dnsPolicy?}
    B -->|ClusterFirst/ClusterFirstWithHostNet| C[Cluster DNS 設定]
    B -->|Default| D[Host DNS 設定]
    B -->|None| E[空の DNS 設定]
    C --> F[clusterDNS をサーバーに設定]
    F --> G[検索ドメイン構成]
    G --> H[ndots:5 オプション追加]
    D --> I[/etc/resolv.conf 読み取り]
    I --> J[ホスト設定をパース]
    E --> K[空の設定]
    H --> L{PodDNSConfig あり?}
    J --> L
    K --> L
    L -->|Yes| M[nameservers/searches/options マージ]
    L -->|No| N[制限チェック]
    M --> N
    N --> O[runtimeapi.DNSConfig 返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-140-01 | デフォルト ndots | Cluster DNS 使用時、デフォルトで ndots:5 を設定 | podDNSCluster |
| BR-140-02 | 検索ドメイン構成 | `{namespace}.svc.{clusterDomain}`, `svc.{clusterDomain}`, `{clusterDomain}` の順で構成 | podDNSCluster |
| BR-140-03 | HostNetwork 対応 | HostNetwork + ClusterFirstWithHostNet の場合はクラスター DNS を使用 | HostNetwork Pod |
| BR-140-04 | 検索パス上限 | 最大32個の検索パス（MaxDNSSearchPaths） | 常時 |
| BR-140-05 | 検索リスト文字数上限 | 最大2048文字（MaxDNSSearchListChars） | 常時 |
| BR-140-06 | 個別検索パス長上限 | 各検索パスは253文字以下（DNS1123SubdomainMaxLength） | 常時 |
| BR-140-07 | resolv.conf サイズ上限 | ホストの resolv.conf は最大10MB | Host DNS 読み取り時 |
| BR-140-08 | 重複排除 | nameserver と search ドメインの重複を排除 | DNS 設定構成時 |
| BR-140-09 | PodDNSConfig マージ | ユーザー指定の設定をベース設定に追加（上書きではない） | dnsConfig 指定時 |

### 計算ロジック

- Cluster 検索ドメイン: `{namespace}.svc.{clusterDomain}` + `svc.{clusterDomain}` + `{clusterDomain}`
- ホスト検索ドメインの付加: Cluster 検索ドメインの後にホストの検索ドメインを追加

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

本機能にはデータベース操作はない。Pod 生成時のインメモリ処理として実行される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 検索パス超過 | 検索パス数が32を超過 | 先頭32個に切り詰め、警告イベント発行 |
| - | 検索リスト文字数超過 | 検索リストの合計文字数が2048を超過 | 超過分を除去、警告イベント発行 |
| - | 個別検索パス長超過 | 検索パスが253文字を超過 | 該当パスを除去 |
| - | resolv.conf 読み取り失敗 | ホストの resolv.conf が読み取れない | 空の DNS 設定を使用、警告ログ出力 |
| - | clusterDNS 未設定 | kubelet の clusterDNS が設定されていない | ホストの DNS 設定にフォールバック、警告イベント発行 |

### リトライ仕様

DNS 設定構成にリトライ機構はない。失敗時は警告を発行してフォールバック設定を使用する。

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

該当なし。

## パフォーマンス要件

- DNS 設定の構成は Pod 起動時に1回実行される
- resolv.conf のパースは軽量な文字列処理

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

- resolv.conf のサイズ制限（10MB）によるDoS防止
- PodDNSConfig によるユーザーカスタマイズの検証（バリデーション済み値のみ許可）
- DNS ポリシー None の場合、ユーザーが全ての DNS 設定を明示的に指定する必要がある

## 備考

- CoreDNS との連携: kubelet が DNS 設定を構成し、CoreDNS がクラスター内 DNS サーバーとして名前解決を提供
- Windows プラットフォーム対応: dns_windows.go で Windows 固有の resolv.conf 処理を実装
- ndots:5 のデフォルト設定は、クラスター内の短縮名解決を優先するため

---

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

### 推奨読解順序

#### Step 1: データ構造と定数

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | dns.go | `pkg/kubelet/network/dns/dns.go` | podDNSType 定数（47-53行目）: Cluster/Host/None の3タイプ |
| 1-2 | dns.go | 同上 | defaultDNSOptions（44行目）: ndots:5 がデフォルト |
| 1-3 | dns.go | 同上 | Configurer 構造体（60-74行目）: clusterDNS, ClusterDomain, ResolverConfig 等の設定保持 |
| 1-4 | dns.go | 同上 | maxResolvConfLength（56行目）: 10MB のサイズ制限 |

#### Step 2: DNS 設定構成ロジック

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dns.go | 同上 | NewConfigurer()（77-87行目）: Configurer の初期化 |
| 2-2 | dns.go | 同上 | formDNSSearchFitsLimits()（102-120行目以降）: 検索パスの制限チェック。maxDNSSearchPaths, maxDNSSearchListChars の適用 |
| 2-3 | dns.go | 同上 | omitDuplicates()（89-100行目）: 重複排除ヘルパー |

**読解のコツ**: DNS 設定の構成は dnsPolicy に応じた3分岐が基本パターン。各分岐の後に PodDNSConfig のマージ処理が共通で適用される。glibc 2.28 の255文字制限への対応（114-119行目）は重要なエッジケース。

#### Step 3: プラットフォーム固有処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dns_other.go | `pkg/kubelet/network/dns/dns_other.go` | Linux 用の getHostDNSConfig 実装 |
| 3-2 | dns_windows.go | `pkg/kubelet/network/dns/dns_windows.go` | Windows 用の getHostDNSConfig 実装 |

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

```
kubelet Pod 起動
    │
    └─ Configurer.GetPodDNS()
           │
           ├─ getPodDNSType() [DNS タイプ判定]
           │
           ├─ [podDNSCluster]
           │      ├─ getClusterDNS() [クラスター DNS 設定取得]
           │      └─ generateSearchesForDNSClusterFirst()
           │             [検索ドメイン構成]
           │
           ├─ [podDNSHost]
           │      └─ getHostDNSConfig() [ホスト DNS 読み取り]
           │
           ├─ [podDNSNone]
           │      └─ (空の設定)
           │
           ├─ appendDNSConfig() [PodDNSConfig マージ]
           │
           ├─ formDNSSearchFitsLimits() [制限チェック]
           │
           └─ omitDuplicates() [重複排除]
```

### データフロー図

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

Pod Spec            ──▶ getPodDNSType()           ──▶ Cluster/Host/None
  (dnsPolicy)

kubelet config      ──▶ getClusterDNS()           ──▶ DNS servers + searches
  (clusterDNS,           generateSearches()
   clusterDomain)

/etc/resolv.conf    ──▶ getHostDNSConfig()        ──▶ host DNS config

base config +       ──▶ appendDNSConfig()         ──▶ merged DNS config
PodDNSConfig

merged config       ──▶ formDNSSearchFitsLimits() ──▶ runtimeapi.DNSConfig
                         (制限チェック・切り詰め)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dns.go | `pkg/kubelet/network/dns/dns.go` | ソース | DNS 設定構成のメインロジック |
| dns_other.go | `pkg/kubelet/network/dns/dns_other.go` | ソース | Linux 固有のホスト DNS 取得 |
| dns_windows.go | `pkg/kubelet/network/dns/dns_windows.go` | ソース | Windows 固有のホスト DNS 取得 |
| dns_test.go | `pkg/kubelet/network/dns/dns_test.go` | テスト | ユニットテスト |
| dns_other_test.go | `pkg/kubelet/network/dns/dns_other_test.go` | テスト | Linux 固有テスト |
| dns_windows_test.go | `pkg/kubelet/network/dns/dns_windows_test.go` | テスト | Windows 固有テスト |
