TT Lab
はじめる
学ぶ 学習パス コース

ネットワーク基礎

自分のPodのネットワークを読む

TT Labで続きを見る

目標

ネットワークを図で学んでも、あまり身につきません。今みなさんが使っているこのPodのネットワークを、自分で読んでみます。

教材用に作った例ではなく、実際の本番クラスターなので、教科書に出てこないものが、そのまま出てきます。/32のアドレス、インターフェースと異なるパスMTU、searchドメインです。

見る場所

ip -4 addr show eth0        # 내 주소
ip route                    # 어디로 나가나
ip route get 1.1.1.1        # 이 목적지로는 어떻게 가나
cat /sys/class/net/eth0/mtu # 인터페이스 MTU
cat /etc/resolv.conf        # 이름을 어떻게 푸나
ss -tan                     # 지금 연결 상태

実験用サーバー

python3 -m http.server 8080 --bind 127.0.0.1 &

ステップ

  1. アドレスとネットマスク → 01-addr.txt
  2. ルーティング → 02-route.txt
  3. MTU → 03-mtu.txt
  4. DNS → 04-dns.txt
  5. ポートの衝突 → 05-port.txt
  6. 手で打ったHTTP → 06-http.txt
  7. 接続の状態 → 07-states.txt
  8. まとめ → 08-notes.md

参考

このPodは、外のインターネットには出られません。DNSの照会だけが開いています。そのため、実験はすべて、このPodの中のサーバーで行います。学ぶべきことは、すべて学べます。

自分のアドレスとネットマスク

このPodのIPとネットマスクを確認して01-addr.txtに残し、そのネットマスクがどういう意味かを1行書いてください。

ip -4 addr show eth0を使います。/32が出るはずです。

/32は、このネットワークに自分1人だけという意味です。普通は/24のように、同じアドレス帯にネイバーがいるのですが、ここにはいません。それなら、外へどう出るのかが、次のステップです。

では、どうやって外へ出るのか

ルーティングテーブルを取り出して02-route.txtに残し、/32なのにゲートウェイに届く理由を書いてください。

ip routeを使います。2行が見えるはずです。default via <게이트웨이>と<게이트웨이> dev eth0 scope linkです(プレースホルダーはゲートウェイのアドレスです)。

2行目が答えです。そのアドレスは、ルーティングなしで直接届く(on-link)とカーネルに知らせるものです。ネットマスクの上では同じアドレス帯ではありませんが、この経路があるおかげで、ゲートウェイに届きます。

インターフェースとパスのMTUが違う

eth0のMTUとデフォルト経路のMTUを、それぞれ確認して03-mtu.txtに残してください。違うなら、なぜ違うのかも書いてください。

インターフェースはcat /sys/class/net/eth0/mtu、経路はip route get 1.1.1.1で確認します。

インターフェースは1500なのに、経路はもっと小さいはずです。トンネルがヘッダーを付け足すからです。このクラスターは、ノード間を暗号化トンネルでつないでおり、その分だけ載せられるサイズが減ります。

MTUを誤って設定すると、小さなリクエストは通るのに、大きなレスポンスだけが止まる症状が出ます。原因を探すのが最も難しい種類です。

短い名前がどう解決されるのか

/etc/resolv.confを見て、短い名前を1つ実際に照会して、04-dns.txtに残してください。

cat /etc/resolv.confにnameserverとsearchがあります。getent hosts kubernetes.defaultのように、短い名前を照会してみてください。

searchに書かれたドメインが、順番に付け足されて試されます。kubernetes.default → kubernetes.default.<네임스페이스>.svc.cluster.local → …という具合です。そのため、短く書いても見つかります(プレースホルダーはネームスペースです)。

ポート1つにプログラム1つ

ポート8080にサーバーを起動した後、同じポートにもう1つ起動してみて、そのときに出るエラーを05-port.txtに残してください。

python3 -m http.server 8080 --bind 127.0.0.1 &で1つ起動し、Pythonで同じアドレスにbindを試してください。

[Errno 98] Address already in useが出ます。アドレス+ポートの組み合わせは、1つのプログラムだけが持てます。「ポートがすでに使用中」というエラーの正体です。

HTTPを手で打つ

ライブラリなしで、TCP接続に直接HTTPリクエストの文字列を書いてレスポンスを受け取り、06-http.txtに残してください。

bashだけでできます。

exec 3<>/dev/tcp/127.0.0.1/8080
printf 'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n' >&3
timeout 3 head -8 <&3

行末は必ず\r\nにします。ヘッダーの最後に、空行がもう1つ必要です。HTTPは、単にTCPの上で、約束された文字をやり取りしているだけです。

接続には状態がある

接続を作って閉じながら、ssで状態がどう変わるかを見て、07-states.txtに残してください。TIME-WAITが見える必要があります。

ss -tanで見ます。接続中はESTAB、閉じた後はTIME-WAITがしばらく残ります。

TIME-WAITはバグではありません。遅れて届いたパケットが次の接続に混ざらないように、しばらく場所を確保しておくものです。短い接続を大量に作るサーバーで、これが溜まるとポートが枯渇します。そのため、接続を再利用(keep-alive)します。

3つのことをまとめる

08-notes.mdに3行以上書きます。/32なのに通信できる理由、MTUがずれたときに出る症状、TIME-WAITがある理由を書いてください。

本文に경로、MTU、TIME-WAITが含まれている必要があります(韓国語の語は「経路」を意味します)。