写点什么

局域网与 Kubernetes 内部网络如何互通

  • 2023-08-12
    江苏
  • 本文字数:6395 字

    阅读完需:约 21 分钟

局域网与Kubernetes内部网络如何互通

K8S 搭建完毕之后,碰到个问题,如何进行远程 debug(别在生产环境远程 debug 哦)?那就需要打通局域网和 K8S 内部网络了。本文主要介绍 Pod 通信、K8S 网络插件、局域网和 K8S 网络如何打通。

1、问题描述

我们在实际使用 K8S 过程中,出现了以下需求:


  • 出现问题时,想进行远程 debug 调试。

  • 开发在电脑完成某个微服务模块开发后,希望本地启动后,能注册到开发环境的注册中心进行调试,而不是本地起一堆依赖的服务。


以上问题,如果在办公室网络 和 K8S Pod 网络不通的情况下就很难受。


由于 Kubernetes 集群会使用 CNI 插件创建 Pod/Service 内部子网,外面一般无法访问内部 IP 和域名,给开发、测试、 联调带来了很大的麻烦,因此打通开发测试环境 Kubernetes 集群内部子网和办公室的局域网,实现互联互通是经常遇到的问题。


在打通之前,我们先了解下 K8S 网络的基本知识。K8S 的网络架构比较复杂,Kubernetes 本身并不负责网络通信,但提供了容器网络接口 CNI(Container Network Interface),具体的网络通信交由 CNI 插件来实现。


这是一种标准设计,为了让用户在创建或销毁容器时都能够更容易地配置容器网络。用户只需要使用 CNI 插件就可以轻松的管理 K8S 网络。目前主流的开源 CNI 插件非常多,像 Flannel、Calico 等。

2、常见术语

在探索 CNI 插件之前先了解下几个术语:


  • eth0:是系统的光纤以太网接口卡名称,也会有别的名称,比如 ens192。

  • veth 虚拟网络设备:veth 设备是成对出现的,一端连着 Pod,另一端连着 CNI。

  • netns:netns 是 Linux Network Namespace 的缩写,是 Linux 提供的原生网络隔离功能组件,能在 Linux 系统中虚拟出来多个网络空间,实现网络资源的隔离。

  • 第 2 层网络:OSI(Open Systems Interconnections,开放系统互连)网络模型的“数据链路”层。第 2 层网络会处理网络上两个相邻节点之间的帧传递。第 2 层网络的一个值得注意的示例是以太网,其中 MAC 表示为子层。

  • 第 3 层网络:OSI 网络模型的“网络”层。第 3 层网络的主要关注点,是在第 2 层连接之上的主机之间路由数据包。IPv4、IPv6 和 ICMP 是第 3 层网络协议的示例。

  • VXLAN:代表“虚拟可扩展 LAN”。首先,VXLAN 用于通过在 UDP 数据报中封装第 2 层以太网帧来帮助实现大型云部署。VXLAN 虚拟化与 VLAN 类似,但提供更大的灵活性和功能(VLAN 仅限于 4096 个网络 ID)。VXLAN 是一种封装和覆盖协议,可在现有网络上运行。

  • Overlay 网络:Overlay 网络是建立在现有网络之上的虚拟逻辑网络。Overlay 网络通常用于在现有网络之上提供有用的抽象,并分离和保护不同的逻辑网络。

  • 封装:封装是指在附加层中封装网络数据包以提供其他上下文和信息的过程。在 overlay 网络中,封装被用于从虚拟网络转换到底层地址空间,从而能路由到不同的位置(数据包可以被解封装,并继续到其目的地)。

  • 网状网络:网状网络(Mesh network)是指每个节点连接到许多其他节点以协作路由、并实现更大连接的网络。网状网络允许通过多个路径进行路由,从而提供更可靠的网络。网状网格的缺点是每个附加节点都会增加大量开销。

  • BGP:代表“边界网关协议”,用于管理边缘路由器之间数据包的路由方式。BGP 通过考虑可用路径,路由规则和特定网络策略,帮助弄清楚如何将数据包从一个网络发送到另一个网络。BGP 有时被用作 CNI 插件中的路由机制,而不是封装的覆盖网络。

  • IP 隧道技术:是路由器把一种网络层协议封装到另一个协议中以跨过网络传送到另一个路由器的处理过程。 IP 隧道(IP tunneling)是将一个 IP 报文封装在另一个 IP 报文的技术,这可以使得目标为一个 IP 地址的数据报文能被封装和转发到另一个 IP 地址。IP 隧道技术亦称为 IP 封装技术。

3、Pod 通信

在打通局域网与 Kubernetes 内部网络之前,先简单描述下,K8S 的 Pod 之间是如何通信的。

3.1、同一个节点中的 Pod 通信

