# 通知設計書 129-CheckLimitsForResolvConf

## 概要

本ドキュメントは、kubelet の DNS Configurer が発行する `CheckLimitsForResolvConf` イベント通知の設計を記述する。ノードの resolv.conf ファイルの制限チェックで問題が発見された場合に発行される警告イベントである。

### 本通知の処理概要

本通知は、kubelet がノードの resolv.conf ファイルを読み取り、DNS 検索パス数や検索リスト文字数がシステム制限を超過しているかを検証する際に発行される。resolv.conf のファイルオープン失敗、パースエラー、検索パス数超過、個別パス長超過、検索リスト文字数超過の各ケースで警告イベントが記録される。

**業務上の目的・背景**：ノードの resolv.conf 設定は Pod の DNS 設定のベースとなる（ClusterFirst ポリシーの場合、ホストの検索パスが追加される）。resolv.conf の設定が制限を超過している場合、Pod 起動時に DNS 設定の切り捨てが発生し、名前解決に問題が生じる可能性がある。この事前チェックにより管理者はノードレベルの DNS 設定問題を早期に検知できる。

**通知の送信タイミング**：kubelet 起動時に `CheckLimitsForResolvConf` メソッドが呼び出され、resolv.conf の各種制限チェック時にイベントが発行される。

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

**通知内容の概要**：resolv.conf のどの制限に抵触しているか（ファイルオープン失敗、パースエラー、検索パス数超過、パス長超過、検索リスト文字数超過）の詳細が記録される。

**期待されるアクション**：クラスタ管理者はノードの /etc/resolv.conf を確認し、検索パス数や文字数が制限内に収まるよう修正する。

## 通知種別

Kubernetes Event（Warning イベント）

## 送信仕様

### 基本情報

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

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

Node オブジェクト（`c.nodeRef`）に対してイベントが記録される。

## 通知テンプレート

### メール通知の場合

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

### 本文テンプレート

```
# ファイルオープン失敗時
<error message>

# パースエラー時
<error message>

# 検索パス数超過時
Resolv.conf file '<path>' contains search line consisting of more than <limit> domains!

# 個別パス長超過時
Resolv.conf file "<path>" contains a search path which length is more than allowed <limit> chars!

# 検索リスト文字数超過時
Resolv.conf file '<path>' contains search line which length is more than allowed <limit> chars!
```

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| path | resolv.confファイルパス | c.ResolverConfig | Yes |
| limit | 制限値 | domainCountLimit / DNS1123SubdomainMaxLength / maxDNSSearchListChars | Yes |
| error message | エラーメッセージ | os.Open / parseResolvConf の戻り値 | Yes（エラー時） |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| kubelet起動 | CheckLimitsForResolvConf呼び出し | resolv.confのオープン失敗 | ファイルアクセスエラー（181行目） |
| kubelet起動 | CheckLimitsForResolvConf呼び出し | resolv.confのパースエラー | パース処理失敗（189行目） |
| kubelet起動 | CheckLimitsForResolvConf呼び出し | 検索パス数 > domainCountLimit | ドメイン数超過（201行目） |
| kubelet起動 | CheckLimitsForResolvConf呼び出し | 個別パス長 > DNS1123SubdomainMaxLength | パス長超過（209行目） |
| kubelet起動 | CheckLimitsForResolvConf呼び出し | 検索リスト文字数 > maxDNSSearchListChars | 文字数超過（217行目） |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| すべてのチェックが正常 | 制限内であればイベントは発行されない |
| ResolverConfigが空文字列 | resolv.conf パスが未設定の場合はチェック自体がスキップされる可能性 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[kubelet起動] --> B[CheckLimitsForResolvConf]
    B --> C{resolv.conf オープン}
    C -->|失敗| D[Warning Event - ファイルオープン失敗]
    C -->|成功| E[parseResolvConf]
    E --> F{パース結果}
    F -->|エラー| G[Warning Event - パースエラー]
    F -->|成功| H{検索パス数チェック}
    H -->|超過| I[Warning Event - ドメイン数超過]
    H -->|正常| J{各パス長チェック}
    J -->|超過| K[Warning Event - パス長超過]
    J -->|正常| L{検索リスト文字数チェック}
    L -->|超過| M[Warning Event - 文字数超過]
    L -->|正常| N[正常終了]
    D --> O[return]
    G --> O
    I --> O
    K --> O
    M --> O
    N --> O
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| resolv.conf | ホストDNS設定の読み取り | ファイルシステムから直接読み取り |

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

