K8s Service 背后是怎么工作的?

kube-proxy 是 Kubernetes 集群中负责服务发现和负载均衡的组件之一。它是一个网络代理,运行在每个节点上, 用于 service 资源的负载均衡。它有两种模式:iptables 和 ipvs

iptables

iptables 是 Linux 系统中的一个用户空间实用程序,用于配置内核的网络包过滤和网络地址转换(NAT)规则。它是 Linux 内核中的 netfilter 框架的一部分,并负责在网络包进入、转发或离开计算机时进行筛选和处理。其主要功能和用途包括:

  1. 防火墙:iptables 提供了强大的防火墙功能,可以根据不同的规则来过滤和拒绝不需要的网络包。管理员可以创建自定义的规则集,允许或拒绝从特定 IP 地址、端口或协议的数据包。

  2. NAT(网络地址转换):iptables 支持 NAT 功能,可以用来将私有网络中的计算机与外部网络连接。例如,它可以在一个 NAT 路由器上将内部网络的多个设备映射到单个外部 IP 地址。

  3. 端口转发:iptables 可以将特定的端口流量从一个网络接口转发到另一个接口或目标 IP 地址,通常用于内部网络的服务公开。

  4. 负载均衡:它也可以通过 DNAT(目标网络地址转换)功能将流量转发给多个内部服务器,实现简单的负载均衡。

iptables 是通过链(chains)和表(tables)来组织规则的。每个链由一组规则组成,当网络数据包经过时,这些规则会逐一执行。常用的表包括:

  • filter 表:用于包过滤,是最常用的表。

  • nat 表:用于网络地址转换。

  • mangle 表:用于修改数据包的 IP 层字段。

  • raw 表:用于绕过连接跟踪。

链的流向为:

 

所以,根据上图,我们能够想象出某些常用场景中,报文的流向:

到本机某进程的报文:PREROUTING –> INPUT

由本机转发的报文:PREROUTING –> FORWARD –> POSTROUTING

由本机的某进程发出报文(通常为响应报文):OUTPUT –> POSTROUTING

尽管在某些情况下配置 iptables 规则可能复杂,但它提供了高度的灵活性和强大的功能,使其成为 Linux 网络安全的重要组成部分。

service 负载均衡

我启动了一个 3 个 nginx pod,和一个对应的 service,service 的类型是 ClusterIP,这样 service 就会有一个虚拟 IP,这个 IP 会被 kube-proxy 代理到后端的 pod 上。

~ » k get pod -owide
NAME                                READY   STATUS    RESTARTS      AGE   IP            NODE       NOMINATED NODE   READINESS GATES
nginx-deployment-59f546cb79-2k9ng   1/1     Running   2 (31m ago)   50m   10.244.0.28   minikube   <none>           <none>
nginx-deployment-59f546cb79-wfw84   1/1     Running   2 (31m ago)   50m   10.244.0.30   minikube   <none>           <none>
nginx-deployment-59f546cb79-zr9xm   1/1     Running   2 (31m ago)   50m   10.244.0.27   minikube   <none>           <none>
-----------------------------------------------------------------------------------------
~ » k get svc nginx-service
NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
nginx-service   ClusterIP   10.101.57.97   <none>        80/TCP    29m

当我们在 master 使用 curl 10.101.57.97 访问 service 的时候,首先会进入 PREROUTING 链:

root@minikube:/# iptables-save |grep PREROUTING
:PREROUTING ACCEPT [0:0]
:PREROUTING ACCEPT [34:2040]
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A PREROUTING -d 192.168.49.1/32 -j DOCKER_OUTPUT
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER

首先会尝试匹配 KUBE-SERVICES 链,这个链是 kube-proxy 生成的,用于处理 service 的请求。后两个是 docker 的链,用于处理 docker 的请求。

