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:80 和 10.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. 总结

不总结。明天见。

深入 K8s 网络原理(二)- Service iptables 模式分析的更多相关文章

  1. k8s网络原理

    https://blog.csdn.net/watermelonbig/article/details/80646988 k8s中,每个 Pod 都有一个独立的 IP 地址,所有 Pod 在一个网络空 ...

  2. K8S网络排故障一则--iptables规则

    这个故障源起来在k8s上同时安装ceph群集(测试的时候机器不多啊) 当这两者都OK之后,原来k8s上的服务实例,则有的通,有的不通了. ==================== 所有可能的故障点,f ...

  3. 一次客户需求引发的K8S网络探究

    前言 在本次案例中,我们的中台技术工程师遇到了来自客户提出的打破k8s产品功能限制的特殊需求,面对这个极具挑战的任务,攻城狮最终是否克服了重重困难,帮助客户完美实现了需求?且看本期K8S技术案例分享! ...

  4. Kubernetes(k8s)底层网络原理刨析

    目录 1 典型的数据传输流程图 2 3种ip说明 3 Docker0网桥和flannel网络方案 4 Service和DNS 4.1 service 4.2 DNS 5 外部访问集群 5.1 外部访问 ...

  5. k8s Nodeport方式下service访问,iptables处理逻辑(转)

    原文 https://www.myf5.net/post/2330.htm k8s Nodeport方式下service访问,iptables处理逻辑 2017年07月11日 0条评论 976次阅读 ...

  6. ASP.NET Core on K8S深入学习(11)K8S网络知多少

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 一.Kubernetes网络模型 我们都知道Kubernetes作为容器编排引 ...

  7. docker+k8s基础篇二

    Docker+K8s基础篇(二) docker的资源控制 A:docker的资源限制 Kubernetes的基础篇 A:DevOps的介绍 B:Kubernetes的架构概述 C:Kubernetes ...

  8. linux基础-第十四单元 Linux网络原理及基础设置

    第十四单元 Linux网络原理及基础设置 三种网卡模式图 使用ifconfig命令来维护网络 ifconfig命令的功能 ifconfig命令的用法举例 使用ifup和ifdown命令启动和停止网卡 ...

  9. k8s网络之Flannel网络

    k8s网络主题系列: 一.k8s网络之设计与实现 二.k8s网络之Flannel网络 三.k8s网络之Calico网络 简介 Flannel是CoreOS团队针对Kubernetes设计的一个网络规划 ...

  10. k8s网络之Calico网络

    k8s网络主题系列: 一.k8s网络之设计与实现 二.k8s网络之Flannel网络 三.k8s网络之Calico网络 简介 Calico 是一种容器之间互通的网络方案.在虚拟化平台中,比如 Open ...

随机推荐

  1. OptiX8入门(一)optixHello

    本人初学者,如有错误和更好的表述,请指出 环境:CLion+VS2022+CUDA Toolkit 12.0.1+OptiX8 下载好后打开SDK就可以看到OptiX官方提供的许多例子,CMake配置 ...

  2. nmcli 命令设置网络

    nmcli 命令设置网络 设置静态 IP 地址 sudo nmcli connection modify "连接名称" ipv4.addresses IP地址/子网掩码 设置网关 ...

  3. KRPANO资源分析工具下载四方环视全景图

    提示:目前分析工具中的全景图下载功能将被极速全景图下载大师替代,相比分析工具,极速全景图下载大师支持更多的网站(包括各类KRPano全景网站,和百度街景) 详细可以查看如下的链接: 极速全景图下载大师 ...

  4. MongoDB慢日志

    MongoDB慢日志 ​ 熟悉 Mysql 的人应该知道,Mysql 是有个慢查询日志的,它可以帮助我们进行优化我们的 sql,并提高我们系统的稳定性和流畅性.那么 MongoDB 中是否也有类似的功 ...

  5. Java 21 新特性:虚拟线程(Virtual Threads)

    在Java 21中,引入了虚拟线程(Virtual Threads)来简化和增强并发性,这使得在Java中编程并发程序更容易.更高效. 虚拟线程,也称为"用户模式线程(user-mode t ...

  6. SpringBoot项目优雅停机+Pid暴力停机

    bootstrap.yaml配置项目的pid输出位置 spring: pid: file: F:/cloud-nacos/cloud_gateway/application.pid springboo ...

  7. VScode+X11支持连接服务器时支持open3d、openCV、matplotlib等可视化

    背景 连接服务器以后,想用open3d可视化点云.matplotlib画点图,但是一直不能用,原因也很简单,就是没有配置GUI传输显示,那肯定是要配置X11相关的东西. 过程 服务器 确保服务器下载了 ...

  8. SQLPLUS使用及Oracle表空间设定自动扩展

    起因:ERP不能登陆,Oracle无法访问,报错如下 后联系鼎捷se提供以下解决方案: 该问题是由于Oracle审计表AUD$数据过大导致数据库异常,现已登录DB服务器使用oracle账号执行语句tr ...

  9. android 反编译 apk 分享 smali2java 1.0.0.558

    smali2java 1.0.0.558 smali2java是一个将smali代码反编译成java代码的工具. 什么是smali?smali是将Android字节码用可阅读的字符串形式表现出来的一种 ...

  10. Android dumpsys介绍

    目录 一.需求 二.环境 三.相关概念 3.1 dumpsys 3.2 Binder 3.3 管道 四.dumpsys指令的使用 4.1 dumpsys使用 4.2 dumpsys指令语法 五.详细设 ...