云原生之深入解析Kubernetes的网络模型

news2024/12/22 14:31:56

一、前言

  • Kubernetes 是为运行分布式集群而建立的,分布式系统的本质使得网络成为 Kubernetes 的核心和必要组成部分,了解 Kubernetes 网络模型可以使你能够正确运行、监控和排查应用程序故障。
  • 网络所涉及的内容很多,拥有许多成熟的技术。对于不熟悉的人来说可能会非常痛苦,因为大多数人对网络都有先入为主的观念,并且有很多新旧概念需要理解并组合成一个连贯的整体,因此的网络可能包括网络命名空间、虚拟接口、IP 转发和网络地址转换等技术。本文旨在通过讨论每种 Kubernetes 相关技术以及如何使用这些技术来启用 Kubernetes 网络模型的描述来揭开 Kubernetes 网络的神秘面纱。

二、Kubernetes 基础知识

① Kubernetes API server

  • 在 Kubernetes 中,一切都是由 Kubernetes API 服务器(kube-apiserver)提供的 API 调用。API 服务器是 etcd 数据存储的网关,它维护应用程序集群的所需状态。
  • 要更新 Kubernetes 集群的状态,可以对描述所需状态的 API 服务器进行 API 调用。

② 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 服务器(由 etcd 支持)写入状态更改。kubelet(一个控制器)然后会注意到新的变化并设置所需的网络功能以使 Pod 在集群内可访问。在这里,两个独立的控制器对两个独立的状态变化做出反应,以使集群的现实与用户的意图相匹配。

③ Pods

  • Pod 是 Kubernetes 的原子——用于构建应用程序的最小可部署对象。单个 Pod 代表集群中正在运行的工作负载,并封装了一个或多个 Docker 容器、任何所需的存储和唯一的 IP 地址,组成 pod 的容器被设计为在同一台机器上共同定位和调度。

④ Nodes

  • 节点是运行 Kubernetes 集群的机器,这些可以是裸机、虚拟机或其他任何东西,主机一词通常与节点互换使用。

二、Kubernetes 网络模型

  • Kubernetes 对 Pod 的联网方式做出了自以为是的选择,特别是 Kubernetes 对任何网络实现都规定了以下要求:
    • 所有 Pod 都可以在不使用网络地址转换 (NAT) 的情况下与所有其他 Pod 通信;
    • 所有节点都可以在没有 NAT 的情况下与所有 Pod 通信;
    • Pod 认为自己的 IP 与其他人认为的 IP 相同。
  • 鉴于这些限制,需要解决四个不同的网络问题:
    • 容器到容器网络;
    • Pod 到 Pod 网络;
    • Pod 到服务网络;
    • Internet 到服务网络。

三、容器和容器之间网络通信

  • 通常,将虚拟机中的网络通信视为直接与以太网设备交互,如下所示:

在这里插入图片描述

  • 实际上,情况比这更微妙,在 Linux 中,每个正在运行的进程都在一个网络命名空间内进行通信,该命名空间为逻辑网络堆栈提供了自己的路由、防火墙规则和网络设备。本质上,网络命名空间为命名空间内的所有进程提供了一个全新的网络堆栈。作为 Linux 用户,可以使用 ip 命令创建网络命名空间。
  • 例如,以下命令将创建一个名为 ns1 的新网络命名空间:
$ ip netns add ns1
  • 创建命名空间时,会在 /var/run/netns 下为其创建一个挂载点,即使没有附加任何进程,命名空间也可以保留。可以通过列出 /var/run/netns 下的所有挂载点或使用 ip 命令来列出可用的命名空间:
$ ls /var/run/netns
ns1
$ ip netns
ns1
  • 默认情况下,Linux 将每个进程分配给根网络命名空间以提供对外部世界的访问,如下所示:

请添加图片描述

  • 就 Docker 结构而言,Pod 被建模为一组共享网络命名空间的 Docker 容器。Pod 中的容器都具有相同的 IP 地址和端口空间,这些 IP 地址和端口空间是通过分配给 Pod 的网络命名空间分配的,并且可以通过 localhost 找到彼此,因为它们位于同一个命名空间中。我们可以为虚拟机上的每个 Pod 创建一个网络命名空间,这是使用 Docker 作为“Pod 容器”实现的,它保持网络命名空间打开,而“应用容器”(用户指定的东西)通过 Docker 的 –net=container: 函数加入该命名空间。图 3 显示了每个 Pod 如何由共享命名空间内的多个 Docker 容器 (ctr*) 组成:

请添加图片描述

  • Pod 中的应用程序还可以访问共享卷,这些卷被定义为 Pod 的一部分,并且可以挂载到每个应用程序的文件系统中。

