LXCコンテナのネットワーク
LXCコンテナを作成した時のホストとのネットワークについて
ProxmoxでLXCコンテナを作成した時、lxcのコマンドラインでPID(プロセスID)を知ることができる。下の例だとPID=1329130。
LinkにはNICっぽい名前が入る。下の例だとveth111i0。このveth111i0とホストの関係をネットワークの面で詳しく見ていく。
root@pve1:~# lxc-ls
111
root@pve1:~# lxc-ls -f
NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED
111 RUNNING 0 - 192.168.10.103 dead:beef:dead:beef:be24:11ff:febf:ee9b, dd41:1630:f594::81d true
root@pve1:~# lxc-info 111
Name: 111
State: RUNNING
PID: 1329130 ★これ
IP: 192.168.10.103
IP: dead:beef:dead:beef:be24:11ff:febf:ee9b
IP: dead:beef:dead:beef::81d
Link: veth111i0 ★これ
TX bytes: 70.95 KiB
RX bytes: 3.59 MiB
Total bytes: 3.66 MiB
親ホストでは8個のネットワークインターフェイスが見える。
root@pve1:~# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master vmbr0 state UP mode DEFAULT group default qlen 1000
link/ether b0:41:6f:0b:a4:47 brd ff:ff:ff:ff:ff:ff
3: wlo1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether f4:6d:3f:c2:1e:6f brd ff:ff:ff:ff:ff:ff
altname wlp2s0
4: vmbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether b0:41:6f:0b:a4:47 brd ff:ff:ff:ff:ff:ff
53: veth111i0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master fwbr111i0 state UP mode DEFAULT group default qlen 1000
link/ether fe:1c:df:49:ab:21 brd ff:ff:ff:ff:ff:ff link-netnsid 0
54: fwbr111i0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 76:d1:50:8f:33:88 brd ff:ff:ff:ff:ff:ff
55: fwpr111p0@fwln111i0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master vmbr0 state UP mode DEFAULT group default qlen 1000
link/ether c6:b7:08:c2:2c:91 brd ff:ff:ff:ff:ff:ff
56: fwln111i0@fwpr111p0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master fwbr111i0 state UP mode DEFAULT group default qlen 1000
link/ether 76:d1:50:8f:33:88 brd ff:ff:ff:ff:ff:ff
そのうち、bridgeは2つ。vmbr0(以下A)とfwbr111i0(以下B)
root@pve1:~# ip link show type bridge
4: vmbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether b0:41:6f:0b:a4:47 brd ff:ff:ff:ff:ff:ff
54: fwbr111i0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 76:d1:50:8f:33:88 brd ff:ff:ff:ff:ff:ff
vethernetは3つ。@の後の文字列で対向がある程度わかる。masterでブリッジがわかる。
veth111i0(B1): bridge fwbr111i0(B)に接続。対向はこの情報だけでは不明(後述するが正体はコンテナ側のeth0)
fwpr111p0(A1): bridge vmbr(A)に接続。対向はB2
fwln111i0(B2): bridge fwbr111i0(B)に接続。対向はA1
root@pve1:~# ip link show type veth
53: veth111i0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master fwbr111i0 state UP mode DEFAULT group default qlen 1000
link/ether fe:1c:df:49:ab:21 brd ff:ff:ff:ff:ff:ff link-netnsid 0
55: fwpr111p0@fwln111i0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master vmbr0 state UP mode DEFAULT group default qlen 1000
link/ether c6:b7:08:c2:2c:91 brd ff:ff:ff:ff:ff:ff
56: fwln111i0@fwpr111p0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master fwbr111i0 state UP mode DEFAULT group default qlen 1000
link/ether 76:d1:50:8f:33:88 brd ff:ff:ff:ff:ff:ff
最初に説明してなかったが、enp1s0(A2)はmaster vmbr0とあるので、これはbridge vmbr0に接続
こんな感じで2つのBridgeがつながっている。A2は物理NICで、外部につながっている。
+---------------------------------+ +------------------------------------+
| vmbr0(A) | | fwbr111i0(B) |
+-- enp1s0(A2) -- fwpr111p0(A1) --+ +-- fwln111i0(B2) -- veth111i0(B1) --+
| | |
external NW--+ +-------------------------+
子コンテナでip linkを実行するとNICは2つ。
loはループバック
eth0は-dをつけると"veth"と出てくるのでvethernet
対向はlink-netnsidが0なので、子コンテナとは別のネットワークネームペースにあり、if53なので、その相手のネットワークネームスペース内でのインデックスが53
今のところコンテナを1個しか作成していないシンプルな構成なのでこれに当てはまるのは親ホストネットワークネームスペースのveth111i0しかないが、もう少しちゃんと見てみる。
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0@if53: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether bc:24:11:bf:ee:9b brd ff:ff:ff:ff:ff:ff link-netnsid 0
root@docker01:~# ip -d link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0 allmulti 0 minmtu 0 maxmtu 0 addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 524280 tso_max_segs 65535 gro_max_size 65536
2: eth0@if53: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether bc:24:11:bf:ee:9b brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0 allmulti 0 minmtu 68 maxmtu 65535
veth addrgenmode eui64 numtxqueues 16 numrxqueues 16 gso_max_size 65536 gso_max_segs 65535 tso_max_size 524280 tso_max_segs 65535 gro_max_size 65536
ネットワークネームスペースはip netns add
で作成した場合は名前が付くので識別しやすいし、名前とID(PID)の関連が/var/配下に保存されるのでip netns ...コマンドで操作可能だが、lxcだと名前がつかない
ip netns系のコマンドではほぼ何もわからない。
root@pve1:~# ip netns
root@pve1:~# ip netns list-id
nsid 0
root@docker01:~# ip netns
root@docker01:~# ip netns list-id
nsid 0
調べるにはもう少しプリミティブなlsns(namespace list), nsenter(namespace enter)を使う。
nsls
で各種ネームスペースが表示される。
root@pve1:~# lsns
NS TYPE NPROCS PID USER COMMAND
4026531834 time 312 1 root /lib/systemd/systemd --system --deserialize=23
4026531835 cgroup 293 1 root /lib/systemd/systemd --system --deserialize=23
4026531836 pid 293 1 root /lib/systemd/systemd --system --deserialize=23
4026531837 user 293 1 root /lib/systemd/systemd --system --deserialize=23
4026531838 uts 289 1 root /lib/systemd/systemd --system --deserialize=23
4026531839 ipc 293 1 root /lib/systemd/systemd --system --deserialize=23
4026531840 net 293 1 root /lib/systemd/systemd --system --deserialize=23
4026531841 mnt 287 1 root /lib/systemd/systemd --system --deserialize=23
4026532447 mnt 1 538 root ├─/lib/systemd/systemd-udevd
4026532448 uts 1 538 root ├─/lib/systemd/systemd-udevd
4026532764 mnt 2 1078 _chrony ├─/usr/sbin/chronyd -F 1
4026532765 uts 2 1078 _chrony ├─/usr/sbin/chronyd -F 1
4026532773 mnt 1 1329110 root ├─/usr/bin/lxc-start -F -n 111
4026532783 user 19 1329130 100000 │ ├─/sbin/init
4026532784 mnt 17 1329130 100000 │ ├─/sbin/init
4026532785 uts 18 1329130 100000 │ ├─/sbin/init
4026532786 ipc 19 1329130 100000 │ ├─/sbin/init
4026532787 pid 19 1329130 100000 │ ├─/sbin/init
4026532788 cgroup 19 1329130 100000 │ ├─/sbin/init
4026532790 net 19 1329130 100000 │ └─/sbin/init
4026532936 uts 1 1329309 100000 │ ├─/lib/systemd/systemd-logind
4026532937 mnt 1 1329309 100000 │ ├─/lib/systemd/systemd-logind
4026532938 mnt 1 1329317 100998 │ └─/lib/systemd/systemd-networkd
4026532821 uts 1 946 root ├─/lib/systemd/systemd-logind
4026532823 mnt 1 946 root └─/lib/systemd/systemd-logind
4026531862 mnt 1 86 root kdevtmpfs
-t net
でネットワークネームスペースがわかる。1行目はPIDが1で親ホスト自体が使っているネットワークネームスペース。
2行目はPIDが1329130で、冒頭のlxc-infoで見たようにコンテナの筆頭プロセス(/sbin/init)のIDになっている。これが子コンテナのネットワークネームスペース。
NETNSIDが0なので、親ホストネットワークネームスペースでのlink-nsid 0はPID 1329130が所属するネットワークネームスペースであるとわかる。
root@pve1:~# lsns -t net
NS TYPE NPROCS PID USER NETNSID NSFS COMMAND
4026531840 net 293 1 root unassigned /lib/systemd/systemd --system --deserialize=23
4026532790 net 19 1329130 100000 0 /sbin/init
ターゲットにPIDを指定してnsenterすると、そのネームスペース内でコマンド実行できる。子コンテナでのip link
と同じ出力が見れる。
root@pve1:~# nsenter -t 1329130 -n ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0@if53: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether bc:24:11:bf:ee:9b brd ff:ff:ff:ff:ff:ff link-netnsid 0
子供の方から親の情報を見ることはできない。
root@docker01:~# lsns
NS TYPE NPROCS PID USER COMMAND
4026531834 time 20 1 root /sbin/init
4026532783 user 20 1 root /sbin/init
4026532784 mnt 18 1 root /sbin/init
4026532785 uts 19 1 root /sbin/init
4026532786 ipc 20 1 root /sbin/init
4026532787 pid 20 1 root /sbin/init
4026532788 cgroup 20 1 root /sbin/init
4026532790 net 20 1 root /sbin/init
4026532936 uts 1 100 root |-/lib/systemd/systemd-logind
4026532937 mnt 1 100 root |-/lib/systemd/systemd-logind
4026532938 mnt 1 108 systemd-network `-/lib/systemd/systemd-networkd
root@docker01:~# lsns -t net
NS TYPE NPROCS PID USER NETNSID NSFS COMMAND
4026532790 net 20 1 root unassigned /sbin/init
子供側も追加すると以下のようなネットワークになっている。
[network namespace X (host)]
+---------------------------------+ +------------------------------------+
| vmbr0(A) | | fwbr111i0(B) |
+-- enp1s0(A2) -- fwpr111p0(A1) --+ +-- fwln111i0(B2) -- veth111i0(B1) --+
| | | |
external NW--+ +-------------------------+ |
====================================================================|=============
[network namespace Y (container)] |
container:eth0
以下にDockerもインストールした構成について書いています。
Discussion