写点什么

Kubernetes 网络快速入门完全指南

  • 2020-05-18
  • 本文字数:8164 字

    阅读完需:约 27 分钟

Kubernetes网络快速入门完全指南

Kubernetes 网络一直是一个非常复杂的主题。本文将介绍 Kubernetes 实际如何创建网络以及如何为 Kubernetes 集群设置网络。


本文不包括如何设置 Kubernetes 集群。这篇文章中的所有例子都将使用 Rancher 2.0 集群(其他平台也同样适用)。即使你打算使用其他的公有云管理 Kubernetes 服务,也希望你对 Kubernetes 网络的工作原理有更好的了解。

如何使用 Kubernetes 网络

许多 Kubernetes 部署指南中包含了在 K8S 部署中部署 Kubernetes 网络 CNI 的说明。但是如果你的 K8S 集群已经运行,并且尚未部署任何网络,那么部署网络就像在 K8S 上运行其提供的配置文件一样简单(对于大多数网络和基本用例而言)。例如,要部署 flannel:



这样,从网络的角度来看,K8S 已经可以使用。为了测试一切是否正常,我们创建了两个 Pod。



这将创建两个 pod,它们正在使用我们的驱动器。查看其中一个容器,我们发现网络的 IP 地址范围为 10.42.0.0/24。



在另一个 Pod 进行的快速 ping 测试表明,网络运行正常。


与 Docker 网络相比,Kubernetes 网络如何工作?

Kubernetes 通过 Docker 之上的 CNI 管理网络,并将设备附加到 Docker。尽管有 Docker Swarm 的 Docker 也具有自己的联网功能(例如 overlay、macvlan、bridging 等),但 CNI 也提供了类似类型的功能。


还有一点十分重要,K8S 并不使用 docker0(这是 Docker 的默认网桥),而是创建自己的网桥,名为 cbr0,该网桥需要与 docker0 区分开来。

为什么我们需要 Overlay 网络?

诸如 vxlan 或 ipsec 之类的 overlay 网络(如果你设置过安全 VPN,你应该对此比较熟悉)可以将数据包封装到另一个数据包中。这使得实体在另一台计算机的范围之外依旧可以寻址。Overlay 网络的替代方案包括如 macvtap(lan)之类的 L3 解决方案,甚至包括 ivtap(lan)之类的 L2 解决方案,但是这些方案具有一定的局限性。


L2 或 L3 上的任何解决方案都可以让 pod 在网络上寻址。这意味着 pod 不仅在 Docker 网络内部访问,还能直接从 Docker 网络外部访问。这些是公共 IP 地址或私有 IP 地址。


然而,在 L2 上进行通信比较麻烦,并且你的经验会因为网络设备而异。某些交换机需要一些时间来注册你的 Mac 地址,然后才能将其实际连接到网络的其余部分。你还可能会遇到一些麻烦,因为系统中其他主机的 neighbor(ARP) table 仍在过时的缓存上运行,并且始终需要使用 dhcp 运行而不是 host-local,这样可以避免主机之间的 ip 冲突。Mac 地址和 neighbor table 问题是诸如 ipvlan 之类的解决方案存在的原因。这些解决方案不会注册新的 mac 地址,而是在现有地址上路由流量(尽管它们也有自己的问题)。


因此,我的建议是,对于大多数用户而言,将 overlay 网络作为默认解决方案应该足够了。但是,一旦工作负载变得更加高级并提出了更具体的要求,你将需要考虑其他的解决方案,如 BGP 和直接路由。

Kubernetes 网络如何工作?

在 Kubernetes 中首先要了解的是,pod 实际上并不等同于容器,而是容器的集合。在同一集合的容器中共享一个网络堆栈。Kubernetes 通过在暂停容器上设置网络来进行管理,你可以在你所创建的每个 pod 中找到这些暂停容器。所有其他 pod 都连接到暂停容器的网络,该容器本身除了提供网络外不执行任何操作。因此,也可以使一个容器通过 localhost 与不同容器中的服务进行通信,此时该容器具有相同 pod 的相同定义。


除了本地通信之外,pod 之间的通信看起来与 Docker 网络中的 container-to-container 通信几乎相同。

