kubernetes的网络策略(kube-proxy)流程探究

关于路由

很多像我这样的网络小白,对于整个路由过程比较模糊。下面以一个简单的PING示例解释一下路由的整个过程。

有两个原则需要记住:

二层网络是通过MAC地址进行交换

三层路由通过IP选路。

一个ICMP的以太网格式报文:

|目的MAC|源MAC|目的IP|源IP|ICMP包|

主机A发送一个ICMP包到主机B, 此时目的IP为10.10.0.2,源IP为192.168.0.2。 主机A发现,这个IP和我不在一个网段,那就需要进行IP选路了。此时它就只能把包发往直接的网关了(192.168.0.1) ,主机A和网关在同一个网段,通过MAC地址进行交换,所以目的MAC就是MACRA, 源Mac就是MACHOSTA。

因此从主机A发出的一个以太网报文格式为:

|MACRA|MACHOSTA|10.10.0.2|192.168.0.2|ICMP包

路由器在接口A处收到以太网包进行分析,选出目的IP,根据自身的路由表发现,这个数据包要经过接口B发出啊。于是就在路由器接口B封装数据包

|MACHOSTB|MACRB|10.10.0.2|192.168.0.2|ICMP包

主机B在二层收到从路由器接口B发生的以太网进行解析发现目的IP是自己的,然后开始回复。首先发现目的IP是192.168.0.2.这货和我不是一个网段的啊,那我就把数据包先发给网关,让网关帮我邮递。于是封装出下面的以太网包:

|MACRB|MACHOSTB|192.168.0.2|10.10.0.2|ICMP

路由器从接口B收到数据包之后,同样进行分析之后知道自己需要通过接口A发出。于是封装的以太网包:

|MACHOSA|MACRA|192.168.0.2|10.10.0.2|ICMP

终于回复的数据包被主机A收到,整个ICMP过程完成。

有一个非常重要的原则要记住:在数据跳转的过程中,改变的是MAC,IP是始终是没有改变的。

关于NAT

NAT是网络地址转换的意思,什么时候会用到它呢, 一个简单的例子就是我们平时上网用到路由器,

上图是我们家里常用的路由器连接示例,HOSTA和HOSTB连接到路由器的LAN口,当主机A访问8.8.8.8时,根据上面讲的路由过程,我们知道到达路由器的以太网包为:

|MACRA|HOSTA|8.8.8.8|192.168.1.2|ICMP包

此时路由器通过WAN口将报文发送到公网上去,按这常理它的数据包格式应该是:

|下一跳路由MAC|路由器A的WAN口的MAC|8.8.8.8|192.168.1.2|ICMP包

我们在深入思考一下,假设这样的一个数据包发送到公网上之后,确定还能按原路找回来吗? 大家的路由器网关都是192.168.1.1 ,数据如果回来之后根本就不知道发送到哪一个路由器了。

这个时候就出现了NAT的技术,如果想让回复的数据包能够返回,那么我就需要更改源IP地址啊,于是路由器在从WAN口路由出去之后更改源IP为WAN口的IP,同时记录NAT转换的信息,保证回复的数据能够投递到指定的目标。这种技术叫做SNAT。同理还有一个叫做DNAT,也就是更改目的地址IP。 后边会在介绍k8s路由过程中解释。 只需要记住SNAT是路由之后进行的,DNAT是路由之前进行的即可。

Iptables原理

在介绍k8s的网络之前,还需要介绍一下iptables的原理,因为k8s中用到了大量iptables的知识,iptables博大精深,本人也只是略懂一二。

Iptables是Linux内核模块netfilter的应用程序,通过iptables这个应用程序来控制netfilter内核的行为。Linux的iptables默认是4表5链,当然也可以自定义自己的规则链。

4表: nat, manage, raw, filter,

5链: prerouting, input, output, forward, postrouting

一般情况下我们只需要关心nat和filter这个两个表。Nat表可以控制非本地的网络包,filter可以控制路由到本地的数据包。

不废话,先上图:(所有图均是自己绘制的,心疼自己几十秒)

上图表示了一个数据包在Linux的netfilter内核模块中流转的流程。可以说Linux的强大的网络功能让我非常震惊。惊呆了。

