k8s网络原理-ipvs

一、背景知识

  本文主要介绍k8s网络中service 的两种模式(clusterIp、nodeport),数据是如何通过ipvs&iptables流转的。在学习上述知识的同时,还需要了解一下ipset、conntrack的相关知识。 往期回顾文章

1.1、ipset

  ipset是什么?ipset其实是iptables的扩展,可以定义一些列地址的集合。拿黑名单来举例,我想让黑名单里面的ip拒绝访问网站(黑名单有很多个),按照传统iptables做法,需要在filter表添加很多规则匹配时一条一条匹配效率很低(严重影响性能),而有了ipset,则只用添加一条规则即可,使用hash结构效率很高。

而使用ipset命令如下

  当然,ipset还支持 hash:ip,hash:ip,port,ip等多种hash key的组成,具体可以通过 ipset -h 查看。接下来说明一下 -m set 后面 src 和 dst 两个的含义。src 指来源,dst 指目标,此规则的意思是来自192.178.113.100 ip 访问本机8410端口的流量给DROP掉。
ipset使用hash结构,比iptables的链表遍历效率要高很多。ipset还有很多更加高级的玩法,本文就不在阐述了。

1.2、ipvs

  lvs是什么?全称是Linux Virtual Server,是由章文嵩博士主导的开源负载均衡项目,目前已经集成到linux内核中。lvs提供了丰富的负载均衡能力,接收到用户请求后根据具体的负载均衡算法在内核态把请求转发到后端的某个server上,也就是说lvs不需要监听具体的端口。接下来我们看一下lvs的一些基本概念。

  ipvs的原理如下。ipvs工作在iptables 的 input链上,VIP一般定义在DS节点上的一个虚拟ip,拿nat模式举例如下。

① : 当请求数据包到DS上最先经过iptables 的PREROUTING链,判断目标ip (VIP) 是本机的ip,于是把请求转发到INPUT链上。
② : 因为lvs工作在INPUT链上,数据到达INPUT链上后lvs会将用户请求和定义的后端服务做对比,如果是请求的后端服务,则使用某种负载均衡算法找到一个后端RIP,修改数据包的目的ip和端口为某个RIP的(DNAT转换)。
③ : 此时数据到达POSTROUTING链(不会做SNAT),数据包的源ip 为CIP,目的ip为RIP,数据包发往RIP上。

lvs提供了三种包转发模式,如下所示

由于k8s使用的是NAT模式,接下来看下 NAT模式下的数据包流向 。如下图所示

①:请求数据包到达DS,数据包经过PREROUTING链,此时ip 包 src ip为CIP,dst ip 为VIP
②:由于请求的VIP是DS上的虚拟ip,数据包发往INPUT链。
③:数据包到INPUT链上后,ipvs发现数据包请求是定义的集群服务,于是使用定义好的负载均衡算法找到一个具体的RS节点,做DNAT,修改数据包dst ip为RIP,数据包到达POSTROUTING链,发送给RS。
④:RS收到数据包后对比dst ip 发现是自己,接收数据包做处理,处理完成后ip 数据包 src ip 为RIP,dst ip 为CIP,把数据包发给DS。
⑤:DS 接收到RS的响应包,修改src ip 为自身的VIP,dst ip 为CIP,把数据包发送给client端。

三种模式对比&优缺点

接下来在简单聊一下ipvs的负载均衡策略,简单介绍下面四种。

  上面介绍完了ipvs内核态的基本原理,接下来介绍一下如何使用 ipvsadm 用户态命令来操作ipvs。说明:此次试验是在四个虚拟机上,ipvs的模式使用的nat模式,RS的网关没有指向DS的ip(没办法做到)在DS节点上手动创建SNAT命令,下文有详细介绍。创建一个vip,在ip为192.168.113.101上

为vip添加RS

添加完成RS后,查看ipvs规则,如下图所示

client端的ip地址为192.168.113.102,client端要想直接访问vip的话,需要在client端添加静态路由,添加命令如下

