K8s Service 背后是怎么工作的?
kube-proxy 是 Kubernetes 集群中负责服务发现和负载均衡的组件之一。它是一个网络代理,运行在每个节点上, 用于 service 资源的负载均衡。它有两种模式:iptables 和 ipvs。
iptables
iptables 是 Linux 系统中的一个用户空间实用程序,用于配置内核的网络包过滤和网络地址转换(NAT)规则。它是 Linux 内核中的 netfilter 框架的一部分,并负责在网络包进入、转发或离开计算机时进行筛选和处理。其主要功能和用途包括:
-
防火墙:iptables 提供了强大的防火墙功能,可以根据不同的规则来过滤和拒绝不需要的网络包。管理员可以创建自定义的规则集,允许或拒绝从特定 IP 地址、端口或协议的数据包。
-
NAT(网络地址转换):iptables 支持 NAT 功能,可以用来将私有网络中的计算机与外部网络连接。例如,它可以在一个 NAT 路由器上将内部网络的多个设备映射到单个外部 IP 地址。
-
端口转发:iptables 可以将特定的端口流量从一个网络接口转发到另一个接口或目标 IP 地址,通常用于内部网络的服务公开。
-
负载均衡:它也可以通过 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:80,10.244.0.28:80,10.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。这样包就能正确返回到客户端了。
相关文章:
K8s Service 背后是怎么工作的?
kube-proxy 是 Kubernetes 集群中负责服务发现和负载均衡的组件之一。它是一个网络代理,运行在每个节点上, 用于 service 资源的负载均衡。它有两种模式:iptables 和 ipvs。 iptables iptables 是 Linux 系统中的一个用户空间实用程序,用于…...
ClickHouse配置与使用
静态IP配置 # 修改网卡配置文件 vim /etc/sysconfig/network-scripts/ifcfg-ens33# 修改文件内容 TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic IPADDR192.168.18.128 NETMASK255.255.255.0 GATEWAY192.168.18.2 DEFROUTEyes IPV4_FAILURE_FATALno IPV6INIT…...
将某一个 DIV 块全屏展示
文章目录 需求分析 需求 上节我们研究了如何将页面中的指定 div 下载为图片:跳转查看 本节演技一下如何将 DIV 全屏展示 全屏展示某一个 DIV 分析 其实就是模拟键盘动作 F11 var element document.getElementById(pic) var requestMethod element.requestFullS…...
K8S集群再搭建
前述:总体是非常简单的,就是过程繁琐,不过都是些重复的操作 master成员: [controller-manager, scheduler, api-server, etcd, proxy,kubelet] node成员: [kubelet, proxy] master要修改的配置文件有 1. vi /etc/etcd/etcd.conf # 数…...
工具-博客搭建
以下相关讲解均基于hexo github pages方案,请注意!!!博客搭建方案选择 参考文章1 搭建教程 参考文章1 hexo github pages搭建过程中遇到的问题 删除categories、tags 1、删除含有需要删除categories、tags的文章 2、hexo …...
贪心算法:合并区间
参考资料:代码随想录 题目链接:. - 力扣(LeetCode) 做过用最少数量的箭引爆气球和无重叠区间这两道题目后,题意和题解都不难理解。唯一的一点儿难点是对于api的运用。 class Solution {public int[][] merge(int[][…...
DFA 算法
为什么要学习这个算法 前一段时间遇到了瓶颈,因为词库太多了导致会有一些速度过慢,而且一个正则表达式已经放不下了,需要进行拆分正则才可以。 正好我以前看过有关 dfa 的介绍,但是并没有深入的进行研究,所以就趁着周…...
Web(数字媒体)期末作业
一.前言 1.本资源为类似于打飞机的网页游戏 2.链接如下:【免费】前端web或者数字媒体的期末作业(类似于打飞机的2D网页小游戏)资源-CSDN文库 二.介绍文档...
展现金融科技前沿力量,ATFX于哥伦比亚金融博览会绽放光彩
不到半个月的时间里,高光时刻再度降临ATFX。而这一次,是ATFX不曾拥有的桂冠—“全球最佳在线经纪商”(Best Global Online Broker)。2024年5月15日至16日,拉丁美洲首屈一指的金融盛会—2024年哥伦比亚金融博览会(Money Expo Colombia 2024) 于…...
html 根字号 以及 设置根元素font-size:calc(100vw/18.75)、元素rem实现自适应
rem 单位介绍:rem 是相对文档根元素(html)字体大小的尺寸单位,当元素的尺寸或文字字号等使用 rem 单位时,会随着根元素的 font-size变化而变化。 得出结论:在不同分辨率的设备下动态设置根元素的字体大小就可以实现页面自适应。 …...
size_t无符号数相关知识点
size_t无符号数相关知识点 在代码编译的时候,报错一个warning: comparison between signed and unsigned interger expression [-wsign-compare] 找到代码,告警这一段代码 size_t count timeProtocol.m_intersectionArray.size(); for (u…...
深度学习之基于Tensorflow+Flask框架Web手写数字识别
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 手写数字识别是深度学习领域中的一个经典问题,也是计算机视觉领域的重要应用之一。…...
2024电工杯B题食谱评价与优化模型思路代码论文分析
2024年电工杯数学建模竞赛B题论文和代码已完成,代码为B题全部问题的代码,论文包括摘要、问题重述、问题分析、模型假设、符号说明、模型的建立和求解(问题1模型的建立和求解、问题2模型的建立和求解、问题3模型的建立和求解)、模型…...
blender安装cats-blender-plugin-0-19-0插件,导入pmx三维模型
UE5系列文章目录 文章目录 UE5系列文章目录前言一、Blender安装二、cats-blender-plugin-0-19-0插件下载三、下载bmp文件四、在blender2.93中安装cats-blender-plugin-0-19-0插件 前言 blender本身不支持pmx三维模型,需要用到cats-blender-plugin-0-19-0插件。 一…...
[源码+搭建教程]西游伏妖篇手游_GM_单机+和朋友玩
为了学习和研究软件内含的设计思想和原理,本人花心血和汗水带来了搭建教程!!! 教程不适于服架设,严禁服架设!!!请牢记!!! 教程仅限学习使用&…...
windows、mac、linux中node版本的切换(nvm管理工具),解决项目兼容问题 node版本管理、国内npm源镜像切换
文章目录 在工作中,我们可能同时在进行2个或者多个不同的项目开发,每个项目的需求不同,进而不同项目必须依赖不同版本的NodeJS运行环境,这种情况下,对于维护多个版本的node将会是一件非常麻烦的事情,nvm就是…...
【MySQL精通之路】全文搜索-布尔型全文搜索
1.使用方法 MySQL可以使用IN BOOLEAN MODE修饰符执行布尔全文搜索。 使用此修饰符,某些字符在搜索字符串中单词的开头或结尾具有特殊含义。 在下面的查询中,和-运算符分别表示单词必须存在或不存在,才能进行匹配。 因此,查询检…...
【学习笔记】C++每日一记[20240520]
简述几种内存泄漏的预防机制 用智能指针代替普通指针,由于智能指针自带引用计数功能,能够记录动态分配空间的引用数量,在引用计数为零时,自动调用析构函数释放空间。 借助一些内存泄漏检测工具,例如Valgrind、Memche…...
【热门话题】一文带你读懂公司是如何知道张三在脉脉上发了“一句话”的
按理说呢,A公司和脉脉属于不同的平台,而且脉脉上大家可以匿名发言,所以,即便我坐在你边上,我发了一句话上去,你也不知道是谁发的。但通过一些技术,我们却可以分析出,公司是如何知道张…...
linux命令日常使用思考
linux命令日常使用思考 复制的相关问题scp和cp的区别root192.168.5.229-r的理解 更新版本的相关问题svn info 根目录和家目录的区别根目录家目录 复制的相关问题 scp和cp的区别 安全性:SCP 是基于 SSH 的加密传输协议,可以保证数据在传输过程中的安全性…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...