root@minikube:/#  iptables-save |grep "\-A KUBE-SERVICES"
-A KUBE-SERVICES -d 10.96.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -j KUBE-SVC-NPX46M4PTMTKRN6Y
-A KUBE-SERVICES -d 10.101.57.97/32 -p tcp -m comment --comment "default/nginx-service cluster IP" -j KUBE-SVC-V2OKYYMBY3REGZOG
-A KUBE-SERVICES -d 10.96.0.10/32 -p udp -m comment --comment "kube-system/kube-dns:dns cluster IP" -j KUBE-SVC-TCOU7JCQXEZGVUNU
-A KUBE-SERVICES -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp cluster IP" -j KUBE-SVC-ERIFXISQEP7F7OF4
-A KUBE-SERVICES -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:metrics cluster IP" -j KUBE-SVC-JD5MR3NA4I4DYORP
-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS

我们这个 nginx-service 的 cluster IP 是 10.101.57.97, 所以会走 KUBE-SVC-V2OKYYMBY3REGZOG 链:

root@minikube:/#  iptables-save |grep "\-A KUBE-SVC-V2OKYYMBY3REGZOG"
-A KUBE-SVC-V2OKYYMBY3REGZOG ! -s 10.244.0.0/16 -d 10.101.57.97/32 -p tcp -m comment --comment "default/nginx-service cluster IP" -j KUBE-MARK-MASQ
-A KUBE-SVC-V2OKYYMBY3REGZOG -m comment --comment "default/nginx-service -> 10.244.0.27:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-POZMZY2HDLRATSJV
-A KUBE-SVC-V2OKYYMBY3REGZOG -m comment --comment "default/nginx-service -> 10.244.0.28:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-Z3HXRORN5VDCFRJU
-A KUBE-SVC-V2OKYYMBY3REGZOG -m comment --comment "default/nginx-service -> 10.244.0.30:80" -j KUBE-SEP-S46ZL6MIFVWDY42O

-A KUBE-SVC-V2OKYYMBY3REGZOG ! -s 10.244.0.0/16 -d 10.101.57.97/32 -p tcp -m comment --comment "default/nginx-service cluster IP" -j KUBE-MARK-MASQ 这条规则的如果源ip 不是 10.244.0.0/16 的 ip(也就是不是 pod发出来的请求),目的ip 是 service ip,jump 跳转到 这个链 KUBE-MARK-MASQ

root@minikube:/# iptables-save |grep "\-A KUBE-MARK-MASQ"
-A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000

这条规则的作用是给数据包打上 0x4000 这个标记。这个标记会被后续的 NAT 规则识别到,从而让这些数据包通过特定的 NAT 规则进行 IP 地址转换。

接下来看主要的三条规则:

-A KUBE-SVC-V2OKYYMBY3REGZOG -m comment --comment "default/nginx-service -> 10.244.0.27:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-POZMZY2HDLRATSJV
-A KUBE-SVC-V2OKYYMBY3REGZOG -m comment --comment "default/nginx-service -> 10.244.0.28:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-Z3HXRORN5VDCFRJU
-A KUBE-SVC-V2OKYYMBY3REGZOG -m comment --comment "default/nginx-service -> 10.244.0.30:80" -j KUBE-SEP-S46ZL6MIFVWDY42O

第一条是说有 33.33% 的几率会被转发到 KUBE-SEP-POZMZY2HDLRATSJV, 第二条是 50% 的几率会被转发到 KUBE-SEP-Z3HXRORN5VDCFRJU, 第三条是一定会被转发到 KUBE-SEP-S46ZL6MIFVWDY42O
转到第一条的概率是 33.33%,转到第二条的概率是 66.67%(没有到第一条的概率) * 50% = 33.33%,第三条就是 66.67%(没有到第一条的概率) * 50%(没有到第二条的概率) = 33.33%。所以这三条规则的概率是一样的。都是 33.33%。
那么 KUBE-SEP-POZMZY2HDLRATSJV 又是什么呢?

