14
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Namespace の学習

Posted at

Linux の Namespace を学んだときの自分用ログ。実施しているきっかけは、Kubernetes のネットワーク周りをしっかり勉強しようと思ったのだけど、そのためには Docker のネットワークをしっかり学ぶ必要があり、Docker といえば Namespace だよね!ということで、壮大なヤクの毛狩りの結果、ちゃんと根本から勉強しようと腹をくくることにしました。

実際は超素晴らしい ip netnsコマンドの使い方(ネットワークの実験の幅が広がるなぁ~を WSL2 で流して実験するだけなので、素晴らしい元記事を読んでいいねしてくださるとよいと思います。

基本的には、ip コマンドを使って、Namespace を使ったり、ネットワークを作ってみたりします。

ip コマンド

私の Linux の知識が古すぎて ifconfig とばかり思っていましたが、現在では ip コマンドです。様々なことが出来るので見ていきましょう。

$ ip help
Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }
       ip [ -force ] -batch filename
where  OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |
                   tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |
                   netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |
                   vrf | sr | nexthop }
       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |
                    -h[uman-readable] | -iec | -j[son] | -p[retty] |
                    -f[amily] { inet | inet6 | mpls | bridge | link } |
                    -4 | -6 | -I | -D | -M | -B | -0 |
                    -l[oops] { maximum-addr-flush-attempts } | -br[ief] |
                    -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |
                    -rc[vbuf] [size] | -n[etns] name | -N[umeric] | -a[ll] |
                    -c[olor]}

環境

ただし、環境は、Windows 10 の WSL2 です。最近面倒なのでこの環境を使うことが多いですが、制限がないかちょっと心配。

$ cat /etc/os-release   # or lsb-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

オプション一覧

ip netns がネットワーク関連のネームスペース関連のコマンドです。ネームスペースを指定することによって、プロセスや、ユーザーや、ネットワークを隔離して管理することができます。このネームスペースや、cgroupをうまく使っているのが Docker のようなコンテナ技術です。この記事がわかりやすかったです。第2回 コンテナの仕組みとLinuxカーネルのコンテナ機能[1]名前空間とは? そして 第3回 Linuxカーネルのコンテナ機能[2] ─cgroupとは?(その1)も cgroupの概要をつかむための良い記事でした。

$ ip netns help
Usage:  ip netns list
        ip netns add NAME
        ip netns attach NAME PID
        ip netns set NAME NETNSID
        ip [-all] netns delete [NAME]
        ip netns identify [PID]
        ip netns pids NAME
        ip [-all] netns exec [NAME] cmd ...
        ip netns monitor
        ip netns list-id [target-nsid POSITIVE-INT] [nsid POSITIVE-INT]
NETNSID := auto | POSITIVE-INT

ネームスペースの追加

WSL2 の環境では、sudo が必要でした。

$ sudo ip netns add test1
[sudo] password for ushio: 
$ sudo ip netns add test2

ネームスペースのリスト

$ ip netns list
test2
test1

ネームスペースの削除

すべてのネームスペースの削除

$ sudo ip -all netns del

個別の削除

$ sudo ip netns delete test1

ネームスペース内でのプロセスの実行

ネームスペース内でbash を実行してみます。ネットワークのインターフェイスも母艦とは別のものになっています。

$ sudo ip netns exec test1 bash# ps
  PID TTY          TIME CMD
31284 pts/3    00:00:00 sudo
31285 pts/3    00:00:00 bash
# ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0

プロセス関連のコマンド

ターミナル1で、bash を実行して、nc コマンドを実行してみます。nc はネットワークの調査で便利なコマンドで、下記のはポート11111でリッスンしています。-l は、リッスンするオプションであり、他の場合は、メッセージを送信します。-k は、コネクションがクローズした後も、次のコネクションを待ち受けます。

ターミナル1
$ tty
/dev/pts/3
$ sudo ip netns exec test1 bash
# nc -kl 11111

