如何从宿主机访问KVM虚拟机中运行的Istio负载均衡器
问题根因
从你贴的集群状态看,Istio组件本身运行完全正常,虚拟机内可访问、宿主机不通的核心原因是:istio-ingressgateway拿到的192.168.1.240外部IP,是集群内LoadBalancer实现(本地单节点集群基本都是MetalLB)分配的虚拟机内部可达地址,Vagrant+KVM默认的网络配置没有打通宿主机到该地址段的路由,宿主机收到发往这个IP的请求时,找不到对应的转发路径,自然无法连通。
方案1:Vagrant端口转发(最快落地,适合临时测试)
不需要改K8s任何配置,直接利用Vagrant自带的NAT端口转发能力把流量导进虚拟机:
- 从你贴的service输出可以看到,istio-ingressgateway的80端口已经映射到节点的
31238端口,443端口映射到节点的30360端口,先记好这两个NodePort。 - 关闭运行中的虚拟机,打开工作目录下的Vagrantfile,保留原有配置,新增端口转发规则:
Vagrant.configure("2") do |config| # 原有配置不要动,新增下面两行 config.vm.network "forwarded_port", guest: 31238, host: 8080, host_ip: "127.0.0.1" config.vm.network "forwarded_port", guest: 30360, host: 8443, host_ip: "127.0.0.1" end
- 执行
vagrant reload重启虚拟机加载配置,重启完成后,宿主机直接访问127.0.0.1:8080就能打到Istio入口网关。调用Knative函数时带上正确的Host头即可,测试示例:
curl -H "Host: 你的函数访问域名" http://127.0.0.1:8080
注意:该方案走NAT转发,性能一般,仅适合本地快速调试,不适合长期使用。
方案2:桥接网络直连(体验最好,适合长期使用)
把Vagrant虚拟机的网卡桥接到宿主机的物理网卡,让虚拟机和宿主机处于同一个二层局域网,直接打通网络:
- 关闭虚拟机,修改Vagrantfile配置公网桥接模式,
dev字段填宿主机当前联网的物理网卡名(PopOs下执行ip a可查看,无线网卡一般以wlp开头,有线网卡以enp开头):
Vagrant.configure("2") do |config| config.vm.network "public_network", :dev => "宿主机物理网卡名", :mode => "bridge", :type => "bridge" end
- 执行
vagrant reload重启,重启后在虚拟机内执行ip a查看新网卡拿到的和宿主机同网段的IP,比如宿主机IP为192.168.1.100,虚拟机桥接IP为192.168.1.101即配置成功。 - 调整集群内MetalLB的IP地址池,把LB分配网段设置成当前物理局域网内未被占用的地址段,确保和宿主机同网段:
apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: default-pool namespace: metallb-system spec: addresses: - 192.168.1.240-192.168.1.250 # 提前确认这些IP没有被路由器DHCP分配、也没有被其他局域网设备占用
- 删除现有istio-ingressgateway的pod,等它自动重建后会重新获取同网段的ExternalIP,此时宿主机直接访问该IP(就是你之前的192.168.1.240,只要没IP冲突)就能连通,局域网内其他设备也可以直接访问。
注意:如果局域网开了DHCP,记得把MetalLB用的IP段加到DHCP的排除列表,避免IP冲突。
方案3:宿主机加静态路由(无需改Vagrant网络配置)
不想调整现有Vagrant网络模式的话,直接在宿主机加路由规则,把发往K8s LB网段的流量导到虚拟机的私网IP:
- 在虚拟机内执行
ip a查看Vagrant默认私网网卡的IP,KVM版Vagrant默认私网网段一般是192.168.121.0/24,虚拟机私网IP通常为该网段下的地址,比如192.168.121.10。 - 在宿主机上执行以下命令添加静态路由(把网段和虚拟机IP替换成你实际的):
# 假设MetalLB分配的LB网段是192.168.1.0/24,虚拟机私网IP是192.168.121.10 sudo ip route add 192.168.1.0/24 via 192.168.121.10
- 添加完成后,在宿主机ping
192.168.1.240,能ping通就可以直接访问Istio网关的80/443端口。如果需要路由永久生效,把规则写到NetworkManager的静态路由配置里即可,否则宿主机重启后路由会失效。
排错提示
如果配置完还是连不通,先检查两点:
- Ubuntu 20.04默认开启ufw防火墙,执行
sudo ufw allow 80/tcp && sudo ufw allow 443/tcp && sudo ufw allow 30000:32767/tcp放开K8s NodePort段和网关端口的入站流量。 - 访问时如果返回404响应属于正常现象,说明流量已经打到Istio网关,只是没有携带Knative函数要求的Host头,补上对应Host头即可拿到正常响应。
内容的提问来源于stack exchange,提问作者Nikitas Tsiris
相关产品推荐
相关产品推荐

