云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍

Linux 虚拟网络

Network Namespace

  • Linux内核提供的功能
  • 实现网络虚拟化的重要功能
  • 能创建多个隔离的网络空间
  • 每个空间有独立的网络栈
  • 多个空间之间试图隔离互不干扰

虚拟网络设备

  • veth
    属于可转移设备,就是可以在不同namespace种进行转移的设备

是成对出现的虚拟网络设备,发送到Veth一端虚拟设备的请求会从另一端的虚拟设备中发出,在容器的虚拟化场景中,会使用Veth来链接不同网络的namespace

linux 提供了 veth pair 。可以把 veth pair 当做是双向的 pipe(管道),从一个方向发送的网络数据,可以直接被另外一端接收到;或者也可以想象成两个 namespace 直接通过一个特殊的虚拟网卡连接起来,可以直接通信。

云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第1张图片

  • lo
    自身的回环设备

  • vxlan

什么是vxlan?

vxlan是一种网络虚拟化技术,通过把源主机发出的数据包封装在UDP中.并且使用物理网络的IP,MAC作为外层头进行封装,然后在IP网络上传输,到达目的地后由隧道终结点解封装并把数据发送给目标主机.

什么是隧道技术?

是一种数据包封装技术.可以把原始IP包封装在另外一个数据包的数据净荷中进行传输.

使用隧道的原因是在不兼容的网络上传输数据或者在不安全网络上提供一个安全路径.

  • bridge 网桥

veth pair只能实现两个网络接口之间的通信
如果实现多个网络接口之间的通信。就是Bridge网桥技术。简单说来,网桥就是把一台机器上的若干个网络接口连接起来。结果就是其中一个网口收到的报文会被转发到其他网口。实现了不同网络接口之间的报文相互转发

网桥工作原理

网桥对报文的转发基于MAC地址,网桥能够解析收发的报文,读取目标MAC地址的信息,然后根据自己的MAC表信息,来决定转发的目标网络端口

如果遇到一个从来没有记录过的地址,可以广播给所有的网络端口

云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第2张图片
多个网络端口借助网桥进行通信与报文转发

Linux内核通过一个虚拟的网桥设备实现桥接,这个虚拟设备可以绑定若干个以太网接口设备,从而把他们连接起来

云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第3张图片

对于协议栈上层,只看得到br0,上层协议栈需要发送报文到br0种,网桥设备的处理代码再判断报文被转发到eth0或者是eth1.

反过来,从eth0或者eth1接收到的报文被提交给网桥的处理代码,也会在br0判断报文应该被转发丢弃还是提交到协议栈上层

iptables/netfilter

  • iptables是Linux实现的防火墙,可以理解为一个客户端代理
  • netfilter是真正的防火墙框架
  • 两者组成了具有封包过滤,封包重定向和地址转换(NAT)功能的包过滤防火墙

Docker 网络模型

  • Docker使用Linux的Bridge技术,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器的时候会根据Docker网桥的网段分配给容器一个IP地址,即Container-IP
  • 同时Docker网桥是每个容器的默认网关
  • 因为同一个宿主机内的容器都接入同一个网桥,所以容器之间能够通过容器的Container-IP直接通信

四种Docker 网络模式

云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第4张图片

  • host模式

容器直接使用宿主机的IP和端口.但是容器的文件系统,进程列表等还是和宿主机隔离

使用host模式的容器可以直接使用宿主机的IP地址和外界通信.容器内部的服务端口可以使用宿主机的端口,不需要进行NAT.host最大优势是网络性能比较好.

缺点: 端口没有做隔离,会有端口占用现象

云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第5张图片

  • container模式

指定新创建的容器和已经存在的一个容器共享一个Network Namespace.

新创建容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP,端口范围等

两个容器除了网络,其他如文件系统,进程列表还是隔离的

两个容器的进程通过lo网卡设备通信 (localhost)

  • none模式
    Docker容器没有进行任何网络配置.Docker容器没有网卡,IP,路由等信息.需要我们自己为Docker容器添加网卡,配置IP

网络模式下容器只有lo回环网络.这种网络没有办法联网,封闭网络能够很好保证容器的安全性.

云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第6张图片

bridge模式

在宿主机创建一个叫docker0的虚拟网桥.
宿主机上启动的Docker容器会连接到这个虚拟网桥上

这个虚拟网桥工作方式和物理交换机类似 主机所有容器通过交换机连在一个二层网络中