Pod 通过虚拟 Ethernet 接口对(Veth Pair)与外部通信,Veth Pair 像一根网线,一端在 Pod 内部,一端在 Pod 外部。同一个节点上的 Pod 通过网桥(Linux Bridge)通信,如下图所示。



在同一节点上的 Pod 会通过 Veth 设备将一端连接到网桥,且它们的 IP 地址是通过网桥动态获取的,和网桥 IP 属于同一网段。此外,同一节点上的所有 Pod 默认路由都指向网桥,网桥会负责将所有非本地地址的流量进行转发。因此,同一节点上的 Pod 可以直接通信。

3.2、不同节点的 Pod 通信

Kubernetes 要求集群 Pod 的地址唯一,因此集群中的每个节点都会分配一个子网,以保证 Pod 的 IP 地址在整个集群内部不会重复。在不同节点上运行的 Pod 通过 IP 地址互相访问,该过程需要通过集群网络插件实现,按照底层依赖大致可分为 Overlay 模式、路由模式、Underlay 模式三类。


  • Overlay 模式是在节点网络基础上通过隧道封装构建的独立网络,拥有自己独立的 IP 地址空间、交换或者路由的实现。VXLAN 协议是目前最流行的 Overlay 网络隧道协议之一。

  • 路由模式采用 VPC 路由表的方式与底层网络相结合,能够更加便捷地连接容器和主机,在性能上会优于 Overlay 的隧道封装。

  • Underlay 模式是借助驱动程序将节点的底层网络接口直接暴露给容器使用的一种网络构建技术,享有较高的性能,较为常见的解决方案有 IP VLAN 等。


4、网络插件

本文只介绍 Calico,因为 Flannel 我也没用过,云上的 K8S 网络插件基本都是云厂商结合自己的 VPC 网络实现的,更不在介绍范围内了。


k8s 网络插件主要分为:underlay 和 overlay,calico 主要分为 3 种模式:BGP、IPIP、VXLAN,BGP 属于 underlay、IPIP 和 VXLAN 属于 overlay。


Calico 是一种开源网络和网络安全解决方案,适用于容器,虚拟机和基于主机的本机工作负载。Calico 支持广泛的平台,包括 Kubernetes,docker,OpenStack 和裸机服务。Calico 后端支持多种网络模式。


本文主要分析 calico 的 ipip 模式,旨在理解 IPIP 网络模式下产生的 calixxxx,tunl0 等设备以及跨节点网络通信方式。ipip 模式主要原理就是在 pod ip 的基础上再封装一层 node ip,这样在通过对应的路由规则,就可以转发到对应的目的地。

4.1、网络初窥

我采用的 CNI 插件 Calico,例如,通过ip addr命令可以看到 K8S Node 节点下有许多cali打头的虚拟网卡,同时,还有tunl0这种 IP 隧道,可以看到采用的是 Calico 的 IPIP 模式。



通过route -n命令也能看到每个 pod 会对应一个虚拟网卡,访问别的网段会通过tunl0这个隧道发出去。


4.2、Calico 的 IPIP 模式:

IPIP 模式:Calico 默认使用这种方式。在原有 IP 报文中封装一个新的 IP 报文,新的 IP 报文中将源地址 IP 和目的地址 IP 都修改为对端宿主机 IP。开启时将 Node 路由之间做一个 tunnel,再把两个网络连接起来的模式,会在各 Node 节点上创建一个名为 tunl0 的虚拟网络接口。


IP 模式下的通信流程,见如下 2 个图:




在 K8S-Node 上执行ip addr可以看到以下信息,其中包含了 tunl0 和 calixxxxxx:


# 回环地址1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00    inet 127.0.0.1/8 scope host lo       valid_lft forever preferred_lft forever# 物理网卡2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000    link/ether 00:50:56:95:32:45 brd ff:ff:ff:ff:ff:ff    inet 10.20.1.22/24 brd 10.20.1.255 scope global noprefixroute ens192       valid_lft forever preferred_lft forever# Docker03: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default    link/ether 02:42:4f:0d:6a:48 brd ff:ff:ff:ff:ff:ff    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0       valid_lft forever preferred_lft forever# cali打头的Calico网卡4: cali7533706c752@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 07: cali6bf54ec99f4@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 38: calif0a8819d7b4@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 49: cali2299828844c@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 510: cali7c84f4d310b@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 6# Calico IP隧道使用的Tunl0网卡15: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1440 qdisc noqueue state UNKNOWN group default qlen 1000    link/ipip 0.0.0.0 brd 0.0.0.0    inet 10.21.230.0/32 brd 10.21.230.0 scope global tunl0       valid_lft forever preferred_lft forever
复制代码


我们也可以看到 veth 是成对出现的,比如进入到 Pod,查看网络情况,在 K8S-Master 执行命令kubectl exec -it ingress-nginx-controller-nginx-d864d97df-22ljk -n ingress-nginx -- ip addr,可以看到虚拟网卡的编号if19,如下情况:


# 回环网卡1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00    inet 127.0.0.1/8 scope host lo       valid_lft forever preferred_lft forever# 虚拟网卡3: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1440 qdisc noqueue state UP    link/ether 66:e5:5b:b6:77:9a brd ff:ff:ff:ff:ff:ff    inet 10.21.69.212/32 scope global eth0       valid_lft forever preferred_lft forever# 隧道网卡4: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000    link/ipip 0.0.0.0 brd 0.0.0.0
复制代码


在到这个 Pod 所在 K8S-Node 执行命令ip addr,可以看到有一个编号是19cailixxxxx,如下情况:


1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00    inet 127.0.0.1/8 scope host lo       valid_lft forever preferred_lft forever2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000    link/ether 00:50:56:95:c0:f4 brd ff:ff:ff:ff:ff:ff    inet 10.20.1.24/24 brd 10.20.1.255 scope global noprefixroute ens192       valid_lft forever preferred_lft forever3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default    link/ether 02:42:2c:ea:87:52 brd ff:ff:ff:ff:ff:ff    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0       valid_lft forever preferred_lft forever5: cali7359ae97a07@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 16: cali763ea01ddd0@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 28: cali0140629a81f@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 410: calid3a5006f559@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 611: calic2abb800440@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 712: cali06eecb511af@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 813: cali26321116fa3@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 917: calia5d32a88758@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 13# Pod内的eht0标记的是19号和这里的19号是配对的19: calib51fc1cd61e@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 1520: cali5910af186a4@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 1621: calie8b8d191185@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 17
复制代码

4.3、Calico 的 BGP 模式:

BGP 模式:将节点做为虚拟路由器通过 BGP 路由协议来实现集群内容器之间的网络访问。不再创建额外的 tunnel。它会以 daemonset 方式安装在所有 node 主机,每台主机启动一个 bird(BGP client),它会将 calico 网络内的所有 node 分配的 ip 段告知集群内的主机,并通过本机的默认网关的网卡(如:eth0)转发数据 BGP 网络相比较 IPIP 网络,最大的不同之处就是没有了隧道设备 tunl0。 前面介绍过 IPIP 网络 pod 之间的流量发送到 tunl0,然后 tunl0 发送对端设备。BGP 网络中,pod 之间的流量直接从网卡发送目的地,减少了 tunl0 这个环节。


BGP 模式下的通信流程,见下图:





BGP 模式的优点:少了封包和解包的过程,性能高一些。


BGP 模式的缺点:需要维护更多的路由规则。


IPIP 隧道模式的优点:简单,原因是大部分工作都是由 Linux 内核的模块实现了,应用层面工作量较少。


IPIP 隧道模式的缺点:主要的问题因为要封包接包,性能低。

5、局域网与 Kubernetes 内部网络互通

如果 K8S 集群就部署在局域网内或者部署在自己的数据中心,整个链路上的网关可配的话,用静态路由表是最简单的办法,其原理是作用在网络模型的第三层 网络层,直接告诉网关某些 IP 要发给谁。


通过上面的 K8S 网络小知识和执行命令看到的路由转发的截图,我们知道 K8S-Node 其实也是一个虚拟路由,只要请求被转发到 K8S-Node,那么就可以访问到 Pod。


举一个最简单的例子,某开发环境的 K8S 部署在和办公室同一个局域网,有下面两条线路可以打通网络,如下图:



此时只需要公司的运维在网关路由器上添加静态路由规则,把属于 K8S 的 Pod/Service CIDR 的 IP 包全转给其中某个 K8S 节点,这样访问 10.96.0.1 这样的 IP,网络包会到达某个集群物理节点,而集群内的物理节点或 VM,一般 K8S 网络插件(CNI)都会做与 Pod/Service CIDR 的互通。


如果 K8S 部署的机器和公司办公室不在同一个网关下,或者部署在自建数据中心的,整个链路会多几个网关,链路上每个网关都需要配置路由表路由相应的 CIDR 到相邻的跃点,如果是办公网络到到达云上的 K8S 集群,也只需要从路由器经过 VPN 到达云上即可,如下图:



总结:本文主要讲了 K8S 网络基础知识、局域网与 K8S 网络如何打通,希望对你有帮助。如果觉得有误,也请纠正,谢谢!


原文:http://www.mangod.top/articles/2023/08/12/1691805102896.htmlhttps://mp.weixin.qq.com/s/YrOzD6KnL-1XQNfgK5tLsA


用户头像

这里可以找到我 mangod.top 2018-09-11 加入

13年IT行业经验,做过架构创过业,一起交流学习。专注于软件开发、云原生、大数据领域。关注我职业发展不焦虑。

评论

发布
暂无评论
局域网与Kubernetes内部网络如何互通_k8s_不焦躁的程序员_InfoQ写作社区