Kubernetes 网络实现——外网通讯

简介: 本文介绍 Kubernetes 网络中外网通讯、LoadBalance 以及 Ingress 部分的实现方案。

引言

本文介绍 Kubernetes 网络中外网通讯、LoadBalance 以及 Ingress 部分的实现方案,更多关于 Kubernetes 的介绍均收录于<Kubernetes系列文章>中。

与外网通讯

到目前为止,我们已经清楚了 Kubernetes 集群内部的网络通讯原理,但是我们还没有讲清楚外部世界的网络怎么和我们的 Kubernetes service 交互。这包含两个部分,集群内的数据包怎么发送到外部网络,以及外部网络的数据包怎么流入 pod。

以我现在使用的内部云服务为例,我的 Kubernetes 集群实际上运行在一个虚拟机上,这些虚拟机都被指定了一个内部 ip,也就是 eth0 的 ip 地址,这个内部地址在我们的 Kubernetes 集群中能够直接访问。为了让我们的数据包能够触及外部世界的网络,云服务商会给我们的虚拟机挂载一个网关,这个网关有两个作用:其一是为我们的虚拟机提供一个路由表的 target,通过这个 target 虚拟机的数据包可以发送给网关继而由网关转发到外部网络。其二是做一个网络地址转换(NAT),给每一个数据包指定到一个公网 ip。由于这个网关的存在,我们的虚拟机才得以访问到公网。但是有一个小问题,因为我们的 pod 有自己的网络域,它是和虚拟机上的 eth0 网络域是独立的。而网关只能负责虚拟机 eth0 网络域的 ip,因为它根本不知道虚拟机上还有 pod subnet。那么 Kubernetes 是怎么解决这个问题的呢?
pod-to-internet
在上图中,数据包由 pod 的网络空间发出,经由 veth 对,连接到宿主机的网络空间 root。当数据包到达,root 网络空间后,会从网桥流向默认网络设备 eth0,因为数据包的目标 ip 没有命中宿主机的任意网络设备。在流到 eth0 之前,别忘了它还会经过 iptables 的处理。iptables 发现这个数据包由 pod 网络中发出,如果它保持这个源 ip 不变,网关 NAT 会无法识别这个网络域,数据包就发不出去,所以在这里 iptables 扮演着一个 NAT 的角色,它将源 ip 从 pod ip 改为 eth0 的 ip。这样这个数据包才能从虚拟机中经由网关传送到公网。在网关中,它还会再次进行一次 NAT,将虚拟机的内网地址,转换成公网地址。而从公网中返回的数据包也是经历了相同的路线,NAT 将目标地址外网 ip 转为虚拟机的内网 ip,然后虚拟机将内网 ip 转为 pod 的 ip。

还记得我们在试玩环节解决的外网访问 service 的实验么,当时我们使用了云服务中的 LoadBalancer,实际上在 Kubernetes 中有两种方式可以解决外网访问我们 service 的问题,一个就是前面说的 LoadBalancer,另一个 Kubernetes 的 Ingress Controller。

LoadBalancer,又称 Layer 4 (传输层)入口。当我们创建好 service 后,可以通过云服务商的 API 来创建 LB,这个 LB 对应了一个外网的 ip 地址,外网的用户可以通过这个 LB public ip 访问到我们的服务。前面的试玩中,因为我使用的云服务没有提供 Kubernetes 对接,所以我 Service type 选为 NodePort,并将L4 LB 绑定到 service 的 node port 上,当 Service type 选为 node port 后,会由 kube-proxy 进程在宿主机上占用一个端口 Service Port,保证该端口不会被其他进程使用,然后修改 iptables 将发送到 Service Port 的包转发到随机 pod 中,这是 kube-proxy 的默认工作模式,该模式的优点是代理过程全部经由内核态完成,而且在第四层就能完成转发工作。

让我们看一看 LB 是怎么工作起来的。首先,我们部署了自己的服务 kubia,然后创建了 LB,外网的数据包到达 LB 后会分发到任意一个 Kubernetes 集群节点,经由该虚拟机节点的 iptables,它会再次进行一个负载均衡,分发到任意一个 service 的 pod 中,当该 pod 返回数据包时,必然是用的 pod 的 ip 地址,这怎么行呢,外网的服务访问者肯定希望返回的数据包 ip 是 LB 的 ip,这样才能对的上啊。所以,当数据包从 pod 中返回时,iptables 和 conntrack 齐心协力地重写了 ip 地址,虚拟机将 ip 改为自己的 eth0 ip 并返回给 LB,LB 再将虚拟机的 ip 改为自己的外网 ip。下面这张图就展示了,这里所说的流程。
internet-to-service
除了,LB 之外,另一种方案是 Layer 7(应用层)入口。一般来说 Layer 7 入口面向的是 HTTP/HTTPS 协议栈。我们需要将 Service 类型置为 NodePort,这样 Kubernetes 会选择一个端口作为服务的名义端口,然后每个节点上的 kube-proxy 都会占用该名义端口,防止其他进程也使用相同端口(会发生传输冲突),然后每个节点都会修改自己的 iptables,将流入该名义端口的包根据负载均衡规则转发到对应的 pod 中。

