局域网与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
# Docker0
3: 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 0
7: 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 3
8: 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 4
9: 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 5
10: 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
,可以看到有一个编号是19
的cailixxxxx
,如下情况:
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: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 forever
3: 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 forever
5: 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 1
6: 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 2
8: 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 4
10: 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 6
11: 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 7
12: 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 8
13: 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 9
17: 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 15
20: 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 16
21: 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.html、https://mp.weixin.qq.com/s/WJZVbhxbUJgc79tXB_nclw