怎么化解 Kubernetes 网络的复杂性?

云栖号资讯:【点击检查更多职业资讯】
在这儿您能够找到不同职业的榜首手的上云资讯,还在等什么,快来!


依据 CNCF 历年发布的 Kubernetes 生态陈述,安全、存储、网络始终是开发者最重视的三大槽点。即便在虚拟网络和恳求路由方面有丰厚经历,许多开发者在处理 Kubernetes 集群网络时仍是很紊乱。

本文将以带有两个 Linux 节点的标准 Google Kubernetes Engine(GKE)集群为例,经过盯梢 HTTP 恳求被传送到集群服务的整个进程,深度拆解 Kubernetes 网络的复杂性。

恳求的旅程

当一个人在阅读网页时,他首要单击一个链接,发作了一些事,之后方针页面就被加载出来。这让人难免猎奇,从单击链接到页面加载,中心究竟发作了什么?

怎么化解 Kubernetes 网络的复杂性?

关于这个问题,咱们能够这样了解。如下图所示,用户恳求经过 Internet 被发送给一个非常大的云供给商,然后再被发送到该云供给商根底架构中保管的 Kubernetes 集群。

怎么化解 Kubernetes 网络的复杂性?

假如进一步扩大 Kubernetes 集群,咱们能够看到云供给商正向 Kubernetes Service 资源(SVC)发送恳求,然后将恳求路由到 Kubernetes ReplicaSet(RS)中的 Pod。

怎么化解 Kubernetes 网络的复杂性?

为了更直观,咱们能够布置 YAML 来创立 Kubernetes Service 和 ReplicaSet:

怎么化解 Kubernetes 网络的复杂性?

现在咱们现已在 hello-world ReplicaSet 下创立了两个 Pod,还创立了一个带有负载均衡器的服务资源 hello-world(假如云供给商和集群网络支撑),以及一个在 host:port 中有两个条目的 Kubernetes Endpoint 资源,每个 Pod 对应一个,以 Pod IP 作为主机值和端口 8080。

在 GKE 集群上,咱们 kubectl 一下会回来以下内容:

怎么化解 Kubernetes 网络的复杂性?

集群 IP 网络信息:

  • Node - 10.138.15.0/24
  • Cluster - 10.16.0.0/14
  • Service - 10.19.240.0/20

已知服务在集群 CIDR 中的虚拟 IP 地址(VIP)是 10.19.240.1。现在,咱们能够从负载均衡器开端,深化盯梢恳求进入 Kubernetes 集群的整个“旅程”。

负载均衡器

Kubernetes 经过本地控制器和 Ingress 控制器供给了许多揭露服务的办法,但这儿咱们仍是运用 LoadBalancer 类型的标准 Service 资源。

咱们的 hello-world 服务需求 GCP 网络负载均衡器。每个 GKE 集群都有一个云控制器,它在集群和 API 端点之间进行接口,以主动创立集群资源所需的 GCP 服务,包含咱们的负载均衡器(不同云供给商的负载均衡器在类型、特性上都有不同)。

经过从不同的视点调查集群,咱们能够检查外部负载均衡器的方位:

怎么化解 Kubernetes 网络的复杂性?

kube-proxy

每个节点都有一个 kube-proxy 容器进程(在 Kubernetes 参阅结构中,kube-proxy 容器坐落 kube-system 命名空间的 Pod 中),它担任把寻址到集群 Kubernetes 服务方针虚拟 IP 地址的流量转发到相应后端 Pod。kube-proxy 当时支撑三种不同的完成办法:

  • User space:即用户空间,服务路由是在用户进程空间的 kube-proxy 中进行的,而不是内核网络仓库。这是kube-proxy 的开端版别,较为安稳,可是功率不太高;
  • iptables:这种办法选用 Linux 内核级 Netfilter 规矩为 Kubernetes Services 装备一切路由,是大多数渠道完成 kube-proxy 的默许形式。当对多个后端 Pod 进行负载均衡时,它运用未加权的循环调度;
  • IPVS:IPVS 依据 Netfilter 结构构建,在 Linux 内核中完成了 L4 负载均衡,支撑多种负载均衡算法,衔接最少,预期推迟最短。它从 Kubernetes v1.11 中开端遍及可用,但需求 Linux 内核加载 IPVS 模块。它也不像 iptables 那样具有各种 Kubernetes 网络项目的广泛支撑。

