K8s之网络通信

目录
  • 网络通信机制
    • flannel
      • flannel pod状态
      • 当前node主机IP地址范围
      • 当前node主机cni信息
      • UDP网络模型(不可用)
        • 修改backend为UDP
      • VxLAN Directrouting
        • 修改flannel支持Directrouting
        • 修改前的路由表
        • 修改后的路由表
      • host-gw网络模型
      • Flannel不同node上的pod的通信流程
    • Calico
      • 部署过程

网络通信机制

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设备以隧道的形式发送到对端。
K8s之网络通信_第1张图片

->: pod中产生数据,根据pod的路由信息,将数据发送到Cni0 
->: Cni0 根据节点的路由表,将数据发送到隧道设备flannel.1 
->: Flannel.1查看数据包的目的ip,从flanneld获得对端隧道设备的必要信息,封装数据包。 
->: Flannel.1将数据包发送到对端设备,对端节点的网卡接收到数据包 
->: 对端节点发现数据包为overlay数据包,解开外层封装,并发送到到本机flannel.1设备。 
->: Flannel.1设备查看数据包,根据路由表匹配,将数据发送给Cni0设备。 
->: Cni0匹配路由表,发送数据给网桥上对应的端口(pod)。

K8s之网络通信_第2张图片

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

K8s之网络通信_第3张图片

部署过程

  • https://docs.projectcalico.org/v3.4/getting-started/kubernetes/
  • 下载镜像
    • https://github.com/projectcalico/calico/releases?after=v3.12.1

修改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

你可能感兴趣的:(K8s之网络通信)