一. 实践说明

首先我们先创建一组资源,包括一个deployment和一个service

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
name: nginx
spec:
selector:
matchLabels:
name: nginx1
replicas: 1
template:
metadata:
labels:
name: nginx1
spec:
nodeName: meizu
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
name: nginx1
spec:
ports:
- port: 4432
targetPort: 80
selector:
name: nginx1

可以看到,我们在指定的node上面创建了一个nginx deployment,并且创建一个服务指向这个pod.然后我们再在其他节点上启动一个pod,在该pod中访问这个service.

src pod  ->  service   ->  backend  pod

172.30.83.9  ->  10.254.40.119:4432  ->  172.30.20.2:80

下面的所有操作都是nginx 服务所在的pod所运行的node上执行的

二. 物理网卡

1.监听nginx pod/src pod 地址

sudo tcpdump -i  enp4s0 ‘dst 172.30.20.9’

sudo tcpdump -i  enp4s0 'src 172.30.83.9'

都没有输出

2. 监听service 地址

sudo tcpdump  -i  enp4s0 ‘dst 10.254.40.119’

没有输出

3.src pod所在的node的物理地址是10.167.226.38,我们现在监听从这个节点发出的所有的到本地8472端口的udp报文,注意8472端口是flannel所监听的端口

sudo tcpdump  -i enp4s0 'src 10.167.226.38 and port 8472 and udp'
看到如下输出:

::22.220286 IP xiaomi. > meizu.otv: OTV, flags [I] (0x08), overlay , instance
IP 172.30.83.0. > 172.30.20.2.http: Flags [S], seq , win , options [mss ,sackOK,TS val ecr ,nop,wscale ], length
::22.221179 IP xiaomi. > meizu.otv: OTV, flags [I] (0x08), overlay , instance
IP 172.30.83.0. > 172.30.20.2.http: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::22.221383 IP xiaomi. > meizu.otv: OTV, flags [I] (0x08), overlay , instance
IP 172.30.83.0. > 172.30.20.2.http: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP: GET / HTTP/1.1
::22.221933 IP xiaomi. > meizu.otv: OTV, flags [I] (0x08), overlay , instance
IP 172.30.83.0. > 172.30.20.2.http: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::22.221949 IP xiaomi. > meizu.otv: OTV, flags [I] (0x08), overlay , instance
IP 172.30.83.0. > 172.30.20.2.http: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::22.222347 IP xiaomi. > meizu.otv: OTV, flags [I] (0x08), overlay , instance
IP 172.30.83.0. > 172.30.20.2.http: Flags [F.], seq , ack , win , options [nop,nop,TS val ecr ], length

我们可以看到在物理网卡上,报文的源地址是物理机的ip,目标地址是目标pod所在的物理机的ip。

报文体中定义的源地址是172.30.83.0,这是源pod所在主机的flannel.1网卡的地址,目标地址是172.30.20.2,这个地址是nginx pod所在的地址

4. 再看看tcp协议的输出

sudo tcpdump  -i enp4s0 'src 10.167.226.38 and port 8472 and tcp'

没有输出,由此可见,flannel之间的通信是通过udp完成的,而不是tcp。

总结:在物理网卡上,所有的通信都是通过源地址和目标地址所在的主机的物理地址进行通信的,这些报文封装了从管理源pod的docker网卡地址到目的nginx pod地址的flannel报文

三. Flannel 网卡

执行下面的指令,其中172.30.83.0是源pod所在的node的flannel网卡地址

