02.k8s网络原理
# 01.前言
# 1.0 k8s网络介绍
- CNI(容器网络接口)是K8s中提供的一种通用网络标准规范,因为k8s本身不提供网络解决方案。
- 目前比较知名的网络解决方案有: flannel、calico、canel、kube-router(目前比较常用的时flannel和calico)
- flannel的功能比较简单,不具备复杂网络的配置能力,calico可以进行复杂网络配置
- 所以相对而言,比较小而简单的集群使用flannel,考虑到日后扩容,配置更多策略,则使用calico更好
# 1.1 docker网络模式
- 1)host模式(常用)
- 容器和宿主机共享Network namespace(–net=host)
- 容器不会获得一个独立的network namespace,而是与宿主机共用一个。
- 这就意味着容器不会有自己的网卡信息,而是使用宿主机的,容器除了网络,其他都是隔离的。
- 2)bridge(常用)
- –net=bridge
- 默认网络,Docker启动后创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。
- 3)none(不常用)
- –net=none
- 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。
- 4)container(不常用)
- –net=container:Name/ID
- 与指定的容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都还是隔离的。
- 5)自定义网络(最佳方式)
- 与默认的bridge原理一样,但自定义网络具备内部DNS发现,可以通过容器名或者主机名容器之间网络通信。
# 1.2 同宿主机容器间通信
在同一宿主机的多台容器正常都是配置在同一网段中的,互相通信只需要一个虚拟交换机即可
在容器中,通过docker0网桥来实现虚拟交换机,凡是连接到docker0的容器,就可以通过它来进行通信
容器通过网络二层发送ARP广播(通过ip获得mac地址),正确的虚拟网卡就会响应这个ARP报文
容器之间就可以通过虚拟交换机进行二层通信(mac地址通讯)
# 02.跨主机通讯CNI
# 2.1 CNI组件由来
- 在 Docker 的默认配置下,不同宿主机上的容器通过 IP 地址进行互相访问是根本做不到的
- 为了解决这个问题,社区中出现了很多网络方案,k8s为了更好的控制网络的接入,推出了
CNI即容器网络的API接口
- 实际上CNI的容器网络通信流程跟前面的基础网络一样,只是CNI维护了一个单独的网桥来代替 docker0
- 这个网桥的名字就叫作:CNI 网桥,它在宿主机上的设备名称默认是:cni0
- cni的设计思想,就是
- Kubernetes 在启动 Infra 容器之后,就可以直接调用 CNI 网络插件
- 为这个 Infra 容器的 Network Namespace,配置符合预期的网络栈
# 2.2 CNI插件三种网络模式
1)overlay (基于隧道)
- 模式是基于隧道技术实现的,整个容器网络和主机网络独立
- 容器之间跨主机通信时将整个容器网络封装到底层网络中,然后到达目标机器后再解封装传递到目标容器
- 不依赖与底层网络的实现。实现的插件有flannel(UDP、vxlan)、calico(IPIP)等等
2)三层路由模式(基于路由)
- 三层路由模式中容器和主机也属于不通的网段,他们容器互通主要是基于路由表打通,无需在主机之间建立隧道封包
- 但是限制条件必须依赖大二层同个局域网内,实现的插件有flannel(host-gw)、calico(BGP)等等
3)underlay网络是底层网络,负责互联互通
- 容器网络和主机网络依然分属不同的网段,但是彼此处于同一层网络,处于相同的地位。
- 整个网络三层互通,没有大二层的限制,但是需要`强依赖底层网络的实现支持,实现的插件有calico(BGP)等等
# 03.flanlel
# 3.1 flannel介绍
flannel项目是在三层物理网络之上构建一个可跨节点通信容器网络
负责为节点下发子网和路由等信息,为容器分发唯一IP,flannel只实现简单的网络通信,不支持网络ACL
flannel 支持vxlan、host-gw模式,udp模式已弃用。
在k8s中flannel作为标准CNI插件,每个节点都会运行一个flanneld的二进制代理程序
每个节点分配一个子网,集群网络状态通过apiserver直接存储在etcd当中
# 3.2 什么是VxLAN
- VXLAN即虚拟扩展局域网,是大二层网络中广泛使用的网络虚拟化技术
- 将虚拟机发出的原始以太报文完整的封装在UDP报文中,然后在外层使用物理网络的IP报文头和以太报文头封装
- 这样,封装后的报文就像普通IP报文一样,可以通过路由网络转发
- 这就像给二层网络的虚拟机插上了路由的翅膀,使虚拟机彻底摆脱了二、三层网络的结构限制
# 3.3 pod跨节点通讯
1、pod-a访问pod-b 因为两者IP不在同一个子网,
首先数据会先到默认网关也就是cni0 10.64.0.1
2、节点上面的
静态路由
可以看出来10.64.1.0/24 是指向flannel.1
的- 本机路由需要静态路由表由flanneld动态维护
3、flannel.1 会使用vxlan协议
把原始IP包加上目的mac地址封装成二层数据帧
- vxlan协议封装数据帧组成VTEP二层网络,那么就必须知道对方VTEP设备 flannel.1的mac地址
- ARP表也由flanneld动态维护,目的mac就是aa:93:00:62:7d:0f
4、原始vxlan数据帧无法在物理二层网络中通信
- flannel.1 (linux 内核支持vxlan,此步骤由内核完成)会把
数据帧封装成UDP报文
经过物理网络发送到node-02 - 封装UDP报文时已知目的mac地址aa:93:00:62:7d:0f,但是却不知道对方eth0的IP地址,FDB表也由flanneld动态维护
- flannel.1 (linux 内核支持vxlan,此步骤由内核完成)会把
5、node-02收到UDP报文中带有vxlan头信息,会
转交给flannel.1解封装得到原始数据
6、flannel.1 根据直连
路由转发到cni0
上面7、
cni0 转发给pod-2
# 3.4 host-gw方式
- host-gw 相对vxlan模式相对比较简单,直接把节点作为一个网关
- 比如节点node-02上的pod子网是10.64.1.0/24,那么集群中所有节点上都会增加一条路由指向node-02
- 很显然host-gw模式对物理网络有严格的要求,中间不能有额外路由,宿主机要求能在二层网络下能直接通信
# 04.Calico
# 4.1 Calico介绍
Calico是一个纯三层的协议,为OpenStack虚机和Docker容器提供多主机间通信
使用虚拟路由代替虚拟交换,每一台虚拟路由通过BGP协议传播可达信息(路由)到剩余数据中心
Calico的特点就是把每个宿主机当中一个虚拟路由器建立与物理网络对等的虚拟网络
该模式BGP协议在网络中通告路由信息,巧妙的把二层网络转换成三层路由网络,避免报文被二次封装数据转发效率很高
Pod IP可以在物理网络中全局路由,当然Calico除了路由模式还是支持Overlay Network网络模式比如vxlan
# 4.2 Calico的主要组件
Felix,Calico agent,跑在每台需要运行 workload 的节点上
Felix
:每个节点都要运行的calico agent,负责配置节点上的路由信息和ACLETCD
:配置中心,主要负责网络元数据一致性,确保Calico网络状态的准确性BGP Client
(BIRD):主要负责把Felix配置的路由信息分发到当前Calico网络,确保节点间能够进行三层通信
etcd,分布式键值存储,主要负责网络元数据一致性,确保 Calico 网络状态的准确性
# 4.3 Calico网络方式(两种)
1)IPIP
- 从字面来理解,就是把一个IP数据包又套在一个IP包里,即把 IP 层封装到 IP 层的一个 tunnel
- 它的作用其实基本上就相当于一个基于IP层的网桥,把两个本来不通的网络通过点对点连接起来
- 一般来说,普通的网桥是基于mac层的,根本不需 IP,而这个 ipip 则是通过两端的路由做一个 tunnel
2)BGP
- 边界网关协议(Border Gateway Protocol, BGP)是互联网上一个核心的去中心化自治路由协议
- 它通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议
- BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由
- 因此,它更适合被称为矢量性协议,而不是路由协议
- BGP,通俗的讲就是讲接入到机房的多条线路(如电信、联通、移动等)融合为一体,实现多线单IP
- BGP 机房的优点:服务器只需要设置一个IP地址,最佳访问路由是由网络上的骨干路由器根据路由跳数与其它技术指标来确定的,不会占用服务器的任何系统。