Know Your Wisdom

从零搭建 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 设备,然后进行测试。

Catalogue