root@minikube:/# iptables-save |grep "\-A KUBE-SEP-POZMZY2HDLRATSJV"
-A KUBE-SEP-POZMZY2HDLRATSJV -s 10.244.0.27/32 -m comment --comment "default/nginx-service" -j KUBE-MARK-MASQ
-A KUBE-SEP-POZMZY2HDLRATSJV -p tcp -m comment --comment "default/nginx-service" -m tcp -j DNAT --to-destination 10.244.0.27:80root@minikube:/# iptables-save |grep "\-A KUBE-SEP-POZMZY2HDLRATSJV"
-A KUBE-SEP-Z3HXRORN5VDCFRJU -s 10.244.0.28/32 -m comment --comment "default/nginx-service" -j KUBE-MARK-MASQ
-A KUBE-SEP-Z3HXRORN5VDCFRJU -p tcp -m comment --comment "default/nginx-service" -m tcp -j DNAT --to-destination 10.244.0.28:80root@minikube:/# iptables-save |grep "\-A KUBE-SEP-S46ZL6MIFVWDY42O"
-A KUBE-SEP-S46ZL6MIFVWDY42O -s 10.244.0.30/32 -m comment --comment "default/nginx-service" -j KUBE-MARK-MASQ
-A KUBE-SEP-S46ZL6MIFVWDY42O -p tcp -m comment --comment "default/nginx-service" -m tcp -j DNAT --to-destination 10.244.0.30:80

第一条规则确保流量从 10.244.0.20 发出时被打上 MASQUERADE 标记,以便通过 NAT 机制进行 IP 伪装。
第二条是将流量转发到 10.244.0.20:80 并使用 DNAT 机制进行目标地址转换, 转换的 ip 10.244.0.27:80 就是 pod 的 ip 和端口。
KUBE-SEP-Z3HXRORN5VDCFRJU 和 KUBE-SEP-S46ZL6MIFVWDY42O 的规则和这条同理。

ipvs

IPVS(IP Virtual Server)是 Linux 内核中实现负载均衡功能的模块。是一种高效的负载均衡技术,可以在第 4 层(传输层)进行流量转发和调度。IPVS 通常被用于构建高性能、高可用性的负载均衡集群。

查看 ipvs 的规则:

root@minikube:/etc/apt# sudo ipvsadm -Ln|grep -A 4 10.101.57.97
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.101.57.97:80 rr
-> 10.244.0.27:80               Masq    1      0          0
-> 10.244.0.28:80               Masq    1      0          0
-> 10.244.0.30:80               Masq    1      0          0
UDP  10.96.0.10:53 rr

这个的意思是到10.101.57.97:80 的 tcp 浏览会使用 rr(轮询)的方式转发到 10.244.0.27:8010.244.0.28:8010.244.0.30:80 这三个 pod 上。Masq:指示 "Masquerading",表示通过 NAT 来处理网络流量。
所以 ipvs 的模式比 iptables 性能高的多,第一因为 ipvs 是轮询选,iptables 是逐条百分比匹配的,这个还是可以接受的。更要命的是第二条,当 pod 频繁变更的时候 service 对应的 endpoint 的 ENDPOINTS 就会增加或者是减少。那么 iptables 对应 service 的所有规则的百分比都会变化,就会导致一个 service 的规则全部要重刷,当 pod 变化太频繁时,会吃掉大量的 CPU。

不是说开启了 ipvs 就不会有 iptables 了,还需要 iptables 的 SNAT 规则来处理返回的数据包。

-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING
-A KUBE-POSTROUTING -m comment --comment "Kubernetes endpoints dst ip:port, source ip for solving hairpin purpose" -m set --match-set KUBE-LOOP-BACK dst,dst,src -j MASQUERADE

-m set --match-set KUBE-LOOP-BACK dst,dst,src 的意思是匹配 KUBE-LOOP-BACK 这个 set,这个 set 里面存放的是 pod 的 ip,这个规则的作用是将数据包的源地址替换为本机的地址,以便数据包能够正确返回到客户端。
为什么是 pod ip 而不是 service cluster ip 呢?因为已经通过 ipvs DNAT 过了,所以这里是 pod ip。

root@minikube:/etc/apt# ipset -L|grep -A 15 KUBE-LOOP-BACK
Name: KUBE-LOOP-BACK
Type: hash:ip,port,ip
Revision: 6
Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xe4e21451
Size in memory: 544
References: 1
Number of entries: 6
Members:
10.244.0.28,tcp:80,10.244.0.28
10.244.0.30,tcp:80,10.244.0.30
10.244.0.29,tcp:9153,10.244.0.29
10.244.0.29,tcp:53,10.244.0.29
10.244.0.27,tcp:80,10.244.0.27
10.244.0.29,udp:53,10.244.0.29