在咱们的 GKE 集群中,kube-proxy 以 iptables 形式运转,所以咱们后续首要研讨该形式的工作办法。

假如检查创立好的 hello-world 服务,咱们能够发现它现已被分配了一个节点端口 30510。节点网络上动态分配的端口答应其间保管的多个 Kubernetes 服务在其端点中运用相同的面向 Internet 的端口。

假如服务已被布置到标准 Amazon EKS 集群,它将由 Elastic Load Balance 供给服务,该服务会将传入的衔接发送到相应 Pod 节点上咱们服务的节点端口。可是,Google Cloud Platform 网络负载均衡器只会将流量转发到与负载均衡器的传入端口坐落同一端口的方针,例如,到负载均衡器上的端口 80 的流量会被发送到方针后端实例上的端口 80。

咱们的 hello-world pods 肯定没有在节点的端口 80 上监听。所以假如在节点上运转 netstat,咱们能够看到没有进程正在监听该端口。

怎么化解 Kubernetes 网络的复杂性?

那么,经过负载均衡器的恳求是怎样成功树立衔接的呢?假如 kube-proxy 在用户空间形式下运转,它实际上是将衔接代理到后端 Pod。可是,在 iptables 形式下,kube-proxy 装备了 Netfilter 链,因而该衔接被节点的内核直接路由到了后端容器的端点。

iptables

在咱们的 GKE 集群中,假如登录到其间一个节点并运转 iptables,咱们能够看到这些规矩。

怎么化解 Kubernetes 网络的复杂性?

依据规矩注释,咱们能够获得与来自服务的负载均衡器到 hello-world 服务的传入衔接相匹配的过滤器链的称号,并遵从该链的规矩(在没有规矩注释的状况下,咱们依然能够将规矩的源 IP 地址与服务的负载均衡器进行匹配)。

怎么化解 Kubernetes 网络的复杂性?

咱们还能够可视化网络仓库中用于评价和修正数据包的链和规矩,检查咱们在集群中创立的服务是怎样把流量定向到副本集成员的。

怎么化解 Kubernetes 网络的复杂性?

KUBE-FW-33X6KPGSXBPETFQV 链有三个规矩,每个规矩都增加了另一个链来处理数据包。

  • KUBE-MARK-MASQ 向发送到 hello-world 服务的包(来自集群网络外部)增加一个 Netfilter 符号。带有此符号的数据包将依照 POSTROUTING 规矩进行更改,以运用源网络地址转化(SNAT),并将节点 IP 地址作为其源 IP 地址;
  • KUBE-SVC-33X6KPGSXBPETFQV 链适用于一切与 hello-world 服务相关的流量(与源无关),而且对每个服务端点(在本例中为两个 Pod)供给规矩。运用哪个端点链是彻底随机确认的:
  • KUBE-SEP-ALRUKLHE5DT3R34X:假如需求,KUBE-MARK-MASQ 会再次向数据包中增加一个 Netfilter 符号用以 SNAT;DNAT 规矩运用 10.16.0.11:8080 端点作为方针来设置方针 NAT
  • KUBE-SEP-X7DMMHFVFOT4JLHD:假如需求,KUBE-MARK-MASQ 会再次为数据包增加一个 Netfilter 符号用以 SNAT;DNAT 规矩运用 10.16.1.8:8080 端点作为方针来设置方针 NAT
  • KUBE-MARK-DROP 向此刻没有启用方针 NAT 的数据包增加 Netfilter 符号。这些数据包将在 KUBE-FIREWALL 链中被丢掉。

需求留意的是,尽管咱们的集群有两个节点,每个节点都有一个 hello-world Pod,但这种路由办法并不存在优先级。假如咱们将服务标准中的 externalTrafficPolicy 更改为 Local,那么状况就会改动。假定此刻存在恳求,这个恳求不只会转到接纳恳求的节点上的 Pod,还会导致没有服务 Pod 的节点回绝衔接。

因而,Local 战略一般需求与 Kubernetes daemon sets 一同运用,后者会在集群中的每个节点上调度一个 Pod。尽管前者能显着下降恳求的均匀网络推迟,但它也或许导致服务 Pods 之间的负载不均衡。

Pod 网络