在 Kubernetes 中,我们称这种 Layer 7 的 HTTP LoadBalance 为 Ingress,它同样需要云服务商提供 L7 的 http LoadBalance,就像 Layer 4 LoadBalance 一样,它只能将请求转发到虚拟机上,然后虚拟机上的 iptables 再转发到对应的 pod 中。

下图展示的就是 Layer 7 应用级 LB 的工作方式,当我们通过 Kubernetes 的 api server 建立 Ingress 对象后,云服务提供商会感知到该事件,并建立自己的应用级 LB(ALB),该 ALB 会指向多个节点来保证可用性,同时会根据 Ingress 中定义的规则将请求转发给对应的节点 NodePort(NP)。
ingress-controller-design
下图中描述了数据包的流转,公网中的数据包发给 Ingress LB 后,它将请求转发到虚拟机上的 NodePort,然后虚拟机根据 iptables 规则将请求转发到正确的 pod 中。就像前面所说的一样,这里也会使用 conntrack 来将返回包的源 ip 地址从 pod ip 改为 lb 的 ip。
ingress-to-service

LB vs Ingress

我们已经知道了 Kubernetes 中当 service 的类型为 LoadBalance 时,会使用 L4 LB,当使用 Ingress 暴露服务时,会使用 L7 LB,那么他们有什么不同呢?

所谓四层负载均衡,也就是主要通过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。以常见的 TCP 为例,负载均衡设备在接收到第一个来自客户端的 SYN 请求时,即通过上述方式选择一个最佳的服务器,并对报文中的目标 IP 地址进行修改(改为后端服务器 IP),直接转发给该服务器。TCP 的连接建立,即三次握手是客户端和服务器直接建立的,负载均衡设备只是起到一个类似路由器的转发动作。在某些部署情况下,为保证服务器回包可以正确返回给负载均衡设备,在转发报文的同时可能还会对报文原来的源地址进行修改,当然大部分情况下可能不会这么做,那样的话服务器的回包可能就不会经过 LB 设备。
l4-vs-l7
所谓七层负载均衡,也称为“内容交换”,也就是主要通过报文中的真正有意义的应用层内容,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。以常见的 TCP 为例,负载均衡设备如果要根据真正的应用层内容再选择服务器,只能先和客户端建立连接(TCP 三次握手)后,才可能接收到客户端发送的真正应用层内容的报文,然后再根据该报文中的特定字段,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。负载均衡设备在这种情况下,更类似于一个代理服务器。负载均衡和前端的客户端以及后端的服务器会分别建立 TCP 连接。所以从这个技术原理上来看,七层负载均衡明显地对负载均衡设备的要求更高,处理七层的能力也必然会低于四层模式的部署方式。

L7 LB 的优点是它更加灵活,举个例子:因为它运行在 HTTP 协议栈中,所以它能知道 URL 信息,所以可以通过 URL 来作为转发规则,同时我们还可以通过 HTTP 的 X-Forwarded-For 头来获取到 HTTP 请求的 client ip。另外一个优点是更加安全,网络中最常见的 SYN Flood 攻击,即黑客控制众多源客户端,使用虚假 IP 地址对同一目标发送 SYN 攻击,通常这种攻击会大量发送 SYN 报文,耗尽服务器上的相关资源,以达到 Denial of Service(DoS) 的目的。从技术原理上也可以看出,四层模式下这些 SYN 攻击都会被转发到后端的服务器上;而七层模式下这些 SYN 攻击自然在负载均衡设备上就截止,不会影响后台服务器的正常运营。

现在的 7 层负载均衡,主要还是着重于应用广泛的 HTTP 协议,所以其应用范围主要是众多的网站或者内部信息平台等基于 B/S 开发的系统。4 层负载均衡则对应其他 TCP 应用,例如基于 C/S 开发的系统。

文章说明

更多有价值的文章均收录于贝贝猫的文章目录

stun

版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

创作声明: 本文基于下列所有参考内容进行创作,其中可能涉及复制、修改或者转换,图片均来自网络,如有侵权请联系我,我会第一时间进行删除。

参考内容