很明显我们的三个 pod 都在这个 set 里面。

-A KUBE-POSTROUTING -m comment --comment "Kubernetes endpoints dst ip:port, source ip for solving hairpin purpose" -m set --match-set KUBE-LOOP-BACK dst,dst,src -j MASQUERADE

这条规则的作用是将数据包的源地址替换为本机的地址,以便数据包能够正确返回到客户端。现在我们使用 curl 发出的包目标 ip 是 pod ip了,源 ip 是 node ip。等到数据包返回的时候,kernel 会根据 链路追踪 中的数据记录,会把包的源ip 的pod ip 替换为 serice cluster ip, 目标 ip 从 node ip 替换为我发起请求的 ip。这样包就能正确返回到客户端了。

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

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

相关文章

Kroma宣布推出Spectrum:以太坊Layer-2的先进原生质押服务

Kroma宣布推出备受期待的Spectrum&#xff0c;这是一项先进的原生质押服务&#xff0c;旨在彻底改变以太坊 Layer-2格局。Spectrum将于2024年5月14日开始运营&#xff0c;为用户提供利用质押ETH、stETH和eETH的奖励机会&#xff0c;助力用户在去中心化金融&#xff08;DeFi&…

爆火!开源多模态大模型在手机端进行本地部署!

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对大模型& AIGC 技术趋势、大模型& AIGC 落地项目经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了…

二叉树遍历操作详解

目录 一、思路详解 1.1 递归思路 1.2 递归分支图 1.3 递归栈帧图 二、C语言实现 2.1 前序遍历 2.2 中序遍历 2.3 后序遍历 三、查找值为x的结点 3.1 递归思路 3.2 C语言代码 一、思路详解 采用递归的思想解决问题&#xff0c;以高度为3的满二叉树为例。 1.1 递归思…

ClickHouse 几年内数据查询及细节

在 ClickHouse 中&#xff0c;查询三年内的时间数据可以使用以下方法&#xff1a; 1. 使用日期函数 可以使用 ClickHouse 支持的日期函数来筛选出三年内的数据。例如&#xff0c;使用 today() 函数获取当天日期&#xff0c;使用 toDate() 函数将日期转换为指定格式&#xff0…

【C++】学习笔记——map和set

文章目录 十五、map和set1. 关联式容器2. set的介绍3. set的使用4. multiset5. map的介绍6. map的使用7. multimap8. map中重载的operator[] 未完待续 十五、map和set 1. 关联式容器 我们已经接触过STL中的部分容器&#xff0c;比如&#xff1a;vector 、list 、deque 等&…

Golang | Leetcode Golang题解之第99题恢复二叉搜索树

题目&#xff1a; 题解&#xff1a; func recoverTree(root *TreeNode) {var x, y, pred, predecessor *TreeNodefor root ! nil {if root.Left ! nil {// predecessor 节点就是当前 root 节点向左走一步&#xff0c;然后一直向右走至无法走为止predecessor root.Leftfor pr…

OpenHarmony开发之MQTT讲解

相信MQTT这个名称大家都不陌生&#xff0c;物联网的开发必然会遇到MQTT相关知识的应用。那么什么是MQTT&#xff1f;它有什么特点&#xff1f;它能解决什么问题&#xff1f;它是如何工作的&#xff1f;OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;的物…

简单快捷的图片格式转换工具:认识webp2jpg-online

经常写博客或记笔记的朋友们可能会碰到图床不支持的图片格式或图片太大需要压缩的情况。通常&#xff0c;我们会在浏览器中搜索在线图片格式转换器&#xff0c;但这些转换器往往伴有烦人的广告或要求登录&#xff0c;并且支持的转换格式有限。最近&#xff0c;我在浏览 GitHub …

hls.js实现分片播放视频

前言&#xff1a;hls.js官网&#xff1a;hls.js - npm 一、demo——在HTML中使用 <audio id"audio" controls></audio><script src"https://cdn.jsdelivr.net/npm/hls.jslatest"></script> <script>document.addEventList…

