mac电脑下无法访问minikube的NodePort端口

本文作者详述了在Mac上使用minikube开发时遇到的网络问题,通过分析发现是由于docker和宿主机间网络限制。通过使用OpenVPN服务器和socat端口转发,作者成功打通了二层和三层网络,解决了访问minikube服务的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

前段时间换了工作,喜提一台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 sshkubectl 命令还是可以访问到虚机中的服务,因此在四层的网络应该还是通的,只是二层和三层的不通。

vpnkit

接着又查了一下hyperkit的文档,看到了hyperkit中是使用vpnkit这个组件来提供宿主机和虚机的网络传输的,然后又看了下vpnkit的文档,vpnkit的网络流向大概如下图,vpnkit一端连接在虚机内的交换设备Switch上充当一个网关,另一端在宿主机上暴露socket服务,所以我们在宿主机上只能通过四层tcp和udp的协议访问到虚机中的服务,minikube也是通过创建ssh隧道然后端口转发的方式,将内部服务暴露到宿主机上。

在这里插入图片描述

解决思路

基于上面的点,宿主机和hyperkit的虚机还是能通过tcp端口通信的,docker的端口映射也是基于此的,那我们其实也可以利用这个点,把宿主机和内部虚机的二层和三层网络打通,这里会借助socat端口转发、docker端口映射、Linux 网桥和openvpn server来打通网络,对这块没兴趣的同学可以忽略,直接跳转到下一节上手操作

查看minikube的网络

首先我们查看一下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,我们的目标就是在宿主机上打通虚机的这个网段即可。

使用openvpn server打通网络

我们知道docker是运行在上面的虚机中的,那我们其实可以在docker中启动一个vpn server的容器那么这个vpn server其实就运行在这个虚机中了,然后我们再把vpnserver的地址暴露在宿主机上,那我们其实就可以基于vpn打通宿主机和虚机的网络了,但是这里还有几个问题要解决

首先docker启动vpn server 的时候必须使用host网络模式才可以,因为vpn server 必须要使用虚机本地的网络,而不是docker的网络。如果使用host网络模式,那么端口就没法映射到宿主机了,因为docker的host网络不会新创建网络命名空间,直接加入本地网络,所以也不用做端口映射。

使用socat做端口转发

所以我们就需要在起一个端口转发的容器,做一个docker端口映射,将宿主机的端口映射到容器中,容器中在将端口转发到本地的open vpn server。

宿主机使用vpn client连接 vpn server

当这些都就绪之后,我们只需要配置一下vpn server的转发规则,将流量转发到192.168.49.0/24网段,宿主机上启动open vpn client,连接到docker的端口转发容器,这样整体网络就通了

上手操作

在mac上安装了docker-desktop 之后会一起安装docker-compose 使用docker-compose安装会方便的多,需要用到的yml和配置文件我都上传github了,可以直接下载下来,改一下配置使用

  1. 下载仓库代码
    仓库地址: https://github.com/yuzhaopeng/minikube-mac-network

    git clone git@github.com:yuzhaopeng/minikube-mac-network.git
    
  2. 使用docker-compose启动

    docker-compose up -d 
    
  3. 启动之后会在当前目录下生成客户端的配置文件 docker-for-mac.ovpn

  4. 安装vpn客户端 Tunnelblick

    官网似乎是被墙了,一直没打开过,可以到github上下载,下载地址

  5. 启动vpn客户端,将配置文件拖到客户端界面,点击连接
    请添加图片描述

  6. 测试网络是否通了

    # 发现此时可以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
    

写在最后

关于vpnkit在网上找到的资料不太多,如果有同学感兴趣的可以在评论区留个言,一起讨论

Minikube 是一个轻量级的 Kubernetes 发行版,它在本地计算机上运行一个单节点的 Kubernetes 集群,非常适合开发人员学习、测试和演示 Kubernetes。当你想要通过外部流量访问Minikube 集群中运行的服务时,可以使用 NodePort 类型的服务。以下是设置 NodePort 的基本步骤: 1. 启动 Minikube 集群: 如果你还没有启动 Minikube,可以使用下面的命令来启动一个基本的集群: ``` minikube start ``` 2. 创建一个 NodePort 类型的服务定义文件,例如 `service.yaml`,内容大致如下: ```yaml apiVersion: v1 kind: Service metadata: name: my-service spec: type: NodePort selector: app: my-app ports: - protocol: TCP port: 80 targetPort: 8080 nodePort: 30000 # 可以指定一个范围内的端口号,如果不指定,则系统会自动分配一个 ``` 在这个例子中,我们定义了一个服务 `my-service`,它会选择标签为 `app: my-app` 的 Pod,并将集群内部的 80 端口转发到 Pod 的 8080 端口。同时,我们指定了一个 NodePort 为 30000,这意味着你可以通过访问 Minikube 节点的 IP 地址加上 30000 端口访问服务。 3. 应用服务定义文件,创建服务: ``` kubectl apply -f service.yaml ``` 4. 获取 Minikube 节点的 IP 地址和 NodePort端口号: ``` minikube ip kubectl get svc my-service ``` 这将返回 Minikube 节点的 IP 地址以及你之前定义或者系统自动分配的 NodePort 端口号。 5. 访问服务: 使用浏览器或者命令行工具,通过 `http://<Minikube-IP>:<NodePort>` 访问你的服务。 请注意,NodePort端口范围默认是 30000-32767。如果你需要使用这个范围之外的端口,可以在启动 Minikube 时通过 `--extra-config` 标志来更改这个范围。
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值