Kubernetes旨在在一组机器集群上运行分布式系统。分布式系统的本质使网络成为Kubernetes部署的核心和必要组成部分,并且了解Kubernetes网络模型将使您能够正确运行,监视和故障排除在Kubernetes上运行的应用程序。
网络是一个拥有许多成熟技术的广阔空间,对于不熟悉该领域的人们来说,这可能会感到不舒服,因为大多数人都对网络已有先入为主的概念,并且有很多新旧概念都可以理解并融合在一起。本文包含很多技术点,可能包括网络名称空间,虚拟接口,IP转发和网络地址转换等技术。本指南旨在通过讨论每种与Kubernetes相关的技术以及如何使用这些技术的说明来揭开Kubernetes网络神秘面纱,从而理解Kubernetes网络模型。
我们首先讨论一些基本的Kubernetes术语,以确保在整个指南中正确使用术语,然后讨论Kubernetes的网络模型以及它所施加的设计和实现决策。随后是本指南,该指南相当长,分为几个部分。本指南中最长,最有趣的部分:深入讨论如何使用几种不同的用例在Kubernetes中路由流量。
如果您不熟悉任何网络术语,则本指南附有网络术语词汇表。
1 Kubernetes 基础
Kubernetes是基于几个核心概念构建而成的,这些核心概念被组合在一起并具有越来越强大的功能。本节列出了这些概念中的每一个,并提供了简要的概述以帮助促进讨论。Kubernetes的功能远不止此处列出的内容。应该作为入门,让读者可以在后面的部分中继续学习。如果您已经熟悉Kubernetes,请随时跳过本部分。
1.1 Kubernetes API server
在Kubernetes中,一切都是由Kubernetes API服务器(kube-apiserver)提供服务的API调用。API服务器是etcd数据存储的网关,可维护您的应用程序集群的所需状态。要更新Kubernetes集群的状态,您可以对描述您所需状态的API服务器进行API调用。
1.2 Controllers
控制器是用于构建Kubernetes的核心抽象。一旦您使用API服务器声明了集群的所需状态,控制器就会通过持续观察API服务器的状态并对任何内容做出反应来确保集群的当前状态与所需状态匹配控制器中的更改通过一个简单的循环进行操作,该循环不断地根据集群的所需状态检查集群的当前状态。如果存在任何差异,控制器将执行使当前状态与所需状态匹配的任务。
while true:
X = currentState()
Y = desiredState()
if X == Y:
return # Do nothing
else:
do(tasks to get to Y)
例如,当您使用API服务器创建新的Pod时,Kubernetes调度程序(一个控制器)会注意到更改并决定将Pod放置在集群中的位置,然后使用API服务器将状态更改写入,然后,kubelet(控制器)注意到新的更改并设置了所需的网络功能,以使Pod在群集中可访问。在这里,两个单独的控制器对两个单独的状态更改做出反应,以使群集的实际情况匹配用户的意图。
1.3 Pods
Pod是Kubernetes的原子,Kubernetes是构建应用程序的最小可部署对象。单个Pod代表集群中正在运行的工作负载,并封装一个或多个Docker容器,任何必需的存储以及唯一的IP地址。被设计为位于同一机器上并位于同一位置。
1.4 Nodes
节点是运行Kubernetes集群的机器,它们可以是裸机,虚拟机或其他任何东西。主机一词通常与节点互换使用。我会尝试使用术语一致性节点,但有时会使用虚拟机一词。根据上下文引用节点。
2 The Kubernetes 网络模型
Kubernetes对于Pod网络做出了明智的选择,尤其是Kubernetes对任何网络实现都规定了以下要求:
- 所有Pod都可以与所有其他Pod通信,而无需使用网络地址转换(NAT)。
- 所有节点都可以在没有NAT的情况下与所有Pod通信。
- Pod看到自己的IP就是其他人看到的IP。
考虑到这些限制,我们剩下四个不同的网络问题要解决:
- 容器到容器网络
- Pod到Pod的网络
- Pod到服务的网络
- 互联网到服务的网络
本指南的其余部分将依次讨论这些问题及其解决方案。
3 容器到容器的网络
通常,我们将虚拟机中的网络通信视为直接与以太网设备进行交互,如图1所示。
实际上,情况比这更微妙。在Linux中,每个正在运行的进程都在网络名称空间中进行通信,该名称空间为逻辑网络堆栈提供了自己的路由,防火墙规则和网络设备。实质上,网络名称空间提供了全新的命名空间内所有进程的网络堆栈。
作为Linux用户,可以使用ip
命令创建网络名称空间。例如,以下命令将创建一个名为ns1
的新网络名称空间。
$ ip netns add ns1
创建名称空间后,将在/var/run/netns下创建该名称的挂载点,即使没有附加任何进程,名称空间也可以保留。
您可以通过列出/var/run/netns
下的所有挂载点,或使用ip
命令来列出可用的名称空间。
$ ls /var/run/netns
ns1
$ ip netns
ns1
默认情况下,Linux将每个进程分配给根网络名称空间,以提供对外部环境的访问,如图2所示。
就Docker架构而言,一个Pod被建模为一组共享网络名称空间的Docker容器。一个Pod中的容器都具有相同的IP地址和通过分配给Pod的网络名称空间分配的端口空间,并且可以通过localhost彼此找到。我们可以为虚拟机上的每个Pod创建一个网络名称空间。首先pause容器,可以理解为“Pod容器”,使网络名称空间保持打开状态,然后“应用程序容器”加入到该网络命名空间,对于Docker的话,即通过docker命令 -net = container:函数
加入该命名空间。图3显示了每个Pod如何由共享命名空间中的多个Docker容器(ctr*
)组成。
Pod中的应用程序还可以访问共享卷,共享卷定义为Pod的一部分,并可以挂载到每个应用程序的文件系统中。
4 Pod到Pod的网络
在Kubernetes中,每个Pod都有一个真实的IP地址,每个Pod都使用该IP地址与其他Pod通信。当前的任务是了解Kubernetes如何使用真实IP启用Pod到Pod的通信,无论Pod是否部署在同一主机上,我们通过考虑调度在同一台机器上的Pod来开始讨论,以避免通过内部网络进行跨节点通信的复杂性。
从Pod的角度来看,它存在于自己的以太网名称空间中,该名称空间需要与同一节点上的其他网络名称空间进行通信,幸运的是,名称空间可以使用Linux虚拟以太网设备或由两个虚拟接口组成的veth对
连接。要连接Pod名称空间,我们可以将veth对的一侧分配给根网络名称空间,另一侧分配给Pod的网络名称空间,每个veth对都像跳线一样工作,将两侧连接起来并允许流量通过它们可以在我们的计算机上复制到尽可能多的Pod。图4显示了将VM上的每个Pod连接到根名称空间的veth对。
至此,我们已经将Pod设置为每个都有自己的网络名称空间,以便他们相信自己具有自己的以太网设备和IP地址,并且已将它们连接到Node的根名称空间。通过根名称空间相互通信,为此,我们使用了网桥。
Linux以太网网桥是一种虚拟的第2层网络设备,用于将两个或多个网段结合在一起,透明地工作以将两个网络连接在一起。网桥通过检查源和目标之间的转发表并检查要传输的数据包的目标来进行操作,桥接代码通过查看网络中每个以太网设备唯一的MAC地址来决定是桥接数据还是丢弃数据。
网桥实施ARP协议以发现与给定IP地址关联的链路层MAC地址。当网桥接收到数据帧时,网桥将帧广播到所有连接的设备(原始发送方除外)和具有相同IP地址的将来流量将使用查找表来发现正确的MAC地址,以将数据包转发到该地址。
4.1 同一节点,不同Pod的数据包传输
有了将每个Pod隔离到其自己的网络堆栈的网络名称空间,将每个名称空间连接到根名称空间的虚拟以太网设备以及将名称空间连接在一起的网桥,我们终于可以在同一节点上的Pod之间发送流量了。如图6所示。
在图6中,Pod 1向其自己的以太网设备eth0
发送一个数据包,该设备可作为Pod的默认设备使用。对于Pod 1,eth0
通过虚拟以太网设备连接到根名称空间veth0
(1)。数据包到达网桥后,网桥将使用ARP协议(3)解析正确的网络段以将数据包发送至— veth1
。当数据包到达虚拟设备veth1
时,将为br配上veth0
并为其连接一个网段。它将直接转发到Pod 2的名称空间和该名称空间中的eth0设备(4)。在此通信流中,每个Pod仅与localhost上的eth0通信,并将通信路由到正确的Pod。是开发人员期望的默认行为。
Kubernetes的网络模型规定Pod必须通过其跨节点的IP地址可以访问,也就是说,Pod的IP地址对于网络中的其他Pod始终可见,并且每个Pod都将自己的IP地址视为与其他Pod相同Pod看到了,我们现在转向在不同节点上的Pod之间路由流量的问题。
4.1 不同节点,Pod到Pod的数据包传输
在确定了如何在同一节点上的Pod之间路由数据包之后,我们继续在不同节点上的Pod之间路由流量。Kubernetes网络模型要求Pod IP在整个网络上都是可访问的,但并未指定必须如何实现。实际上,这是特定于网络的,但是已经建立了一些模式来简化此过程。
通常,为群集中的每个节点分配一个CIDR块,以指定该节点上运行的Pod可用的IP地址。目的地为CIDR块的流量一旦到达该节点,则该节点负责将流量转发到正确的Pod。假设网络可以将CIDR块中的流量路由到正确的节点,则这是两个节点之间的流量。
图7以与图6相同的请求开头,除了这次,目标Pod(以绿色突出显示)与源Pod(以蓝色突出显示)位于不同的节点上。该数据包首先通过Pod 1的以太网设备发送它与根名称空间中的虚拟以太网设备配对(1)。最终,数据包最终到达根名称空间的网络桥接器(2)。ARP将在桥接器处失败,因为没有设备连接到具有正确名称的网桥数据包的MAC地址。如果发生故障,网桥会将数据包发送到默认路由-根名称空间的eth0
设备。这时,该路由离开Node进入网络(3)。我们现在假设网络可以路由根据分配给节点(4)的CIDR块将数据包发送到正确的节点。数据包进入目标节点的根名称空间(VM 2上的eth0),然后通过网桥将其路由到正确的虚拟以太网设备( 5)。最后,路线com通过流过Pod 4的命名空间(6)中的虚拟以太网设备对来完成。一般来说,每个节点都知道如何将数据包传递到其中运行的Pod。一旦数据包到达目标节点,数据包的流动方式与它们相同在同一节点上的Pod之间路由流量。
我们方便地回避了如何配置网络以将Pod IP的流量路由到负责这些IP的正确节点的过程。这是特定于网络的,但是查看特定示例将提供一些有关问题的见解,例如,借助AWS,亚马逊为Kubernetes维护了一个容器网络插件,该容器插件可使用容器网络接口(CNI)插件 在Amazon VPC环境中运行节点到节点网络。
容器网络接口(CNI)提供了用于将容器连接到外部网络的通用API。作为开发人员,我们想知道Pod可以使用IP地址与网络进行通信,并且我们希望此操作的机制透明。由AWS开发的CNI插件试图满足这些需求,同时通过AWS提供的现有VPC,IAM和安全组功能提供安全和可管理的环境,解决方案是使用弹性网络接口。
在EC2中,每个实例都绑定到一个弹性网络接口(ENI),并且所有ENI都在VPC内连接— ENI可以相互访问,而无需付出额外的努力。默认情况下,每个EC2实例都部署有单个ENI,但是您可以自由创建多个ENI并将其部署到您认为合适的EC2实例。Kubernetes的AWS CNI插件通过为部署到节点的每个Pod创建一个新的ENI来利用这种灵活性。因为VPC中的ENI已在现有内部连接在AWS基础设施上,这使得每个Pod的IP地址都可以在VPC内本地寻址。当CNI插件部署到集群时,每个Node(EC2实例)都会创建多个弹性网络接口并为这些实例分配IP地址,从而形成CIDR块部署Pods时,作为DaemonSet部署到Kubernetes集群的小型二进制文件会收到来自Nodes本地kubelet进程的将Pod添加到网络的任何请求。从节点的可用ENI池中获得可用的IP地址,并通过连接虚拟以太网设备和Linux内核中的网桥,将其分配给Pod,如在同一节点内将Pod联网时所描述的那样。
5 Pod到Service的网络
我们已经展示了如何在Pod及其关联的IP地址之间路由流量,这在我们需要处理更改之前非常有用。Pod IP地址不是持久性的,并且会随着规模的扩大或缩小,应用程序崩溃或出现而消失节点重启。这些事件中的每一个都可以使Pod IP地址更改而不会发出警告。Kubernetes中内置了服务来解决此问题。
Kubernetes服务管理一组Pod的状态,使您可以跟踪随时间动态变化的Pod IP地址集。服务充当Pod的抽象,并为一组Pod IP地址分配一个虚拟IP地址寻址到服务虚拟IP的任何流量都将被路由到与虚拟IP关联的Pod集合。这允许与服务关联的Pod集合随时更改-客户端只需要知道服务的虚拟IP,不会更改。
创建新的Kubernetes服务时,将代表您创建一个新的虚拟IP(也称为集群IP)。在集群中的任何位置,寻址到该虚拟IP的流量将负载均衡到与该虚拟IP相关联的一组支持Pod。服务实际上,Kubernetes会自动创建并维护一个分布式集群内负载均衡器,该负载均衡器将流量分配给与服务相关联的健康Pod,让我们仔细看看它是如何工作的。
5.1 netfilter 和 iptables
为了在群集内执行负载平衡,Kubernetes依赖于Linux内置的网络框架netfilter; Netfilter是Linux提供的框架,它允许以自定义处理程序的形式实现与网络相关的各种操作。数据包筛选,网络地址转换和端口转换的操作,提供了通过网络引导数据包所需的功能,并提供了禁止数据包到达计算机网络内敏感位置的功能。
iptables是一个用户空间程序,它提供了一个基于表的系统,用于定义使用netfilter框架处理和转换数据包的规则。在Kubernetes中,iptables规则由kube-proxy控制器配置,该控制器监视Kubernetes API服务器的更改。更改为服务或Pod会更新服务的虚拟IP地址或Pod的IP地址,更新iptables规则以将定向到服务的流量正确路由到后备Pod。iptables规则监视发往服务虚拟的流量IP,并从一组可用的Pod中随机选择一个Pod IP地址,并且iptables规则将数据包的目标IP地址从服务的虚拟IP更改为所选Pod的IP。换句话说,iptables已在计算机上完成了负载平衡,以将定向到服务IP的流量变为实际流量。iptables规则集已更新以反映集群状态的变化。
在返回路径上,该IP地址来自目标Pod。在这种情况下,iptables再次重写IP标头,用服务的IP替换Pod IP,以便Pod认为它一直在与服务的IP进行通信。
5.2 IPVS
Kubernetes的最新版本(1.11)包括用于集群内负载均衡的第二个选项:IPVS。IPVS(IP虚拟服务器)也基于netfilter构建,并作为Linux内核的一部分实现传输层负载均衡。集成到LVS(Linux虚拟服务器)中,它在主机上运行,并充当真实服务器群集之前的负载均衡器。IPVS可以将对基于TCP和UDP的服务的请求定向到真实服务器,并进行真实服务器的服务在单个IP地址上显示为虚拟服务,这使得IPVS自然适合Kubernetes Services。
声明Kubernetes服务时,您可以指定是否要使用iptables或IPVS完成集群内负载均衡。IPVS专为负载均衡而设计,并使用更高效的数据结构(哈希表),几乎可以无限扩展创建使用IPVS均衡的服务负载时,会发生三件事:在节点上创建虚拟IPVS接口,将服务的IP地址绑定到虚拟IPVS接口,并为每个服务IP地址创建IPVS服务器。
将来,IPVS有希望成为集群内负载均衡的默认方法。此更改仅会影响群集内负载均衡,在本指南的其余部分中,您可以安全地用IPVS替换iptables以实现集群内负载均衡影响剩下的讨论。现在让我们来看一看集群内负载均衡服务的数据包传输。
5.3 Pod到Service的数据包传输
在Pod和Service之间路由数据包时,过程以与以前相同的方式开始。数据包首先通过连接到Pod网络名称空间(1)的eth0接口离开Pod,然后通过虚拟以太网设备到达网桥(2)。网桥上运行的ARP协议不了解服务,因此它通过默认路由eth0(3)将数据包传输出去,这里发生了一些变化。在eth0接受之前,数据包是收到数据包后,iptables使用kube-proxy响应服务或Pod事件使用在节点上安装的规则,将数据包的目标从服务IP重写到特定的Pod IP(4)。现在注定要到达Pod 4而非服务的虚拟IP。iptables充分利用了Linux内核的conntrack实用程序,以记住做出的Pod选择,以便将来的流量被路由到相同的Pod(除非有任何扩展事件)。本质上,iptables直接在节点上完成了集群内负载均衡,然后使用我们已经研究过的Pod到Pod路由将流量流到Pod。
5.4 Service到Pod的数据包传输
接收到该数据包的Pod会做出响应,将源IP标识为自己的IP,将目标IP标识为最初发送该数据包的Pod(1)。进入节点后,数据包流经iptables,后者使用conntrack来记住此处先前已做出选择,并将数据包的源重写为服务的IP而不是Pod的IP(2)。从此处,数据包通过网桥流到与Pod的命名空间(3)配对的虚拟以太网设备,并到达如我们之前所见(4)。
5.5 使用DNS
Kubernetes可以选择使用DNS以避免将服务的群集IP地址硬编码到您的应用程序中。Kubernetes DNS作为在群集上部署的常规Kubernetes服务运行,它配置在每个Node上运行的kubelet,以便容器使用DNS服务的IP地址以解析DNS名称。群集中定义的每个服务(包括DNS服务器本身)都分配有DNS名称。DNS记录根据需要将DNS名称解析为服务的群集IP或POD的IP。 SRV记录用于指定运行服务的特定命名端口。
CoreDNS与kubedns的工作原理相似,但使用的插件体系结构使其更加灵活。从Kubernetes 1.11开始,CoreDNS是Kubernetes的默认DNS实现。
6 互联网到Service网络
到目前为止,我们已经研究了如何在Kubernetes集群中路由流量。在某些时候,您希望将服务公开给外部流量。此需求突出了两个相关的问题:(1)将Kubernetes服务的流量发送到Internet,以及(2)将Internet的流量发送到Kubernetes服务。
6.1 Egress — 路由流量到Internet
从节点到公共Internet的流量路由是特定于网络的,并且实际上取决于将网络配置为发布流量的方式。为了使本节更具体,我将使用AWS VPC讨论任何特定的细节。
在AWS中,Kubernetes集群在VPC内运行,其中为每个节点分配了一个私有IP地址,该IP地址可从Kubernetes集群内访问。要使从集群外的访问变得可行,请将Internet网关连接到VPC。有两个目的:在VPC路由表中为可路由到Internet的流量提供目标,并对已分配了公共IP地址的任何实例执行网络地址转换(NAT)。NAT转换负责更改节点的IP地址。集群专用的内部IP地址到公用Internet上可用的外部IP地址。
有了Internet网关后,VM可以自由地将流量路由到Internet。不幸的是,存在一个小问题:Pod拥有自己的IP地址,该IP地址与托管Pod的节点的IP地址不同。 Internet网关上的NAT转换仅适用于VM IP地址,因为它不了解哪些Pod在哪些VM上运行-网关不支持容器。让我们看看Kubernetes如何使用iptables解决这个问题(再次)。
6.1.1 Node到Internet的数据包传输
在下图中,数据包起源于Pod的名称空间(1),并经过连接到根名称空间(2)的veth对。一旦在根名称空间中,由于IP为IP,数据包从网桥移动到默认设备。在到达根名称空间的以太网设备(3)之前,iptables会处理数据包(3)。在这种情况下,数据包的源IP地址是Pod,如果将源保持为Pod,Internet网关将拒绝它,因为网关NAT仅了解连接到VM的IP地址。解决方案是让iptables执行源NAT(更改数据包源),以便数据包似乎即将到来从虚拟机而不是Pod。有了正确的源IP,数据包现在可以离开虚拟机(4)到达Internet网关(5)。Internet网关将执行另一个NAT,从VM内部重写源IP IP到外部IP。通常,数据包将到达公共Internet(6)。在回程中,数据包遵循相同的路径,并且任何源IP处理都将被撤消,以便系统的每一层都接收其能够理解的IP地址:VM-internal位于节点或VM级别,以及Pod名称空间中的Pod IP。
6.2 Ingress — 路由Internet流量到Kubernetes
Ingress(将流量传入您的集群)是一个非常棘手的问题,同样,它特定于您所运行的网络,但总的来说,Ingress分为两种解决方案,它们可在网络堆栈的不同部分工作:(1 )Service LoadBalancer和(2)Ingress controller。
6.2.1 4层: LoadBalancer
创建Kubernetes服务时,可以选择指定一个LoadBalancer来配合使用。LoadBalancer的实现由知道如何为服务创建负载平衡器的云控制器提供。创建服务后,它将发布负载平衡器的IP地址。作为最终用户,您可以开始将流量定向到负载平衡器,以开始与服务进行通信。
借助AWS,负载均衡器可以了解其目标组中的节点,并将平衡群集中所有节点上的流量。一旦流量到达节点,先前在整个群集中为您的服务安装的iptables规则将确保流量到达Pod您感兴趣的服务。
6.2.2 LoadBalancer到Service数据包传输
让我们看一下它是如何工作的。一旦部署了服务,您正在使用的云提供商将为您创建一个新的负载均衡器(1)。由于负载均衡器不支持容器,因此一旦流量达到负载-balancer,它分布在组成群集的所有VM中(2)。每个VM上的iptables规则会将来自负载均衡器的传入流量定向到正确的Pod(3)-这些是与IP规则相同的规则在服务创建过程中(前面已经讨论过)。从Pod到客户端的响应将返回Pod的IP,但是客户端需要具有负载均衡器的IP地址.iptables和conntrack用于在返回路径上正确地重写IP,例如我们之前看到了。
下图显示了在托管Pods的三个VM之前的网络负载平衡器,传入流量(1)定向到Service的负载平衡器。一旦负载平衡器收到数据包(2),它将随机选择一个VM。在这种情况下,我们从病理上选择了没有运行Pod的VM:VM 2(3)。在此,在VM上运行的iptables规则将使用安装到群集中的内部负载平衡规则将数据包定向到正确的Pod。 kube-proxy.iptables执行正确的NAT,并将数据包转发到正确的Pod(4)。
6.2.3 7层: Ingress Controller
第7层网络Ingress在网络堆栈的HTTP/HTTPS协议范围内运行,并且构建在服务之上。启用Ingress的第一步是使用Kubernetes中的NodePort服务类型在服务上打开端口。服务的类型字段到NodePort,Kubernetes主服务器将在您指定的范围内分配一个端口,并且每个Node都会将该端口(每个Node上的相同端口号)代理到您的Service中,也就是说,任何定向到Node端口的流量都会服务到Pod的路由遵循了我们已经在将流量从服务路由到Pod时使用iptables规则转发到服务时使用的内部集群负载均衡模式。
若要将Node的端口暴露给Internet,请使用Ingress对象.Ingress是将HTTP请求映射到Kubernetes Services的高级HTTP负载均衡器.Ingress方法将有所不同,具体取决于Kubernetes云提供商控制器如何实现HTTP负载平衡器(像第4层网络负载平衡器一样)仅了解节点IP(而非Pod IP),因此流量路由同样利用kube-proxy在每个节点上安装的iptables规则提供的内部负载均衡。
在AWS环境中,ALB入口控制器使用Amazon的第7层应用程序负载平衡器提供Kubernetes入口,下图详细说明了该控制器创建的AWS组件,还演示了入口流量从ALB到Kubernetes集群的路线。
创建后,(1)Ingress Controller监视来自Kubernetes API服务器的Ingress事件,当发现满足其要求的Ingress资源时,便开始创建AWS资源.AWS使用Application Load Balancer(ALB)(2)负载均衡器与用于将请求路由到一个或多个已注册节点的目标组协同工作。(3)在AWS中为入口资源描述的每个唯一的Kubernetes服务创建了目标组。(4)一个侦听器是ALB进程使用您配置的协议和端口检查连接请求。Ingress控制器为Ingress资源注释中详细说明的每个端口创建侦听器。最后,为Ingress资源中指定的每个路径创建目标组规则。这样可以确保将到特定路径的流量路由到正确的Kubernetes服务(5)。
6.2.4 Ingress到Service数据包传输
流经Ingress的数据包的传输与LoadBalancer的传输非常相似,主要区别在于Ingress知道URL的路径(允许并可以根据其路径将流量路由到服务)以及初始连接入口和节点之间的连接是通过每个服务在节点上公开的端口实现的。
让我们看一下它在实际中是如何工作的。一旦部署了服务,您正在使用的云提供商将为您创建一个新的Ingress负载均衡器(1)。由于负载均衡器不支持容器,因此一旦流量到达负载均衡器,它通过服务的公告端口分布在组成群集(2)的所有VM上。每个VM上的iptables规则会将来自负载均衡器的传入流量定向到正确的Pod(3)-如我们所见从Pod到客户端的响应将随Pod的IP返回,但是客户端需要具有负载均衡器的IP地址。iptables和conntrack用于正确地在返回路径上重写IP,如我们之前所见。
第7层负载平衡器的优点之一是它们可以识别HTTP,因此可以了解URL和路径,这使您可以按URL路径对服务流量进行细分。它们通常还可以在X-Forwarded中提供原始客户端的IP地址。 -对于HTTP请求的标头。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。