从零搭建 K8S 集群
2022-04-09
以下是本文中会用到的变量的说明:
- A: Apple Mac M1,即我的笔记本电脑
192.168.31.198
- B: RaspberryPi400,即树莓派,所有网络操作都在树莓派上完成
192.168.31.134
MacVLAN
全称:Media Access Control Virtual Local Area Network
第一个例子尝试用 macvlan 给 B(树莓派)创建一个新的 MAC 地址,然后在该地址上运行一个 web server,最终要求能在 A(Apple)上成功访问。
首先创建 macvlan,然后给他赋予一个 IP 地址: 198.18.1.1/16
,最后在该地址上运行一个 web server
>>> sudo ip link add mvl0 link wlan0 type macvlan mode bridge
>>> sudo ip addr add 198.18.1.1/16 dev mvl0
>>> ip a show dev mvl0
54: mvl0@wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether f2:07:7a:8f:d1:6f brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 68 maxmtu 1500
macvlan mode bridge numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
inet 198.18.1.1/16 scope global mvl0
valid_lft forever preferred_lft forever
inet6 fe80::3c17:bbb9:6450:982c/64 scope link
valid_lft forever preferred_lft forever
>>> python3 -m http.server 8080 --bind 198.18.1.1
Serving HTTP on 198.18.1.1 port 8080 (http://198.18.1.1:8080/) ...
此时在 B 上尝试访问这个 web server,可见已经可以成功返回:
>>> curl 198.18.1.1:8080
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
....
然而由于 A 的默认路由规则走的是 192.168.31.1/24
,此时由于不在同一子网下,所以数据包将直接被路由器发往公网,肯定是无响应的。要想能够成功响应,需要先给 A 配置一条特殊的路由规则,把 198.18.1.1
的数据转发到 B 的 IP 地址( 192.168.31.134
)上:
>>> ip r add 198.18.1.1/32 via 192.168.31.134
Executing: /usr/bin/sudo /sbin/route add 198.18.1.1/32 192.168.31.134
add net 198.18.1.1: gateway 192.168.31.134
>>> curl 198.18.1.1:8080
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
...
看看个数据包具体用的是哪个 MAC 地址:
# terminal 1
>>> sudo arping -I en0 198.18.1.1
ARPING 198.18.1.1
42 bytes from e4:5f:01:a7:2a:86 (198.18.1.1): index=0 time=50.996 msec
42 bytes from e4:5f:01:a7:2a:86 (198.18.1.1): index=1 time=51.021 msec
...
# terminal 2
>>> sudo tcpdump -ens0 -i en0 'arp'
Password:
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on en0, link-type EN10MB (Ethernet), snapshot length 524288 bytes
18:50:39.193962 a0:78:17:5e:8c:c4 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 58: Request who-has 198.18.1.1 tell 192.168.31.198, length 44
18:50:39.214239 e4:5f:01:a7:2a:86 > a0:78:17:5e:8c:c4, ethertype ARP (0x0806), length 42: Reply 198.18.1.1 is-at e4:5f:01:a7:2a:86, length 28
18:50:39.214247 e4:5f:01:a7:2a:86 > a0:78:17:5e:8c:c4, ethertype ARP (0x0806), length 42: Reply 198.18.1.1 is-at f2:07:7a:8f:d1:6f, length 28
这里可以看到 B 居然有两条回复:
- 我在
e4:5f:01:a7:2a:86
- 我在
f2:07:7a:8f:d1:6f
而数据发送端的 MAC 地址都是 e4:5f:01:a7:2a:86
。
看看 A 和 B 通信时具体用的哪个 MAC 地址:
# terminal 1
>>> ping 198.181.1.1
PING 198.18.1.1 (198.18.1.1): 56 data bytes
64 bytes from 198.18.1.1: icmp_seq=0 ttl=64 time=7.469 ms
64 bytes from 198.18.1.1: icmp_seq=1 ttl=64 time=17.078 ms
....
# terminal 2
>>> sudo tcpdump -ens0 -i en0 'not arp and host 198.18.1.1'
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on en0, link-type EN10MB (Ethernet), snapshot length 524288 bytes
19:05:18.113143 a0:78:17:5e:8c:c4 > e4:5f:01:a7:2a:86, ethertype IPv4 (0x0800), length 98: 192.168.31.198 > 198.18.1.1: ICMP echo request, id 55460, seq 0, length 64
19:05:18.120379 e4:5f:01:a7:2a:86 > a0:78:17:5e:8c:c4, ethertype IPv4 (0x0800), length 98: 198.18.1.1 > 192.168.31.198: ICMP echo reply, id 55460, seq 0, length 64
....
同样 A 给 B 的回复地址也是 e4:5f:01:a7:2a:86
,那我要这 macvlan 有何用?通信过程中照样用的 B 的地址啊!
试试能不能强制指定 arp table,让 A 用 e4:5f:01:a7:2a:86
去访问 B,结果 MacOS 不支持修改。
试试能不能指定树莓派 arp table,让 B 的两个 MAC 地址互相访问,结果数据没走 arp table,直接走了 lo
网口,什么狗屁玩意。
>>> sudo tcpdump -ens0 -i lo 'not arp and host 198.18.1.1'
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
19:18:25.963338 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 98: 198.18.1.1 > 198.18.1.1: ICMP echo request, id 7, seq 1, length 64
19:18:25.963414 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 98: 198.18.1.1 > 198.18.1.1: ICMP echo reply, id 7, seq 1, length 64
19:18:26.995209 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 98: 198.18.1.1 > 198.18.1.1: ICMP echo request, id 7, seq 2, length 64
那现在只有最后一种方法,再找一个 linux 设备,然后进行测试。