Kubernetes 流量路由

我将以两种场景为例,详细地说明如何在 Pod 之间路由流量。

1、 在同一主机上路由流量:

在两种情况下,流量不会离开主机。一是当调用的服务在同一节点上运行,一是单个 pod 中的同一个容器集合。


如果从第一个 pod 中的容器 1 调用 localhost:80 并在容器 2 中运行服务,则流量将通过网络设备并将数据包转发到其他目的地。在这种情况下,路由流量的路线很短。


如果我们想要与其他 pod 进行通信,时间会更长一些。首先,流量将传递到 cbr0,接下来 cbr0 将会注意到我们在同一个子网通信,因此它会将流量转发到目标 Pod,过程如下图所示:


2、 跨主机路由流量:

当我们离开节点时,这将变得更加复杂。现在,cbr0 会将流量传递到下一个节点,该节点的配置由 CNI 管理。这些基本上只是以目标主机为网关的子网路由。然后,目标主机可以继续使用自己的 cbr0 并将流量转发到目标容器,如下所示:


究竟什么是 CNI?

CNI 是 Container Networking Interface(容器网络接口)的缩写,基本上是一个具有定义明确的外部接口,Kubernetes 可以调用它来提供网络功能。


你可以在以下链接中找到维护的参考插件,其中包括容器网络官方 repo 中的大多数重要插件:


https://github.com/containernetworking/plugins


CNI 3.1 版不是很复杂。它包含三个必需的功能,ADD、DEL 和 VERSION,这些功能可以尽其所能管理网络。有关每个函数应返回和传递的内容的更详细说明,您可以在此处阅读规范:


https://github.com/containernetworking/cni/blob/master/SPEC.md

CNI 之间的区别

以下我们将介绍一些最受欢迎的 CNI:


Flannel


Flannel 是一个简单的网络,并且是 overlay 网络最简单的设置选项。它的功能包括原生网络,但在多个网络中使用时会受到限制。对于大多数用户来说,Flannel 是 Canal 下面的默认网络,部署起来非常简单,甚至还有本地网络功能,如主机网关。但是 Flannel 有一些限制,包括缺乏对网络安全策略的支持以及没有多网络的功能。


Calico


Calico 与 Flannel 采用不同的方法,从技术的角度来说,它不是 overlay 网络,而是在所有相关系统之间配置路由的系统。为此,Calico 利用边界网关协议(BGP),它在名为 peering 的过程中用于 Internet。其中每方 peering 交换流量并参与 BGP 网络。BGP 协议本身会在其 ASN 下传播路由,不同之处在于它们是私有的,不需要再 RIPE 中注册它们。


但是,在某些情况下,Calico 可与 overlay 网络配合使用,如 IPINIP。当节点位于不同网络上时使用,以便启动两个主机之间的流量交换。


Canal


Canal 基于 Flannel,但有一些 Calico 自己的组件,例如 felix(主机代理),它可以利用网络安全策略。这些通常在 Flannel 中不存在。因此,它基本上通过添加安全策略来扩展 Flannel。


Multus


Multus 是一个 CNI,但实际上它本身并不是网络接口。只是它编排了多个接口,并且没有配置实际的网络,因而 Pod 无法单独与 Multus 通信。实际上,Multus 是多设备和多子网网络的推动者。下图显示了它是如何工作的,Multus 本身基本上调用了真正的 CNI 而不是 kubelet,并将结果传递回 kubelet。



Kube-Router


同样值得一提的是 kube-router,与 Calico 一样,它可以与 BGP 和路由而不是 overlay 网络一起使用。就像 Calico 一样,它在必要的时候可以使用 IPINIP。它还能利用 ipvs 进行负载均衡。

设置多网络 K8S 集群

如果您需要使用多个网络,则可能需要 Multus。

设置 Multus

我们需要做的第一件事是设置 Multus。我们使用的几乎是 Multus 仓库示例中的配置,但进行了一些重要的调整。请参阅下面的示例。


