iT邦幫忙

2022 iThome 鐵人賽

DAY 25
1

昨天我們做了一個小實驗,建立了一對 veth,並且分別把他們放在不同的 net namespace,透過 ping 指令驗證了 veth 可以可以幫我們進行跨 namespace 的溝通,昨天這樣的方式是讓 veth pair 之間直接溝通,今天我們來試試看另外一種溝通方式,也是 docker bridge 使用的方式。

今天的步驟如下:

  1. 建立兩個 net namespace
  2. 建立一個 bridge,並且啟動這個 bridge
  3. 建立兩對 veth
  4. 分別將兩對 veth 的某一端加入 bridge,另外一端則分別加入各自的 net namespace
  5. 分別為 net namespace 裡的 veth 介面設定 ip 且啟動起來
  6. 測試看看連線

今天的結構比昨天又更複雜了一點點,所以我們先來看最後想完成的樣子:
https://ithelp.ithome.com.tw/upload/images/20221010/20151857fA8cjDHqA0.png


那現在就讓我們開始:

  1. 一樣在開始前先用 ip 來看一下目前 host 的情況,可以看到跟昨天一樣,就是只有 lo, ens5 跟 docker0。
ubuntu@ip-xxx:~$ ip link list
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: ens5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 0e:24:0e:79:cc:2d brd ff:ff:ff:ff:ff:ff
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
    link/ether 02:42:ea:22:dd:97 brd ff:ff:ff:ff:ff:ff
  1. 建立兩個 net namespace (這步驟跟昨天一模一樣)
ubuntu@ip-xxx:~$ sudo ip netns add ns1
ubuntu@ip-xxx:~$ sudo ip netns add ns2

# 確認一下目前的 netns 的情況:
ubuntu@ip-xxx:~$ sudo ip netns list
ns2
ns1

# 在 /var/run/netns 也可以看到
ubuntu@ip-xxx:~$ sudo ls -l /var/run/netns/
  1. 建立一個 bridge,名稱就叫做 docker1 好了,建立完成後啟動這個 bridge:
ubuntu@ip-xxx:~$ sudo ip link add docker1 type bridge

# 建立後先觀察一下,可以看到多了一個 278 docker1,但 state 是 DOWN
ubuntu@ip-xxx:~$ ip link list
1: lo: ...略
2: ens5: ...略
4: docker0: ...略
278: docker1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 9e:74:76:1e:f7:1e brd ff:ff:ff:ff:ff:ff

# 啟動一下這個 bridge,啟動後可以看到 state 變成 UNKNOWN 了
ubuntu@ip-xxx:~$ sudo ip link set docker1 up
ubuntu@ip-xxx:~$ ip link list
1: lo: ...略
2: ens5: ...略
4: docker0: ...略
278: docker1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether 9e:74:76:1e:f7:1e brd ff:ff:ff:ff:ff:ff
    
# 也可以透過 brctl 這個指令來管理 bridge
ubuntu@ip-xxx:~$ brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242ea22dd97	no
docker1		8000.000000000000	no
  1. 建立兩對 veth:
ubuntu@ip-xxx:~$ sudo ip link add veth0 type veth peer name veth0-br
ubuntu@ip-xxx:~$ sudo ip link add veth1 type veth peer name veth1-br

ubuntu@ip-xxx:~$ sudo ip link list
1: lo: ...略
2: ens5: ...略
4: docker0: ...略
278: docker1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether 9e:74:76:1e:f7:1e brd ff:ff:ff:ff:ff:ff
279: veth0-br@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 76:68:d0:f0:ee:19 brd ff:ff:ff:ff:ff:ff
280: veth0@veth0-br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 36:ba:6c:ca:c4:91 brd ff:ff:ff:ff:ff:ff
281: veth1-br@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 52:ae:58:eb:bd:5e brd ff:ff:ff:ff:ff:ff
282: veth1@veth1-br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether e2:32:6c:77:41:2a brd ff:ff:ff:ff:ff:ff

建立完成後觀察一下,可以看到目前有兩對 veth:

279: veth0-br@veth0 <----> 280: veth0@veth0-br
281: veth1-br@veth1 <----> 282: veth1@veth1-br
  1. 分別將兩對 veth 的某一端加入 bridge,另外一端則分別加入各自的 net namespace
ubuntu@ip-xxx:~$ sudo ip link set veth0 netns ns1
ubuntu@ip-xxx:~$ sudo ip link set veth0-br master docker1
ubuntu@ip-xxx:~$ sudo ip link set veth0-br up

ubuntu@ip-xxx:~$ sudo ip link set veth1 netns ns2
ubuntu@ip-xxx:~$ sudo ip link set veth1-br master docker1
ubuntu@ip-xxx:~$ sudo ip link set veth1-br up

ubuntu@ip-xxx:~$ sudo ip link list
1: lo: ...略
2: ens5: ...略
4: docker0: ...略
278: docker1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
    link/ether 52:ae:58:eb:bd:5e brd ff:ff:ff:ff:ff:ff
279: veth0-br@if280: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue master docker1 state LOWERLAYERDOWN mode DEFAULT group default qlen 1000
    link/ether 76:68:d0:f0:ee:19 brd ff:ff:ff:ff:ff:ff link-netns ns1
281: veth1-br@if282: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue master docker1 state LOWERLAYERDOWN mode DEFAULT group default qlen 1000
    link/ether 52:ae:58:eb:bd:5e brd ff:ff:ff:ff:ff:ff link-netns ns2

可以看到 280: veth0@veth0-br282: veth1@veth1-br1 因為分別被放進 ns1 跟 ns2 中,所以在目前的 net namespace 中看不到了。此外,也可以觀察到 279: veth0-br@veth0 這邊多了一個 master docker1,281: veth1-br@veth1 亦然。

  1. 分別為 net namespace 裡的 veth 介面設定 ip 且啟動起來
ubuntu@ip-xxx:~$ sudo ip netns exec ns1 ip addr add 172.18.0.2/24 dev veth0
ubuntu@ip-xxx:~$ sudo ip netns exec ns1 ip link set veth0 up
ubuntu@ip-xxx:~$ sudo ip netns exec ns1 ip addr
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
280: veth0@if279: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 36:ba:6c:ca:c4:91 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.2/24 scope global veth0
       valid_lft forever preferred_lft forever
    inet6 fe80::34ba:6cff:feca:c491/64 scope link
       valid_lft forever preferred_lft forever

ubuntu@ip-xxx:~$ sudo ip netns exec ns2 ip addr add 172.18.0.3/24 dev veth1
ubuntu@ip-xxx:~$ sudo ip netns exec ns2 ip link set veth1 up
ubuntu@ip-xxx:~$ sudo ip netns exec ns2 ip addr
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
282: veth1@if281: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether e2:32:6c:77:41:2a brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.3/24 scope global veth1
       valid_lft forever preferred_lft forever
    inet6 fe80::e032:6cff:fe77:412a/64 scope link
       valid_lft forever preferred_lft forever

直的放,讓大家比對一下:
https://ithelp.ithome.com.tw/upload/images/20221010/20151857536DikejNZ.png

  1. 測試看看連線
ubuntu@ip-xxx:~$ sudo ip netns exec ns1 ping 172.18.0.3
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.

然後你會發現 ping 不通!!!這是為什麼呢?


雖然我們最後沒有成功地完成連線,但到這邊應該更有感覺 docker bridge 的做法了,甚至我們用 brctl show 這個指令查看 host 中目前有哪些 bridge 時,是可以看到 docker0 跟我們自己的 docker1 並列在一起的。至於為什麼這樣無法連通,以及兩個 net namespace 之間可以互相溝通,可不代表能跟外界溝通,剩下的這些要怎麼做到呢?就讓我們明天繼續看下去~


上一篇
Day 24: 什麼是 veth pair?
下一篇
Day 26: 真的過橋了!
系列文
那些關於 docker 你知道與不知道的事32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言