# 通知設計書 128-MissingClusterDNS

## 概要

本ドキュメントは、kubelet の DNS Configurer が発行する `MissingClusterDNS` イベント通知の設計を記述する。kubelet に ClusterDNS IP が設定されていない状態で、DNSClusterFirst ポリシーを使用する Pod が起動しようとした場合に発行される警告イベントである。

### 本通知の処理概要

本通知は、Pod の DNS ポリシーが `ClusterFirst`（または `ClusterFirstWithHostNet`）であるにもかかわらず、kubelet に ClusterDNS の IP アドレスが設定されていない場合に発行される。この場合、Pod の DNS 設定はフォールバックとして `Default`（ホストの DNS 設定を使用）に切り替わる。

**業務上の目的・背景**：多くの Kubernetes アプリケーションはクラスタ内 DNS によるサービスディスカバリに依存している。ClusterDNS が設定されていない状態では、Pod はクラスタ内のサービス名を解決できず、アプリケーションが正常に動作しない可能性がある。この通知により管理者は kubelet の DNS 設定の不備を早期に検知できる。

**通知の送信タイミング**：GetPodDNS 関数内で、dnsType が `podDNSCluster` の場合に `len(c.clusterDNS) == 0` を検出した時点で発行される。ノードオブジェクトと Pod オブジェクトの両方にイベントが記録される。

**通知の受信者**：Kubernetes Event として Node オブジェクトと Pod オブジェクトの両方に対して記録される。クラスタ管理者が参照する。

**通知内容の概要**：kubelet に ClusterDNS IP が設定されていないこと、ClusterFirst ポリシーの Pod を作成できないこと、Default ポリシーにフォールバックすることが記録される。

**期待されるアクション**：クラスタ管理者は kubelet の `--cluster-dns` フラグを正しく設定し、kubelet を再起動する。

## 通知種別

Kubernetes Event（Warning イベント）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（イベント記録） |
| 優先度 | 高（Warning - DNS機能障害） |
| リトライ | なし |

### 送信先決定ロジック

2つのイベントが記録される：
1. Node オブジェクト（`c.nodeRef`）に対してノードレベルの警告
2. Pod オブジェクトに対してPod固有の警告（Pod名を含む）

## 通知テンプレート

### メール通知の場合

本通知はKubernetes Eventであり、メール送信は行わない。

### 本文テンプレート

```
# Nodeオブジェクト宛
kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to "Default" policy.

# Podオブジェクト宛
pod: "<namespace>/<pod-name>(<pod-uid>)". kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to "Default" policy.
```

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| pod名 | Pod の表示名 | format.Pod(pod) | Yes（Pod宛のみ） |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| Pod起動処理 | GetPodDNS呼び出し | dnsType == podDNSCluster かつ len(c.clusterDNS) == 0 | ClusterDNS未設定 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| clusterDNSが設定済み | len(c.clusterDNS) != 0 の場合 |
| dnsTypeがpodDNSCluster以外 | DNSNone や DNSDefault の場合は ClusterDNS 不要 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[Pod起動] --> B[GetPodDNS]
    B --> C[getPodDNSType]
    C --> D{dnsType}
    D -->|podDNSCluster| E{clusterDNS設定あり?}
    D -->|podDNSNone| F[空DNS設定]
    D -->|podDNSHost| G[ホストDNS使用]
    E -->|Yes| H[ClusterDNS設定適用]
    E -->|No| I[Warning Eventf MissingClusterDNS - Node宛]
    I --> J[Warning Eventf MissingClusterDNS - Pod宛]
    J --> K[DNSDefaultにフォールバック]
    H --> L[formDNSConfigFitsLimits]
    F --> L
    G --> L
    K --> G
    L --> M[DNS設定返却]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| Pod（API リソース） | DNSポリシーの確認 | pod.Spec.DNSPolicy |
| Configurer内部状態 | ClusterDNS設定の確認 | c.clusterDNS スライス |

### テーブル別参照項目詳細

#### Pod

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| spec.dnsPolicy | DNSポリシーの判定 | Pod起動時 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| Event（API リソース） | INSERT | Warning イベントの記録（2件） |

#### 送信ログテーブル

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | Event (Node) | Warning / MissingClusterDNS | ノードレベルの警告 |
| INSERT | Event (Pod) | Warning / MissingClusterDNS | Podレベルの警告 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ClusterDNS未設定 | c.clusterDNS が空 | DNSDefaultにフォールバックして処理続行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | N/A（フォールバックで処理続行） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | Kubernetes Event APIのデフォルトレート制限に従う |
| 1日あたり上限 | 制限なし |

### 配信時間帯

特に制限なし。Pod起動時に発生する。

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

本イベントにはPod名とNamespaceが含まれるが、機密情報は含まれない。

## 備考

- 2つのイベントが同時に発行される（Node宛とPod宛）
- フォールバック後はホストの /etc/resolv.conf の DNS 設定が使用される
- `fallthrough` によりpodDNSHostケースに遷移する（422行目）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | dns.go | `pkg/kubelet/network/dns/dns.go` | Configurer構造体（60-74行目）、特にclusterDNSフィールド（67行目）とnodeRefフィールド（63行目） |

**読解のコツ**: clusterDNS は kubelet の `--cluster-dns` フラグで設定される net.IP のスライスである。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dns.go | `pkg/kubelet/network/dns/dns.go` | GetPodDNS関数（386-450行目）の402-422行目がMissingClusterDNSの発行箇所 |

**主要処理フロー**:
1. **393行目**: getPodDNSType(pod) でDNSタイプを判定
2. **402行目**: case podDNSCluster の分岐に入る
3. **403行目**: len(c.clusterDNS) != 0 のチェック
4. **417行目**: clusterDNSが空の場合の処理開始
5. **418行目**: nodeErrorMsg メッセージ構築
6. **419行目**: recorder.Eventf(c.nodeRef, ..., "MissingClusterDNS", ...) - Node宛
7. **420行目**: recorder.Eventf(pod, ..., "MissingClusterDNS", ...) - Pod宛
8. **422行目**: fallthrough で podDNSHost ケースに遷移

#### Step 3: DNSタイプ判定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dns.go | `pkg/kubelet/network/dns/dns.go` | getPodDNSType関数（304-323行目）でDNSポリシーからDNSタイプへの変換 |

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

```
Configurer.GetPodDNS (386行目)
    |
    +-- getHostDNSConfig (388行目)
    +-- getPodDNSType (393行目)
    |
    +-- [dnsType == podDNSCluster && len(clusterDNS) == 0]
    |      +-- recorder.Eventf(nodeRef, "MissingClusterDNS") (419行目)
    |      +-- recorder.Eventf(pod, "MissingClusterDNS") (420行目)
    |      +-- fallthrough → podDNSHost ケース
    |
    +-- formDNSConfigFitsLimits (449行目)
```

### データフロー図

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

Pod.spec.dnsPolicy ───> GetPodDNS ───> clusterDNSチェック ───> Event記録 x2
                                        (len == 0?)              (MissingClusterDNS)
                                            |                        |
                                            v                        v
                                       fallthrough            ホストDNS設定を使用
                                       → podDNSHost
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dns.go | `pkg/kubelet/network/dns/dns.go` | ソース | Configurer, GetPodDNS, MissingClusterDNS発行 |
| dns_test.go | `pkg/kubelet/network/dns/dns_test.go` | テスト | MissingClusterDNS のテスト |
| kubelet.go | `pkg/kubelet/kubelet.go` | ソース | kubelet本体、CheckLimitsForResolvConf呼び出し元 |
