目录
网络通信机制
k8s的网络基于第三方插件实现,但是定义了一些插件兼容规范,该规范有CoreOS和Google联合定制,叫做 CNI(Container Network Interface)。
calicoz支持更多的网络层的安全策略,flannel不支持
公有云大多使用flannel,使用vxlan+Directrouting模式
自建IDC使用哪种模型都可以,flannel配置比较简单,calico功能较多
性能差别不大,calico性能会略高于flannel
私有云推荐使用calico
公有云推挤使用flannel
flannel
官网:https://coreos.com/flannel/docs/latest/
文档:https://coreos.com/flannel/docs/latest/kubernetes.html
Flannel 网络模型 (后端),Flannel目前有三种方式实现 UDP/VXLAN/host-gw
UDP:早期版本的Flannel使用UDP封装完成报文的跨越主机转发,其安全性及性能略有不足。
VXLAN:Linux 内核在在2012年底的v3.7.0之后加入了VXLAN协议支持,因此新版本的Flannel也有UDP转换为 VXLAN,VXLAN本质上是一种tunnel(隧道)协议,用来基于3层网络实现虚拟的2层网络,目前flannel 的网络模型已 经是基于VXLAN的叠加(覆盖)网络。
Host-gw:也就是Host GateWay,通过在node节点上创建到达各目标容器地址的路由表而完成报文的转发,因此这种 方式要求各node节点本身必须处于同一个局域网(二层网络)中,因此不适用于网络变动频繁或比较大型的网络环境,但是 其性能较好。
Flannel 组件的解释
- Cni0:网桥设备,每创建一个pod都会创建一对 veth pair,其中一端是pod中的eth0,另一端是Cni0网桥中的端口 (网卡),Pod中从网卡eth0发出的流量都会发送到Cni0网桥设备的端口(网卡)上,Cni0 设备获得的ip地址是该节 点分配到的网段的第一个地址。
- Flannel.1: overlay网络的设备,用来进行vxlan报文的处理(封包和解包),不同node之间的pod数据流量都从 overlay设备以隧道的形式发送到对端。
Flannel的系统文件及目录
- root@node2:~# find / -name flannel
/run/flannel
/usr/bin/flannel
/var/lib/cni/flannel
flannel pod状态
root@master1:~# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-85bd4f9784-95qcb 1/1 Running 0 6h15m
kube-flannel-ds-amd64-4dvn9 1/1 Running 0 23h
kube-flannel-ds-amd64-6zk8z 1/1 Running 0 23h
kube-flannel-ds-amd64-d54j4 1/1 Running 0 23h
kube-flannel-ds-amd64-hmnsj 1/1 Running 0 22h
kube-flannel-ds-amd64-k52kz 1/1 Running 0 23h
kube-flannel-ds-amd64-q42lh 1/1 Running 0 23h
当前node主机IP地址范围
root@node1:~# cat /run/flannel/subnet.env
FLANNEL_NETWORK=10.20.0.0/16
FLANNEL_SUBNET=10.20.3.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
当前node主机cni信息
root@node1:~# cat /var/lib/cni/flannel/0929d39656c75c9518ac16a785c12ebc301a254d03e58387d27ff365e04562a0
{"cniVersion":"0.3.1","hairpinMode":true,"ipMasq":false,"ipam":{"routes":[{"dst":"10.20.0.0/16"}],"subnet":"10.20.3.0/24","type":"host-local"},"isDefaultGateway":true,"isGateway":true,"mtu":1450,"name":"cbr0","type":"bridge"}
UDP网络模型(不可用)
重新执行网络并重启master与node服务器
- 设置flannel 后端
- FLANNEL_BACKEND: "host-gw"
- FLANNEL_BACKEND: "vxlan"
- FLANNEL_BACKEND: "UDP
修改backend为UDP
Type有变量FLANNEL_BACKEND定义
root@master1:~# vim /etc/ansible/roles/flannel/templates/kube-flannel.yaml.j2
net-conf.json: |
{
"Network": "{{ CLUSTER_CIDR }}",
"Backend": {
{% if FLANNEL_BACKEND == "vxlan" and DIRECT_ROUTING %}
"DirectRouting": true,
{% endif %}
"Type": "{{ FLANNEL_BACKEND }}"
}
}
查找定义FLANNEL_BACKEND变量的文件
root@master1:~# grep FLANNEL_BACKEND /etc/ansible/roles/flannel/ -R
/etc/ansible/roles/flannel/defaults/main.yml:#FLANNEL_BACKEND: "host-gw"
/etc/ansible/roles/flannel/defaults/main.yml:FLANNEL_BACKEND: "vxlan"
/etc/ansible/roles/flannel/templates/kube-flannel.yaml.j2:{% if FLANNEL_BACKEND == "vxlan" and DIRECT_ROUTING %}
/etc/ansible/roles/flannel/templates/kube-flannel.yaml.j2: "Type": "{{ FLANNEL_BACKEND }}"
将FLANNEL_BACKEND设置为UDP
root@master1:~# cat /etc/ansible/roles/flannel/defaults/main.yml
# 部分flannel配置,参考 docs/setup/network-plugin/flannel.md
# 设置flannel 后端
#FLANNEL_BACKEND: "host-gw"
#FLANNEL_BACKEND: "vxlan"
FLANNEL_BACKEND: "udp"
DIRECT_ROUTING: false
#flanneld_image: "quay.io/coreos/flannel:v0.10.0-amd64"
flanneld_image: "easzlab/flannel:v0.11.0-amd64"
# 离线镜像tar包
flannel_offline: "flannel_v0.11.0-amd64.tar"
k8s需要重新安装生效
VxLAN Directrouting
Directrouting 为在同一个二层网络中的node节点启用直接路由机制,类似于host-gw模式。
修改flannel支持Directrouting
需要让配置文件在node节点重新生效
修改DIRECT_ROUTING:为true
root@master1:~# vim /etc/ansible/roles/flannel/defaults/main.yml
# 部分flannel配置,参考 docs/setup/network-plugin/flannel.md
# 设置flannel 后端
#FLANNEL_BACKEND: "host-gw"
FLANNEL_BACKEND: "vxlan"
DIRECT_ROUTING: true
#flanneld_image: "quay.io/coreos/flannel:v0.10.0-amd64"
flanneld_image: "easzlab/flannel:v0.11.0-amd64"
# 离线镜像tar包
flannel_offline: "flannel_v0.11.0-amd64.tar"
重新配置network
root@master1:/etc/ansible# ansible-playbook 06.network.yml
master和node节点重启或重装k8s生效
root@node1:~# reboot
修改前的路由表
root@node1:~# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.203.104.254 0.0.0.0 UG 0 0 0 ens160
10.20.0.0 10.20.0.0 255.255.255.0 UG 0 0 0 flannel.1
10.20.1.0 10.20.1.0 255.255.255.0 UG 0 0 0 flannel.1
10.20.2.0 10.20.2.0 255.255.255.0 UG 0 0 0 flannel.1
10.20.3.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
10.20.4.0 10.20.4.0 255.255.255.0 UG 0 0 0 flannel.1
10.20.5.0 10.20.5.0 255.255.255.0 UG 0 0 0 flannel.1
10.203.104.0 0.0.0.0 255.255.255.0 U 0 0 0 ens160
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
修改后的路由表
root@node1:~# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.203.104.254 0.0.0.0 UG 0 0 0 ens160
10.20.0.0 10.203.104.21 255.255.255.0 UG 0 0 0 ens160
10.20.1.0 10.203.104.20 255.255.255.0 UG 0 0 0 ens160
10.20.2.0 10.203.104.27 255.255.255.0 UG 0 0 0 ens160
10.20.3.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
10.20.4.0 10.203.104.28 255.255.255.0 UG 0 0 0 ens160
10.20.5.0 10.203.104.22 255.255.255.0 UG 0 0 0 ens160
10.203.104.0 0.0.0.0 255.255.255.0 U 0 0 0 ens160
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
host-gw网络模型
修改FLANNEL_BACKEND为host-gw模型
root@master1:~# vim /etc/ansible/roles/flannel/defaults/main.yml
# 部分flannel配置,参考 docs/setup/network-plugin/flannel.md
# 设置flannel 后端
FLANNEL_BACKEND: "host-gw"
#FLANNEL_BACKEND: "vxlan"
DIRECT_ROUTING: false
#flanneld_image: "quay.io/coreos/flannel:v0.10.0-amd64"
flanneld_image: "easzlab/flannel:v0.11.0-amd64"
# 离线镜像tar包
flannel_offline: "flannel_v0.11.0-amd64.tar"
重新配置network
root@master1:/etc/ansible# ansible-playbook 06.network.yml
master和node节点重启或重装k8s生效
root@node1:~# reboot
Flannel不同node上的pod的通信流程
Flannel.1 是一个overlay网络的设备,用来进行 vxlan 报文的处理(封包和解包),不同node之间的pod数据流量 都从overlay设备以隧道的形式发送到对端。
->: pod中产生数据,根据pod的路由信息,将数据发送到Cni0
->: Cni0 根据节点的路由表,将数据发送到隧道设备flannel.1
->: Flannel.1查看数据包的目的ip,从flanneld获得对端隧道设备的必要信息,封装数据包。
->: Flannel.1将数据包发送到对端设备,对端节点的网卡接收到数据包
->: 对端节点发现数据包为overlay数据包,解开外层封装,并发送到到本机flannel.1设备。
->: Flannel.1设备查看数据包,根据路由表匹配,将数据发送给Cni0设备。
->: Cni0匹配路由表,发送数据给网桥上对应的端口(pod)。
Calico
官网:https://www.projectcalico.org/
github: https://github.com/projectcalico/calico
Calico是一个纯三层的网络解决方案,为容器提供多node间的访问通信,calico将每一个node节点都当做为一个路 由器(router),各节点通过BGP(Border Gateway Protocol) 边界网关协议学习并在node节点生成路由规则,从而 将不同node节点上的pod连接起来进行通信。
BGP是一个去中心化的协议,它通过自动学习和维护路由表实现网络的可用性,但是并不是所有的网络都支持 BGP,另外为了跨网络实现更大规模的网络管理,calico 还支持IP-in-IP的叠加模型,简称IPIP,IPIP可以实现跨不 同网段建立路由通信,但是会存在安全性问题,其在内核内置,可以通过Calico的配置文件设置是否启用IPIP,在 公司内部如果k8s的node节点没有跨越网段建议关闭IPIP。
IPIP是一种将各Node的路由之间做一个tunnel,再把两个网络连接起来的模式。启用IPIP模式时,Calico将在各 Node上创建一个名为"tunl0"的虚拟网络接口。
BGP模式则直接使用物理机作为虚拟路由路(vRouter),不再创建额外的tunnel。
calico 核心组件
Felix:calico的agent,运行在每一台node节点上,其主要是维护路由规则、汇报当前节点状态以确保pod的夸主机 通信。
BGP Client:每台node都运行,其主要负责监听node节点上由felix生成的路由信息,然后通过BGP协议广播至其他剩 余的node节点,从而相互学习路由实现pod通信。
Route Reflector:集中式的路由反射器,calico v3.3开始支持,当Calico BGP客户端将路由从其FIB(Forward Information dataBase,转发信息库)通告到Route Reflector时,Route Reflector会将这些路由通告给部署 集群中的其他节点,Route Reflector专门用于管理BGP网络路由规则,不会产生pod数据通信。
注:calico默认工作模式是BGP的node-to-node mesh,如果要使用Route Reflector需要进行相关配置。 https://docs.projectcalico.org/v3.4/usage/routereflector https://docs.projectcalico.org/v3.2/usage/routereflector/calico-routereflector
部署过程
修改ansible的hosts文件中的CLUSTER_NETWORK为calico
root@master1:~# grep CLUSTER_NETWORK /etc/ansible/hosts
CLUSTER_NETWORK="calico"
下载镜像并上传到harbor
root@master1:~# docker images | grep calico
calico/node v3.4.4 a8dbf15bbd6f 14 months ago 79.6MB
calico/cni v3.4.4 f5e5bae3eb87 14 months ago 75.4MB
calico/kube-controllers v3.4.4 0030ff291350 14 months ago 56.5MB
root@master1:~# docker tag calico/node:v3.4.4 harbor.linux.com/calico/node:v3.4.4
root@master1:~# docker push harbor.linux.com/calico/node:v3.4.4
root@master1:~# docker tag calico/cni:v3.4.4 harbor.linux.com/calico/cni:v3.4.4
root@master1:~# docker push harbor.linux.com/calico/cni:v3.4.4
root@master1:~# docker tag calico/kube-controllers:v3.4.4 harbor.linux.com/calico/kube-controllers:v3.4.4
root@master1:~# docker push harbor.linux.com/calico/kube-controllers:v3.4.4
calico-v3.4.yaml.j2配置文件
将image修改为harbor的地址,其他字段不需要修改
root@master1:/etc/ansible/roles/calico/templates# vim calico-v3.4.yaml.j2
开启和关闭IPIP
root@master1:/etc/ansible# cat roles/calico/defaults/main.yml
# 部分calico相关配置,更全配置可以去roles/calico/templates/calico.yaml.j2自定义
# 如果 node 节点有多块网卡,请设置 true
# 另外发现设置为 true 时能够解决v1.10使用ipvs偶尔出现pod内‘dial tcp 10.68.0.1:443: i/o timeout’的 bug
NODE_WITH_MULTIPLE_NETWORKS: "true"
# etcd 集群服务地址列表, 根据etcd组成员自动生成
TMP_ENDPOINTS: "{% for h in groups['etcd'] %}https://{{ h }}:2379,{% endfor %}"
ETCD_ENDPOINTS: "{{ TMP_ENDPOINTS.rstrip(',') }}"
# 设置 CALICO_IPV4POOL_IPIP=“off”,可以提高网络性能,条件限制详见 docs/setup/calico.md
CALICO_IPV4POOL_IPIP: "Always" # 开启IPIP
# 设置 Felix 日志级别
FELIX_LOG_LVL: "warning"
# 设置 calico-node使用的host IP,bgp邻居通过该地址建立,可手工指定也可以自动发现
#IP_AUTODETECTION_METHOD: "interface=eth0"
IP_AUTODETECTION_METHOD: "can-reach={{ groups['kube-master'][0] }}"
# 更新支持calico 版本: [v3.2.x] [v3.3.x] [v3.4.x]
calico_ver: "v3.4.4"
# calico 主版本
calico_ver_main: "{{ calico_ver.split('.')[0] }}.{{ calico_ver.split('.')[1] }}"
# 离线镜像tar包
calico_offline: "calico_{{ calico_ver }}.tar"
部署集群
root@master1:/etc/ansible# ansible-playbook 06.network.yml
验证当前路由表
root@node1:~# calicoctl node status