AgentSkillsCN

kubectl-localmesh-macos-localhost

介绍 macOS 中 .localhost 域名的特殊行为,以及在配置 TCP 服务时需要注意的事项。

SKILL.md
--- frontmatter
name: kubectl-localmesh-macos-localhost
description: macOSにおける.localhostドメインの特殊な挙動と、TCPサービス設定時の注意点を提供します
allowed-tools: ["Bash", "Read"]

macOSにおける.localhostドメインの挙動

このskillは、macOSが.localhostドメインを特別に扱う挙動と、kubectl-localmeshのTCPサービス設定への影響について説明します。

概要

macOSはRFC 6761に基づき、.localhost TLDを予約済みドメインとして特別扱いします。 その結果、.localhostのサブドメインは**/etc/hostsの設定を無視**して、常に127.0.0.1または::1に解決されます。

問題が発生するケース

TCPサービス(DB接続など)で.localhostを使用した場合

yaml
# 設定ファイル(services.yaml)
services:
  - kind: tcp
    host: db.localhost      # ← これは動かない
    ssh_bastion: primary
    target_host: 10.0.0.1
    target_port: 5432

期待される動作:

  • kubectl-localmeshが/etc/hosts127.0.0.2 db.localhostを追加
  • クライアントがdb.localhost:5432に接続
  • 127.0.0.2:5432(Envoy)に到達

実際の動作(macOS):

  • /etc/hosts127.0.0.2 db.localhostが追加される
  • クライアントがdb.localhost:5432に接続
  • macOSが/etc/hostsを無視し、127.0.0.1:5432に接続しようとする
  • Envoyは127.0.0.2:5432でリッスンしているため接続失敗

確認方法

bash
# /etc/hostsの内容を確認
$ cat /etc/hosts | grep db
127.0.0.2 db.localhost

# macOSのDNS解決を確認
$ python3 -c "import socket; print(socket.gethostbyname('db.localhost'))"
127.0.0.1

# pingでも確認可能
$ ping -c 1 db.localhost
PING localhost (127.0.0.1): 56 data bytes

/etc/hostsには127.0.0.2と書いてあるのに、127.0.0.1に解決されているのが問題です。

解決方法

TCPサービスには.localhost以外のTLDを使用する

yaml
# OK: .localdomain を使用
services:
  - kind: tcp
    host: db.localdomain   # ← これは動く
    ssh_bastion: primary
    target_host: 10.0.0.1
    target_port: 5432

推奨TLD

TLD説明
.localdomain一般的なローカル用TLD
.localmDNS/Bonjourでも使用されるが、/etc/hostsが優先される
.dev開発用(ただしHTTPS強制される場合あり)
.testRFC 2606で予約されたテスト用TLD

自動警告

kubectl-localmeshは、TCPサービスで.localhostドメインが使用された場合、起動時に警告を出力します:

code
Warning: TCP service 'db.localhost' uses .localhost domain (db.localhost)
  macOS ignores /etc/hosts for .localhost subdomains and resolves them to 127.0.0.1
  This may cause connection failures. Consider using .localdomain or another TLD instead.

なぜHTTP/gRPCサービスは.localhostで動くのか

HTTP/gRPCサービスは仕組みが異なります:

  • Envoyが0.0.0.0:80(全インターフェース)でリッスン
  • ホストヘッダー(Host: users-api.localhost)でルーティング
  • macOSが.localhost127.0.0.1に解決しても、127.0.0.1:80でEnvoyに到達
  • Envoyがホストヘッダーを見て正しいバックエンドにルーティング

結論: HTTP/gRPCは.localhostで問題なし、TCPは.localhostを避けること

技術的背景

RFC 6761 - Special-Use Domain Names

RFC 6761は、以下のドメインを「特別な用途」として定義しています:

  • .localhost - ローカルホスト用
  • .invalid - 明らかに無効なドメイン
  • .test - テスト用
  • .example - ドキュメント例示用

macOSの実装

macOS(Darwin)は、localhostおよびその全てのサブドメインを、DNSクエリやhostsファイル参照なしに、直接127.0.0.1/::1に解決します。

これはセキュリティ上の理由(DNSリバインディング攻撃の防止など)からの設計判断です。

診断コマンド

bash
# /etc/hostsの確認
cat /etc/hosts

# macOSのDNS解決確認
python3 -c "import socket; print(socket.gethostbyname('your-host.localhost'))"

# dscacheutilでの確認
dscacheutil -q host -a name your-host.localhost

# Envoyのリッスン状態確認
sudo lsof -i :5432

# loopbackエイリアス確認
ifconfig lo0 | grep inet

参考情報

関連Skills

  • kubectl-localmesh-operations: 起動・運用全般
  • kubectl-envoy-debugging: Envoy設定のデバッグ