[wlh@meizu ~]$ sudo tcpdump  -i flannel. 'host 172.30.83.0 and tcp'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on flannel., link-type EN10MB (Ethernet), capture size bytes
::43.362239 IP 172.30.83.0. > 172.30.20.2.http: Flags [S], seq , win , options [mss ,sackOK,TS val ecr ,nop,wscale ], length
::43.363702 IP 172.30.20.2.http > 172.30.83.0.: Flags [S.], seq , ack , win , options [mss ,sackOK,TS val ecr ,nop,wscale ], length
::43.364106 IP 172.30.83.0. > 172.30.20.2.http: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::43.364180 IP 172.30.83.0. > 172.30.20.2.http: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP: GET / HTTP/1.1
::43.364218 IP 172.30.20.2.http > 172.30.83.0.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::43.364482 IP 172.30.20.2.http > 172.30.83.0.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP: HTTP/1.1 OK
::43.364608 IP 172.30.20.2.http > 172.30.83.0.: Flags [FP.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::43.364868 IP 172.30.83.0. > 172.30.20.2.http: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::43.364888 IP 172.30.83.0. > 172.30.20.2.http: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::43.365226 IP 172.30.83.0. > 172.30.20.2.http: Flags [F.], seq , ack , win , options [nop,nop,TS val ecr ], length
::43.365271 IP 172.30.20.2.http > 172.30.83.0.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length

可以看到物理层的报文被解封装后提交给了flannel.1网卡,它处理的报文就是从源pod所在的node的flannel.1网卡地址到目标pod的地址的通信

四. Docker0网卡

其中172.30.83.0是源pod所在的主机的flannel.1网卡的地址

 [wlh@meizu ~]$ sudo tcpdump  -i docker0 'host 172.30.83.0 and tcp'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size bytes
::00.681066 IP 172.30.83.0. > 172.30.20.2.http: Flags [S], seq , win , options [mss ,sackOK,TS val ecr ,nop,wscale ], length
::00.681110 IP 172.30.20.2.http > 172.30.83.0.: Flags [S.], seq , ack , win , options [mss ,sackOK,TS val ecr ,nop,wscale ], length
::00.681548 IP 172.30.83.0. > 172.30.20.2.http: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::00.681560 IP 172.30.83.0. > 172.30.20.2.http: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP: GET / HTTP/1.1
::00.681608 IP 172.30.20.2.http > 172.30.83.0.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::00.681773 IP 172.30.20.2.http > 172.30.83.0.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP: HTTP/1.1 OK
::00.681853 IP 172.30.20.2.http > 172.30.83.0.: Flags [FP.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::00.682018 IP 172.30.83.0. > 172.30.20.2.http: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::00.682031 IP 172.30.83.0. > 172.30.20.2.http: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::00.682504 IP 172.30.83.0. > 172.30.20.2.http: Flags [F.], seq , ack , win , options [nop,nop,TS val ecr ], length
::00.682523 IP 172.30.20.2.http > 172.30.83.0.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length

我们可以看到这里的通信是以tcp协议进行并且所有的通信和flannel类似,也是在源主机的flannel网卡地址和目标pod地址之间进行的。

五 容器网卡

容器网卡的输出和前面的比较类似这里不再赘述。

六总结

下面总结一下整个过程

  1. 首先容器内的进程发送一个访问service的请求,这个被交给容器内网卡进行处理,容器内网卡将请求发送给veth pair的另一端。此时请求是从src pod ip-> service ip。
  2. 然后根据NAT表的设置, 目的地址被转化为backend pod 的ip,这个请求再传送给docker0网卡。此时请求是 src pod ip -> backend pod ip
  3. docker0 网卡收到请求后直接将请求发出去,请求根据路由表(route -n)被传送给flannel.1网卡。此时请求是flanne.1 ip -> backend pod ip
  4. flannel.1网卡将请求发送给flanneld进程进行处理,该进程读取etcd的配置,给请求封装上一个udp协议头,然后发出去, 该报文是 source node ip -> dst node ip
  5. 本地网卡收到这个请求后将报文从物理网络上发出去,到达远程主机。

flannel.1

k8s 网络模型解析之实践的更多相关文章

  1. k8s 网络模型解析之原理

    今天研究了一下k8s的网络模型,该解析基于flannel vxlan+ kubeproxy iptables 模式. 一.Docker 首先分析一下Docker层面的网络模型,我们知道容器是基于内核的 ...

  2. k8s 网络模型

    一.前言 k8s对Pods之间如何进行组网通信提出了要求,k8s对集群的网络有以下要求: 所有的Pods之间可以在不使用NAT网络地址转换的情况下相互通信 所有的Nodes之间可以在不使用NAT网络地 ...

  3. Tengine HTTPS原理解析、实践与调试【转】

    本文邀请阿里云CDN HTTPS技术专家金九,分享Tengine的一些HTTPS实践经验.内容主要有四个方面:HTTPS趋势.HTTPS基础.HTTPS实践.HTTPS调试. 一.HTTPS趋势 这一 ...

  4. k8s loadbalancer与ingress实践

    k8s可以通过三种方式将集群内服务暴露到外网,分别是NodePort.LoadBalancer.Ingress,其中NodePort作为基础通信形式我们在<k8s网络模型与集群通信>中进行 ...

  5. [转帖]我花了10个小时,写出了这篇K8S架构解析

    我花了10个小时,写出了这篇K8S架构解析 https://www.toutiao.com/i6759071724785893891/   每个微服务通过 Docker 进行发布,随着业务的发展,系统 ...

  6. k8s网络模型与集群通信

    在k8s中,我们的应用会以pod的形式被调度到各个node节点上,在设计集群如何处理容器之间的网络时是一个不小的挑战,今天我们会从pod(应用)通信来展开关于k8s网络的讨论. 小作文包含如下内容: ...

  7. 从零开始入门 K8s | etcd 性能优化实践

    作者 | 陈星宇(宇慕)  阿里云基础技术中台技术专家 本文整理自<CNCF x Alibaba 云原生技术公开课>第 17 讲. 导读:etcd 是容器云平台用于存储关键元信息的组件.阿 ...

  8. ELK:收集k8s容器日志最佳实践

    简介 关于日志收集这个主题,这已经是第三篇了,为什么一再研究这个课题,因为这个课题实在太重要,而当今优秀的开源解决方案还不是很明朗: 就docker微服务化而言,研发有需求标准输出,也有需求文件输出, ...

  9. 一文看懂 K8s 日志系统设计和实践

    上一篇中我们介绍了为什么需要一个日志系统.为什么云原生下的日志系统如此重要以及云原生下日志系统的建设难点,相信DevOps.SRE.运维等同学看了是深有体会的.本篇文章单刀直入,会直接跟大家分享一下如 ...

随机推荐

  1. spring 的自动定时任务

    spring的自动定时任务有两种 第一种:通过xml配置来设置 需要在xml中引入新的约束,并且需要配置<task:scheduled-tasks> ,主要配置内容如下: <?xml ...

  2. JS中BOM和DOM之间的关系

    一.Javascript组成JavaScript的实现包括以下3个部分:1.核心(ECMAScript):描述了JS的语法和基本对象.2.文档对象模型 (DOM):处理网页内容的方法和接口.3.浏览器 ...

  3. SSH登录卡顿解决方案

    在使用ssh远程登录Linux主机时,经常出现需要等待一段时间才能登录,甚至登录超时的情况 原因一:SSH服务器默认开启了DNS的查询功能:UseDNS=yes 当UseDNS选项处于开启状态时,客户 ...

  4. CodeForces - 837E - Vasya's Function | Educational Codeforces Round 26

    /* CodeForces - 837E - Vasya's Function [ 数论 ] | Educational Codeforces Round 26 题意: f(a, 0) = 0; f( ...

  5. 【Android-自定义控件】 漂亮的Toast

    修改Toast属性,美化Toast //创建一个Toast Toast toast=new Toast(getApplicationContext()); //创建Toast中的文字 TextView ...

  6. 洛谷P3935 Calculation [数论分块]

    题目传送门 格式难调,题面就不放了. 分析: 实际上这个就是这道题的升级版,没什么可讲的,数论分块搞就是了. Code: //It is made by HolseLee on 18th Jul 20 ...

  7. oracle的事务

    一.事务 保证数据的一致性,有一组相关的dml语句组成,该组的dml语句要么全部成功,要么全部失败 如:网上转账就是典型的要用事物来处理,用以保证数据的一致性 二.事务和锁 当执行事物操作时(dml语 ...

  8. 关于keepalive

    linux内核配置有一项tcp_keepalive_time,即tcp的保活定时器.当网络上两个建立连接的进程都没有数据向对方发送的时候,tcp会隔段时间发送一次保活数据,以保持连接,间隔时间就是tc ...

  9. vga转HDMI与hdmi转VGA区别

  10. 设置Fedora能够使用root用户登录

    1. 切换到root工作环境,因为一下操作必须拥有root权限 [ha@localhost ~]$ su root密码: 2. 编辑/etc/pam.d/gdm [root@localhost ha] ...