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?

Docker・Kubernetesネットワーク技術 - ③Network Namespace -

0
Posted at

はじめに

業務に邁進する中でネットワークの知見が足りていないことに気づき、ネットワークの基礎固めに精進することにしました。最終的にはDockerおよびKubernetesで利用されるネットワーク技術を解説できるようになること、を目標とし、シリーズ記事として記載する予定です。

参考にする書籍

Docker・Kubernetesで利用されるネットワーク技術に関する本

ネットワークの基礎を理解するための本

本記事で理解すること

  • Network Namespaceとは
  • DockerとNetwork Namespaceの関係性

シリーズ(予定)

  1. (基礎)TCP/IP4階層モデル
  2. VXLAN(Virtual eXtensible Local Area Network)
  3. Network Namespce ←今回はこれ
  4. iptables

Network Namespace(netns)とは

Linuxカーネルの機能で、ネットワークリソースを仮想化して独立した環境を作成するための技術。1台のサーバの中にあたかも独立した複数のネットワークがあるかのように振舞わせることができます。

Docker技術との関連
コンテナごとに独立したIPアドレスが割り振られ、他のコンテナと干渉せずに通信できるのは、この netns が裏側で動いているからです。

Network Namespaceを実現する技術

veth

Virtual Ethernet Device。必ずペアで生成され、片方を作成されたnetnsに、もう片方をホストに置くことで、作成されたnetnsとホスト間で通信が可能となる。

仮想ブリッジ

仮想的なL2スイッチのこと。作成したveth同士を繋げて、異なるnetns同士が通信可能となる。

Network Namespaceでネットワークを隔離する

以下の図を用いてNetwork Namespaceによるネットワークの隔離について説明しようと思います。

1. Network Namespaceの作成
ホストのネットワークと隔離されたネットワークを空間(netns1...4)を、Network Namespaceを作成します。以下のようなコマンドで作成できます。

sudo ip nents add nents1

2. hostネットワークとの通信をvethを通じて行う
次に、ホストとのネットワーク経路を確保するため、vethのペアを作成し、一方をnetnsに、もう一方をホストネットワークに配置します。以下のようなコマンドで作成できます。

# vethのペアの作成
sudo ip link add name veth_netns1 type veth peer name veth_host2
# vethの片方(veth_netns1)を作成したnetns(netns1)に移動させる
sudo ip link set dev veth_netns1 netns netns1

3. 仮想bridgeの作成
次に、異なるnetns間で通信を行うため、仮想ブリッジを作成し、vethと接続します。

# bridgeの作成
sudo ip link add name bridge1 type bridge

# bridgeとvethを接続する
sudo ip link set dev veth_host1 master bridge1
sudo ip link set dev veth_host2 master bridge1

ここからIPアドレスの設定とデバイスの起動を行うことで、通信が可能となります。

image.png

ネットワーク通信の動き
※Container1からContainer2にパケットを飛ばす場合

  1. Container1でパケットを生成
  2. veth_netns1 → veth_host1を通り、hostネットワークへ
  3. bridge1がパケットを受信し、MACアドレスを見てveth_host2へ転送
  4. veth_host2 → veth_netns2を通り、目的のContainer2へ到着

Network NamespaceとDockerの関係

まずは検証してみよう

Dockerコンテナがどのように隔離され、ホストと繋がっているのか。その「配線」をLinuxコマンドで一本ずつ確認してみました。

1. 検証用コンテナの起動

まず、ネットワークを保持し続けるための軽量なコンテナを起動します。

docker run -d --name test-container alpine sleep 3600

2. Dockerのnetnsを見れるようにする

Dockerは標準では ip netns コマンドから隠されているため、プロセスのネットワーク空間をマウントして見える化します。

# コンテナのプロセスID(PID)を取得
PID=$(docker inspect -f '{{.State.Pid}}' test-container)

# ip netns が参照するディレクトリを作成
sudo mkdir -p /var/run/netns

# プロセスのネットワーク空間をファイルとしてマウント(紐付け)
sudo touch /var/run/netns/test-container
sudo mount --bind /proc/$PID/ns/net /var/run/netns/test-container

# 確認:リストに現れる
ip netns list
# 結果 -> test-container

3. netns内のvethを確認する

作成した名前(test-container)を使って、vethの詳細を見ます。

sudo ip netns exec test-container ip addr

実行結果(抜粋)

2: eth0@if6: <...>
link/ether c2:63:2e:1c:cb:18 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 ...
  • コンテナ内の eth0 は インデックス番号 2。
  • @if6 と書いてあります。これは「対向相手のインデックス番号は 6 だよ」というサインです。

4. ホスト側のbridgeとvethを確認する

今度はホストOS(コンテナの外)側で、インデックス番号 6 を探します。

ip link show

実行結果(抜粋)

6: veth267fedd@if2: <...> master docker0 state UP ...
link/ether 5e:4e:93:76:62:82 <...> link-netns test-container
  • ホスト側の インデックス番号 6 の名前は veth267fedd。
  • @if2 と書いてあります。これは「対向相手は 2(コンテナ内の eth0)」を指しています。
  • master docker0 の表記により、このケーブルが仮想ブリッジ(ハブ)に刺さっていることがわかります

まとめ

以上のように、docker runを実行すると、Linuxでは手動で行う以下のステップを、Docker は裏側で一瞬でこなしてくれます。

  1. netnsを用意する
  2. vethを生成し、両端を差し込む
  3. ケーブルの片方をハブ(docker0)に接続する
  4. 個室にIP アドレスを割り当てる
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?