从docker0子网中分配一个IP给容器使用,并且设置docker0的IP地址作为容器的默认网关.在主机上创建一对虚拟网卡设备veth pair.

Docker把veth pair设备的一端放在新创建的容器中,命名为eth0

另外一端放在宿主机上,以vethxxx这样的方式命名.然后把这个网络设备加入到docker0网桥中.

bridge模式就是docker的默认网络模式.

云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第7张图片

K8s 网络模型

约法三章:

  • 任意Pod之间可以直接通信,无需经过显式使用NAT来接收数据和地址的转换
  • node和pod之间可以直接通信.无需使用明显地址转换
  • pod的私有ip(自己看到自己的ip)和别人看到它所用的ip是一样的,中间不会经过转换

四大目标:

搞清楚

  • 外部世界和service之间如何通信?
  • service如何与pod通讯?
  • pod和pod之间调用怎么做到通信?
  • pod内部容器之间的通信?

本文解决后面两个问题

容器网络方案:

大体分为UnderlayOverlay两种方案

  • underlay
    与host网络同层,与host网络使用同样的网段,输入输出基础设备,容器IP地址是不是需要与host网络取得协同.啥意思呢,就是ip地址是否由host网络来进行中心分配或者统一划分.

  • overlay
    不一样的地方:并不需要从host网络的ipm的管理组件去申请IP
    只需要与host网络不冲突,这个ip可以自由分配

总结: underlay和overlay区别在于容器网络是否与宿主机网络同层

Netns

Network Namespace

runC容器的技术不依赖于任何硬件,执行基础就在内核里面.进程内核代表就是task.

如果不需要隔离,那么用的主机空间就是主机的空间,不需要设置特别的空间隔离数据结构.

  • Network namespace是实现网络虚拟化的内核基础,创建了隔离的网络空间.一个namespace里面,
  • 有独立的附属网络设备(lo,veth等虚拟设备/物理网卡)
  • 独立的协议栈,IP地址和路由表
  • iptables规则
  • ipvs等

ipvs 是啥?iptables是啥?

ipvs

  • IP Virtual Server
    实现了传输层负载均衡.也就是通常所说的4层LAN,作为Linux内核一部分.

ipvs运行在主机上,在真实的服务器集群中充当负载均衡器.

ipvs可以将基于TCP和UDP的服务请求转发到真实的服务器.使得真实服务器的服务在单个IP地址上显示为虚拟服务.

iptables

iptables不是防火墙.我们可以理解成一个客户端代理.用户通过iptables这个代理,把用户的安全设定执行到防火墙中

先回顾以下报文从网卡到
当客户端访问服务端的web服务的时候,客户端发送报文到网卡。

tcp/ip协议栈是内核的一部分,所以客户端的信息会通过内核的TCP协议传输到用户空间的web服务中。

这个时候客户端报文的终点为web服务监听的套接字。

我们所说的防火墙,是内核空间的一部分,所有进出报文都需要通过关卡。符合条件的关卡才可以放行。

这些关卡在iptables中称为"链"
云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第8张图片
上面那个是demo啦

当我们开启了防火墙功能的时候,报文需要经过以下关卡,也就是要根据实际情况不同,报文经过的转发链其实是不同的。
下图中红色的框就是“链”,链是因为每个关卡中所有规则都会串成一条链。
报文只有满足链上所有规则的时候才能通过这个关卡。
云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第9张图片
到本机某进程的报文: PREROUTING -> INPUT
由本机转发的报文: PREROUTING -> FORWARD -> POSTROUTING
由本机的某进程发出报文: OUTPUT->POSTROUTING

我们回到K8s网络的讨论

如果网络是需要隔离的话,并不需要特别设置空间隔离数据结构(nsproxy)

一个隔离的网络空间会有什么?

  • 有自己的网卡或者是网络设备

  • 网卡可能是虚拟的,也可能是物理网卡

  • 拥有自己的IP地址,IP表和路由表

  • 拥有自己的协议栈

  • 拥有自己的status

  • 拥有自己的iptables和ipvs

  • Pod和Netns的关系
    云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第10张图片
    每个Pod都有独立的网络空间。
    所有容器都会通过pod的IP对外提供服务。
    宿主机还有Root namespace,可以看作成一个特殊的网络空间,不过pid为1

