首页 > 系统相关 >深入 K8s 网络原理(二)- Service iptables 模式分析

深入 K8s 网络原理(二)- Service iptables 模式分析

时间:2023-12-21 09:02:05浏览次数:43  
标签:iptables Service nginx 模式分析 anywhere KUBE any

目录

1. 概述

接上一篇《深入 K8s 网络原理(一)- Flannel VXLAN 模式分析》,今天我们继续来分析 Kubernetes Service 的实现原理。

2. 准备 Service 和 Pods 资源

镜像和上一篇一样;

Deployment 的 YAML 如下:

  • nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:test1
        ports:
        - containerPort: 80

对应的 Service YAML 如下:

  • nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    nodePort: 30007

3. K8s 里 Service 的实现原理

Kubernetes 提供了几种不同类型的 Service,包括:

  • ClusterIP:这是最常见的 Service 类型,为 Service 提供一个集群内部的 IP 地址,使得 Service 只能在集群内部访问。
  • NodePort:这种类型的 Service 在每个节点上开放一个端口(NodePort),从而允许从集群外部通过 <NodeIP>:<NodePort> 访问 Service。
  • LoadBalancer:这种类型的 Service 通常由云提供商支持,它会在集群外部创建一个负载均衡器,将外部流量分发到集群内的 Pods。
  • ExternalName:通过返回一个名字(而非 IP 地址)来指向外部服务。

接着具体来看 Service 的实现。

3.1 kube-proxy 组件

Kubernetes 集群中每个节点上会运行一个关键组件 kube-proxy,它负责为 Service 对象实现网络代理,使得网络流量可以透明地定向到后端 Pods。kube-proxy 支持几种不同的代理模式,最常见的是 iptables 模式和 IPVS 模式。

  1. iptables 模式
  • 在这种模式下,kube-proxy 使用 iptables 规则来捕获到达 Service 的流量,并将其重定向到后端 Pods。每当 Service 或 Pod 发生变化时,kube-proxy 都会更新 iptables 规则。
  • iptables 模式是最简单且广泛使用的,但在大规模集群中可能会面临性能问题,因为每个网络包都需要通过不短的规则链进行处理。
  1. IPVS (IP Virtual Server) 模式
  • IPVS 模式使用内核的 IPVS 功能,该功能提供了内置的负载均衡功能。与 iptables 相比,IPVS 可以处理更大规模的流量,拥有更好的性能和更复杂的负载均衡算法(最少连接等)。
  • 在这种模式下,kube-proxy 会创建一个虚拟服务器,为每个 Service 分配一个虚拟 IP(VIP),并将流量负载均衡到后端 Pods。

以 kube-proxy 的 iptables 模式为例,我们具体来看下 Service 创建后,iptables 是如何将 Service 流量转到 pods 上的。

3.2 iptables 简介

简单介绍下 iptables:

iptables 是一种在 Linux 系统中广泛使用的工具,它允许管理员配置内核的 netfilter 模块,以控制网络数据包的流入流出。这个工具提供了一个框架,用于定义规则,这些规则决定了如何处理经过网络接口的数据包。

iptables 的核心功能主要包括:

  • 数据包过滤:iptables 最常用于过滤数据包,即决定哪些数据包可以通过网络接口,哪些应该被阻止。
  • 网络地址转换 (NAT):它可以用于修改数据包的源或目的地址,常用于路由和隐藏内部网络结构。
  • 端口转发:iptables 可以重定向到特定端口的数据流,用于设置端口转发。

刚从铺灰的硬盘里发现一张三年前画的 iptables 相关的图(我都忘记这个图应该叫啥名字了):

3.3 iptables 规则

下面具体看下 Service 对应的 iptables 规则。

3.3.1 Service,Pod 和 Host 信息

前面创建了 Service 和 Deployment,对应的 Service 和 Pod 资源如下:

  • kgsvc
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
nginx-service   NodePort    10.107.33.105   <none>        80:30007/TCP   152m
  • kgpoowide
NAME                                READY   STATUS    RESTARTS   AGE    IP           NODE
nginx-deployment-7fbb8f4b4c-89bds   1/1     Running   0          155m   10.244.2.4   minikube-m03
nginx-deployment-7fbb8f4b4c-d29zm   1/1     Running   0          155m   10.244.1.5   minikube-m02

此外,我的 K8s 集群包括3个节点,nodes 的 ip/hostname 信息如下:

192.168.49.2	minikube
192.168.49.3	minikube-m02
192.168.49.4	minikube-m03

3.3.2 从 NodePort 入手寻找 iptables 规则

现在进到 minikube 节点,也就是 K8s 主节点,查看下 nat 表的链信息,过滤下 NodePort 端口 30007:

  • sudo iptables -t nat -L | grep 30007
KUBE-EXT-V2OKYYMBY3REGZOG  tcp  --  anywhere anywhere /* default/nginx-service */ tcp dpt:30007

可以看到一条链:KUBE-EXT-V2OKYYMBY3REGZOG,具体看下这条链的信息:

  • sudo iptables -t nat -L KUBE-EXT-V2OKYYMBY3REGZOG -v
