怀念一下LINUX的网络相关知识,做个铺垫
工作在物理层,没有隔离和过滤功能 (就是说外部进来的流量会传到与集线器相连的每一个节点上)。网络是广播方式
为了让节点不接受到不必接收到的流量(因为集线器会把流量广播出去),可以将网络的多个网段在数据链路层连接起来的网络设备,其工作原理是在L2数据链路层根据MAC地址进行过滤和转发,常用于连接两个不同的网段。
功能强大的网桥,有更多的接口连接更多的不同网段的子网
工作在网络层,根据网络地址(IP地址)进行过滤-分割网络信息流-连接网络分支。主要是用于广域网与局域网的连接
把信息重新包装(封装流量),以适应目标环境要求
不同命名空间网络栈完全隔离,命名空间中包括:独立路由表,独立IPTables,独立NAT,独立IP包过滤,独立进程,独立套接字,独立网络设备。网络设备(网卡)属于公共资源,通过修改属性在各个命名空间移动进而实现共享。
成对出现,并拼接成一起,可以将两个命名空间进行数据通信,数据从协议栈接收到数据后,会发送到另一台设备上。命名空间通过Veth进行通信。
网桥会将接收到的数据与自己保存起来的MAC地址表进行比较,查询数据应该被转发到的地方。当MAC地址表数据失效的时候,就需要通过广播的方式来更新数据。虚拟网桥是被用来连接单台物理机内的物理网卡和其他虚拟网络设备的。
TUN和TAP是由纯软件实现的Linux内核虚拟网络设备,是一种以太网设备,TUN和TAP包含字符设备驱动和网卡驱动两部分,其中字符设备驱动是模拟物理链路的数据接收和发送,网卡驱动是接受来自TCP/IP协议栈的网络分包并发送,常用于加密/VPN/隧道/虚拟机等。
浏览器发送了一个Socket请求,数据不会立即到物理网卡,它会被TUN/TAP这种网络设备接收到,会转发给VPN的应用,VPN的应用会对原有的数据进行一个转化,转化之后再通过物理网卡进行发出(相当于对之前的数据进行了一个封装加密)。从图中可以看出不同的容器使用了不同的网络命名空间,也就会有独立的网络协议栈,他们之间的沟通是因为命名空间内都有一个虚拟网卡,跟与之对应的网桥(Docker0)的虚拟网卡(veth)形成一个veth设备对进行通信。。
Linux网络协议栈中回调函数挂载点的实现包括IPTables和NetFilter负责内核中执行各种挂接规则,运行在内核模式下。IPTables在用户模式下,协助和维护内核中Netfilter的各种规则表。
Linux网络协议栈其实是用来一个过滤,转发,数据处理的,为了方便修改的各种处理规则,他就有了回调函数挂载点,对普通用户来说,就是修改IPTables的规则来影响Netfilter的规则最终影响到内核。就会让某个外部网络请求过来之后按照我们预定的网络规则进行一个数据处理。
Linux的路由功能是通过路由表来实现的,IP层在处理和转发数据时,会根据路由表记录的目的地IP地址与下一个路由IP的关系,进行数据的转发。
二层网络: 是通过MAC地址获取目标,在数据链路层进行数据传递;好处是不需要解封包,效率高;坏处是所以机器必须同在一个子网,只能通过交换机连接,机器数量有限
三层路由:需要通过IP进行寻址,好处是网络可以更加复杂,规模更大,坏处是性能相对二层网络低
Kubernetes的网络分层与OSI七层网络侧重不同,Kubernetes的四层网络是从Kubernetes网络功能层面描述的。
Docker的网络是通过创建Docker0网桥设备,使Docker容器实现与外部通信。这个过程由于Docker0网桥的存在,每个物理机上的容器与外部网络处于不同的网段,无法直接与外部网络通信,更无法实现不同主机上的不同的容器的直接通信。目前都需要进行NAT转换才能通信,也就导致Docker容器内部看到自身的网络IP(Docker0的子网IP【Podip】)与物理机外部看到的容器的公网IP不一样。
为了让容器之间的网络连通,就产生了网络模型
CNM通过Network sandbox,Endpoint,Network实现。容器中会有一个Network sandbox,Network sandbox中会有一个或者多个Endpoint,Network实现多个Endpoint的相连,从而实现容器的网络连通
CNI表示通过绑定网络插件的模式加入网络中,他只定义了容器运行环境与网络插件之间的接口规范,网络插件则由不同的供应商实现。CNI会让所有的容器拥有独立的Linux网络命名空间,可以绑定多个网络插件加入多个网络,每个网络则要能够做到使用该插件的容器相互连接,且各自拥有独立且唯一的IP地址
K8S采用CNI的网络模型,本身不自带网络控制,由第三方组件进行网络实现。网络模型的要求本质是IP-per-Pod,在网络层面做到可以将每个Pod看作集群中相互直连的独立虚拟机或物理机。K8S网络要求如下:
第一条: Pod在集群中是相互独立的,任意两个Pod之间是可以直接通信的,无需经过显式的使用NAT来接收数据和地址的转换
第二条: Node和Pod之间是可以直接通信的,无需使用明显的地址转换
第三条: Pod看到自己的IP跟别人看见他使用的IP是一样的,中间不能经过转换。
容器的网络最终还是要靠物理网络来实现的,
接入:是容器与宿主机用那种机制做连接(意思是容器怎么和宿主机实现链接呢?),如:Veth+bridge,Veth+Pair,MAC,IPVlan
流控:看方案是否支持Network policy ,以及怎么支持
通道:两个主机通过什么方式完成包的传输
CNI的三种实现模式:
方案:
维护Pod IP方案:Flannel借助ETCD维护所有的Pod的IP,保证所有的Pod的IP唯一。然后通过修改Docker启动参数,指定每个Pod的IP。
Pod到Pod的网络通信方案:通过对Docker0传输数据的包装,利用物理网络转发到目标Pod所在机器,再由目标机器的Flannel解包,转发给目标Pod
劣势:
需要封包,解包,有网络的性能损耗
方案:
维护Pod IP方案:需要实现先规划好
Pod到Pod的网络通信方案:在交换机中配置每个docker0子网到Node的路由项,在Linux系统中配置docker0和Node之间的匹配关系,这样实现Pod到Pod到网络的连通。
劣势:
需要维护路由项,集群规模大时,会有很大的路由表维护的工作量
维护Pod IP方案:也是借助ETCD进行Pod的IP维护
Pod到Pod的网络通信方案:Calico默认模式是BGP,该模式利用Linux内核实现虚拟路由器进行数据转发。每个虚拟路由vRouter通过BGP协议将路由信息对整个Calico进行网络广播,自动扩展各个节点路由规则。当网络规模小,集群节点处于一个子网中时,可以通过上面的方式直连,当规模较大时,需要额外的BGP route reflector实现分级路由分发。这种模式是Underlay的方案。
Calico也可以通过设置IP Pool的模式为IPIP,采用节点间搭隧道的模式进行网络传输,这种模式就需要解包,封包造成的性能损耗了,这就是Overlay的方案。
用于网络隔离,相当于一个Pod网络连通的白名单。基本原理是:通过选择器找到一组Pod,再通过流量的特征描述决定他们之间能否连通。选用的CNI插件要能支持Network Policy,K8S没有内部自有的实现方式。
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: backend-policy
namespace: development
spec:
podSelector: # 控制对象选择器
matchLabels:
app: webapp
role: backend
ingress: # 流入控制
- from:
- namespaceSelector: {}
podSelector:
matchLabels:
app: webapp
role: frontend
engross: # 流出控制
- to:
- ipBlock:
cidr: 10.11.51.0/24 # 只允许流到这个方向去
1.我们想访问某个服务的时候,Pod的DNS域名为..Pod.其中Pod-ip中要用 “-” 替换 “.” ,如:10-11-51-14.default.pod.cluster.local是IP为10.11.51.14的Pod的DNS域名
2.Pod的DNS策略
.51.14的Pod的DNS域名
2.Pod的DNS策略
K8S的网络核心在于K8S采用的网络模型。