違うターミナルからこのプロセスを見てみます。tty は現在使っているターミナルに割り当てられているデバイスファイルを表示しています。ps -C nc で、nc コマンドを実行しているプロセスを表示します。別のネームスペースで実行しているプロセスでも、ps aux 等であれば見ることが出来ます。

ターミナル2
$ tty
/dev/pts/5
$ ps -C nc
  PID TTY          TIME CMD
31343 pts/3    00:00:00 nc

ちなみにネームスペースから、aux コマンドを実行しても結果は同じです。この辺は docker と違いを感じます。

ターミナル2
$ sudo ip netns exec test1 bash
# ps
  PID TTY          TIME CMD
31416 pts/5    00:00:00 sudo
31417 pts/5    00:00:00 bash
31424 pts/5    00:00:00 ps
# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0    896   576 ?        Sl   Feb27   0:00 /init
root        11  0.0  0.0    896    88 ?        S    Feb27   0:00 /init
root     27172  0.3  2.5 9125368 156384 ?      Sl   Feb27   5:35 /usr/bin/dockerd -p /var/run/docker.pid
root     27194  0.3  0.9 2369808 56864 ?       Ssl  Feb27   5:37 containerd --config /var/run/docker/containerd/containerd.toml --log-level info
root     27677  0.0  0.0    904    88 ?        Ss   07:14   0:00 /init
root     27678  0.0  0.0    904    96 ?        S    07:14   0:00 /init
ushio    27679  0.0  0.0   2608   540 pts/1    Ss+  07:14   0:00 sh -c "$VSCODE_WSL_EXT_LOCATION/scripts/wslServer.sh" 622cb03f7e070a9670c94bae1a45d78d7181fbd4 stable .vscode-server 0  
ushio    27680  0.0  0.0   2608  1796 pts/1    S+   07:14   0:00 sh /mnt/c/Users/tsushi/.vscode/extensions/ms-vscode-remote.remote-wsl-0.53.4/scripts/wslServer.sh 622cb03f7e070a9670c94bae1a45d78d7181fbd4 stable .vs
ushio    27685  0.0  0.0   2608   596 pts/1    S+   07:14   0:00 sh /home/ushio/.vscode-server/bin/622cb03f7e070a9670c94bae1a45d78d7181fbd4/server.sh  --port=0 --use-host-proxy --enable-remote-auto-shutdown --print
ushio    27687  0.1  1.2 1022480 76736 pts/1   Rl+  07:14   0:23 /home/ushio/.vscode-server/bin/622cb03f7e070a9670c94bae1a45d78d7181fbd4/node /home/ushio/.vscode-server/bin/622cb03f7e070a9670c94bae1a45d78d7181fbd4/
ushio    27723  0.0  0.6 856768 40184 pts/1    Sl+  07:14   0:00 /home/ushio/.vscode-server/bin/622cb03f7e070a9670c94bae1a45d78d7181fbd4/node /home/ushio/.vscode-server/bin/622cb03f7e070a9670c94bae1a45d78d7181fbd4/
ushio    27777  0.0  1.3 943272 83604 pts/1    Sl+  07:14   0:08 /home/ushio/.vscode-server/bin/622cb03f7e070a9670c94bae1a45d78d7181fbd4/node /home/ushio/.vscode-server/bin/622cb03f7e070a9670c94bae1a45d78d7181fbd4/
ushio    27784  0.0  0.0  10128  5036 pts/3    Ss   07:14   0:00 /bin/bash
ushio    31210  0.0  0.0  10132  5328 pts/5    Ss   10:08   0:00 /bin/bash
root     31317  0.0  0.0  11008  4520 pts/3    S    10:14   0:00 sudo ip netns exec test1 bash
root     31318  0.0  0.0   8960  3908 pts/3    S    10:14   0:00 bash
root     31343  0.0  0.0   3252   764 pts/3    S+   10:20   0:00 nc -kl 11111
ushio    31346  0.0  0.0  10236  5308 pts/6    Ss   10:21   0:00 /bin/bash
ushio    31395  0.0  0.0   8788  3924 pts/6    S+   11:14   0:00 man nc
ushio    31405  0.0  0.0   7596  2232 pts/6    S+   11:14   0:00 pager
root     31416  0.0  0.0  11008  4592 pts/5    S    11:19   0:00 sudo ip netns exec test1 bash
root     31417  0.0  0.0   8960  4000 pts/5    S    11:19   0:00 bash
root     31425  0.0  0.0  10600  3256 pts/5    R+   11:19   0:00 ps aux

