0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

野良Prometheusがネットワーク障害の原因だった話

0
Last updated at Posted at 2026-05-28

社内LANで時々ネットワークアクセス障害が発生していて、一部PCを切り戻すと復活する。ある程度繋がっている範囲は絞れているが個々の業務PCのため家宅捜査できずに、切り離して他のルータ配下(2段NAT配下)への島流しで対応していた。

ネットワークの更改とともにルーターをIX2107に変更したのを機に再加入させてみたら再度障害が発生。

今度はsyslogサーバーに転送していたので本気で解析を行なった結果、野良Prometheusだということが判明。あまり情報がないのでメモとしておいておく。

結論から書くと

  • 有線 LAN でルーター(NEC IX2107)にPingが届かなくなり、一部の PC群を切り離すと回復するという奇妙な症状が発生していた。過去のRTX830やSynologyルーターでも同様の謎症状有
  • syslog を見ると、1台の PC からの TCP/53(DNS over TCP)ストームでルーターの DNS プロキシが枯渇し、その煽りで他端末への ARP 解決まで失敗していた
  • 元凶は Windows + WSL2 + Docker Desktop で動かしていた Prometheus コンテナ
  • 多段の DNS チェーン(Container → Docker → WSL2 → Windows → ルーター)のどこにもキャッシュが効いていない状態で、Go の非キャッシュリゾルバ × dns_sd_configs × TCP フォールバックが重なり、ルーターのセッションを使い切り障害発生

一見「ルーターの調子が悪い」だけに見える事象が、監視スタックの内部挙動と DNS の仕様、ルーターのリソース上限の合わせ技で発生した話です。ということで、調査の過程を。

症状

有線 LAN 配下のいくつかの PC から、ゲートウェイである 192.168.1.1(NEC IX2107)に通信が届かなくなった。Web 管理画面も開けない、当然外にも出られない。頻繁に発生するわけでないが、ある程度の頻度で発生する。

ポイントは:

  • 全PCが一斉に死んだわけではなく、使えるPCもある
  • 一部PCを物理的に切り離すと、残った PC のネットが復活する

「ルーターが死んだわけではない」「特定の端末がパケットを撒いてるっぽい」までは直感で見えたが、どの端末が犯人なのか分かりませんでした。今回、syslogをちゃんと記録していたので調査する気になりました。

第1段: syslog を読む

事象発生時刻周辺の IX2107 syslog(約2分間で 1,000 行)を取得して眺めると、特定パターンが目立つ:

TKY-RT  TCP[006]: Child TCP status changed for port 53, type transmit
TKY-RT  TCP[006]: Child TCP status changed for port 53, type receive
TKY-RT  TCP[006]: Sending RESET to host 192.168.1.126, GigaEthernet1.0
TKY-RT  TCP[006]: Child TCP read stop for port 53, reason close-cb-error

集計すると:

種別 件数
Child TCP status changed for port 53 401
Child TCP read stop for port 53, reason cleanup 118
Child TCP read stop for port 53, reason close-cb-error 98
Sending RESET to host 192.168.1.126 181
Sending RESET to host 192.168.1.104 12
Sending RESET to host 192.168.1.101 3

約2分間で 192.168.1.126 に 181 発の RESET。ルーターの DNS プロキシが受けた TCP/53 セッションが 600件超close-cb-error の連発はソケットの強制切断。

つまり .126 がルーターに TCP/53 を投げ続け、ルーターが応えきれずに RESET を打ち返していた。

巻き添え:他端末の通信も落ちていた

同じ時間帯にこういうログも:

TKY-RT   IP[006]: Packet 192.168.1.1 > 192.168.1.155 discarded for
  LINK-FRMWRK: NO ENTRY IN LOOKUP TABLE TO COMPLETE OPERATION, GigaEthernet1.0
TKY-RT   IP[006]: Packet 8.8.8.8     > 192.168.1.155 discarded for ...
TKY-RT   IP[006]: Packet 192.168.1.1 > 192.168.1.127 discarded for ...