Chain KUBE-EXT-V2OKYYMBY3REGZOG (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-SVC-V2OKYYMBY3REGZOG  all  --  any    any     anywhere             anywhere

从这里可以看到 KUBE-EXT-V2OKYYMBY3REGZOG 有一条子链 KUBE-SVC-V2OKYYMBY3REGZOG。继续看 KUBE-SVC-V2OKYYMBY3REGZOG 链:

  • sudo iptables -t nat -L KUBE-SVC-V2OKYYMBY3REGZOG -v
Chain KUBE-SVC-V2OKYYMBY3REGZOG (2 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-SEP-J2DHXTF62PN2AN4F  all  --  any    any     anywhere             anywhere             /* default/nginx-service -> 10.244.1.5:80 */ statistic mode random probability 0.50000000000
    0     0 KUBE-SEP-A4R5AW5RLMEQF7RP  all  --  any    any     anywhere             anywhere             /* default/nginx-service -> 10.244.2.4:80 */

进一步可以找到两条 KUBE-SVC-V2OKYYMBY3REGZOG 的子链 KUBE-SEP-J2DHXTF62PN2AN4F 和 KUBE-SEP-A4R5AW5RLMEQF7RP,这里对应2个 pods。以 KUBE-SEP-J2DHXTF62PN2AN4F 为例继续跟:

  • sudo iptables -t nat -L KUBE-SEP-J2DHXTF62PN2AN4F -v
Chain KUBE-SEP-J2DHXTF62PN2AN4F (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DNAT       tcp  --  any    any     anywhere             anywhere             /* default/nginx-service */ tcp to:10.244.1.5:80

到这里 target 不再是其他链,而是 DNAT,也就是请求 Service 的 NodePort 最终流量被 DNAT 到了 10.244.1.5:8010.244.2.4:80 这两个 Endpoints,它们分别对应2个 pods。

3.3.3 从 PREROUTING 和 OUTPUT 链寻找 K8s 相关子链

先看 PREROUTING:

  • sudo iptables -t nat -L PREROUTING -v
Chain PREROUTING (policy ACCEPT 5 packets, 300 bytes)
 pkts bytes target     prot opt in     out     source               destination
   99  5965 KUBE-SERVICES  all  --  any    any     anywhere             anywhere             /* kubernetes service portals */

可以看到入向流量全部都会经过 KUBE-SERVICES 链处理。继续看 OUTPUT:

sudo iptables -t nat -L OUTPUT -v

Chain OUTPUT (policy ACCEPT 3355 packets, 202K bytes)
 pkts bytes target     prot opt in     out     source               destination
29961 1801K KUBE-SERVICES  all  --  any    any     anywhere             anywhere             /* kubernetes service portals */

同样全部出向流量也被 KUBE-SERVICES 链处理。继续看下 KUBE-SERVICES 链:

  • sudo iptables -t nat -L KUBE-SERVICES -v
Chain KUBE-SERVICES (2 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-SVC-V2OKYYMBY3REGZOG  tcp  --  any    any     anywhere             10.107.33.105        /* default/nginx-service cluster IP */ tcp dpt:http
 3391  203K KUBE-NODEPORTS  all  --  any    any     anywhere             anywhere             /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL

可以看到2条子链,一个是表示 Nginx Service 的 Cluster IP 的子链 KUBE-SVC-V2OKYYMBY3REGZOG,另外一个是表示集群 NodePort 的 KUBE-NODEPORTS 子链。KUBE-SVC-V2OKYYMBY3REGZOG 在前面已经具体看过了,那么 KUBE-NODEPORTS 子链具体又包含啥信息呢:

  • sudo iptables -t nat -L KUBE-NODEPORTS -v
Chain KUBE-NODEPORTS (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-EXT-V2OKYYMBY3REGZOG  tcp  --  any    any     anywhere             anywhere             /* default/nginx-service */ tcp dpt:30007

可以看到当 TCP 流量的目的端口是 30007 的时候,就会匹配到 KUBE-EXT-V2OKYYMBY3REGZOG 子链,KUBE-EXT-V2OKYYMBY3REGZOG 子链的内容前面已经具体看过了。换言之,每多创建一个 NodePort 类型的 Service,kube-proxy 就会在 KUBE-NODEPORTS 子链下新挂一条 KUBE-EXT-XXX 子链。

3.3.4 总结下

IP 包进出主机都会经过 KUBE-SERVICES 链,进而根据 destination 地址匹配到不同的子链:

  1. 如果目的地址是某个 Service 的 Cluster IP,那么就匹配到具体的 KUBE-SVC-XXX 处理;
  2. 否则,就匹配到 KUBE-NODEPORTS 处理;流量匹配到 KUBE-NODEPORTS 后,会进一步根据 tcp 目的端口 来匹配具体的子链 KUBE-EXT-XXX;

如果流量匹配到 KUBE-EXT-XXX 子链,端口命中,那么下一条依旧是表示 Cluster IP 的 KUBE-SVC-XXX,所以两条子链在这里汇合。而 KUBE-SVC-XXX 链上的规则会进一步将 IP 包匹配到 KUBE-SEP-XXX 子链上,这些子链表达的是“Service Endpoints”。默认情况下 KUBE-SVC-XXX 会根据 Pod 数量按照相等的概率将流量分流到多个 KUBE-SEP-XXX 上进一步匹配。而 KUBE-SEP-XXX 链会执行类似“DNAT to:10.244.1.5:80”过程,最终将一开始请求 Service 的流量就丢给了 Pod。

所以,当你通过 NodePort/ClusterIP 方式访问 pods 的时候,以两副本为例,整体流量匹配过程大致如下图:

4. 总结

不总结。明天见。

标签:iptables,Service,nginx,模式分析,anywhere,KUBE,any
From: https://www.cnblogs.com/daniel-hutao/p/17918196.html

相关文章

  • 使用 Amazon Fault Injection Service 演示多区域和多可用区应用程序弹性
    文章作者:JeffAmazonFaultInjectionService(FIS)可帮助您将混沌工程大规模付诸实践。今天,我们推出了新的场景,这些场景可以让您演示在亚马逊云科技可用区完全断电,或从一个亚马逊云科技区域到另一个亚马逊云科技区域的连接中断时,您的应用程序是否按预期运行。亚马逊云科技开发者社......
  • 使用WinSW将jar创建成Windows服务;使用Microsoft.Extensions.Hosting.WindowsServices
    【背景】我们有几个历史产品,需要部署在Windows系统上,产品有jar包,也有.net工程,为了优美的启动服务,思考了两种处理方式。第一种是电脑开机启动,将启动命令设置为快捷键,并将快捷键拷贝到C:\ProgramData\Microsoft\Windows\StartMenu\Programs\Startup目录下,该方式有个缺点,由于ja......
  • Databend 源码阅读: Meta-service 数据结构
    作者:张炎泼(XP)DatabendLabs成员,Databend分布式研发负责人https://github.com/drmingdrmer引言Databend是一款开源的云原生数据库,采用Rust语言开发,专为云原生数据仓库的需求而设计。面向云架构:Databend是完全面向云架构的数据库,可以在云环境中灵活部署和扩展简介|......
  • Databend 源码阅读: Meta-service 数据结构
    作者:张炎泼(XP)DatabendLabs成员,Databend分布式研发负责人https://github.com/drmingdrmer引言Databend是一款开源的云原生数据库,采用Rust语言开发,专为云原生数据仓库的需求而设计。面向云架构:Databend是完全面向云架构的数据库,可以在云环境中灵活部署和扩展简介|......
  • 深入 K8s 网络原理(一)- Flannel VXLAN 模式分析
    目录1.概述2.TL;DR3.Pod间通信问题的由来4.测试环境准备5.从veth设备聊起6.网桥cni06.1在Pod内看网卡信息6.2在host上看网卡信息7.VTEPflannel.18.最后看下Flannel的配置9.总结1.概述这周集中聊下K8s的集群网络原理,我初步考虑分成3个方向:Pod-to-Pod......
  • 启动微服务报错:java.lang.IllegalStateException: Service id not legal hostname (se
    Order微服务通过opneFeign调用storage和account时报错原因分析:服务名称不能有下划线,可以使用中划线,Springcloud无法识别下划线,将下划线改为中划线即可注意:这个改了之后,你在进行远程调用的时候,接口对应的方法接口也需要相应改变【分布式开发,一个微服务模块修改了,很可能......
  • Docker启动Nacos报错:Nacos Server did not start because dumpservice bean construct
    一、表象重启服务器之后Docker运行Nacos容器,启动成功,但是外网无法访问。查看了一下Nacos启动日志(dockerlogsnacos容器名)二、分析很明显是数据库配``置问题。。如果是数据库配置的问题,可以着重检查以下信息尤其是MySQL内网Host,查询方式见Docker安装Nacos三、解决我已......
  • 【Azure App Service】当App Service中使用系统标识无法获取Access Token时
    问题描述AppSerive上的应用配置了系统标识(SystemIdentity),通过系统标识获取到访问KeyVault资源的AccessToken。但这次确遇见了无法获取到正常的AccessToken。 验证问题1:查看AppService的门户中是否启用了系统标识  2:进入AppService的Kudu站点,查看Environment参数中IDENT......
  • Istio从入门到精通—— 流量治理的原理 —— VirutalService —— HTTPRedirect
    流量治理的原理——VirutalService——HTTPRedirecthttps://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPRedirect HTTPRedirectcanbeusedtosenda301redirectresponsetothecaller,wheretheAuthority/HostandtheURIinthe......
  • Istio从入门到精通—— 流量治理的原理 —— VirutalService —— TLSMatchAttributes
    流量治理的原理——VirutalService—— TLSMatchAttributeshttps://istio.io/latest/docs/reference/config/networking/virtual-service/#TLSMatchAttributesTLSconnectionmatchattributes.FieldTypeDescriptionRequiredsniHostsstring[]SNI(s......