前段时间换了工作,喜提一台mac电脑,为了方便在本地搞k8s开发,就打算安装minikube。minikube的安装步骤就不赘述了,参照官网即可。 当minikube安装完了之后,为了测试下是否安装成功,就起了个deployment 然后暴露了一个service 使用nodeport访问,但是我在本地浏览器访问却发现访问不通??? 基于此,就研究了下minikube的网络。
我首先启动了一个deployment ,然后暴露了service,如下
# 启动一个nginx的deployment
MacBook-Pro-2:~ jxrt$ kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 1/1 1 1 23d
# 将nginx服务暴露在31908的nodeport上
MacBook-Pro-2:~ jxrt$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-deploy NodePort 10.103.97.88 <none> 80:31908/TCP 23d
然后我使用minikube的ip 访问
# 查看minikube的ip
MacBook-Pro-2:~ jxrt$ minikube ip
192.168.49.2
# 访问minikube的nodeport的端口,发现访问不通
MacBook-Pro-2:~ jxrt$ wget 192.168.49.2:31908
--2022-07-15 15:48:28-- http://192.168.49.2:31908/
正在连接 192.168.49.2:31908...
# ping了 minikube的ip也不通
MacBook-Pro-2:~ jxrt$ ping 192.168.49.2
PING 192.168.49.2 (192.168.49.2): 56 data bytes
Request timeout for icmp_seq 0
^C
--- 192.168.49.2 ping statistics ---
2 packets transmitted, 0 packets received, 100.0% packet loss
从上面可以看到,访问minikube 的ip是不通的,我的minikube是通过docker方式启动的,mac电脑的docker是运行在虚机中的,目前看来是宿主机和虚机的网络不通。
又查了下文档,通过docker启动的minikube确实没有和宿主机打通网络,严格来说是没有打通二层和三层的网络,minikube给出的解决方案是通过端口代理的方式来访问服务,如下:
# 可以使用这种方式来访问minikube中暴露出来的service,本质是临时起了一个ssh端口转发的隧道
MacBook-Pro-2:~ jxrt$ minikube service nginx-deploy --url
Starting tunnel for service nginx-deploy.
❗ Because you are using a Docker driver on darwin, the terminal needs to be open to run it.
但是我的电脑上这种方式好像不生效,查了下github也有其他人遇到了这种问题,目前还无解,参考GitHub的 Issues 14268
因为mac下的docker是运行在hyperkit的虚机中的,所以就打算看下hyperkit启动的虚机是怎么解决网络问题的,目前的现象是虽然minikube 的ip不通,但是使用 minikube ssh
和 kubectl
命令还是可以访问到虚机中的服务,因此在四层的网络应该还是通的,只是二层和三层的不通。
接着又查了一下hyperkit的文档,看到了hyperkit中是使用kit这个组件来提供宿主机和虚机的网络传输的,然后又看了下kit的文档,kit的网络流向大概如下图,kit一端连接在虚机内的交换设备Switch上充当一个网关,另一端在宿主机上暴露socket服务,所以我们在宿主机上只能通过四层tcp和udp的协议访问到虚机中的服务,minikube也是通过创建ssh隧道然后端口转发的方式,将内部服务暴露到宿主机上。
基于上面的点,宿主机和hyperkit的虚机还是能通过tcp端口通信的,docker的端口映射也是基于此的,那我们其实也可以利用这个点,把宿主机和内部虚机的二层和三层网络打通,这里会借助socat端口转发、docker端口映射、Linux 网桥和open server来打通网络,对这块没兴趣的同学可以忽略,直接跳转到下一节上手操作
首先我们查看一下minikube的ip,然后可以找到对应的Linux网桥,其实通过命名也可以直接找到网桥
# 查看一下minikube的ip地址,其实可以猜一下看这个ip应该也是某个网桥给分配的
MacBook-Pro-2:~ jxrt$ minikube ip
192.168.49.2
#然后我们查看一下网桥信息
jxrtdeMacBook-Pro-2:~ jxrt$ docker network ls
NETWORK ID NAME DRIVER SCOPE
ce64d9141d75 host host local
03517ace23ec minikube bridge local
# 查看一下minikube 网桥的详细信息,信息太多了我就截取了一小段如下
xrtdeMacBook-Pro-2:~ jxrt$ docker network inspect 03517ace23ec
[
{
"Name": "minikube",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.49.0/24",
"Gateway": "192.168.49.1"
}
]
},
}]
从上面minikube的网桥IPAM中可以看到网段是 192.168.49.0/24
,我们的目标就是在宿主机上打通虚机的这个网段即可。
我们知道docker是运行在上面的虚机中的,那我们其实可以在docker中启动一个 server的容器那么这个 server其实就运行在这个虚机中了,然后我们再把server的地址暴露在宿主机上,那我们其实就可以基于打通宿主机和虚机的网络了,但是这里还有几个问题要解决
首先docker启动 server 的时候必须使用host网络模式才可以,因为 server 必须要使用虚机本地的网络,而不是docker的网络。如果使用host网络模式,那么端口就没法映射到宿主机了,因为docker的host网络不会新创建网络命名空间,直接加入本地网络,所以也不用做端口映射。
所以我们就需要在起一个端口转发的容器,做一个docker端口映射,将宿主机的端口映射到容器中,容器中在将端口转发到本地的open server。
当这些都就绪之后,我们只需要配置一下 server的转发规则,将流量转发到192.168.49.0/24
网段,宿主机上启动open client,连接到docker的端口转发容器,这样整体网络就通了
在mac上安装了docker-desktop 之后会一起安装docker-compose
使用docker-compose安装会方便的多,需要用到的yml和配置文件我都上传github了,可以直接下载下来,改一下配置使用
下载仓库代码
仓库地址: https://github.com/yuzhaopeng/minikube-mac-network
git clone [email protected]:yuzhaopeng/minikube-mac-network.git
使用docker-compose启动
docker-compose up -d
启动之后会在当前目录下生成客户端的配置文件 docker-for-mac.o
安装客户端 Tunnelblick
官网似乎是被墙了,一直没打开过,可以到github上下载,下载地址
测试网络是否通了
# 发现此时可以ping通minikube的ip了
MacBook-Pro-2:~ jxrt$ ping 192.168.49.2
PING 192.168.49.2 (192.168.49.2): 56 data bytes
64 bytes from 192.168.49.2: icmp_seq=0 ttl=63 time=11.028 ms
64 bytes from 192.168.49.2: icmp_seq=1 ttl=63 time=5.558 ms
^C
--- 192.168.49.2 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 5.558/8.293/11.028/2.735 ms
关于kit在网上找到的资料不太多,如果有同学感兴趣的可以在评论区留个言,一起讨论