一. 实践说明

首先我们先创建一组资源,包括一个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. JavaScript 基础知识梳理——事件

    事件 1)事件是文档或浏览器窗口中发生的特定的交互瞬间. JavaScript和HTML之间的交互是通过事件实现的. 2)事件流——描述的是从页面中接受事件的顺序 IE——事件冒泡流 Netscape ...

  2. 本地安装mysql脚本

    [root@tianyun ~]# vim mysql_install.sh #!/usr/bin/env bash #mysql install 2 #by tianyun #yum 配置yum源 ...

  3. java双指针的简单理解

    一.什么是双指针 双指针我所理解地是在遍历对象时,不是使用单个指针进行访问,而是使用两个相同方向或者相反方向的指针进行遍历,从而达到相应的目的. 在JAVA中并没有像C/C++指针地概念,所以这里所说 ...

  4. Bootstrap-轮播图-No.3

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  5. 洛谷【P2257】 YY的GCD

    出处:http://www.cnblogs.com/peng-ym/p/8652288.html   (  直接去出处那看就好了 ) 题目描述 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求 ...

  6. HZOJ 20190819 NOIP模拟26题解

    考试过程: 照例开题,然后觉得三道题都挺难,比昨天难多了(flag×1),T1 dp?T2 数据结构? T3 dp?事实证明我是sb然后决定先搞T2,但是,woc,这题在说什么啊,我怎么看不懂题啊,连 ...

  7. Java 面试题 三 <JavaWeb应用调优线程池 JVM原理及调优>

    1.Java Web应用调优线程池 不论你是否关注,Java Web应用都或多或少的使用了线程池来处理请求.线程池的实现细节可能会被忽视,但是有关于线程池的使用和调优迟早是需要了解的.本文由浅入深,介 ...

  8. JAVA的面向对象1

    如何理解面向对象 我们说面向对象具有三大特征:封装性.继承性和多态性,那么我们怎么去理解所谓的封装.继承.多态? 1.封装:功能都给你做好了,你不必去理解它是怎么写出来的,直接使用即可. 如:房子.电 ...

  9. Django-静态文件导入/url命名及反向解析

    一.静态文件导入 js.css.img等都叫做静态文件,那么关于django中静态文件的配置,我们就需要在settings配置文件里面写上这写内容: # STATIC_URL = '/xxx/' #别 ...

  10. Sqlite3错误:Recursive use of cursors not allowed 的解决方案

    感悟] 写完这篇日志后,有调了一段时间程序,又有了一点心得分享下: 一)爬稳定的数(dong)据(xi)最好存储下来,特别是数据库在国外的那种,下载时间成本太高昂了,存起来再处理,会节约很多时间: 二 ...