首先是调整 configmap。因为我们计划使用 Flannel 创建默认网络,所以我们在 Multus 配置的 delegates 数组中定义配置。这里用红色标记的一些重要设置是“ masterplugin”:true,用于定义 Flannel 网络本身的网桥。你将在接下来的步骤中了解为什么我们需要这样做。除此之外,还需要添加配置映射的安装定义,其他则不需要调整,因为由于某些原因,此示例未完成。


关于此 configmap 的另一件重要事情是,这一 configmap 中定义的所有内容都是默认网络,这些默认网络会自动安装到容器,而无需进一步说明。另外,如果要编辑此文件,请注意,你要么需要终止并重新运行守护进程的容器,要么重新启动节点才能使更改生效。


示例 yaml 文件:


设置主要的 Flannel Overlay 网络

对于主要的 Flannel 网络,设置非常简单。我们可以从 Multus 仓库中获取示例,然后进行部署。此处所做的调整是 CNI 安装、容差的调整以及对 Flannel 的 CNI 设置所做的一些调整。例如,添加“ forceAddress”:true 并删除“ hairpinMode”:true。


这已在使用 RKE 设置的集群上进行了测试,但是只要您从主机正确安装 CNI(在本例中为/ opt / cni / bin),它就可以在其他集群上工作。


Multus 本身并没有太大的改变。他们只注释了 initcontainer 配置,你可以删除它。之所以如此,是因为 Multus 将建立其 delegates,并充当主要的“ CNI”。


这是修改后的 Flannel daemonset:



部署了这些样本之后,我们已经完成了很多工作,现在应该为 pod 分配一个 IP 地址。让我们测试一下:



如你所见,我们已经成功部署了 Pod,并在 eth0 接口(默认接口)上为其分配了 IP 10.42.2.43。所有其他接口都将显示为 netX,即 net1。

设置辅助网络

辅助网络还需要进行一些调整,这些调整的前提是假设你要部署 vxlan。为了实际服务于辅助 overlay,我们需要更改 VXLAN 标识符“ VIN”,默认情况下将其设置为 1,并且我们的第一个 overlay 网络现在已经使用了它。因此,我们可以通过在 etcd 服务器上配置网络来更改此设置。我们使用自己的集群 etcd,此处标记为绿色(并且假设 job 在运行 etcd 客户端的主机上运行),然后从本地主机(在我们的情况下,将其存储在本地主机)中装入密钥(此处标记为红色),存储在/ etc / kubernetes / ssl 文件夹中。


完整的 YAML 文件示例:



接下来,我们可以实际部署辅助网络。此设置几乎与主要网络设置相同,但有一些关键区别。最明显的是,我们更改了子网,但是我们还需要更改其他一些内容。


首先,我们需要设置一个不同的 dataDir,即/ var / lib / cni / flannel2,以及一个不同的 subnetFile,即/run/flannel/flannel2.env。这十分必要,因为它们已经被我们的主要网络占用。接下来,我们需要调整网桥,因为主要的 Flannel overlay 网络已经使用了 kbr0。


其余还需更改的配置包括将其更改为实际针对我们之前配置的 etcd 服务器。在主网络中,这是通过–kube-subnet-mgr flag 直接连接到 K8S API 来完成的。但是我们不能这样做,因为我们还需要修改要读取的前缀。你可以在下面看到橙色标记的内容,而集群 etcd 连接的设置则显示为红色。最后一个设置是再次指定子网文件,在示例中以绿色标记。最后一点是,我们添加了一个网络定义。其余部分与我们的主要网络配置相同。


有关上述步骤,请参见示例配置文件:




完成此操作后,我们便准备好了辅助网络。

分配额外的网络

既然我们已经准备好辅助网络,那么我们现在需要分配他。为此,我们需要先定义一个 NetworkAttachmentDefinition,之后我们可以使用它将网络分配给容器。基本上,这是在初始化 Multus 之前,我们设置的 configmap 的动态替代方案。这样,我们可以按需安装所需的网络。在此定义中,我们需要指定网络类型(本例中是 Flannel)以及必要的配置。这包括前面提到的 subnetFile、dataDir 和网桥名称。


我们需要确定的最后一件事是网络的名称,我们将其命名为 flannel2。



现在,我们终于可以使用辅助网络生成第一个 pod。



