赞
踩
Flannel由CoreOS推出,解决跨主机通信的一种方式;支持3种实现:UDP、VXLAN、host-gw
udp模式:使用设备flannel.0进行封包解包,不是内核原生支持,上下文切换较大,性能非常差;
vxlan模式:使用flannel.1进行封包解包,内核原生支持,性能较强;
host-gw模式:无需flannel.1这样的中间设备,直接宿主机当作子网的下一跳地址,性能最强,host-gw的性能损失大约在10%左右,而其他所有基于VXLAN“隧道”机制的网络方案,性能损失在20%~30%左右
VXLAN,即Virtual Extensible LAN(虚拟可扩展局域网),是Linux本身支持的一网种网络虚拟化技术。VXLAN可以完全在内核态实现封装和解封装工作,从而通过“隧道”机制,构建出覆盖网络(Overlay Network)
在现有的三层网络之上,“覆盖”一层虚拟的、由内核VXLAN模块负责维护的二层网络,使得连接在这个VXLAN二nfcu网络上的“主机”(虚拟机或容器都可以),可以像在同一个局域网(LAN)里那样自由通信。
为了能够在nfcu网络上打通“隧道”,VXLAN会在宿主机上设置一个特殊的网络设备作为“隧道”的两端,叫VTEP:VXLAN Tunnel End Point(虚拟隧道端点)
图例解释:
Container:即运行的容器--包含各自的IP;
Cni0:网桥设备,没创建一个POD都会创建一对veth pair。其中一端是POD中的eth0,另一端是Cni0网桥中的端口(即网卡)
Flanel.1:TUN设备(虚拟网卡),用来进行VXLAN报文的处理(封装和解封)。不同node之间的pod数居流都是从高overlay设备以隧道模式发送到对端的。
Flanneld:flannel在每个主机中运行flanneld作为agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内所有容器的IP地址都将从中分配。同时Flanneld监听K8s集群数据库,为flannel1设备提供封装数据时必要的mac、ip等网络数据信息。
过程解释:
1、当要发送数据包时,首先通过veth pair发送到cni网桥,再路由到本机的flannel.1设备进行处理;
2、VTEP设备之间通过二层数据桢进行通信;源VTEP设备收到原始IP包后,在上面加上一个目的MAC地址,封装成一个导去数据桢,发送给目的VTEP设备(获取 MAC地址需要通过三层IP地址查询,这是ARP表的功能);
3、对于得到的内部数据帧,并不能在宿主机的二层网络传输,Linux内核还需要把它进一步封装成为宿主机的一个普通的数据桢,好让它带着“内部数据桢”通过宿主机的eth0进行传输,Linux会在内部数据桢前面,加上一个VXLAN头,VXLAN头里有一个重要的标志叫VNI,它是VTEP识别某个数据桢是不是应该归自己处理的重要标识。
4、当数据伪装完毕则可以通过eth0进行转发,然后到目的主机进行相应的解析即可。
其中在Flannel中,VNI的默认值是1,这也是为什么宿主机的VTEP设备都叫flannel.1的原因;一个flannel.1设备只知道另一端flannel.1设备的MAC地址,却不知道对应的宿主机地址是什么。
在linux内核里面,网络设备进行转发的依据,来自FDB的转发数据库,这个flannel.1网桥对应的FDB信息,是由flanneld进程维护的。linux内核再在IP包前面加上二层数据桢头,把Node2的MAC地址填进去。这个MAC地址本身,是Node1的ARP表要学习的,需Flannel维护,这时候Linux封装的“外部数据桢”的格式如下
在这里插入图片描述
host-gw是一种纯三层网络的方案,性能最高。
工作原理:就是将每个Flannel子网的下一跳,设置成了该子网对应的宿主机的IP地址,也就是说,宿主机(host)充当了这条容器通信路径的“网关”(Gateway),这正是host-gw的含义。所有的子网和主机的信息,都保存在Etcd中,flanneld只需要watch这些数据的变化 ,实时更新路由表就行了。
核心:IP包在封装成桢的时候,使用路由表的“下一跳”设置上的MAC地址,这样可以经过二层网络到达目的宿主机。
- ##host-gw模式
- [root@server1 fannel]# cp ~/kube-flannel.yml . ##将flannel.yml pod清单复制到当前目录下
-
- [root@server1 fannel]# vim kube-flannel.yml ##编辑kube-flannel.yml文件,将网络类型改为直接路由模式(host-gw)
-
- [root@server1 fannel]# kubectl apply -f kube-flannel.yml
- Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
- podsecuritypolicy.policy/psp.flannel.unprivileged created
- clusterrole.rbac.authorization.k8s.io/flannel created
- clusterrolebinding.rbac.authorization.k8s.io/flannel created
- serviceaccount/flannel created
- configmap/kube-flannel-cfg created
- daemonset.apps/kube-flannel-ds created
-
- [root@server1 fannel]# kubectl get pod -n kube-system ## 查看flannel网络插件应用成功
查看三台Node的IP,发现都存在gw:10.96.0.1/32
创建测试用例:
- ###创建pod:
- [root@server1 network]# vim pod2.yml
- 1 Version: apps/v1
- 2 kind: Deployment
- 3 metadata:
- 4 name: deployment-example
- 5 spec:
- 6 replicas: 4
- 7 selector:
- 8 matchLabels:
- 9 app: myapp
- 10 template:
- 11 metadata:
- 12 labels:
- 13 app: myapp
- 14 spec:
- 15 containers:
- 16 - name: myapp
- 17 image: nginx
-
- ##创建服务:
- 1 nd: Service
- 2 apiVersion: v1
- 3 metadata:
- 4 name: myservice
- 5 spec:
- 6 ports:
- 7 - protocol: TCP
- 8 port: 80
- 9 targetPort: 80
- 10 selector:
- 11 app: myapp
- 12 type: NodePort
-
查看节点上的IP:10.224.1.0/24 10.224.2.0/24
通过外部访问:不卡顿,server2 server3 轮循访问
- ##删除之前的模式:
- [root@server1 fannel]# kubectl delete -f kube-flannel.yml
-
- ##重新设置配置
- [root@server1 fannel]# vim kube-flannel.yml
-
- ##应用新的配置
- [root@server1 fannel]# kubectl apply -f kube-flannel.yml
-
- ##查看服务是否启动
- [root@server1 fannel]# kubectl get pod -n kube-system
使用curl进行访问测试,和host-gw相同,这里不再赘述。
默认当前的通信模式为calico,具体切换方式,请查看文章:
kubernetes---fannel和calico之间的切换
官方参考:
https://projectcalico.docs.tigera.io/getting-started/kubernetes/self-managed-onprem/onpremises
Fannal只解决通信,没有策略,k8s本事有相应的策略,但是需要相应的服务进行支持。
Calico 就是一种开源网络和网络安全解决方案,适用于容器,虚拟机和基于主机的本机工作负载。Calico 支持广泛的平台,包括 Kubernetes,docker,OpenStack 和裸机服务。Calico 后端支持多种网络模式。
BGP 模式:将节点做为虚拟路由器通过 BGP 路由协议来实现集群内容器之间的网络访问。
IPIP 模式:在原有 IP 报文中封装一个新的 IP 报文,新的 IP 报文中将源地址 IP 和目的地址 IP 都修改为对端宿主机 IP。
cross-subnet:Calico-ipip 模式和 calico-bgp 模式都有对应的局限性,对于一些主机跨子网而又无法使网络设备使用 BGP 的场景可以使用 cross-subnet 模式,实现同子网机器使用 calico-BGP 模式,跨子网机器使用 calico-ipip 模式。
Felix: 监听ECTD中心的存储获取事件,用户创建pod后,Felix负责将其网卡、IP、MAC都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。同样如果用户制定了限离策略,Felix同样会将该策略创建到ACL中,以实现隔离。
BIRD: 一个标准的路由程序,它会从内核里面获取哪一些IP的路由发生了变化,然后通过标准 BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这个P在这里,路由的时候到这里来。
- ##安装和配置calico
-
- ##下载配置文件
- curl https://projectcalico.docs.tigera.io/manifests/calico.yaml -O
-
- ##根据配置文件,下载相应的镜像
- [root@server1 fannel]# docker pull docker.io/calico/cni:v3.22.2
- [root@server1 fannel]# docker pull docker.io/calico/pod2daemon-flexvol:v3.22.2
- [root@server1 fannel]# docker pull docker.io/calico/node:v3.22.2
- [root@server1 fannel]# docker pull docker.io/calico/kube-controllers:v3.22.2
-
- ##编写配置文件的模式,设置IPIP为OFF
-
- ##应用配置文件
- [root@server1 calico]# kubectl apply -f calico.yaml
-
- ##查看应用状态
- [root@server1 calico]# kubectl get pod -n kube-system
- [root@server1 calico]# kubectl get daemonset.apps -n kube-system
-
- ##查看运行的模式
- [root@server1 calico]# kubectl describe ippools
-
-
- ##配置pod和svc,查看通信状态
- [root@server1 network]# cat pod2.yml
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: deployment-example
- spec:
- replicas: 4
- selector:
- matchLabels:
- app: myapp
- template:
- metadata:
- labels:
- app: myapp
- spec:
- containers:
- - name: myapp
- image: nginx
-
- [root@server1 network]# cat server2.yml
- kind: Service
- apiVersion: v1
- metadata:
- name: myservice
- spec:
- ports:
- - protocol: TCP
- port: 80
- targetPort: 80
- selector:
- app: myapp
- type: NodePort
-
- ##查看路由环,观察通信模式
- [root@server1 network]# ip route
- [root@server1 calico]# vim calico.yaml
- # Enable IPIP
- - name: CALICO_IPV4POOL_IPIP
- value: "Always"
-
- - name: CALICO_IPV4POOL_CIDR
- value: "192.168.0.0/16"
- [root@server1 calico]# kubectl apply -f calico.yaml
calico的限制策略都是通过标签来进行匹配,设置相应的主机服务。
官方网址:https://projectcalico.docs.tigera.io/security/
- apiVersion: networking.k8s.io/v1
- kind: NetworkPolicy
- metadata:
- name: deny-nginx
- spec:
- podSelector: ##通过标签选择含有指定label的pod进行通信
- matchLabels:
- app: nginx
- kind: NetworkPolicy
- apiVersion: networking.k8s.io/v1
- metadata:
- name: access-nginx
- spec:
- podSelector:
- matchLabels:
- app: nginx
- ingress: ##允许通过
- - from:
- - podSelector: ##选择含有对应的标签的pod
- matchLabels:
- app: demo
- apiVersion: networking.k8s.io/v1
- kind: NetworkPolicy
- metadata:
- name: default-deny
- namespace: default
- spec:
- podSelector: {} ##没有选择任何标签,则为拒绝所有POD
- kind: NetworkPolicy
- apiVersion: networking.k8s.io/v1
- metadata:
- name: deny-namespace
- spec:
- podSelector:
- matchLabels:
- ingress: ##没有选择其他的namespace,则为禁止其他的namespace
- - from:
- - podSelector: {}
- kind: NetworkPolicy
- apiVersion: networking.k8s.io/v1
- metadata:
- name: access-namespace
- spec:
- podSelector:
- matchLabels:
- app: myapp
- ingress:
- - from:
- - namespaceSelector: ##指定有相应标签的namespace
- matchLabels:
- role: prod
- kind: NetworkPolicy
- apiVersion: networking.k8s.io/v1
- metadata:
- name: web-allow-external
- spec:
- podSelector:
- matchLabels:
- app: web
- ingress: ##指定特定端口
- - ports:
- - port: 80
- from: [] ##来自于任何地方均可以
【注】上述代码只给出了核心代码,测试时需要编写相应的POD和SVC的yml文件
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。