NO ENTRY IN LOOKUP TABLE = ARP/ND テーブル参照失敗。ルーターが他端末(.155 や .127)への戻りパケットを「宛先 MAC が分からない」と落としている。本来なら ARP リクエストを出して解決するはずが、それすらこなせていない。

CPU/制御プレーンが TCP/53 ストームの処理に取られて、ARP の応答処理が間に合っていなかった、という構図。

第2段: 犯人を物理特定する

MACアドレスでASUSのものだとはわかったけど、マザーボードNICなのでどれかわからず。ということで、そのマシンから全通信をルーターでDropさせて待つ。

「PCつながらないんですけど...」 という申告にて特定。

プロセス調査

ログからDNSリクエストであることは判明していたので問題のPCで、TCP/53 を出しているプロセスを PowerShell で探す:

# TCP/53 を開いている接続を全部見る
Get-NetTCPConnection -RemotePort 53 |
  Select-Object LocalAddress, LocalPort, RemoteAddress, State, OwningProcess |
  ForEach-Object {
    $proc = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
    $_ | Add-Member -NotePropertyName ProcessName `
         -NotePropertyValue $proc.ProcessName -PassThru
  }

# 古典的に
netstat -ano -p tcp | findstr ":53"
tasklist /FI "PID eq <上で出たPID>"

実行すると犯人プロセスは vmmem(または vmmemWSL)。これは WSL2 の VM プロセスで、内部で動いている Linux 上の何かが TCP/53 を投げまくっているということ。

WSL2 に入って更に追う:

# WSL2 のシェルから
sudo ss -tnp 'dport = :53'
sudo lsof -nP -iTCP:53

docker ps
# 順に止めていく、または docker stats で CPU/Network が突出しているものを探す

「Prometheus コンテナ」が犯人! で確定。

第3段: UFS Cacheオーバーフロー

ZabbixのSNMPログを見てみると同じ時刻に、Zabbix の IX2107: IPv6 UFS Cache Overflows グラフが階段状に上昇していた。事件の最中にカウンタが進み、その後平坦。

ルーターで現在値:

IPv6 UFS Cache - 1175 entries, 8825 frees, 10000 peaks
                 17938700 creates, 4366 overflows
IPv4 UFS Cache -  972 entries, 19028 frees,  6949 peaks
                 12488008 creates,    0 overflows

UFS(Unified Forwarding Subsystem)は IX シリーズの高速転送フローキャッシュ。peaks = 10000 は構造上限への到達、overflows = 4366 はあふれた累積回数。

  • 障害の主因 = DNS プロキシの TCP ソケットプール枯渇(UFS とは別の資源)
  • IPv6 UFS overflow = 副次的な現象.126 が並行して張っていた外部向け IPv6 通信が UFS を食った)
  • 「他端末まで切れた」根本理由 = ARP 解決パスの詰まり

今回はIPv6通信で溢れているが、IPv4 単独環境でも、DNS プロキシ枯渇 + ARP 失敗の経路で同じ症状になると思われる(なった。

第4段: Prometheus の問題点は?

Prometheus がなぜそんなに大量のTCP/53 を投げるのかを調査。

Windows + WSL2 + Docker の DNS チェーンでキャッシュが無い。

DNS クエリは以下の経路を通る:

[Prometheus container]
        ↓ (resolv.conf: nameserver 127.0.0.11)
[Docker 組み込み DNS]
        ↓ (WSL2 distro の resolv.conf に従う、通常 10.255.255.254 等)
[WSL2 仮想 NIC の DNS プロキシ]
        ↓ (Windows のネットワーク設定)
[Windows DNS Client サービス (Dnscache)]
        ↓ (ホストの DNS 設定)
[192.168.1.1 (NEC IX2107 の DNS プロキシ)]
        ↓
[ISP の DNS / 1.1.1.1 など]

各層を見ていくと、DNS素通しで誰もキャッシュしていません。

Go の net パッケージは DNS をキャッシュしない

Prometheus は Go 製。Go 標準リゾルバはスクレイプごとに毎回 DNS を引きに行く。OS リゾルバ任せなので、上述のチェーンに有効なキャッシュが無いと 1スクレイプ = 1問い合わせになる。

dns_sd_configs の SRV と再解決

dns_sd_configs を使っていると:

  1. 定期的に SRV を引いてターゲット一覧を更新(デフォルト 30秒ごと)
  2. SRV で返ってきた各ターゲットの A レコード(および環境次第で AAAA)を引く
  3. その後、スクレイプ毎にターゲット名を毎回再解決

ターゲット数が増えると比例して問い合わせが増えるが、それ以上に効くのが次の TCP フォールバック。

応答が 512 バイトを超えると TCP フォールバック

DNS 仕様(RFC 1035)で UDP メッセージは最大 512 バイト。これを超えると応答に TC ビットが立ち、クライアントは同じクエリを TCP で再送する

何が 512 バイトを超えるか:

  • 多数の A/AAAA レコード(CDN 等)
  • SRV レコードdns_sd_configs が引くやつ。ターゲット数次第で簡単に超える)
  • DNSSEC 署名付き
  • TXT レコード(SPF/DKIM の長文)

EDNS0 で 1232 や 4096 まで拡張できるが、経路上のミドルウェアが落とすケースもあり、現実には TCP フォールバックは普通に起きる。今回のログで TCP/53 が大量に観測されたのはこれ

A + AAAA の二重問い合わせ

デュアルスタック環境では IPv4 と IPv6 の両方を引く。これだけで ×2。

補足: IPv4 単独環境でも、Go や glibc は AI_ADDRCONFIG の判定次第で AAAA を引きに行くことがある(loopback ::1 が有効だと「IPv6 capable」とみなす実装もある)。なので「IPv4 単独だから AAAA は来ない」とは言い切れない。

全部掛け算するとどうなるか

控えめに見積もっても:

要素 倍率 IPv4 単独でも該当?
純粋なスクレイプ起因の解決 数 lookups/sec
Go の非キャッシュ仕様 ×1(実質キャッシュ無し)
TCP フォールバック(>512B) ×2(UDP の後 TCP)
失敗時リトライ ×2
A + AAAA 二重問い合わせ ×2 △ (AI_ADDRCONFIG 次第)
dns_sd_configs 多ターゲット ×N

ざっくり 数十 TCP/53 connections/secなので、IX2107 の DNS プロキシ TCP ソケットプールが2分で枯渇するのに十分な量。

重要:このうち IPv6 特有なのは「A + AAAA の ×2」だけ。残りは全て IPv4 単独環境でも起きる。私が以前 IPv4 単独環境で同様の症状を経験していたのは、これで説明がつく。

対策

ベストプラクティスは「Prometheus に DNS を引かせない、もしくは引いてもローカルで止める」仕組みを作ること。Windows + WSL2 + Docker 環境向けに優先順位ごとに:

1. Docker ネットワーク内に DNS キャッシュコンテナを置く(最優先)

dnsmasq などをコンテナで立て、Prometheus の DNS をそこに向ける。Windows / WSL2 の事情に依存せず、Docker ネットワーク内で完結するのが利点。

# docker-compose.yml
services:
  dns-cache:
    image: 4km3/dnsmasq
    container_name: dns-cache
    cap_add:
      - NET_ADMIN
    command:
      - --no-daemon
      - --server=1.1.1.1
      - --server=8.8.8.8
      - --cache-size=10000
      - --neg-ttl=60
    networks:
      monitoring:
        ipv4_address: 172.20.0.2

  prometheus:
    image: prom/prometheus
    dns:
      - 172.20.0.2
    dns_search: []
    dns_opt:
      - ndots:1
      - timeout:2
      - attempts:2
    networks:
      - monitoring

networks:
  monitoring:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

2. Prometheus の DNS 周り設定を見直す

scrape_configs:
  - job_name: 'nodes'
    dns_sd_configs:
      - names: ['_metrics._tcp.example.lan']
        refresh_interval: 5m   # デフォルト 30s から延長

dns_sd_configs が必須でないなら、static_configsIP 直書きにする。

# 解決負荷あり(毎スクレイプで DNS を引く)
- targets: ['node1.example.lan:9100', 'node2.example.lan:9100']

# 解決負荷なし
- targets: ['192.168.1.10:9100', '192.168.1.11:9100']

3. WSL2 / Windows 側の見直し

  • /etc/wsl.conf[network] generateResolvConf = false を入れて /etc/resolv.conf を固定し、外部 DNS(1.1.1.1 など)に直接向ける選択肢もある
  • Windows の Dnscache サービスが動いているか確認:
Get-Service Dnscache
ipconfig /displaydns | more

4. ルーター側の制限

根本対策が他のホストで再発する可能性を考えて、TCP/53 に per-host レートリミットNAT セッション数の上限を設定しておく。IX2107 なら ACL でホスト単位の TCP/53 制限が組める。

わかったこと

ログ大事

「特定の PC が原因」までは皆気づくが、その先に「監視ツールの DNS 挙動 + WSL2 の DNS チェーン + ルーターのリソース上限」という三段重ねがあるとは、症状からは想像しづらい。ログとカウンタを横断的に見ないと辿り着けなかった。

ルーターの DNS プロキシは注意

ルーターの DNS プロキシ機能は便利だが、内部の TCP ソケットプールサイズは限られている。LAN 内に「DNS を大量に引くデバイス」が現れた瞬間に、全体のネットが詰まる場合がある。

Prometheus は DNS を引きすぎる

これは Prometheus の中の人も認識していて、issue #15262 などで議論されている。でも、ちょっとひどすぎん?

参考リンク

おまけ

トラブル時に手早く状況を掴むためのメモ:

Windows 側

# プロセス別 TCP/53 接続
Get-NetTCPConnection -RemotePort 53 |
  Group-Object OwningProcess |
  Sort-Object Count -Descending

# DNS キャッシュ確認
Get-DnsClientCache | Sort-Object Entry

# Windows DNS Client が動いているか
Get-Service Dnscache

# パケットキャプチャ(管理者 PowerShell)
pktmon filter add -p 53
pktmon start --etw -m real-time
# ... Ctrl+C で停止
pktmon filter remove

# DNS テスト
Resolve-DnsName example.com -Type A
Resolve-DnsName _metrics._tcp.example.lan -Type SRV

WSL2 側

# DNS 設定確認
cat /etc/resolv.conf
cat /etc/wsl.conf   # 無いことも多い

# TCP/53 接続
sudo ss -tnp 'dport = :53'

# DNS 引き比較(UDP vs TCP)
dig example.com @192.168.1.1 +bufsize=512
dig example.com @192.168.1.1 +tcp
dig _metrics._tcp.example.lan SRV @192.168.1.1

Docker / コンテナ側

# コンテナの DNS 設定
docker exec prometheus cat /etc/resolv.conf

# Docker ネットワーク確認
docker network inspect bridge
docker network inspect monitoring

# Prometheus 自身の DNS 統計
curl -s http://localhost:9090/metrics | grep -E 'dns_lookups|sd_dns'

# コンテナ内パケットキャプチャ
docker exec prometheus sh -c 'apk add tcpdump 2>/dev/null || apt-get install -y tcpdump'
docker exec prometheus tcpdump -i any -nn -c 200 port 53

IX2107(ルーター)側

show ip arp                          # IP/MAC 対応
show mac-address-table               # MAC が居る物理ポート
show ufs                             # UFS の状態サマリ
show ufs cache statistics            # キャッシュ使用率・overflow
show dhcp server binding             # DHCP リースのホスト名
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?