现在应该使用辅助网络创建新的 Pod,并且我们将那些附加网络视为额外添加的网络接口。



成功啦,辅助网络分配 10.5.22.4 作为其 IP 地址。

Troubleshooting

如果该示例没有正常工作,你需要查看 kubelet 的日志。


一个常见的问题的是缺少 CNI。我第一次测试的时候,遗漏了 CNI 网桥,因为 RKE 没有部署它。但是这个问题十分容易解决。

外部连接和负载均衡

现在我们已经建立并运行网络,接下来我们要做的是使我们的应用程序可以访问并将其配置为高可用和可扩展。高可用性和可伸缩性不仅可以通过负载均衡来实现,它还我们需要具备的关键组件。


Kubernetes 有四个概念,可以使应用程序在外部可用。

使用负载均衡器

Ingress


Ingress 基本上就是具有 Layer7 功能的负载均衡器,特别是 HTTP(s)。最常用的 ingress controller 是 NGINX ingress。但这主要取决于你的需求以及你的使用场景。例如,你还可以选择 traefik 或 HA Proxy。


配置一个 ingress 十分简单。在以下例子中,你将了解一个链接服务的例子。蓝色标注的是指向服务的基本配置。绿色标注的是链接 SSL 证书所需的配置(需要在此之前安装这一证书)。最后,你会看到调整了 NGINX ingress 的一些详细设置。



Layer 4 负载均衡器


在 Kubernetes 中,使用 type: LoadBalancer 定义 Layer 4 负载均衡器,这是一个依赖于负载均衡解决方案的服务提供程序。对于本地计算机,大概率会使用 HA 代理或一个路由解决方案。云提供商会使用自己的解决方案以及专用硬件,也可以使用 HA 代理或路由解决方案。


最大的区别是第 4 层负载平衡器不了解高级应用程序协议(layer 7),并且仅能够转发流量。此级别上的大多数负载均衡器还支持 SSL 终止。这通常需要通过注释进行配置,并且尚未标准化。


使用 {host,node} 端口


{host,node} Port 基本上等同于 docker -p port:port,尤其是 hostPort。与 hostPort 不同,nodePort 在所有节点上可用,而不是仅在运行 pod 的节点上可用。对于 nodePort,Kubernetes 首先创建一个 clusterIP,然后通过该端口负载均衡流量。nodePort 本身只是将端口上的流量转发到 clusterIP 的 iptable 规则。


除了快速测试外,很少使用 nodePort,只有在你希望每个节点公开端口(即用于监视)时才会在生产中使用 nodePort。大多数时候,你需要使用 Layer 4 负载均衡器。hostPort 仅用于测试,或者少数时候,将 pod 粘贴到特定节点并在指向该节点的特定 IP 地址下发布。


例如,在容器规范中定义了 hostPort,如下所示:



什么是 ClusterIP ?


clusterIP 是 Kubernetes 集群及其中所有服务的内部可访问 IP。该 IP 本身将负载均衡流量到与其 selector 规则匹配的所有 Pod。在很多情况下,例如在指定类型:LoadBalancer 服务或设置 nodePort 时,也会自动生成 clusterIP。其背后的原因是所有负载均衡都是通过 clusterIP 进行的。


clusterIP 作为一个概念是为了解决多个可寻址主机以及这些主机的有效更新的问题。具有不变的单个 IP 比始终通过服务发现针对服务的所有性质重新获取数据要容易得多。尽管有时在某些情况下更适合使用服务发现,但如果你想要 explicit control,那么还是建议使用 clusterIP,如在某些微服务环境中。

常见的故障

如果您使用公有云环境并手动设置主机,则您的集群可能缺少防火墙规则。例如,在 AWS 中,您将需要调整安全组,以允许集群间通信以及 ingress 和 egress。如果不这样做,将导致集群无法运行。确保始终打开主节点和 worker 节点之间的必要端口。直接在主机上打开的端口(即 hostPort 或 nodePort)也是如此。

网络安全