添加完命令后,在client端curl 10.10.0.1:8410 发现不通,此时去某个RS上抓包如下

  上图抓包显示,client 直接访问的vip,而数据包的目的ip 变为了rs的ip,因此可以看出ipvs做了DNAT转换。因为做了DNAT,RS发送响应数据直接发给client,client收到RS的数据包。client给vip发的包却收到了RS的响应包(client 想我从来没有给RS发过数据),因此client端会把此数据包丢弃。

  因为ipvs没有做SNAT,接下来在DS上添加iptables规则自己实现SNAT的功能,添加完SNAT后, RS就看不到真实的CIP了

  此时还是不通,查找资料后发现ipvs 的 conntrack 没有开,手动打开,后续文章介绍conntrack是什么,设置完成后可以愉快的访问了。

  总结:通过ipvs提供的DNAT功能和负载均衡功能,很容易实现外部用户访问内网的需求。但是还要考虑高可用层面,比如主DS宕机VIP要漂移到备DS上,后端RS重启或宕机,ipvs负载均衡列表中要及时把有问题的RS剔除,这样才能真正的实现高可用。

1.3、conntrack

  大家在家上网时用到的都是192.168.x.x的ip地址,这是私网ip地址。那么大家是如何能够成功的访问外网的呢?答案是路由器帮我们做了SNAT的功能,使我们发出的数据包的src ip变为路由器的公网ip,这样数据包就能在互联网上愉快的转发了。从而实现了对内网的保护。

  那么问题来了,既然做了SNAT转换,那响应数据包回来以后路由器怎么知道转到哪台PC上呢?路由器可能链接了很多PC,不可能都给每一个PC转发吧。。。答案就是conntrack实现的。

  接下来我拿上面ipvs的例子举例,我们手动实现了在DS上SNAT转换,在client上curl vip:8410,这时候查看DS上和client上的conntrack表如下

先从client上的连接跟踪分析起:主要看 src、dst、sport、dport这几个字段。
client发送数据包

client端发出数据包的src ip 为192.168.113.102,dst ip 为10.10.0.1 (VIP), sport 为35562这个端口,dport为8410(VIP 定义端口)。

client端接收响应数据包

期望src ip 为vip(10.10.0.1),dst ip 为CIP(192.168.113.102),sport为8410,dport为35562

DS接收数据包

DS接收到src ip 为CIP(192.168.113.102),dst ip 为vip(10.10.0.1),sport为35562,dport为8410的数据包

DS接收响应数据包

  由于在DS侧做了DNAT转换,根据负载均衡策略找到了一个RS(RIP 192.168.113.99),同时也做了SNAT转换(判断是否是VIP和端口),转换为DS的DIP。所以当DS收到src ip 为192.168.113.99(RIP),dst ip 为192.168.113.101(DIP),sport为8080,dport为35562,会根据连接跟踪表找到这个包是192.168.113.102这个client发过来的,因此把数据包在转发给192.168.113.102:35562 上。

conntrack各个字段的含义

总结:

  本文只是简单的说明了一下conntrack,并没有具体说明数据流经netfilter时何时创建记录,数据存储的数据结构啥样,底层比较复杂,感兴趣的大佬可以自行研究~

二、k8s网络通信

  介绍完了ipset、ipvs、conntrack,接下来进入正题,看一下ipvs模式下k8s的网络通信。kube-proxy 的主要作用是watch apiserver,当监听到pod 或service变化时,修改本地的iptables规则或ipvs规则。

2.1、clusterIp模式

clusterIp模式为一个集群内部可访问的ip,集群外部没办法访问这个ip,试验环境如下:

创建完deployment和service后,查看一下service的ip如下。

接下来看下宿主机网卡、ipvs规则、ipset规则有什么变化

查看iptables 的nat表和filter表,看一下k8s创建了哪些规则以及经过哪些链

接下来分析一下curl 10.108.113.237 数据是如何走的,只讨论在nat表和filter表的流向,因为在mangle和raw都没有规则。

1、nat表PREROUTING链
①:数据首先进入PREROUTING链,所有请求都会进入KUBE-SERVICES链。
②:进入KUBE-SERVICES后,查看对应在此链上的规则,发现请求的目的ip和port在KUBE-CLUSTER-IP 对应的ipset里面(上面已有展示),匹配上了则跳往KUBE-MARK-MASQ链。

③:数据流向KUBE-MARK-MASQ链,主要做了mark 打标记的功能,iptables命令如下