このプロセスIDがどのネームスペースに所属しているか見てみます。

ターミナル2
$ sudo ip netns identify 31343
test1

Bash の実行状況を観ます。tty のパートでわかるように、ターミナル1で動いているbash は2つあって、一つが、ネームスペースで実行したものです。

ターミナル2
$ ps -C bash -o comm,pid,lstart,tty
COMMAND           PID                  STARTED TT
bash            27784 Sun Feb 28 07:14:05 2021 pts/3
bash            31210 Sun Feb 28 10:08:49 2021 pts/5
bash            31318 Sun Feb 28 10:14:36 2021 pts/3
bash            31346 Sun Feb 28 10:21:08 2021 pts/6

それは次の比較でわかります。

ターミナル2
$ sudo ip netns identify 31318
test1
$ sudo ip netns identify 27784

ホスト、ルーターの環境構築

実際やりたかったのはこのパートです。WSL2 で動くかな?もともと CKA のコースを受けていた時に、このコマンドの紹介があったのですが、その通りに WSL2 で動かなかったので気になってここでやっている感じです。まずは元のブログ通りの環境を作ってみます。

image.png

ネームスペースの作成

$ sudo ip netns add host1
$ sudo ip netns add host2
$ sudo ip netns add router
$ sudo ip netns list
router
host2
host1

インターフェイスの作成

仮想のネットワークインターフェイスを作成して、対向のネットワークインターフェイスを指定します。もちろん最初なので、DOWN したままです。

$ sudo ip link add name veth-h1 type veth peer name veth1-rt
$ sudo ip link add name veth-h2 type veth peer name veth2-rt
$ sudo ip link | grep veth
76: veth1-rt@veth-h1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
77: veth-h1@veth1-rt: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
78: veth2-rt@veth-h2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
79: veth-h2@veth2-rt: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000

ネームスペースをネットワークインターフェイスに割り当てる

host, host2, router にインターフェスを割り当てます。

$ sudo ip link set veth-h1 netns host1
$ sudo ip link set veth-h2 netns host2
$ sudo ip link set veth1-rt netns router
$ sudo ip link set veth2-rt netns router

IP アドレスの割り当て

$ sudo ip netns exec host1 ip addr add 192.168.100.10/24 dev veth-h1
$ sudo ip netns exec host2 ip addr add 192.168.200.10/24 dev veth-h2
$ sudo ip netns exec router ip addr add 192.168.100.20/24 dev veth1-rt
$ sudo ip netns exec router ip addr add 192.168.200.20/24 dev veth2-rt

インターフェイスの UP

$ sudo ip netns exec host1 ip link set veth-h1 up
$ sudo ip netns exec host2 ip link set veth-h2 up
$ sudo ip netns exec router ip link set veth1-rt up
$ sudo ip netns exec router ip link set veth2-rt up

確認すると、正しく設定されています。

$ sudo ip netns exec host1 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
77: veth-h1@if76: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether aa:9c:34:e9:11:2f brd ff:ff:ff:ff:ff:ff link-netns router
    inet 192.168.100.10/24 scope global veth-h1
       valid_lft forever preferred_lft forever
    inet6 fe80::a89c:34ff:fee9:112f/64 scope link 
       valid_lft forever preferred_lft forever