既然我们已经设置了所有 Kubernetes 网络,我们还需要确保它们具备一定的安全性。保证安全性的最低原则是为应用程序提供其运行所需的最少访问量。这可以在一定程度上确保即使在发生安全漏洞的情况下,攻击者也将难以深入挖掘你的网络。虽然它不能完全确保你的安全,但无疑会使攻击者进行攻击时变得更加困难和耗时。这很重要,因为它会使你有更多的时间做出反应并防止进一步的破坏。这里有一个典型的例子,不同应用程序的不同 exploits/漏洞的组合,这使得攻击者只有从多个维度(例如,网络、容器、主机)到达任何攻击面的情况下,才能进行攻击。


这里的选择要么是利用网络策略,要么是寻求第三方安全解决方案以实现容器网络安全。有了网络策略,我们有坚实的基础来确保流量仅在流量应流的地方进行,但这仅适用于少数几个 CNI。例如,它们可与 Calico 和 Kube-router 一起使用。Flannel 不支持它,但是幸运的是,你可以移至 Canal,这使得 Flannel 可以使用 Calico 的网络策略功能。对于大多数其他 CNI,则没有支持,目前尚未有支持的计划。


但这不是唯一的问题。问题在于,网络策略规则只是针对特定端口的防火墙规则,它十分简单。这意味着你无法应用任何高级设置。例如,如果你发现某个容器可疑,就不能按需阻止它。进一步来说,网络规则无法理解流量,因此你不知道流量的流向,并且仅限于在第 3 层和第 4 层上创建规则。最后,它还无法检测到基于网络的威胁或攻击,例如 DDoS,DNS,SQL 注入以及即使在受信任的 IP 地址和端口上也可能发生的其他破坏性网络攻击。


因此,我们需要专用的容器网络安全解决方案,它可为关键应用程序(例如财务或合规性驱动的应用程序)提供所需的安全性。我个人喜欢 NeuVector。它具有我曾在 Arvato / Bertelsmann 进行部署的容器防火墙解决方案,并提供了我们所需的 Layer7 可见性和保护。


应该注意的是,任何网络安全解决方案都必须是云原生的,并且可以自动扩展和调整。部署新应用程序或扩展 Pod 时,你无需检查 iptable 规则或更新任何内容。也许对于几个节点上的简单应用程序堆栈,你可以手动进行管理,但是对于任何企业而言,部署安全不能减慢 CI / CD 流水线的速度。


除了安全性和可见性之外,我还发现拥有连接和数据包级容器网络工具有助于在测试和 staging 期间调试应用程序。借助 Kubernetes 网络,除非您能看到流量,否则您将永远无法真正确定所有数据包的去向以及将哪些 Pod 路由到其中。

选择网络 CNI 的一些建议

现在已经介绍了 Kubernetes 网络和 CNI,始终会出现一个大问题:应该选择哪种 CNI 解决方案?我将尝试提供一些有关如何做出此决定的建议。


首先,定义问题


每个项目的第一件事是尽可能详细地定义你需要首先解决的问题。你也许想知道要部署哪种应用程序以及它们将产生什么样的负载。你可能会问自己的一些问题:


我的应用程序:


  • 网络是否繁忙?

  • 是否对延迟敏感?

  • 是单体架构吗?

  • 还是微服务架构服务?

  • 需要在多个网络上吗?


我可以承受宕机时间吗,甚至是最小的宕机时间?


这是一个十分重要的问题,因为你需要事先决定。如果你现在选择一种解决方案,以后再进行切换,则需要重新设置网络并重新部署所有容器。除非你已经拥有 Multus 之类的东西并且可以使用多个网络,否则这将意味着您的服务会停机。在大多数情况下,如果你有计划的维护时段,那么事情会没那么严重,但是随着应用程序的不断迭代,零停机时间变得更加重要!


我的应用程序在多个网络上


这一情况在本地安装中十分常见,实际上,如果你只想将通过专用网络和公用网络的流量分开,那么这需要你设置多个网络或者有智能的路由。


我是否需要 CNI 中的某些特定功能?


影响你做决定的另一件事是,你需要一些特定的功能,在某些 CNI 中可用,而其他 CNI 中不可用。例如,你想使用 Weave 或希望通过 ipvs 进行更为成熟的负载均衡。