四、Pod 和 Pod 之间网络通信

  • 在 Kubernetes 中,每个 Pod 都有一个真实的 IP 地址,并且每个 Pod 都使用该 IP 地址与其他 Pod 通信。现在任务是了解 Kubernetes 如何使用真实 IP 实现 Pod 到 Pod 的通信,无论 Pod 部署在集群中的同一个物理节点还是不同的节点上,可以通过考虑驻留在同一台机器上的 Pod 来开始讨论,以避免通过内部网络跨节点通信的复杂性。
  • 从 Pod 的角度来看,它存在于自己的以太网命名空间中,需要与同一节点上的其他网络命名空间进行通信。值得庆幸的是,可以使用 Linux 虚拟以太网设备或由两个虚拟接口组成的 veth 对连接命名空间,这些虚拟接口可以分布在多个命名空间上。要连接 Pod 命名空间,可以将 veth 对的一侧分配给根网络命名空间,将另一侧分配给 Pod 的网络命名空间。每对 veth 对的工作方式就像一根跳线,连接两侧并允许流量在它们之间流动,这个设置可以复制到机器上的尽可能多的 Pod。
  • 如下所示,显示了将 VM 上的每个 Pod 连接到根命名空间的 veth 对:

请添加图片描述

  • 此时,已将 Pod 设置为每个都有自己的网络命名空间,以便它们相信自己拥有自己的以太网设备和 IP 地址,并且它们连接到节点的根命名空间,现在希望 Pod 通过根命名空间相互通信,为此我们使用网桥。
  • Linux 以太网网桥是一个虚拟的第 2 层网络设备,用于联合两个或多个网段,透明地工作以将两个网络连接在一起。网桥通过检查通过它的数据包的目的地并决定是否将数据包传递到连接到网桥的其他网段来维护源和目标之间的转发表来运行,桥接代码通过查看网络中每个以太网设备的唯一 MAC 地址来决定是桥接数据还是丢弃数据。
  • 网桥实现 ARP 协议以发现与给定 IP 地址关联的链路层 MAC 地址,当网桥接收到数据帧时,网桥将帧广播到所有连接的设备(原始发送者除外),响应该帧的设备存储在查找表中, 具有相同 IP 地址的未来流量使用查找表来发现将数据包转发到的正确 MAC 地址。

在这里插入图片描述

① 同节点 Pod 通信

  • 给定将每个 Pod 与自己的网络堆栈隔离的网络命名空间、将每个命名空间连接到根命名空间的虚拟以太网设备以及将命名空间连接在一起的网桥,终于准备好在同一节点上的 Pod 之间进行通信,如下所示:

在这里插入图片描述

  • 在上图中,Pod 1 将数据包发送到它自己的以太网设备 eth0,该设备可用作 Pod 的默认设备。对于 Pod 1,eth0 通过虚拟以太网设备连接到根命名空间 veth0 (1),网桥 cbr0 配置有 veth0 连接到它的网段。一旦数据包到达网桥,网桥会解析正确的网段以使用 ARP 协议将数据包发送到 veth1 (3)。当数据包到达虚拟设备 veth1 时,它被直接转发到 Pod 2 的命名空间和该命名空间内的 eth0 设备 (4)。在整个流量流中,每个 Pod 仅与 localhost 上的 eth0 通信,并且流量被路由到正确的 Pod。使用网络的开发体验是开发人员所期望的默认行为。
  • Kubernetes 的网络模型规定 Pod 必须可以通过其 IP 地址跨节点访问。也就是说,一个 Pod 的 IP 地址始终对网络中的其他 Pod 可见,每个 Pod 看待自己的 IP 地址的方式与其他 Pod 看待它的方式相同。

② 跨节点 Pod 通信

  • 了解了在同一节点上的 Pod 之间如何进行通信之后,继续研究在不同节点上的 Pod 如何进行通信,Kubernetes 网络模型要求 Pod IP 可以通过网络访问,但它没有指定必须如何完成。
  • 通常,集群中的每个节点都分配有一个 CIDR 块,指定该节点上运行的 Pod 可用的 IP 地址。一旦流向 CIDR 块的流量到达节点,节点就有责任将流量转发到正确的 Pod,如下所示说明了两个节点之间的流量流,假设网络可以将 CIDR 块中的流量路由到正确的节点:

在这里插入图片描述

  • 在上面的图和同节点 Pod 通信的示例图相同的请求开始,但这次,目标 Pod(以绿色突出显示)与源 Pod(以蓝色突出显示)位于不同的节点上。数据包首先通过 Pod 1 的以太网设备发送,该设备与根命名空间 (1) 中的虚拟以太网设备配对。最终,数据包最终到达根命名空间的网桥 (2)。ARP 将在网桥上失败,因为没有设备连接到网桥并具有正确的数据包 MAC 地址。失败时,网桥将数据包发送到默认路由——根命名空间的 eth0 设备。此时路由离开节点并进入网络 (3)。现在假设网络可以根据分配给节点的 CIDR 块将数据包路由到正确的节点 (4),数据包进入目标节点的根命名空间(VM 2 上的 eth0),在那里它通过网桥路由到正确的虚拟以太网设备 (5),最后路由通过位于 Pod 4 的命名空间 (6) 中的虚拟以太网设备对来完成。
  • 一般来说,每个节点都知道如何将数据包传递给在其中运行的 Pod,一旦数据包到达目标节点,数据包的流动方式与在同一节点上的 Pod 之间路由流量的方式相同。我们轻松地避开了如何配置网络以将 Pod IP 的流量转发到负责这些 IP 的正确节点,这是特定于网络的,但查看特定示例将提供对所涉及问题的一些见解。例如,借助 AWS,Amazon 为 Kubernetes 维护了一个容器网络插件,允许节点到节点网络使用容器网络接口 (CNI) 插件 在 Amazon VPC 环境中运行 -vpc-cni-k8s)。
  • 容器网络接口 (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 插件部署到集群时,每个节点(EC2 实例)都会创建多个弹性网络接口并为这些实例分配 IP 地址,从而为每个节点形成一个 CIDR 块。部署 Pod 时,作为 DaemonSet 部署到 Kubernetes 集群的小型二进制文件会从 Nodes 本地 kubelet 进程接收任何将 Pod 添加到网络的请求。这个二进制文件从节点的可用 ENI 池中选择一个可用的 IP 地址,并通过在 Linux 内核中连接虚拟以太网设备和网桥将其分配给 Pod,如在同一节点内联网 Pod 时所述。有了这个,Pod 流量就可以跨集群内的节点路由。

五、Pod 和 Service 之间网络通信

  • 上文中已经如何在 Pod 及其关联的 IP 地址之间路由转发,在需要应对变化之前,这很有效。Pod IP 地址不是持久的,并且会随着扩展或缩减、应用程序崩溃或节点重启而出现和消失,这些事件中的每一个都可以使 Pod IP 地址在没有警告的情况下更改,Service被内置到 Kubernetes 中来解决这个问题。
  • Kubernetes Service 管理一组 Pod 的状态,允许跟踪一组随时间动态变化的 Pod IP 地址。Service充当对 Pod 的抽象,并将单个虚拟 IP 地址分配给一组 Pod IP 地址,任何发往 Service 虚拟 IP 的流量都将被转发到与虚拟 IP 关联的 Pod 集,这允许与 Service 关联的 Pod 集随时更改——客户端只需要知道 Service 的虚拟 IP即可,它不会更改。
  • 创建新的 Kubernetes Service时,会创建一个新的虚拟 IP(也称为集群 IP),在集群中的任何地方,发往虚拟 IP 的流量都将负载均衡到与服务关联的一组支持 Pod。实际上,Kubernetes 会自动创建并维护一个分布式集群内负载均衡器,将流量分配到服务相关联的健康 Pod。

① netfilter 和 iptables

  • 为了在集群中执行负载平衡,Kubernetes 依赖于 Linux 内置的网络框架 Netfilter。Netfilter 是 Linux 提供的一个框架,它允许以自定义处理程序的形式实现各种与网络相关的操作。Netfilter 为数据包过滤、网络地址转换和端口转换提供了各种功能和操作,它们提供了引导数据包通过网络所需的功能,以及提供禁止数据包到达计算机网络中敏感位置的能力。
  • iptables 是一个用户空间程序,它提供了一个基于表的系统,用于定义使用 netfilter 框架操作和转换数据包的规则。在 Kubernetes 中,iptables 规则由 kube-proxy 控制器配置,该控制器监视 Kubernetes API 服务器的更改。当对 Service 或 Pod 的更改更新 Service 的虚拟 IP 地址或 Pod 的 IP 地址时,iptables 规则会更新以正确地将指向 Service 的流量转发到正确的Pod。iptables 规则监视发往 Service 的虚拟 IP 的流量,并且在匹配时,从可用 Pod 集中选择一个随机 Pod IP 地址,并且 iptables 规则将数据包的目标 IP 地址从 Service 的虚拟 IP 更改为选定的 Pod。当 Pod 启动或关闭时,iptables 规则集会更新以反映集群不断变化的状态。换句话说,iptables 已经在机器上进行了负载平衡,以将定向到服务 IP 的流量转移到实际 pod 的 IP。
  • 在返回路径上,IP 地址来自目标 Pod。在这种情况下,iptables 再次重写 IP 标头以将 Pod IP 替换为 Service 的 IP,以便 Pod 认为它一直只与 Service 的 IP 通信。

② IPVS

  • Kubernetes 的最新版本 (1.11) 包括用于集群内负载平衡的第二个选项:IPVS。IPVS(IP 虚拟服务器)也构建在 netfilter 之上,并将传输层负载平衡作为 Linux 内核的一部分实现。IPVS 被合并到 LVS(Linux 虚拟服务器)中,它在主机上运行并充当真实服务器集群前面的负载平衡器。IPVS 可以将基于 TCP 和 UDP 的服务的请求定向到真实服务器,并使真实服务器的服务在单个 IP 地址上表现为虚拟服务。这使得 IPVS 非常适合 Kubernetes 服务。
  • 声明 Kubernetes Service时,您可以指定是否希望使用 iptables 或 IPVS 完成集群内负载平衡。IPVS 专为负载平衡而设计,并使用更高效的数据结构(哈希表),与 iptables 相比允许几乎无限的规模。在使用 IPVS 创建负载均衡的 Service 时,会发生三件事:在 Node 上创建一个虚拟 IPVS 接口,将 Service 的 IP 地址绑定到虚拟 IPVS 接口,并为每个 Service IP 地址创建 IPVS 服务器。
  • 未来,IPVS 有望成为集群内负载均衡的默认方法。此更改仅影响集群内负载平衡,并且在本指南的其余部分中,您可以安全地将 iptables 替换为 IPVS 以实现集群内负载平衡,而不会影响其余讨论。

③ Pod 和 Service 通信

在这里插入图片描述

  • 在上图中 Pod 和 Service 之间路由数据包时,与以前相同的方式开始,数据包首先通过连接到 Pod 的网络命名空间 (1) 的 eth0 接口离开 Pod,然后它通过虚拟以太网设备到达网桥 (2)。网桥上运行的 ARP 协议不知道 Service,因此它通过默认路由 eth0 (3) 将数据包传输出去。在这里,发生了一些不同的事情。在 eth0 接受之前,数据包会通过 iptables 过滤。iptables 收到数据包后,使用 kube-proxy 安装在 Node 上的规则响应 Service 或 Pod 事件,将数据包的目的地从 Service IP 重写为特定的 Pod IP(4)。数据包现在注定要到达 Pod 4,而不是服务的虚拟 IP。iptables 利用 Linux 内核的 conntrack 实用程序来记住所做的 Pod 选择,以便将来的流量路由到同一个 Pod(除非发生任何扩展事件)。本质上,iptables 直接在 Node 上做了集群内负载均衡。然后流量使用我们已经检查过的 Pod 到 Pod 路由流向 Pod (5)。

④ Service 和 Pod 通信

在这里插入图片描述

  • 在上图中的收到此数据包的 Pod 将响应,将源 IP 识别为自己的 IP,将目标 IP 识别为最初发送数据包的 Pod (1)。进入节点后,数据包流经 iptables,它使用 conntrack 记住它之前所做的选择,并将数据包的源重写为服务的 IP 而不是 Pod 的 IP (2)。从这里开始,数据包通过网桥流向与 Pod 的命名空间配对的虚拟以太网设备 (3),然后流向我们之前看到的 Pod 的以太网设备 (4)。

⑤ 使用 DNS

  • Kubernetes 可以选择使用 DNS 来避免将服务的集群 IP 地址硬编码到您的应用程序中。Kubernetes DNS 作为在集群上调度的常规 Kubernetes 服务运行。它配置在每个节点上运行的 kubelet,以便容器使用 DNS 服务的 IP 来解析 DNS 名称。集群中定义的每个服务(包括 DNS 服务器本身)都被分配了一个 DNS 名称。DNS 记录将 DNS 名称解析为服务的集群 IP 或 POD 的 IP,具体取决于需求,SRV 记录用于指定运行服务的特定命名端口。
  • DNS Pod 由三个独立的容器组成:
    • kubedns:监视 Kubernetes 主服务器的服务和端点变化,并维护内存中的查找结构以服务 DNS 请求;
    • dnsmasq:添加 DNS 缓存以提高性能;
    • sidecar:提供一个单一的健康检查端点来执行 dnsmasq 和 kubedns 的健康检查。
  • DNS Pod 本身作为 Kubernetes 服务公开,具有静态集群 IP,该 IP 在启动时传递给每个正在运行的容器,以便每个容器都可以解析 DNS 条目。DNS 条目通过维护内存中 DNS 表示的 kubedns 系统解析。etcd 是集群状态的后端存储系统,kubedns 使用一个库将 etcd 键值存储转换为 DNS 整体,以便在必要时重建内存中 DNS 查找结构的状态。
  • CoreDNS 与 kubedns 的工作方式类似,但使用插件架构构建,使其更加灵活。从 Kubernetes 1.11 开始,CoreDNS 是 Kubernetes 的默认 DNS 实现。

六、Internet 和 Service 之间网络通信

① Egress- 将 Kubernetes 流量转发到 Internet

  • 从节点到公共 Internet 的流量转发是特定于网络的,并且实际上取决于您的网络如何配置以发布流量。在 AWS 中,Kubernetes 集群在 VPC 中运行,其中每个节点都分配有一个私有 IP 地址,该地址可从 Kubernetes 集群内访问。要从集群外部访问流量,您需要将 Internet 网关连接到您的 VPC。
  • Internet 网关有两个用途:在 VPC 路由表中为可路由到 Internet 的流量提供目标,以及为已分配公共 IP 地址的任何实例执行网络地址转换 (NAT)。NAT 转换负责将集群专用的节点内部 IP 地址更改为公共 Internet 中可用的外部 IP 地址。
  • 有了 Internet 网关,VM 就可以自由地将流量路由到 Internet。不幸的是,有一个小问题,Pod 有自己的 IP 地址,与托管 Pod 的节点的 IP 地址不同,并且 Internet 网关的 NAT 转换仅适用于 VM IP 地址,因为它不知道 Pod 正在运行什么哪些虚拟机,网关不支持容器。
  • 在下图中,数据包源自 Pod 的命名空间 (1),并经过连接到根命名空间 (2) 的 veth 对:

在这里插入图片描述

  • 一旦进入根命名空间,数据包就会从网桥移动到默认设备,因为数据包上的 IP 与连接到网桥的任何网段都不匹配。在到达根命名空间的以太网设备 (3) 之前,iptables 会破坏数据包 (3)。在这种情况下,数据包的源 IP 地址是 Pod,如果我们将源保留为 Pod,Internet 网关将拒绝它,因为网关 NAT 只了解连接到 VM 的 IP 地址。解决方案是让 iptables 执行源 NAT,更改数据包源使数据包看起来来自 VM 而不是 Pod。有了正确的源 IP,数据包现在可以离开 VM (4) 并到达 Internet 网关 (5)。Internet 网关将执行另一个 NAT,将源 IP 从 VM 内部 IP 重写为外部 IP。最后,数据包将到达公共 Internet (6)。在返回的路上,数据包遵循相同的路径,并且任何源 IP 修改都被撤消,以便系统的每一层都接收到它理解的 IP 地址:节点或 VM 级别的 VM 内部,以及 Pod 内的 Pod IP命名空间。

② Ingress- 将 Internet 流量转发到 Kubernetes

  • 这是特定于正在运行的网络的,但一般来说,Ingress 分为两种解决方案,适用于网络堆栈的不同部分:服务负载平衡器和入口控制。
  • 四层转发 -Loadbalancer:当创建一个 Kubernetes 服务时,可以选择指定一个 LoadBalancer 来配合它,LoadBalancer 的实现由知道如何为服务创建负载均衡器的云控制器提供;创建服务后,它将公布负载均衡器的 IP 地址,作为最终用户,可以开始将流量引导到负载均衡器以开始与服务通信。借助 AWS,负载均衡器可以了解其目标组中的节点,并将平衡集群中所有节点的流量。一旦流量到达一个节点,之前为您的服务在整个集群中安装的 iptables 规则将确保流量到达您感兴趣的服务的 Pod。
  • Loadbalancer 和 Service 通信:来看看这在实践中是如何工作的,部署服务后,正在使用的云提供商将创建一个新的负载均衡器 (1),因为负载均衡器不支持容器,所以一旦流量到达负载均衡器,它就会分布在组成集群的所有虚拟机中 (2)。每个 VM 上的 iptables 规则会将来自负载均衡器的传入流量引导到正确的 Pod (3) — 这些是在服务创建期间实施并在前面讨论过的相同 IP 表规则。Pod 到客户端的响应将返回 Pod 的 IP,但客户端需要有负载均衡器的 IP 地址。正如之前看到的,iptables 和 conntrack 用于在返回路径上正确重写 IP。
  • 如下图所示,显示了托管 Pod 的三个 VM 前面的网络负载均衡器,传入流量 (1) 指向服务的负载均衡器,一旦负载均衡器收到数据包 (2),它就会随机选择一个 VM。在这种情况下,我们病态地选择了没有运行 Pod 的 VM:VM 2 (3)。在这里,运行在 VM 上的 iptables 规则将使用 kube-proxy 安装到集群中的内部负载平衡规则将数据包定向到正确的 Pod,iptables 执行正确的 NAT 并将数据包转发到正确的 Pod (4):

在这里插入图片描述

③ 七层转发 -Ingress Controller

  • 第 7 层网络 Ingress 在网络堆栈的 HTTP/HTTPS 协议范围内运行,并构建在 Services 之上。启用 Ingress 的第一步是使用 Kubernetes 中的 NodePort 服务类型在您的服务上打开一个端口,如果将 Service 的 type 字段设置为 NodePort,Kubernetes master 将从您指定的范围内分配一个端口,并且每个 Node 都会将该端口(每个 Node 上的相同端口号)代理到您的 Service 中。也就是说,任何指向节点端口的流量都将使用 iptables 规则转发到服务。这个 Service 到 Pod 的路由遵循我们在将流量从 Service 路由到 Pod 时已经讨论过的相同的内部集群负载平衡模式。
  • 要向 Internet 公开节点的端口,需要使用 Ingress 对象,Ingress 是一个更高级别的 HTTP 负载均衡器,它将 HTTP 请求映射到 Kubernetes 服务,Ingress 方法将根据 Kubernetes 云提供商控制器的实现方式而有所不同。HTTP 负载均衡器,如第 4 层网络负载均衡器,仅了解节点 IP(而不是 Pod IP),因此流量路由同样利用由 kube-proxy 安装在每个节点上的 iptables 规则提供的内部负载均衡。
  • 在 AWS 环境中,ALB 入口控制器使用 Amazon 的第 7 层应用程序负载均衡器提供 Kubernetes 入口。如下图,介绍了此控制器创建的 AWS 组件,并且还演示了 Ingress 流量从 ALB 到 Kubernetes 集群的路由:

在这里插入图片描述

  • 创建后:
    • (1) Ingress Controller 监视来自 Kubernetes API 服务器的 Ingress 事件,当它找到满足其要求的 Ingress 资源时,它会开始创建 AWS 资源,AWS 将 Application Load Balancer (ALB);
    • (2) 用于 Ingress 资源,负载均衡器与用于将请求路由到一个或多个注册节点的目标组一起工作;
    • (3) 在 AWS 中为 Ingress 资源描述的每个唯一 Kubernetes 服务创建目标组;
    • (4) Listener 是一个 ALB 进程,它使用您配置的协议和端口检查连接请求,侦听器由 Ingress 控制器为您的 Ingress 资源注释中详述的每个端口创建;
    • (5) 为 Ingress 资源中指定的每个路径创建目标组规则,这确保了到特定路径的流量被路由到正确的 Kubernetes 服务 。

④ Ingress 和 Service 通信

  • 流经 Ingress 的数据包的生命周期与 LoadBalancer 的生命周期非常相似,主要区别在于 Ingress 知道 URL 的路径(允许并可以根据路径将流量路由到服务),并且 Ingress 和 Node 之间的初始连接是通过 Node 上为每个服务公开的端口。
  • 让我们来看看这在实践中是如何工作的,部署服务后,您正在使用的云提供商将为您创建一个新的 Ingress 负载均衡器 (1)。由于负载均衡器不支持容器,因此一旦流量到达负载均衡器,它就会通过为您的服务提供的广告端口分布在组成集群 (2) 的整个 VM 中。每个 VM 上的 iptables 规则会将来自负载均衡器的传入流量引导到正确的 Pod (3) — 正如我们之前所见。Pod 到客户端的响应将返回 Pod 的 IP,但客户端需要有负载均衡器的 IP 地址。
  • 正如之前看到的,iptables 和 conntrack 用于在返回路径上正确重写 IP:

在这里插入图片描述

  • 第 7 层负载均衡器的一个好处是它们可以识别 HTTP,因此它们知道 URL 和路径。这使可以按 URL 路径对服务流量进行分段,它们通常还在 HTTP 请求的 X-Forwarded-For 标头中提供原始客户端的 IP 地址。

七、网络术语

  • 二层网络:第 2 层是提供节点到节点数据传输的数据链路层,它定义了在两个物理连接的设备之间建立和终止连接的协议,还定义了它们之间的流量控制协议。
  • 四层网络:传输层通过流量控制控制给定链路的可靠性,在 TCP/IP 中,这一层是指用于在不可靠网络上交换数据的 TCP 协议。
  • 七层网络:应用层是最接近最终用户的层,这意味着应用层和用户都直接与软件应用程序交互,该层与实现通信组件的软件应用程序交互,通常,第 7 层网络是指 HTTP。
  • Nat 网络地址转换:
    • NAT 或网络地址转换是将一个地址空间重新映射到另一个地址空间的 IP 级别,映射通过在数据包通过流量路由设备传输时修改数据包的 IP 标头中的网络地址信息来实现;
    • 基本 NAT 是从一个 IP 地址到另一个 IP 地址的简单映射,更常见的是,NAT 用于将多个私有 IP 地址映射到一个公开的 IP 地址。
    • 通常,本地网络使用私有 IP 地址空间,并且该网络上的路由器在该空间中被赋予私有地址,然后路由器使用公共 IP 地址连接到 Internet,当流量从本地网络传递到 Internet 时,每个数据包的源地址都从私有地址转换为公共地址,这使得请求看起来好像直接来自路由器;
    • 路由器维护连接跟踪,以将回复转发到本地网络上的正确专用 IP,NAT 提供了一个额外的好处,即允许大型专用网络使用单个公共 IP 地址连接到 Internet,从而节省公共使用的 IP 地址的数量。
    • snat-源地址转换:SNAT 只是指修改 IP 数据包源地址的 NAT 过程。这是上述 NAT 的典型行为。
    • dnat-目标地址转换:DNAT 是指修改 IP 数据包的目的地址的 NAT 过程。DNAT 用于将位于专用网络中的服务发布到可公开寻址的 IP 地址。
  • 网络名称空间:
    • 在网络中,每台机器(真实的或虚拟的)都有一个以太网设备(eth0),所有流入和流出机器的流量都与该设备相关联。事实上,Linux 将每个以太网设备与一个网络命名空间相关联,整个网络堆栈的逻辑副本,以及它自己的路由、防火墙规则和网络设备。
    • 最初,所有进程共享来自 init 进程的相同默认网络命名空间,称为根命名空间。默认情况下,进程从其父进程继承其网络命名空间,因此,如果不进行任何更改,所有网络流量都会流经为根网络命名空间指定的以太网设备。
  • veth 虚拟网卡对:
    • 计算机系统通常由一个或多个网络设备(eth0、eth1 等)组成,这些设备与负责将数据包放置到物理线路上的物理网络适配器相关联;
    • Veth 设备是虚拟网络设备,始终以互连的对创建,它们可以充当网络命名空间之间的隧道,以创建到另一个命名空间中的物理网络设备的桥接,但也可以用作独立的网络设备,可以将 veth 设备视为设备之间的虚拟跳线一端连接的设备将连接另一端。
  • 网络桥接:网桥是从多个通信网络或网段创建单个聚合网络的设备,桥接连接两个独立的网络,就好像它们是一个网络一样,桥接使用内部数据结构来记录每个数据包发送到的位置,以作为性能优化。
  • CIDR:
    • CIDR 是一种分配 IP 地址和执行 IP 路由的方法,对于 CIDR,IP 地址由两组组成:网络前缀(标识整个网络或子网)和主机标识符(指定该网络或子网上的主机的特定接口)。
    • CIDR 使用 CIDR 表示法表示 IP 地址,其中地址或路由前缀写有表示前缀位数的后缀,例如 IPv4 的 192.0.2.0/24,IP 地址是 CIDR 块的一部分,如果地址的初始 n 位和 CIDR 前缀相同,则称其属于 CIDR 块。
  • CNI:
    • CNI(容器网络接口)是一个云原生计算基金会项目,由规范和库组成,用于编写插件以在 Linux 容器中配置网络接口;
    • CNI 只关心容器的网络连接以及在容器被删除时移除分配的资源。
  • VIP 地址:虚拟 IP 地址或 VIP 是软件定义的 IP 地址,与实际的物理网络接口不对应。
  • netfilter:
    • netfilter 是 Linux 中的包过滤框架。实现此框架的软件负责数据包过滤、网络地址转换 (NAT) 和其他数据包处理;
    • netfilter、ip_tables、连接跟踪(ip_conntrack、nf_conntrack)和NAT子系统共同构建了框架的主要部分。
  • iptables:
    • iptables 是一个允许 Linux 系统管理员配置 netfilter 及其存储的链和规则的程序;
    • IP 表中的每条规则都由许多分类器(iptables 匹配)和一个连接的操作(iptables 目标)组成。
  • conntrack:
    • conntrack 是建立在 Netfilter 框架之上的用于处理连接跟踪的工具,连接跟踪允许内核跟踪所有逻辑网络连接或会话,并将每个连接或会话的数据包定向到正确的发送者或接收者;
    • NAT 依靠此信息以相同的方式翻译所有相关数据包,并且 iptables 可以使用此信息充当状态防火墙。
  • IPVS:
    • IPVS 将传输层负载平衡作为 Linux 内核的一部分来实现;
    • IPVS 是一个类似于 iptables 的工具,它基于 Linux 内核的 netfilter 钩子函数,但使用哈希表作为底层数据结构。这意味着,与 iptables 相比,IPVS 重定向流量更快,在同步代理规则时具有更好的性能,并提供更多的负载平衡算法。
  • DNS:域名系统 (DNS) 是一个分散的命名系统,用于将系统名称与 IP 地址相关联,它将域名转换为用于定位计算机服务的数字 IP 地址。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/571221.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python做GUI:介绍与优化SEO

Python做GUI:介绍与优化SEO Python是一种受欢迎的编程语言,尤其是在数据分析和开发领域。但是,Python也可以用于GUI(图形用户界面)应用程序的开发。在本文中,我们将介绍Python GUI开发的基础知识&#xff…

滤镜美颜sdk的实现方式和工作流程:从技术层面了解美颜算法

众所周知,实现美颜功能的核心技术之一就是滤镜美颜sdk。在本文中,我们将从技术层面来探讨滤镜美颜sdk的实现方式和工作流程,帮助读者更深入了解美颜算法。 一、美颜算法的基本原理 美颜算法的基本原理是通过图像处理技术,对人物…

第十八章_Redis缓存预热+缓存雪崩+缓存击穿+缓存穿透

缓存预热 缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据。 可以通过PostConstruct初始化白名单数据 缓存雪崩 …

23种设计模式之命令模式(Command Pattern)

前言:大家好,我是小威,24届毕业生,在一家满意的公司实习。本篇文章将23种设计模式中的命令模式,此篇文章为一天学习一个设计模式系列文章,后面会分享其他模式知识。 如果文章有什么需要改进的地方还请大佬不…

CASIA-FaceV5 抠出的人脸数据集

CASIA-FaceV5亚洲人脸数据集,以该数据集作为测试集所生成的同一人和不同人对应的测试文件。 CASIA-FaceV5亚洲人脸数据集有500人、每个人5张图片,共2500张图片,图片大小为640*480。数据集共有500个文件夹,文件夹名称为&#xff1…

【实战记录】手游内存优化(内存泄露检测)

故事背景: 手上有一个完整的页游项目,线上运营数据还不错,所以打算把这个项目手游化。因为这个项目本来就是用cocos的creator写的,所以手游化成本比较低,在修改了大概6~7个只能在页游上运行的接口后&#xff0…

Ansible介绍

文章目录 Ansible介绍Ansible的架构为什么要有Ansible TowerAnsible Tower Ansible介绍 Ansible是一种自动化工具,可以用于自动化部署、配置和管理IT基础设施。它是一种基于Python的开源软件,提供了一个简单易用的语言和工具集,使得自动化管…

内网渗透—代理Socks协议、路由不出网、SMB绕过、CS-MSF控制上线

内网渗透—代理Socks协议、路由不出网、SMB绕过、CS-MSF控制上线 1. 前言1.1. 实验背景1.2. 环境准备1.2.1. 环境介绍1.2.2. 环境测试 2. CS上线2.1. Windows2008上线2.2. Windows2003上线2.2.1. 设置socks代理2.2.2. 设置正向连接2.2.3. 生成木马2.2.4. 上线木马 2.3. Windows…

Flutter数据库操作看这一篇就够了

文章目录 Flutter常用数据库操作库最常用的sqflite介绍简介举例 依赖sqflite,单例模式封装一个sqlite操作类说明initDb说明conflictAlgorithm说明 Flutter常用数据库操作库 Flutter是一种跨平台的移动应用程序开发框架,支持使用多种类型的数据库进行数据存储和管理…

【CSDN快速获得铁粉小经验】厉昱辰的经验分享

如何快速的涨粉呢?今天将带领大家一起涨粉喽🥰🥰🥳🥳 一、最低阅读量过滤 官方算法进行最低阅读量过滤,阅读量太低的直接不参与热榜计算,刚创建的文章应该在其他渠道有一些冷启动的过程。但是阅…

c++ 11标准模板(STL) std::map(四)

定义于头文件<map> template< class Key, class T, class Compare std::less<Key>, class Allocator std::allocator<std::pair<const Key, T> > > class map;(1)namespace pmr { template <class Key, class T, clas…

150套开发板免费送!还有5G手机拿?米尔RZ/G2L开发板创意秀

人间最美五月天 不负韶华不负卿 米尔又来送板子了 不是3套&#xff0c;也不是4套 150套米尔RZ/G2L开发板 送&#xff01;免费&#xff01;板卡不回收&#xff01; 这是什么样的有奖活动&#xff1f; 米尔RZ/G2L开发板创意秀 为感谢广大客户一直以来的支持&#xff0c;推动…

15 个非常流行的VsCode插件,让你的编码效率倍增!

VS Code已经成为了最受欢迎的代码编辑器之一。 它的简洁性、易用性和可扩展性使得它成为了许多开发者的首选。 而在VS Code中&#xff0c;插件是其最大的卖点之一。 通过安装插件&#xff0c;你可以将VS Code打造成一个功能强大的开发环境&#xff0c;从而提高你的编码效率。…

【2023A题】电采暖负荷参与电力系统功率调节的技术经济分析(思路、代码)

目录 &#x1f4a5;1 概述 &#x1f4da;2 Matlab代码实现 &#x1f389;3 参考文献 &#x1f308;4 运行结果 &#x1f4a5;1 概述 建设以新能源为主体的新型电力系统是应对全球气候变化挑战的重要举措。高比例新能源接入导致电力系统调节能力稀缺&#xff0c;亟需开发新的调…

Node版本管理器nvm的安装与使用

前言&#xff1a; 多项目新旧项目管理的时候&#xff0c;往往与依赖不同的node版本&#xff0c;不同的版本对其他依赖的安装有一定的影响&#xff0c;因此我们需要对node的版本进行方便快捷管理和切换&#xff0c;如果直接卸载重装对应版本&#xff0c;切换项目再次卸载重装明显…

word打印为pdf去掉批注和修订记录

对于这个问题某乎上充斥着垃圾回答&#xff0c;大多引流到自家开发的pdf产品上。其实背后的方法都是一样的&#xff0c;就是关掉批注&#xff0c;用word自带的功能就能解决&#xff0c;凡是word编辑软件都有类似功能 直接用word打印为pdf后的效果 下图为打印出来的pdf文件&…

杜绝开源依赖风险,许可证扫描让高效合规「两不误」

目录 开源许可证及其常见类型 开源许可证扫描是软件研发过程中&#xff0c;不可或缺的工具 极狐GitLab 开源许可证扫描的优势与应用 Step 1&#xff1a;启用及设置许可证策略 Step 2&#xff1a;自动创建策略文件存放项目 Step 3&#xff1a;查看许可证合规情况 Step 4&…

<Linux开发>驱动开发 -之-gpio子系统

&#xff1c;Linux开发&#xff1e;驱动开发 -之-gpio子系统 交叉编译环境搭建&#xff1a; &#xff1c;Linux开发&#xff1e; linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下&#xff1a; &#xff1c;Linux开发&#xff1e; -之-系统移植 uboot移植过程详细记录&…

vue实现倒计时功能

vue实现倒计时功能 首先我们需要一个 Vue. js的函数&#xff0c;这个函数用于实现倒计时&#xff0c;这里我们采用 vue. js的 import来实现&#xff0c;这是 vue. js的一个特殊功能&#xff0c;将函数调用的参数以列表的形式加入到函数中&#xff0c;当在函数执行完后返回结果。…

Java基础--->IO流(2)【常见IO模型】

文章目录 计算机角度IO操作系统IO常见的IO模型Java 中 3 种常见 IO 模型BIO&#xff08;BlockingI/O&#xff09;【同步阻塞IO】NIO&#xff08;Non-blocking/New I/O&#xff09;【非阻塞IO】IO多路复用AIO&#xff08;Asynchronous I/O&#xff09;【异步IO】 计算机角度IO 根…