对于新读者,请参考我之前的文章。此外,建议掌握基本的网络和IP地址空间知识。它将帮助您更好地理解Kubernetes网络!
那么这篇文章实际上涵盖了什么呢?它是关于剖析Kubernetes集群的不同网络层。一个强大的平台和许多智能的设计选择一起构成了Kubernetes。但讨论真正的交互是否令人困惑?例如,POD网络、服务网络、集群IP、容器端口、主机端口、节点端口等。是的,讨论交互会使事情变得困难。但是,讨论每一个,一次一个,是有意义的!一旦理解清楚了,一切都可以合并。
为了使读者集中精力,减少工作量,我决定把文章分成三个不同的部分。第一部分包括容器和Pods。第二部分包括服务检查和对外暴露层。第三部分包括ingress和收集从集群外部进入pods的流量。
所以让我们打开所有网络层,轻松地理解它们,然后理解交互。
原子是化学元素的基本单位,细胞是生物体的基本单位,pod是kubernetes应用的基本单位。它由一个或多个容器组成。根据配置,它们并置在同一主机上,共享一个网络堆栈。他们还共享一些资源,如存储卷。在简单介绍之后,让我问你一个问题。“共享网络堆栈”是什么意思?我刚才在同一段提到过,对吗?实际上,这意味着一个pod中的容器可以在本地主机上相互连接。
例如,从上面的图片中,查看Kubernetes pod 1。它有两个container。假设container1正在运行nginx监听端口80,并在container2运行scrapyd。现在,container2可以通过http://localhost:80 访问到容器1。但是它是如何工作的呢?
在上图中,您可以看到我们有一个物理网络接口。标记为eth0,并连接到网桥上,标记为docker0。它还连接到标记为veth0的虚拟网络接口。请理解docker0和veth0在同一级别,共享同一网络。他们的网络地址是172.17.0.0/24。而他们的个人地址是:docker0为172.17.0.1,veth0为172.17.0.2。
在容器内运行的程序,只能看到veth0。但他们与外界的交流是由Docker0和eth0实现的。
在上图中,将解释下一步。第二个容器获得新的虚拟网络接口。它被称为veth1。请记住,它仍然连接到同一个Docker0网桥。分配给veth1的地址是172.17.0.3。它共享相同的逻辑网络,如网桥和container1。主要的是,两个容器都可以通过网桥进行通信。唯一的条件是他们要知道另一个容器的IP地址。
但有些东西不见了。我们还没有到达“共享网络堆栈”!幸运的是,名称空间是灵活的。因此Docker可以从一个新的容器开始,也可以创建一个新的虚拟网络接口。当然,应该指定它共享一个现有的接口。
是的,图像不一样。第二个容器似乎对veth0更感兴趣,而不是它自己的veth1。这是什么意思?首先,两个容器现在都可以从外部寻址,即172.17.0.2。从内部来说,每个端口都可以自由访问本地主机上另一个打开的端口。第二件事是,两个容器不能打开同一个端口。所以有某种限制。但是,如果我们将它与在单个主机上运行多个进程进行比较,这种情况就类似了!是同一个吗?在这里,进程享有分离和隔离容器的特权。同时,他们可以轻松协作!
Kubernetes网络系统以一种独特的方式实现了这种模式。怎样实现的呢?Kubernetes为每个pod创建一个特殊的容器。专用容器用于单个任务。它为其他容器提供网络接口。现在,ssh进入一个kubernetes集群node,该node节点可以调度的pods并运行docker。你会看到什么?至少有一个容器是用pause命令启动的!此命令将挂起当前进程。因此,除非收到信号,否则这些容器不会做任何事情。人们可以说,他们只是睡觉或进入深度睡眠。一旦kubernetes发出“SIGTERM”信号,它们就会醒来。
令人惊讶的是,这种暂停模式或“pause container”对于任何Pod都非常重要。可以说它是pod的核心!为什么呢?它提供虚拟网络接口。它将被所有容器用于内部和外部通信。
这一切都很酷,对吧?但这够了吗?一个装满容器的pod,彼此交谈,这不是唯一的事情!建立一个系统是不够的。接下来是什么?
接下来是一个pod网络系统!在接下来的文章中,我将讨论“services”。它将增强您的知识,使您更好地了解POD网络。所以你必须等待。目前,有必要讨论POD网络。让我告诉你一些非常有趣的事情。Kubernetes的主要设计要求之一是pod应能与其他pod通信。不管pods、本地主机或独立主机的位置如何,都可以进行通信。
那这一切是怎么发生的呢?为了理解它,我们需要查看集群中的node节点。在本节中,IP路由知识非常有用。
一个Kubernetes集群包含一个或多个节点。每个节点都是主机系统。它要么是虚拟的,要么是物理的,提供一个容器运行时它的依赖项,主要是Docker。它还包括许多Kubernetes系统组件。它们连接到某个网络。到群集中不同节点的连接依赖于此网络。上图是一个完整的Kubernetes集群。让我们简化一下。
另外,您不需要担心单个节点的状态,因为它们是集群的一部分。例如,如果单个节点的性能不好,那么应该有人来管理所有这些。所有节点将它们的资源集中在一起,共同构成一台强大的机器。
集群运行在云平台上。著名的云平台(如GCP或AWS)促进了单个项目环境。它是默认的网络体系结构。在图像中,专用网络地址为10.100.0.0/24。对于这个网络地址,路由器地址是10.100.0.1。两个实例地址分别为10.100.0.2和10.100.0.3。
在eth0的帮助下,每个实例都可以进行内部通信。但是要知道早期的pod,并不在私有网络上。它位于其他网络的某个网桥下。它是虚拟的,并且存在于特定节点上。
如果你看图像,左边的主机有一个eth0接口,地址为10.100.0.2,其默认网关路由器位于10.100.0.1。eth0通过网桥docker0地址为172.17.0.1与地址为172.17.0.2的接口veth0相连。
还记得pause container吗?是的,veth0接口是用pause container创建的,在所有三个容器中都可见,这在共享网络堆栈的帮助下是可能的。路由在本地路由规则的帮助下启动,这些规则是在创建网桥时创建的。因此,任何到达eth0且目的地地址为172.17.0.2的数据包都将转发到网桥。然后它将被发送到veth0。现在的路线听起来很完美。在阅读本文时,请不要忘记将其与图片联系起来。所以我们知道我们有一个172.17.0.2的pod。在这个主机上,我们应该根据我们的需求和路由器设置添加规则。接下来,这条路线将我们引向10.100.0.2。从那里,它将被转发到veth0。
您是否了解了这个路由过程呢?不过听起来很困惑!这里有一个提示,我通常在一张纸上画出这个图像,一个草图,然后追踪路由路线。
所以右边的主机也可以访问eth0。地址为10.100.0.3,并使用相同的默认网关10.100.0.1。它连接到Docker0网桥上,地址为172.17.0.1。但这里有个问题,此地址可能与host1相同,也可能不同。现在,如果所选网络不同,那么这是一个更大的问题。这里的根本问题是所有节点都不知道分配给其他节点上的网桥的专用地址空间。想象一下,如果我们给它发包,让它们到达正确的地方,会怎么样?应该需要一些结构。
是的,这里有一个解决方案Kubernetes提供了它。有两步。第一步,为每个节点上的网桥分配一个总地址空间。然后,它根据节点分配空间中的地址为网桥分配地址。第二,路由规则在10.100.0.1的网关上应用,这些规则指定了数据包是如何发送到每个网桥的,以及它们应该如何路由。那么eth0桥通过哪个node节点?这是指定的。如果您注意到了,所有这些都是虚拟网络接口、网桥和路由规则的组合。它合称为覆盖网络。
在kubernetes中它称为“pod network”。为什么叫“pod network”呢?答案很简单,它允许pods在任何node节点上通信。上图解释了这一切。在图中,“docker0”替换为“cbr”。意思是“custom bridge”。
老实说,上面提到的所有内容都是抽象的。你不需要考虑内在实现,但是理解这个概念是必须的。你甚至不知道一个pod如何与另一个pod对话!但是pod network地址显示在日志中,调试时,在某些情况下,需要显式路由网络,在那个时候,对pod network的理解将成为你的救星。
Kubernetes提供了很多自由的设置。Kubernetes用户可以自由决定和定义应用程序的运行和通信方式。用户还可以扩缩容服务、执行滚动更新、在不同应用程序版本之间切换流量等等。因此,学习如何与Kubernetes共事,享受自由。
原文地址