需要什么网络性能?


如果你的应用程序对延迟敏感或网络繁忙,那么你需要避免使用任何 overlay 网络。Overlay 在性能上并不划算,规模上也是如此。这这种情况下,提高网络性能的唯一方法是避免 overlay 并改用路由之类的网络实用程序。寻找网络性能时,你有几种选择,例如:


  • Ipvlan:它有良好的性能,但需要注意,你不能在同一主机上同时使用 macv{tap,lan}。

  • Calico:这个 CNI 不是对用户最友好的,但于 vxlan 相比,它可以为你提供更好的性能,并且可以进行扩展而无需担心。

  • Kube-Router:它通过使用 BGP 和路由,以及支持 LVS/IPVS,来提供更好的性能(这与 Calico 类似)。但 Calico 比它更为成熟。

  • 云提供商解决方案:一些云提供商提供了自己的网络解决方案,这些方案的好坏需要根据具体情况来确定,这里无法一概而论。值得一提的是,Rancher 的一个开源项目Submariner。它支持多个 Kubernetes 集群之间的跨集群网络连接,并且创建了必要的隧道和路径,能为部署在需要相互通信的多个 Kubernetes 集群中的微服务提供网络连接。


我只是想要一些可行的方法!


在这样的情况下,推荐使用 canal 或带有 vxlan 的 flannel,因为它们十分容易且有效。但是正如我之前所提到的,vxlan 速度很慢,随着应用程序的不断发展,它将耗费大量资源。但是对于刚刚起步的项目而言,这绝对是最简单的方法。

做出决定

这实际上是做出决定而不是根本不做出决定的问题。如果你没有特定的功能要求,则可以从 Flannel 和 vxlan 开始。如果您已部署到生产环境,稍后需要一些工作以进行迁移,但是从长远来看,做出错误的决定总比完全不做出决定要好。


有了所有这些信息,我希望您对 Kubernetes 网络的工作方式有一些相关的背景和更好的了解。


原文链接:

https://dzone.com/articles/how-to-understand-and-setup-kubernetes-networking


2020-05-18 18:071252

评论

发布
暂无评论
发现更多内容

眼睛一闭一睁,2020年上半年就过去了

赵新龙

2020 年度计划

【架构师训练营 - 作业 -4】大型互联网架构

Andy

架构师训练营第四周作业

Geek_2dfa9a

架构师训练营第四周作业

lwy

极客大学架构师训练营

架构师训练营第4期作业/学习总结

JUN

week04总结

seki

第四周学习总结

天之彼方

【极客大学】【架构师训练营】【第四周】学习总结

NieXY

极客大学架构师训练营

想解耦必分层

菜根老谭

程序员 架构思维 分层思维

架构师训练营第 4 周学习总结

Season

高可用 分布式系统 高性能 极客大学架构师训练营

软件架构发展史

Jeannette

架构师训练营 第四周 作业

亮灯

奔向 10W+ 的第二次 update

赵新龙

写作平台 B站 Quora

第四周作业

安阳

架构师训练营0期第四周 - 学习总结

lei Shi

大型互联网技术架构体系

dony.zhang

第四周学习总结

慵秋

架构师训练营第四周总结

Geek_2dfa9a

一个典型大型互联网应用系统:从问题到技术方案和手段

走过路过飞过

架构师训练营 -week04 作业

GunShotPanda

架构师训练营 第四周 总结 互联网系统架构演进

CR

极客大学架构师训练营

案例讲解,设计模式定义

秤须苑

【架构师训练营 - 总结4】

Andy

【架构课总结 - 第四周】常见架构模式和技术

Nelson

架构总结

大型互联网应用系统技术和手段

纯纯

第四周总结

lwy

极客大学架构师训练营

架构师训练营 -week04 学习总结

GunShotPanda

架构师训练营第四课总结

曾祥斌

大型互联网应用系统使用技术方案和手段

wei

week04作业

seki

【第四周】命题作业——大型互联网系统的技术解决方案和手段

三尾鱼

极客大学架构师训练营

Kubernetes网络快速入门完全指南_文化 & 方法_Rancher_InfoQ精选文章