K8s的容器网络实现方案

  • Flannel 最为普遍的实现,可以提供多种网络backend的实现
  • Calico 主要采用策略路由,节点之间采用BGP协议进行路由同步
  • Cilium Flannel和Calico优点集合的产物
  • WeaveNet 可以对数据做加密

Flannel

  • 目前最为普遍的方案,通过把backend机制独立,支持多种数据路径,也可以适用于overlay/underlay多种场景
  • 封装可以选用用户态udp,内核Vxlan,如果集群规模不大,处在同一二层域,那么也可以采用host-gw方式

云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第11张图片
上面解决的是容器的包如何到达host,这里通过加一个网桥Bridge.它的bckend其实是独立的,也就是这个包如何离开host,采用何种封装方法,或者是是否需要封装,都是可选择的。

Network Policy

提供基于策略的的网络控制,用来隔离应用并且减少攻击面。

使用Node Selector模拟传统的分段网络,并且通过策略控制他们之间的流量以及来自外部的流量,因为我们约法三章的时候提到Pod之间是可以实现全互联的。带来的问题是,在K8s集群中,可能希望某些Pod不能去访问其他的Pod,这个时候需要用到策略。

Network Policy需要决定:

  • 控制对象,如实例里面的spec部分,通过podSelector或者是namespace中的selector来选择一组特定的pod来接受我们控制
  • 决定流向考虑 需要控制入方向还是出方向

流与端口

Network Policy之前,需要注意

  • apiserver开启extensions/v1beta1/networkpolicies
  • 网络插件要支持Network Policy,例如Calico,Romana,Weave Net和trireme

下面我们着重解决文章开始提出的问题:

Pod内容器之间如何通信?

简而言之,container之间的默认网关都是Docker网桥,同一个宿主机内的容器都接入同一个网桥,那么容器之间可以通过容器的Container-IP直接通信

  • IP在K8s中是以Pod为单位进行分配的
  • 一个Pod内部的所有容器会共享一个网络堆栈(共享网络命名空间,包括IP地址,网络设备和配置)
  • 所以一个Pod的容器之间是不会跨宿主机进行操作的。
  • Pod其实就相当于一个逻辑主机,所以一个Pod内部的容器都好像在一台机器上一样,甚至可以用localhost地址访问彼此的端口。
    云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第12张图片

Pod之间的通信

分为两类:同一个Node内的Pod之间的通信,和不同Node之间Pod的通信。

  • 同一个Node内部的Pod通信

每个Pod都有一个真实的全局IP地址。

云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第13张图片

Pod1和Pod2都是通信veth pair连接到同一个docker0网桥上

它们的IP1,IP2都是通过docker0动态获取。他们和网桥本身的IP3是在同一个网段。

Pod1和Pod2处于同一个局域网,他们之间可以通过docker0作为路由来进行通信。

不同Node上的Pod之间的通信

Pod之间假设通过访问对方的Pod IP进行通信。

不同Node之间的通信只能通过Node的物理网卡进行

Pod的IP地址由各个Node上的docker0网桥动态分配。

需要满足三个条件

  1. 我们知道Pod IP 和 Node IP之间映射关系,通过NodeIP转发到Pod IP
  2. 整个Kubernetes集群中对Pod的IP分配不能出现冲突
  3. 从Pod发出的数据包不应该进行NAT地址转换

对于第一个条件:K8s会记录Pod IP和Node IP之间的映射关系,信息保存在etcd中

对于第二个条件:以Flannel实现的容器跨主机通信为例,我们做解析

  • 每个主机上安装并运行etcd和flannel
  • 在etcd中规划配置所有主机的docker0子网范围
  • 每个主机上的flannelID根据etcd中的配置,为本主机的docker0分配子网,保证所有主机上的网段不重复。然后再把结果存入etcd中。etcd存储主机上docker子网信息和本主机IP的对应关系(key:value - docker子网:本主机ip)
  • 当需要与其他主机上的容器进行通信的时候,查找etcd数据库,找到目的容器子网对应的宿主机ip
  • 装包: 把原始数据包封装在VXLAN或者是UDP数据包中。IP层以宿主机目的IP进行封装
  • VXLAN或者UDP数据包到达目的宿主机解封装

云原生公开课笔记-----Linux虚拟化网络,Docker网络模型与K8s网络模型介绍_第14张图片

ref

https://www.cnblogs.com/hongdada/p/9758939.html
K8s网络实现
https://www.jianshu.com/p/22a7032bb7bd

你可能感兴趣的:(k8s)