K8s的网络流程

终于,终于到正题了,大家看看就行了,吾生也有涯,而知也无涯。以有涯随无涯,怠矣。

当你使用kubernets的时候,可能会感到奇怪,为何我访问的集群的任意一个IP均可以访问到指定的应用。 为何在集群的机器上访问一个不存在的IP(clusterIP)却能够帮我路由到指定的pod,而且还是等概率的访问一个节点。

上面是一张k8s的架构图(这张不是我画的),我们只看proxy部分,kube-proxy是k8s的一个核心组件。每台机器上都运行一个kube-proxy服务,它监听API server中service和endpoint的变化情况,并通过iptables等来为服务配置负载均衡。 所以接下来我们通过例子结合iptable表中的规则来梳理整个流程。

环境:

master01: 172.24.6.153

master02: 172.24.6.154

master03: 172.24.6.145

我们以kdcos-keystone这个应用为例来分析访问流程。

从图中可以看出, kdcos-keystone的clusterIP为10.0.0.10, 容器端口是8080, 集群端口是30808.

Keystonde的pod分布:

master01的路由表:

现在我们先不看iptable的规则,自己去考虑一下,如果我想在master01 上访问10.0.0.80(随便找一个不冲突的IP都行) 最终能够访问到master02上的keystone(10.254.59.219)应该怎么做呢?

1. 首先可以确定的是肯定是在iptable的nat表上进行添加规则。

2. 我们在集群内部访问的clusterIP是一个虚拟IP,最终要访问的IP是10.254.59.219. 所有肯定是要进行DNAT转换的。(这样数据包应该是从本地协议发出 会经过nat的OUTPUT和POSTROUTING链。看上图的iptable流程图即可明白)

3. 我们通过在集群外部访问nodeport,最终如果要访问到10.254.59.219,需要进行DNAT转换,这个和第二步一样,另外,在上面讲解NAT的时候说到,如果要想让消息能返回客户端,那就需要进行SNAT转换。如果实在觉得理解困难,可以把master01当做一个路由器,客户端就是一个主机。

# 在集群中访问虚拟IP最终访问到keystone

iptables -t nat -I OUTPUT -p tcp -m

comment --comment "this is clusterip demo" -d 10.0.0.80/32 --dport 8080 -j DNAT --to-destination 10.254.59.219:8080

# 让外部客户端访问nodeport最终访问到keystone

iptables -t nat -I POSTROUTING -p tcp -d

10.254.59.219 --dport 8080 -j MASQUERADE

iptables -t nat -I PREROUTING -p tcp -m

comment --comment "this is nodeport demo" --dport 40808 -j DNAT --to-destination 10.254.59.219:8080

这个时候 在集群的master01上访问10.0.0.80:8080 或者在外部访问172.24.6.153:408080,就会发现惊讶的发现原来k8s还能这样操作。是不是很惊喜。无图无真相:

下图是在master01上访问10.0.0.80:8080 时设置的iptable规则。

下图是让外部能够通过nodeport访问keystone设置的规则。

在自己的电脑上访问nodeport:

留个问题:

上面的iptable规则可以保证在master01上通过虚拟ip(10.0.0.80)访问到keystone,可以保证在外部访问172.24.6.153:8080访问到keystone,但是如果你尝试在master01(172.24.6.153)上通过访问172.24.6.153:40808到达keystone确是不行的。 不信?我截图给你看?

那你觉得应该如何设置才能在master01上通过自身IP也能访问到keystone呢?

另:

MASQUERADE和SNAT的功能类似,只是SNAT需要明确指明源IP的的值,MASQUERADE会根据网卡IP自动更改,所以更实用一些。

所以说,如果在开发过程中,想外部访问某个应用(比如redis),但是呢碰巧这个应用的svc又没有开启nodeport,那你就可以模仿我刚才设置的iptable规则,从而达到不修改SVC也能通过外部应用访问。

到这里,也许你大概明白了k8s的kube-proxy的工作原理了,总结起来就是通过更改iptable的规则让我们可以访问一个虚拟IP从而能够到达后端pod。如果看到这里还不是很了解的话,建议还是从头再看一下,因为下面分析的k8s生成的iptable链要比这个会更复杂一下。