本文不会深化介绍 Pod 网络,可是在咱们的 GKE 集群中,Pod 网络有自己的 CIDR 块,与节点网络分隔。Kubernetes 网络模型要求集群中的一切 Pod 能够直接彼此寻址(无视其主机节点)。GKE 群集运用 kubenet CNI,它在每个节点上创立到 Pod 网络的网桥接口,为每个节点供给自己的 Pod IP 地址专用 CIDR 块,以简化分配和路由。Google Compute Engine(GCE)网络能够在 VM 之间路由该 Pod 网络流量。

恳求

以下是是咱们获取 HTTP 200 呼应代码的办法:

怎么化解 Kubernetes 网络的复杂性?

本文提到了许多改动路由的办法,它们由不同 Kubernetes 渠道供给,下面是一个简略的清单:

  • 容器网络接口(CNI)插件:每个云供给商默许运用与其 VM 网络模型兼容的 CNI 完成。本文以默许设置的 GKE 集群为例,但假如是 Amazon EKS,那会很不相同,由于 AWS VPC CNI 把容器直接放在节点的 VPC 网络上;
  • Kubernetes Network Policy:Calico 是施行网络战略最受欢迎的 CNI 插件之一,它在节点上为每个 Pod 创立一个虚拟网络接口,并运用 Netfilter 规矩来施行其防火墙规矩;
  • 尽管大多数状况下依然运用 Netfilter,但 kube-proxy IPVS 路由形式一般会把服务路由和 NAT 移出 Netfilter 规矩;
  • 外部负载均衡器或其他能够将流量直接发送到服务节点端口的源将匹配 iptables 中的不同链(KUBE-NODEPORTS);
  • Kubernetes Ingress 控制器能够经过多种办法更改边际服务路由;
  • 比如 Istio 之类的服务网格或许会绕过 kube-proxy,直接衔接服务容器之间的内部路由。

维护服务

Kubernetes 网络需求很多可移动部件,它非常复杂,但假如开发者对集群中发作的事有根本了解,这会有助于开发者更有效地监控、维护它。

榜首,关于 Kubernetes 服务资源创立的云负载均衡器,增加防火墙约束的通用办法是不存在的。一些云供给商会支撑服务标准中的 loadBalancerSourceRanges 字段,这个字段答应开发者供给能够衔接到负载均衡器的 IP CIDR 块白名单。假如云供给商不支撑此字段,它就会被疏忽,因而开发者需求验证外部负载均衡器的网络装备。

而关于不支撑 loadBalancerSourceRanges 字段的云供给商,除非现已在云供给商等级采纳办法确定了负载均衡器和运转它们的云网络,开发者仍是应该假定负载均衡器上的服务端点是对全世界敞开的。由于各种因素,云供给商负载均衡器产品的默许防火墙设置千差万别,一些云供给商或许还支撑对 Service 方针的注释,以装备负载均衡器的安全性。

其次,请留意,咱们没有经过在 GKE 集群中启用 Kubernetes 网络战略支撑来装置 Calico CNI,由于 Calico 创立了很多其他 iptables 规矩,这给可视化盯梢到 Pod 的虚拟路由时增加了额定过程。尽管如此,咱们仍是主张开发者在出产集群中完成 NetworkPolicy API 的 CNI,并创立约束 Pod 流量的战略。

第三,启用 HostNetwork 特点创立的 Pod 将同享节点的网络空间。尽管存在一些这样做的比如,但一般状况下,大多数 Pod 不需求在主机网络上,尤其是关于有 root 特权的 Pod,这或许会导致受进犯的容器能够检查网络流量。假如开发者需求在节点网络上揭露容器端口,而运用 Kubernetes Service 节点端口无法满意需求,一个保险的挑选是能够在 PodSpec 中为容器指定 hostPort。

最终,运用主机网络的 Pod 不该运用 NET_ADMIN 功用运转,这将使它们能够读取和修正节点的防火墙规矩。

【云栖号在线讲堂】每天都有产品技能专家共享!
课程地址:https://yqh.aliyun.com/live

当即参加社群,与专家面对面,及时了解课程最新动态!
【云栖号在线讲堂 社群】https://c.tb.cn/F3.Z8gvnK

原文发布时刻:2020-05-15
本文作者:翔宇
本文来自:“dockone”,了解相关信息能够重视“dockone”