$ sudo ip netns exec host2 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
79: veth-h2@if78: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether e6:d6:9a:c7:0e:60 brd ff:ff:ff:ff:ff:ff link-netns router
    inet 192.168.200.10/24 scope global veth-h2
       valid_lft forever preferred_lft forever
    inet6 fe80::e4d6:9aff:fec7:e60/64 scope link 
       valid_lft forever preferred_lft forever
$ sudo ip netns exec router ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
76: veth1-rt@if77: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 2e:8d:45:ae:d7:b4 brd ff:ff:ff:ff:ff:ff link-netns host1
    inet 192.168.100.20/24 scope global veth1-rt
       valid_lft forever preferred_lft forever
    inet6 fe80::2c8d:45ff:feae:d7b4/64 scope link 
       valid_lft forever preferred_lft forever
78: veth2-rt@if79: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 9e:80:da:c0:3c:2f brd ff:ff:ff:ff:ff:ff link-netns host2
    inet 192.168.200.20/24 scope global veth2-rt
       valid_lft forever preferred_lft forever
    inet6 fe80::9c80:daff:fec0:3c2f/64 scope link 
       valid_lft forever preferred_lft forever

ルーティングテーブルの設定

この手順が前に試したときに抜けていたと思います。ip_forward の設定をしないと、デフォルトでは、IPフォワードをしない設定になっています。

$ sudo ip netns exec host1 ip route add 192.168.200.0/24 via 192.168.100.20 dev veth-h1
$ sudo ip netns exec host2 ip route add 192.168.100.0/24 via 192.168.200.20 dev veth-h2
$ sudo ip netns exec router sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

Ping

きっちり動作しています。

$ sudo ip netns exec host1 ping  192.168.200.10
PING 192.168.200.10 (192.168.200.10) 56(84) bytes of data.
64 bytes from 192.168.200.10: icmp_seq=1 ttl=63 time=0.055 ms
64 bytes from 192.168.200.10: icmp_seq=2 ttl=63 time=0.065 ms
64 bytes from 192.168.200.10: icmp_seq=3 ttl=63 time=0.056 ms
64 bytes from 192.168.200.10: icmp_seq=4 ttl=63 time=0.057 ms

ルーター機能の確認

tcpdump を使ってルーター機能が正常に動いているか確認します。

ターミナル1
$ sudo ip netns exec router tcpdump -i veth1-rt icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth1-rt, link-type EN10MB (Ethernet), capture size 262144 bytes

Ping を1回送ります。

ターミナル2
$sudo ip netns exec host1 ping -c 1 192.168.200.10

しっかりと、tcpdump で観察できます。

ターミナル1
$sudo ip netns exec router tcpdump -i veth1-rt icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth1-rt, link-type EN10MB (Ethernet), capture size 262144 bytes
11:54:38.197299 IP 192.168.100.10 > 192.168.200.10: ICMP echo request, id 31512, seq 1, length 64

次に、iptable を使って確認します。router の IPテーブルに icmp をフォワードします。

ターミナル1
$ sudo ip netns exec router bash
# iptables -A FORWARD -p icmp
# iptables -nvL FORWARD
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0            icmp --  *      *       0.0.0.0/0            0.0.0.0/0      

1回Pingを送ると、値が変わります。

ターミナル2
$ sudo ip netns exec host1 ping -c 1 192.168.200.10
ターミナル1
# iptables -nvL FORWARD
Chain FORWARD (policy ACCEPT 2 packets, 168 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    2   168            icmp --  *      *       0.0.0.0/0            0.0.0.0/0           

同じブログの方が素晴らしいブログを書いてくれています。iptable や tpcdump についても学ばねばですが、先にもとにやってたことに戻ります。ネットワークはマジ奥深い。コントロール配下に置きたいところ。

14
8
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
14
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?