#### resolv.conf

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| search行 | 検索パスの取得 | parseResolvConf関数で解析 |
| nameserver行 | ネームサーバの取得 | parseResolvConf関数で解析 |
| options行 | DNSオプションの取得 | parseResolvConf関数で解析 |

### 更新テーブル一覧

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

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

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | Event | Warning / CheckLimitsForResolvConf | Kubernetes Event APIを通じて記録 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ファイルオープン失敗 | resolv.conf が存在しないまたは読取権限なし | Warningイベント発行後return |
| パースエラー | resolv.conf の形式が不正 | Warningイベント発行後return |
| 検索パス数超過 | search行のドメイン数が制限超過 | Warningイベント発行後return |
| パス長超過 | 個別検索パスが255文字超過 | Warningイベント発行後return |
| 文字数超過 | search行全体の文字数が制限超過 | Warningイベント発行後return |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（起動時の1回のみ） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | N/A（起動時の1回のみ） |
| 1日あたり上限 | N/A |

### 配信時間帯

kubelet起動時のみ。

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

本イベントにはresolv.confのファイルパスとDNS設定内容が含まれる。内部ネットワーク構成の一部が露出する可能性があるが、Kubernetes RBAC によりイベントの閲覧権限が制御される。

## 備考

- ClusterDomain が設定されている場合、domainCountLimit は MaxDNSSearchPaths - 3 となる（196-198行目）。これはクラスタDNS検索パス（ns.svc.cluster.local, svc.cluster.local, cluster.local の3つ）分を差し引くためである。
- 各チェックは最初の制限超過を検出した時点でreturnし、以降のチェックは行われない

---

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

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

### 推奨読解順序

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

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

**読解のコツ**: ResolverConfig はkubeletの `--resolv-conf` フラグで設定されるファイルパスで、デフォルトは `/etc/resolv.conf` である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dns.go | `pkg/kubelet/network/dns/dns.go` | CheckLimitsForResolvConf関数（178-222行目）が本イベントの発行箇所 |

**主要処理フロー**:
1. **179行目**: os.Open(c.ResolverConfig) でresolv.confを開く
2. **180-183行目**: オープン失敗時にWarningイベント発行しreturn
3. **187行目**: parseResolvConf(f) でファイルをパース
4. **188-191行目**: パースエラー時にWarningイベント発行しreturn
5. **194行目**: domainCountLimit と maxDNSSearchListChars の取得
6. **196-198行目**: ClusterDomain設定時にdomainCountLimitから3を引く
7. **200-204行目**: 検索パス数超過チェック
8. **207-213行目**: 個別パス長超過チェック
9. **216-221行目**: 検索リスト文字数超過チェック

#### Step 3: resolv.conf パースロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dns.go | `pkg/kubelet/network/dns/dns.go` | parseResolvConf関数（226-275行目）でnameserver/search/options行を解析 |

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

```
kubelet起動
    |
    +-- Configurer.CheckLimitsForResolvConf (178行目)
           |
           +-- os.Open(c.ResolverConfig) (179行目)
           |      +-- [失敗] recorder.Event("CheckLimitsForResolvConf") (181行目)
           |
           +-- parseResolvConf(f) (187行目)
           |      +-- [失敗] recorder.Event("CheckLimitsForResolvConf") (189行目)
           |
           +-- 検索パス数チェック (200行目)
           |      +-- [超過] recorder.Event("CheckLimitsForResolvConf") (202行目)
           |
           +-- 個別パス長チェック (207行目)
           |      +-- [超過] recorder.Event("CheckLimitsForResolvConf") (210行目)
           |
           +-- 検索リスト文字数チェック (216行目)
                  +-- [超過] recorder.Event("CheckLimitsForResolvConf") (218行目)
```

### データフロー図

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

/etc/resolv.conf ───> CheckLimitsForResolvConf ───> Event記録
                      (ファイル読取 + パース           (CheckLimitsForResolvConf)
                       + 各種制限チェック)
```

### 関連ファイル一覧

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