现在我们分析k8s的iptable的流程:

分析1: 集群内部通过clusterIP访问到pod。

上面我们分析过,首先这个数据包是通过本地协议发出的,然后需要更改NAT表,那看来k8s只能在OUTPUT这个链上来动手了。

看下图:

到达OUTPUT链的包要过KUBE-SERVICES这个k8s自定义的链

上图就是KUBE-SERVICES 链,访问10.0.0.10:8080 可以匹配到上图的第一条红线的规则,注意第二条红线,下面会说到。

匹配到10.0.0.10:8080的时候会跳转到KUBE-SVC-VZEERQ5BHBSZ5PRL这个链,那这个链又做了啥子呢?

看到上图的--mode random --probability 0.33332999982 了吗?它就是访问SVC时能够随机访问到后端POD的原因。

因为我们后面有三个pod,所以会有三条链, 我们只分析其中一条。

最终这个链做了两件事,跳转到KUBE-MARK-MASQ,我就不跳了,直接说结果就是给这个包打上标签,这个标签的用处,一会说。

然后我们终于看到了对这个包进行了一次DNAT转换。 转到了10.254.59.212:8080上面了。

这个OUTPUT走完之后,它就该到POSTROUTING链了。

跳转到KUBE-POSTROUTING链,这个链只做了一个事,就是对打上了标签的包进行SNAT转换。这就引入了一个问题,在一个pod访问一个clusterIP的时候,如果这个clusterIP的DNAT目标是自己的话,看到的IP却是自己宿主机的IP。还有一点大家可能会有疑问,这个--mark 0x4000/0x4000是什么鬼,就是对匹配这个标签的数据包进行SNAT,上面说到的KUBE-MARK-MASQ就是给数据包打上了这样的一个标签。

这样一个访问clusterIP最终访问到pod的流程就算走完了。

分析2: 下面我们来分析通过外部nodeport访问后端pod的流程。

根据iptable的流程我们知道,首先我们应该对nat表的PREROUTING链动手脚。看看k8s做了啥?

对,你没看错,这货又把它跳到了KUBE-SERVICES这个链上去了,但是上面我们知道,这回我是通过nodeport访问的,你根本匹配不上啊,不错确实匹配不上,还记得我说的第二根红线吗?忘了?在贴下上面的图。

那既然你们匹配不上那就给我跳转到KUBE-NODEPORTS链上来。

在这个KUBE-NODEPORTS最后还是调到之前的KUBE-SVC-VZEERQ5BHBSZ5PRL上,打上标签,DNAT转换,SNAT转换。完成。

另外:

在最开始我提到了一个问题,在集群上使用nodeport却访问不了后端pod, 那是因为我们没有在OUTPUT链设置匹配nodeport的包进行DNAT转换呀,那k8s做了吗? 当然了,反正不管你是PREROUTING还是OUTPUT链,我都给你跳到KUBE-SERVICE, 到了KUBE-SERVICE匹配不上我就给你跳到KUBE-NODEPORTS,这就解决了不管是那种情况,无论是访问clusterIP,还是nodeport最终都能访问到了后端pod

总之: Linux的网络功能复杂且强大,且学且珍惜!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容

  • 防火墙的概念iptables的简介iptables命令网络防火墙NATfirewalld服务 一、防火墙的概念 (...
    哈喽别样阅读 1,808评论 0 1
  • Teredo 原理概述 http://www.ipv6bbs.cn/thread-144-1-1.html (出处...
    我是叶问小盆友阅读 1,941评论 0 1
  • ----写于2014.5.07 今天preK没课。所有学生到体育馆欣赏小学和初中的乐队表演。表演前,乐队老...
    素秋微菊阅读 413评论 0 1
  • 《一个人的朝圣---奎尼的情歌》,看到这个名字的时候就知道应该是个爱情故事。事实也是如此。奎尼爱着哈罗德。读完第一...
    披着羽毛的猪阅读 411评论 5 2
  • 一个人 一张票 不要问我去哪儿 到站了 我没有下车 只想这样一直走 我没有遇见上车的人 也没有遇见下车的人 心涌没...
    為靑䦮阅读 141评论 0 0