[1] kubernetes GitHub 仓库
[2] Kubernetes 官方主页
[3] Kubernetes 官方 Demo
[4] 《Kubernetes in Action》
[5] 理解Kubernetes网络之Flannel网络
[6] Kubernetes Handbook
[7] iptables概念介绍及相关操作
[8] iptables超全详解
[9] 理解Docker容器网络之Linux Network Namespace
[10] A Guide to the Kubernetes Networking Model
[11] Kubernetes with Flannel — Understanding the Networking
[12] 四层、七层负载均衡的区别

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
运维 Kubernetes 前端开发
如何用 eBPF 实现 Kubernetes 网络可观测性?实战指南
本文深入探讨了Kubernetes网络观测的挑战与eBPF技术的应用。首先分析了传统工具在数据碎片化、上下文缺失和性能瓶颈上的局限性,接着阐述了eBPF通过零拷贝观测、全链路关联和动态过滤等特性带来的优势。文章进一步解析了eBPF观测架构的设计与实现,包括关键数据结构、内核探针部署及生产环境拓扑。实战部分展示了如何构建全栈观测系统,并结合NetworkPolicy验证、跨节点流量分析等高级场景,提供具体代码示例。最后,通过典型案例分析和性能数据对比,验证了eBPF方案的有效性,并展望了未来演进方向,如智能诊断系统与Wasm集成。
591 0
|
人工智能 弹性计算 运维
ACK Edge与IDC:高效容器网络通信新突破
本文介绍如何基于ACK Edge以及高效的容器网络插件管理IDC进行容器化。
|
Kubernetes 负载均衡 网络安全
Kubernetes 网络模型与实践
【8月更文第29天】Kubernetes(K8s)是当今容器编排领域的佼佼者,它提供了一种高效的方式来管理容器化应用的部署、扩展和运行。Kubernetes 的网络模型是其成功的关键因素之一,它支持服务发现、负载均衡和集群内外通信等功能。本文将深入探讨 Kubernetes 的网络模型,并通过实际代码示例来展示服务发现和服务网格的基本概念及其实现。
712 3
|
Kubernetes Shell Windows
【Azure K8S | AKS】在AKS的节点中抓取目标POD的网络包方法分享
在AKS中遇到复杂网络问题时,可通过以下步骤进入特定POD抓取网络包进行分析:1. 使用`kubectl get pods`确认Pod所在Node;2. 通过`kubectl node-shell`登录Node;3. 使用`crictl ps`找到Pod的Container ID;4. 获取PID并使用`nsenter`进入Pod的网络空间;5. 在`/var/tmp`目录下使用`tcpdump`抓包。完成后按Ctrl+C停止抓包。
552 12
|
Kubernetes 网络协议 应用服务中间件
Kubernetes Ingress:灵活的集群外部网络访问的利器
《Kubernetes Ingress:集群外部访问的利器-打造灵活的集群网络》介绍了如何通过Ingress实现Kubernetes集群的外部访问。前提条件是已拥有Kubernetes集群并安装了kubectl工具。文章详细讲解了Ingress的基本组成(Ingress Controller和资源对象),选择合适的版本,以及具体的安装步骤,如下载配置文件、部署Nginx Ingress Controller等。此外,还提供了常见问题的解决方案,例如镜像下载失败的应对措施。最后,通过部署示例应用展示了Ingress的实际使用方法。
1113 2
|
Kubernetes 容器 Perl
Kubernetes网络插件体系及flannel基础
文章主要介绍了Kubernetes网络插件体系,特别是flannel网络模型的工作原理、配置和测试方法。
560 3
Kubernetes网络插件体系及flannel基础
|
Kubernetes 网络协议 网络安全
k8s中网络连接问题
【10月更文挑战第3天】
1309 7
|
Kubernetes 应用服务中间件 nginx
搭建Kubernetes v1.31.1服务器集群,采用Calico网络技术
在阿里云服务器上部署k8s集群,一、3台k8s服务器,1个Master节点,2个工作节点,采用Calico网络技术。二、部署nginx服务到k8s集群,并验证nginx服务运行状态。
4859 3
|
Kubernetes 容器
基于Ubuntu-22.04安装K8s-v1.28.2实验(三)数据卷挂载NFS(网络文件系统)
基于Ubuntu-22.04安装K8s-v1.28.2实验(三)数据卷挂载NFS(网络文件系统)
784 0
|
Kubernetes Cloud Native 网络安全
云原生入门指南:Kubernetes和容器化技术云计算与网络安全:技术融合的新篇章
【8月更文挑战第30天】在云计算的浪潮中,云原生技术如Kubernetes已成为现代软件部署的核心。本文将引导读者理解云原生的基本概念,探索Kubernetes如何管理容器化应用,并展示如何通过实践加深理解。

热门文章

最新文章

推荐镜像

更多