④:之后走向KUBE-NODE-PORT链,因为没有定义nodepode 类型的service,此处先略过。 2、filter表的INPUT链
⑤:首先进入INPUT链,所有数据转向KUBE-FIREWALL链。
⑥:进入KUBE-FIREWALL链,如果发现数据包打了0x8000/0x8000,DROP掉。因为ipvs工作在INPUT链上,做完DNAT之后直接转发到POSTROUTING链上。
3、nat表POSTROUTING链
⑦:进入POSTROUTING链,所有数据转向KUBE-POSTROUTING链
⑧:进入KUBE-POSTROUTING链,对有0x4000/0x4000标记的数据包做SNAT转换,因为ipvs只有DNAT功能。

4、数据转发给flannel网卡,进行转发
⑨:flannel 根据具体的backend模式,对数据做封包等操作,然后发出去。flannel的网络模式比较复杂,之后会专门文章进行说明。

2.2、nodeport模式

  要想把集群内部的服务可以让集群外部访问,可以使用nodeport模式在物理机上开一个端口,这样外部就能访问集群内部的服务了。说明:还是使用上面创建的deployment。

查看创建service的信息,发现也创建了集群内部的一个ip。

iptables规则如下

接下来看下ipset规则有什么变化,发现KUBE-NODE-PORT-TCP下的一个成员是刚才我们指定的那个nodePort的值。

接下来看一下iptables规则,nat表和filter表
1、nat表PREROUTING链
①:数据首先进入PREROUTING链,所有请求都会进入KUBE-SERVICES链。
②:ip和port匹配不上KUBE-CLUSTER-IP 的ipset,判断是访问的本地地址,进入KUBE-NODE-PORT链。

③:进入KUBE-NODE-PORT链后,判断访问端口在 KUBE-NODE-PORT-TCP ipset规则中,因此进入KUBE-MARK-MASQ链。

④:进入KUBE-MARK-MASQ链,对数据做mark标记

后续流程跟clusterIp一样,此处就不在阐述。
2.3、dns相关

  k8s中的dns默认使用的是coredns,通过以下命令查看。k8s中定义的service是有域名的,访问域名要通过dns解析,此时coredns就发挥它的作用了。

  上面的试验时我们创建了一个my-service 的nodePort的service,此时查看一下此域名对应的ip,如下图所示,域名解析出来的ip与service对应的ip相同,大功告成。

参考:


以上相关内容介绍了k8s service ipvs的相关实现,如有错误欢迎指出~



  • k8s缃戠粶鍘熺悊-ipvs
    绛旓細  浠嬬粛瀹屼簡ipset銆ipvs銆乧onntrack,鎺ヤ笅鏉ヨ繘鍏ユ棰,鐪嬩竴涓媔pvs妯″紡涓k8s鐨勭綉缁閫氫俊銆俴ube-proxy 鐨勪富瑕佷綔鐢ㄦ槸watch apiserver,褰撶洃鍚埌pod 鎴杝ervice鍙樺寲鏃,淇敼鏈湴鐨刬ptables瑙勫垯鎴杋pvs瑙勫垯銆 2.1銆乧lusterIp妯″紡 clusterIp妯″紡涓轰竴涓泦缇ゅ唴閮ㄥ彲璁块棶鐨刬p,闆嗙兢澶栭儴娌″姙娉曡闂繖涓猧p,璇曢獙鐜濡備笅: 鍒涘缓瀹宒eployment...
  • k8s闆嗙兢涓ipvs璐熻浇璇﹁В
    绛旓細浣跨敤IPVS鍚庢槸闇瑕佸vs(铏氭嫙鏈嶅姟涔熷氨鏄痸ip)杩涜绠$悊锛岀敱浜IPVS鐨DNAT閽╁瓙鎸傚湪 INPUT閾句笂锛屽洜姝ゅ繀椤昏璁╁唴鏍歌瘑鍒 VIP(cluster-ip) 鏄湰鏈虹殑 IP銆k8s 閫氳繃璁剧疆灏 service cluster ip 缁戝畾鍒拌櫄鎷熺綉鍗ube-ipvs0锛屽叾涓笅闈㈢殑10.96.x.x閮芥槸VIP锛屼篃灏 鏄痗luster-ip銆傚涓嬪浘锛歩pvs 浼氫娇鐢 iptab...
  • K8S涔婼ervice浠g悊妯″紡
    绛旓細IPVS浠g悊妯″紡鍩轰簬绫讳技浜巌ptables妯″紡鐨刵etfilter鎸傞挬鍑芥暟锛屼絾鏄娇鐢ㄥ搱甯岃〃浣滀负鍩虹鏁版嵁缁撴瀯锛屽苟涓斿湪鍐呮牳绌洪棿涓伐浣溿傝繖鎰忓懗鐫锛屼笌iptables妯″紡涓嬬殑kube-proxy鐩告瘮锛孖PVS妯″紡涓嬬殑kube-proxy鍙互浠ヨ緝浣庣殑寤惰繜閲嶅畾鍚戦氫俊锛屽苟涓斿湪鍚屾浠g悊瑙勫垯鏃跺叿鏈夋洿濂界殑鎬ц兘銆備笌鍏朵粬浠g悊妯″紡鐩告瘮锛孖PVS妯″紡杩樻敮鎸佹洿楂樼殑缃戠粶娴侀噺鍚炲悙...
  • K8s鐨勭綉缁璇﹁В
    绛旓細棣栧厛锛岃鐞嗚ВK8s鐨鐢ㄥ鍏跺疄鏄鍣ㄧ殑缂栨帓鍜岀鐞嗭紝鏈灏忕粍鎴愬叾瀹炰笉鏄鍣紝鏄痯od锛岀墿鐞嗘満鎴栬呰櫄鎷熸満鍙玭ode锛宲od鏄熀纭鍗曞厓锛宲od閲屽彲浠ユ湁澶氫釜瀹瑰櫒锛屼篃鍙互鍙湁涓涓鍣紝鍚屼竴涓猵od鐨勫鍣ㄥ郊姝ゆ槸鍏变韩缃戠粶鍜屼富鏈洪厤缃殑锛屾崲鍙ヨ瘽璇达紝褰兼鏄彲浠ョ洿鎺ocalhost閫氫俊鐨勶紝绫讳技浜庡悓涓鍙版満鍣ㄤ笂杩涜閫氫俊锛屾墍浠ヨ繖閲岄潰鏄棤鎵璋...
  • Kubernetes Service鍘熺悊瑙f瀽
    绛旓細kube-proxy璐熻矗service鐨勫疄鐜帮紝鍗冲疄鐜颁簡k8s鍐呴儴浠巔od鍒皊ervice鍜屽閮ㄤ粠node port鍒皊ervice鐨勮闂俴ube-proxy浣滀负涓涓帶鍒跺櫒锛屼綔涓簁8s鍜孡inux kernel Netfilter浜や簰鐨勪竴涓灑绾姐傜洃鍚琸ubernetes闆嗙兢Services鍜孍ndpoints瀵硅薄鐨勫彉鍖栵紝骞舵牴鎹甼ube-proxy涓嶅悓鐨勬ā寮(iptables or ipvs), 瀵瑰唴鏍歌缃笉鍚岀殑瑙勫垯锛屾潵瀹炵幇...
  • k8s鐨Service璇﹁В
    绛旓細IPVS妯″紡鏄埄鐢╨inux鐨処PVS妯″潡瀹炵幇锛屽悓鏍锋槸鐢眐ube-proxy瀹炴椂鐩戣闆嗙兢鐨剆ervice鍜宔ndpoint锛岃皟鐢╪etlink鎺ュ彛鐩稿簲鐨勫垱寤ipvs瑙勫垯锛岀敱ipvs瀹炵幇璐熻浇鍧囪 璁块棶銆侷PVS 涓撲负璐熻浇骞宠 鑰岃璁★紝骞跺熀浜庡唴鏍稿唴鍝堝笇琛紝鏈夋洿楂樼殑缃戠粶娴侀噺鍚炲悙閲忥紙iptables 妯″紡鍦ㄥぇ瑙勬ā闆嗙兢 姣斿10000 涓湇鍔′腑鎬ц兘涓嬮檷鏄捐憲锛夛紝骞朵笖鍏锋湁鏇村鏉傜殑...
  • K8S楂樺彲鐢ㄤ箣Sealos
    绛旓細Sealos 閫夋嫨閫氳繃鍐呮牳 IPVS 鏉ュ疄鐜颁富瑕佹湁浠ヤ笅鍑犱釜鍘熷洜锛 1锛夊鏋滀娇鐢 Envoy 绛夐渶瑕佸湪姣忎釜鑺傜偣涓婇兘璺戜竴涓繘绋嬶紝娑堣楁洿澶氳祫婧愩傝櫧鐒 IPVS 瀹為檯涓婁篃浼氬璺戜竴涓 lvscare 杩涚▼ 锛屼絾鏄 lvscare 鍙槸璐熻矗绠$悊 IPVS 瑙勫垯锛鍘熺悊鍜 Kube-Proxy 绫讳技銆傜湡姝g殑娴侀噺鐩存帴浠庡唴鏍稿眰闈㈣蛋锛屼笉闇瑕佹妸鏁版嵁鍖呭厛璧板埌鐢ㄦ埛鎬佷腑...
  • k8s绯诲垪02-kubeadm閮ㄧ讲flannel缃戠粶鐨刱8s闆嗙兢
    绛旓細铏界劧鏂扮増鏈殑k8s宸茬粡鏀寔鍙屾爤缃戠粶锛屼絾鏄湰娆$殑闆嗙兢閮ㄧ讲杩囩▼骞朵笉娑夊強IPv6缃戠粶鐨勯氫俊锛屽洜姝ゅ叧闂璉Pv6缃戠粶鏀寔 IPVS鏄笓闂ㄨ璁$敤鏉ュ簲瀵硅礋杞藉潎琛″満鏅殑缁勪欢锛 kube-proxy 涓殑 IPVS 瀹炵幇 閫氳繃鍑忓皯瀵 iptables 鐨勪娇鐢ㄦ潵澧炲姞鍙墿灞曟с傚湪 iptables 杈撳叆閾句腑涓嶄娇鐢 PREROUTING锛岃屾槸鍒涘缓涓涓亣鐨勬帴鍙o紝鍙仛 kube-...
  • k8s calico flannel cilium 缃戠粶鎬ц兘娴嬭瘯
    绛旓細纭欢锛氫笁鍙扮墿鐞嗘満锛屽崈鍏嗙綉鍗★紝鍗曠綉鍗★紝澶勪簬鍚屼竴缃戞锛堝湪鍚屼竴涓簩灞缃戠粶涓級OS锛歎buntu 18.04锛屽唴鏍 4.15 k8s锛 1.10.0 kube-proxy锛 ipvs 妯″紡 flannel : 0.10 鐗堟湰锛 vxlan妯″紡锛堥粯璁よ缃級calico: 3.1 鐗堟湰锛宨pip 妯″紡锛堥粯璁よ缃級cilium锛 1.0 鐗堟湰锛寁xlan 妯″紡锛堥粯璁よ缃級娴嬭瘯鏂规硶锛
  • 01-Kubernetes 缁勪欢浠嬬粛
    绛旓細IPVS锛 kubernetes 1.9寮曞叆鍒1.11涓烘寮忕増鏈紝闇瑕佸畨瑁卛pvadm銆乮pset宸ュ叿鍖呭拰鍔犺浇ip_vs鍐呮牳妯″潡銆俴ubectl 姒傝堪 鏄竴涓氳繃鍛戒护琛屽kubernetes闆嗙兢绠$悊鐨勫伐鍏 鍩轰簬Web鐨勭敤鎴锋帴鍙o紝鐢ㄤ簬鍙鍖k8s闆嗙兢銆俤ashborad鍙敤浜庤幏鍙栭泦缇や腑璧勬簮瀵硅薄鐨勮缁嗕俊鎭紝Dashboard鎻愪緵GUI锛屼綔涓鸿繍缁翠汉鍛橈紝浣跨敤kubectl鍛戒护琛屽伐鍏风鐞嗚冻鐭...
  • 扩展阅读:80s理论电网 ... k8线三线理论 ... e人e本t8s和k8s ... k82经典版全集免费观看 ... k8手机经典版最新款2024 ... 最新k8s经典 ... 经典k8线理论 ... k8s手机经典网 ... k82手机经典版官网 ...

    本站交流只代表网友个人观点,与本站立场无关
    欢迎反馈与建议,请联系电邮
    2024© 车视网