upload-labs 通关方法

目录 Less-1&#xff08;JS前端验证&#xff09; Less-2&#xff08;MIME验证&#xff09; Less-3&#xff08;黑名单&#xff0c;特殊过滤&#xff09; Less-4&#xff08;黑名单验证&#xff0c;.htaccess&#xff09; Less-5&#xff08;黑名单&#xff0c;点空格点绕过…

Qt | QCalendarWidget 类(日历)

01、QCalendarWidget 类 1、QCalendarWidget 类是 QWidget 的直接子类,该类用于日历,见下图 02、QCalendarWidget 属性 ①、dateEditAcceptDelay:int 访问函数:int dateEditAcceptDelay()const; void setDateEditAcceptDelay(int) 获取和设置日期编辑器的延迟时间(以毫秒…

给树莓派配置静态IP地址

第一步&#xff1a;查找默认网关 打开windowr&#xff1b;输入cmd&#xff0c; 输入 最后一行就是默认网关 ipconfig第二步&#xff1a;确定分配好给树莓派的IP地址 要注意&#xff1a;&#xff08;1&#xff09;静态ip地址与路由器网段保持一致&#xff08;2&#xff09;与…

压缩设备液压控制比例放大器

液压比例阀放大器是液压控制系统中的重要部件之一&#xff0c;用于控制输出油压方向流量和压力的精确控制。它由BEUEC比例放大器和比例电磁阀组成&#xff0c;通过调节比例放大器的增益和灵敏度参数&#xff0c;可以实现对液压系统输出油压方向流量和压力的精确控制。适用于各种…

动态IP与静态IP有什么区别?如何选择?

动态IP和静态IP都是指网络设备&#xff08;如计算机、服务器、路由器等&#xff09;在互联网上分配的IP地址的类型。 一、什么是动态IP&#xff0c;什么是静态IP&#xff1f; 1、什么是动态IP&#xff1f; 动态IP是指由Internet服务提供商&#xff08;ISP&#xff09;动态分配…

SpringBoot中使用AOP实现日志记录功能

目录 一、SpringBoot框架介绍 二、什么是 AOP 三、日志记录的必要性 四、SpringBoot中如何使用AOP实现日志记录功能 一、SpringBoot框架介绍 SpringBoot是一个开源的Java开发框架&#xff0c;旨在简化基于Spring框架的应用程序的开发。它提供了一套开箱即用的工具&#xf…

express.js--连接数据库,并且增删改查(四)

使用数据库需要在电脑安装mysql&#xff0c;然后使用navicat 我没有下载mysql,我使用的是小皮里面的数据库&#xff0c;需要破解版的navicat可以私信我 安装mysql npm i mysql 数据库的基本信息&#xff0c;我是直接写到配置文件里面的 config/index.js module.exports {…

【Android】联系人列表补充

真布局--叠起来垂直管 效果展示 部分代码&#xff08;在activity_main&#xff09;里面 <FrameLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"…

如何在Windows下使用Docker Desktop运行CentOS容器

引言&#xff1a; 在Windows操作系统中&#xff0c;我们可以使用Docker Desktop来轻松运行和管理各种Linux容器&#xff0c;包括CentOS。今天&#xff0c;我们就来详细讲解一下如何在Windows环境下使用Docker Desktop来运行CentOS容器。 一、安装Docker Desktop 首先&#x…

WPF中CommandParameter用法

1. 界面样式 2. XAML中代码部分 <ButtonGrid.Row"0"Grid.Column"1"Command"{Binding BtnClick_Number}"CommandParameter"7"Content"7"Style"{StaticResource BtnStyle_Num}" /> <ButtonGrid.Row"…

【个人商业画布】你有思考过把自己当成一家公司来经营吗?

商业模式画布(Business Model Canvas)&#xff0c;是亚历山大奥斯特瓦德在《商业模式新生代》中提出的一种用于描述商业模式、可视化商业模式、评估商业模式以及改变商业模式的通用语言。它由9个模块构成&#xff0c;帮助创业者理清为“细分客户提供独有价值”&#xff0c;从而…