欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

042.集群网络-flannel及calico

程序员文章站 2022-03-05 17:17:37
一Flannel组件 1.1flannel介绍 Kubernetes的网络模型假定了所有Pod都在一个可以直接连通的扁平网络空间中。若需要实现这个网络假设,需要实现不同节点上的Docker容器之间的互相访问,然后运行Kubernetes。目前已经有多个开源组件支持容器网络模型。如Flannel、 ......

一 flannel组件

1.1 flannel介绍

kubernetes的网络模型假定了所有pod都在一个可以直接连通的扁平网络空间中。若需要实现这个网络假设,需要实现不同节点上的docker容器之间的互相访问,然后运行kubernetes。目前已经有多个开源组件支持容器网络模型。如flannel、open vswitch、直接路由和calico。
flannel之所以可以搭建kubernetes依赖的底层网络,是因为它能实现以下两点。
  1. 它能协助kubernetes,给每一个node上的docker容器都分配互相不冲突的ip地址。
  2. 它能在这些ip地址之间建立一个覆盖网络(overlay network),通过这个覆盖网络,将数据包原封不动地传递到目标容器内。
flannel架构图:
042.集群网络-flannel及calico
如上图所示,flannel首先创建了一个名为flannel0的网桥,而且这个网桥的一端连接docker0网桥,另一端连接一个叫作flanneld的服务进程。flanneld进程上连etcd,利用etcd来管理可分配的ip地址段资源,同时监控etcd中每个pod的实际地址,并在内存中建立了一个pod节点路由表;flanneld进程下连docker0和物理网络,使用内存中的pod节点路由表,将docker0发给它的数据包包装起来,利用物理网络的连接将数据包投递到目标flanneld上,从而完成pod到pod之间的直接地址通信。
flannel之间的底层通信协议的可选技术包括udp、vxlan、aws vpc等多种方式。通过源flanneld封包、目标flanneld解包,最终docker0收到的就是原始的数据,对容器应用来说是透明的,感觉不到中间flannel的存在。
flannel每次分配的地址段都在同一个公共区域获取,从而实现不同node上的pod分配的ip不产生冲突。而且在flannel分配好地址段后,其余操作由docker完成的,flannel通过修改docker的启动参数将分配给它的地址段传递进去:
--bip=172.17.18.1/24
通过如上方式,flannel就控制了每个node上的docker0地址段的地址,从而保障了所有pod的ip地址在同一个水平网络中且不产生冲突。flannel完美地实现了对kubernetes网络的支持,但是它引入了多个网络组件,在网络通信时需要转到flannel0网络接口,再转到用户态的flanneld程序,到对端后还需要走这个过程的反过程,所以也会引入一些网络的时延损耗。另外,flannel模型默认采用了udp作为底层传输协议,udp本身是非可靠协议,虽然两端的tcp实现了可靠传输,但在大流量、高并发的应用场景下还建议多次测试。

提示:更多flannel实现和部署参考:《008.docker flannel+etcd分布式网络部署》。

二 calico组件

2.1 calco组件简介

calico是一个基于bgp的纯三层的网络方案,与openstack、kubernetes、aws、gce等云平台都能够良好地集成。calico在每个计算节点都利用linux kernel实现了一个高效的vrouter来负责数据转发。每个vrouter都通过bgp1协议把在本节点上运行的容器的路由信息向整个calico网络广播,并自动设置到达其他节点的路由转发规则。
calico保证所有容器之间的数据流量都是通过ip路由的方式完成互联互通的。calico节点组网时可以直接利用数据中心的网络结构(l2或者l3),不需要额外的nat、隧道或者overlay network,没有额外的封包解包,能够节约cpu运算,提高网络效率。
042.集群网络-flannel及calico
calico在小规模集群中可以直接互联,在大规模集群中可以通过额外的bgp route reflector来完成。calico基于iptables还提供了丰富的网络策略,实现了kubernetes的network policy策略,提供容器间网络可达性限制的功能。

2.2 calico架构

042.集群网络-flannel及calico
calico的主要组件:
felix:calico agent,运行在每个node上,负责为容器设置网络资源(ip地址、路由规则、iptables规则等),保证跨主机容器网络互通。
etcd:calico使用的后端存储。
bgp client:负责把felix在各node上设置的路由信息通过bgp协议广播到calico网络。
route reflector:通过一个或者多个bgp route reflector来完成大规模集群的分级路由分发。
calicoctl:calico命令行管理工具。

2.3 calico步骤过程

在kubernetes中部署calico的主要步骤如下:
  1. 修改kubernetes服务的启动参数,并重启服务。
  1. 设置master上kube-apiserver服务的启动参数:--allow-privileged=true(因为calico-node需要以特权模式运行在各node上)。
  2. 设置各node上kubelet服务的启动参数:--networkplugin=cni(使用cni网络插件)。
  1. 创建calico服务,主要包括calico-node和calico policy controller。需要创建的资源对象如下:
  1. 创建configmap calico-config,包含calico所需的配置参数。
  2. 创建secret calico-etcd-secrets,用于使用tls方式连接etcd。
  3. 在每个node上都运行calico/node容器,部署为daemonset。
  4. 在每个node上都安装calico cni二进制文件和网络配置参数(由install-cni容器完成)。
  5. 部署一个名为calico/kube-policy-controller的deployment,以对接kubernetes集群中为pod设置的network policy。

2.4 正式部署

[root@k8smaster01 ~]# curl \
https://docs.projectcalico.org/v3.6/getting-started/kubernetes/installation/hosted/canal/canal.yaml \
-o
[root@k8smaster01 ~]# pod_cidr="<your-pod-cidr>" \
sed -i -e "s?10.10.0.0/16?$pod_cidr?g" canal.yaml
如上yaml文件包括calico所需全部配置,如下为重点部分分段解析:
  • configmap解析
  1 kind: configmap
  2 apiversion: v1
  3 metadata:
  4   name: calico-config
  5   namespace: kube-system
  6 data:
  7   typha_service_name: "none"
  8   calico_backend: "bird"
  9   veth_mtu: "1440"
 10   cni_network_config: |-
 11     {
 12       "name": "k8s-pod-network",
 13       "cniversion": "0.3.0",
 14       "plugins": [
 15         {
 16           "type": "calico",
 17           "log_level": "info",
 18           "datastore_type": "kubernetes",
 19           "nodename": "__kubernetes_node_name__",
 20           "mtu": __cni_mtu__,
 21           "ipam": {
 22               "type": "calico-ipam"
 23           },
 24           "policy": {
 25               "type": "k8s"
 26           },
 27           "kubernetes": {
 28               "kubeconfig": "__kubeconfig_filepath__"
 29           }
 30         },
 31         {
 32           "type": "portmap",
 33           "snat": true,
 34           "capabilities": {"portmappings": true}
 35         }
 36       ]
 37     }
对主要参数说明如下。
etcd_endpoints:calico使用etcd来保存网络拓扑和状态,该参数指定etcd服务的地址,可手动设置。
calico_backend:calico的后端,默认为bird。
cni_network_config:符合cni规范的网络配置。其中type=calico表示kubelet将从/opt/cni/bin目录下搜索名为calico的可执行文件,并调用它来完成容器网络的设置。ipam中的type=calico-ipam表示kubelet将在/opt/cni/bin目录下搜索名为calico-ipam的可执行文件,用于完成容器ip地址的分配。
提示:如果etcd服务配置了tls安全认证,则还需指定相应的ca、cert、key等文件。
  • secret解析
  1 apiversion: v1
  2 kind: secret
  3 type: opaque
  4 metadata:
  5   name: calico-etcd-secrets
  6   namespace: kube-system
  7 data:
  8   # populate the following with etcd tls configuration if desired, but leave blank if
  9   # not using tls for etcd.
 10   # the keys below should be uncommented and the values populated with the base64
 11   # encoded contents of each file that would be associated with the tls data.
 12   # example command for encoding a file contents: cat <file> | base64 -w 0
 13   # 如果配置了tls ,则需要设置相应的证书和密钥文件路径
 14   # etcd-key: null
 15   # etcd-cert: null
 16   # etcd-ca: null
  • daemonset解析
  1 kind: daemonset
  2 apiversion: extensions/v1beta1
  3 metadata:
  4   name: calico-node
  5   namespace: kube-system
  6   labels:
  7     k8s-app: calico-node
  8 spec:
  9   selector:
 10     matchlabels:
 11       k8s-app: calico-node
 12   updatestrategy:
 13     type: rollingupdate
 14     rollingupdate:
 15       maxunavailable: 1
 16   template:
 17     metadata:
 18       labels:
 19         k8s-app: calico-node
 20       annotations:
 21         scheduler.alpha.kubernetes.io/critical-pod: ''
 22     spec:
 23       nodeselector:
 24         beta.kubernetes.io/os: linux
 25       hostnetwork: true
 26       tolerations:
 27         - effect: noschedule
 28           operator: exists
 29         - key: criticaladdonsonly
 30           operator: exists
 31         - effect: noexecute
 32           operator: exists
 33       serviceaccountname: calico-node
 34       terminationgraceperiodseconds: 0
 35       initcontainers:
 36         - name: upgrade-ipam
 37           image: calico/cni:v3.6.0
 38           command: ["/opt/cni/bin/calico-ipam", "-upgrade"]
 39           env:
 40             - name: kubernetes_node_name
 41               valuefrom:
 42                 fieldref:
 43                   fieldpath: spec.nodename
 44             - name: calico_networking_backend
 45               valuefrom:
 46                 configmapkeyref:
 47                   name: calico-config
 48                   key: calico_backend
 49           volumemounts:
 50             - mountpath: /var/lib/cni/networks
 51               name: host-local-net-dir
 52             - mountpath: /host/opt/cni/bin
 53               name: cni-bin-dir
 54         - name: install-cni
 55           image: calico/cni:v3.6.0
 56           command: ["/install-cni.sh"]
 57           env:
 58             - name: cni_conf_name
 59               value: "10-calico.conflist"
 60             - name: cni_network_config
 61               valuefrom:
 62                 configmapkeyref:
 63                   name: calico-config
 64                   key: cni_network_config
 65             - name: kubernetes_node_name
 66               valuefrom:
 67                 fieldref:
 68                   fieldpath: spec.nodename
 69             - name: cni_mtu
 70               valuefrom:
 71                 configmapkeyref:
 72                   name: calico-config
 73                   key: veth_mtu
 74             - name: sleep
 75               value: "false"
 76           volumemounts:
 77             - mountpath: /host/opt/cni/bin
 78               name: cni-bin-dir
 79             - mountpath: /host/etc/cni/net.d
 80               name: cni-net-dir
 81       containers:
 82         - name: calico-node
 83           image: calico/node:v3.6.0
 84           env:
 85             - name: datastore_type
 86               value: "kubernetes"
 87             - name: wait_for_datastore
 88               value: "true"
 89             - name: nodename
 90               valuefrom:
 91                 fieldref:
 92                   fieldpath: spec.nodename
 93             - name: calico_networking_backend
 94               valuefrom:
 95                 configmapkeyref:
 96                   name: calico-config
 97                   key: calico_backend
 98             - name: cluster_type
 99               value: "k8s,bgp"
100             - name: ip
101               value: "autodetect"
102             - name: ip_autodetection_method
103               value: "can-reach=172.24.8.2"
104             - name: calico_ipv4pool_ipip
105               value: "always"
106             - name: felix_ipinipmtu
107               valuefrom:
108                 configmapkeyref:
109                   name: calico-config
110                   key: veth_mtu
111             - name: calico_ipv4pool_cidr
112               value: "10.10.0.0/16"
113             - name: calico_disable_file_logging
114               value: "true"
115             - name: felix_defaultendpointtohostaction
116               value: "accept"
117             - name: felix_ipv6support
118               value: "false"
119             - name: felix_logseverityscreen
120               value: "info"
121             - name: felix_healthenabled
122               value: "true"
123           securitycontext:
124             privileged: true
125           resources:
126             requests:
127               cpu: 250m
128           livenessprobe:
129             httpget:
130               path: /liveness
131               port: 9099
132               host: localhost
133             periodseconds: 10
134             initialdelayseconds: 10
135             failurethreshold: 6
136           readinessprobe:
137             exec:
138               command:
139               - /bin/calico-node
140               - -bird-ready
141               - -felix-ready
142             periodseconds: 10
143           volumemounts:
144             - mountpath: /lib/modules
145               name: lib-modules
146               readonly: true
147             - mountpath: /run/xtables.lock
148               name: xtables-lock
149               readonly: false
150             - mountpath: /var/run/calico
151               name: var-run-calico
152               readonly: false
153             - mountpath: /var/lib/calico
154               name: var-lib-calico
155               readonly: false
156       volumes:
157         - name: lib-modules
158           hostpath:
159             path: /lib/modules
160         - name: var-run-calico
161           hostpath:
162             path: /var/run/calico
163         - name: var-lib-calico
164           hostpath:
165             path: /var/lib/calico
166         - name: xtables-lock
167           hostpath:
168             path: /run/xtables.lock
169             type: fileorcreate
170         - name: cni-bin-dir
171           hostpath:
172             path: /opt/cni/bin
173         - name: cni-net-dir
174           hostpath:
175             path: /etc/cni/net.d
176         - name: host-local-net-dir
177           hostpath:
178             path: /var/lib/cni/networks
在该pod中包括如下两个容器:
  • install-cni:在node上安装cni二进制文件到/opt/cni/bin目录下,并安装相应的网络配置文件到/etc/cni/net.d目录下,设置为initcontainers并在运行完成后退出。
  • calico-node:calico服务程序,用于设置pod的网络资源,保证pod的网络与各node互联互通。它还需要以hostnetwork模式运行,直接使用宿主机网络。
calico-node服务的主要参数如下。
  • calico_ipv4pool_cidr:calico ipam的ip地址池,pod的ip地址将从该池中进行分配。
  • calico_ipv4pool_ipip:是否启用ipip模式。启用ipip模式时,calico将在node上创建一个名为tunl0的虚拟隧道。
  • ip_autodetection_method:获取node ip地址的方式,默认使用第1个网络接口的ip地址,对于安装了多块网卡的node,可以使用正则表达式选择正确的网卡,例如"interface=eth.*"表示选择名称以eth开头的网卡的ip地址。
  • felix_ipv6support:是否启用ipv6。
  • felix_logseverityscreen:日志级别。
  • securitycontext.privileged=true:以特权模式运行。
另外,如果启用rbac权限控制,则可以设置serviceaccount。
ip pool可以使用两种模式:bgp或ipip。使用ipip模式时,设置calico_ipv4pool_ipip="always",不使用ipip模式时,设置calico_ipv4pool_ipip="off",此时将使用bgp模式。
  • calico-kube-controllers解析
calico-kube-controllers容器,用于对接kubernetes集群中为pod设置的network policy
  1 apiversion: extensions/v1beta1
  2 kind: deployment
  3 metadata:
  4   name: calico-kube-controllers
  5   namespace: kube-system
  6   labels:
  7     k8s-app: calico-kube-controllers
  8   annotations:
  9     scheduler.alpha.kubernetes.io/critical-pod: ''
 10 spec:
 11   replicas: 1
 12   strategy:
 13     type: recreate
 14   template:
 15     metadata:
 16       name: calico-kube-controllers
 17       namespace: kube-system
 18       labels:
 19         k8s-app: calico-kube-controllers
 20     spec:
 21       nodeselector:
 22         beta.kubernetes.io/os: linux
 23       tolerations:
 24         - key: criticaladdonsonly
 25           operator: exists
 26         - key: node-role.kubernetes.io/master
 27           effect: noschedule
 28       serviceaccountname: calico-kube-controllers
 29       containers:
 30         - name: calico-kube-controllers
 31           image: calico/kube-controllers:v3.6.0
 32           env:
 33             - name: enabled_controllers
 34               value: node
 35             - name: datastore_type
 36               value: kubernetes
 37           readinessprobe:
 38             exec:
 39               command:
 40               - /usr/bin/check-status
 41               - -r
如果启用rbac权限控制,则可以设置serviceaccount。用户在kubernetes集群中设置了pod的network policy之后,calicokube-controllers就会自动通知各node上的calico-node服务,在宿主机上设置相应的iptables规则,完成pod间网络访问策略的设置。
[root@k8smaster01 ~]# docker pull calico/cni:v3.9.0
[root@k8smaster01 ~]# docker pull calico/node:v3.9.0
[root@k8smaster01 ~]# docker pull calico/kube-controllers:v3.9.0 #建议提前pull镜像
[root@k8smaster01 ~]# kubectl apply -f calico.yaml
042.集群网络-flannel及calico

2.5 查看验证

[root@k8smaster01 ~]# kubectl get pods --all-namespaces -o wide #查看部署
042.集群网络-flannel及calico
[root@k8smaster01 ~]# ll /etc/cni/net.d/
calico-node在正常运行之后,会根据cni规范,在/etc/cni/net.d/目录下生成如下文件和目录,并在/opt/cni/bin/目录下安装二进制文件calico和calico-ipam,供kubelet调用。
  • 10-calico.conf:符合cni规范的网络配置,其中type=calico表示该插件的二进制文件名为calico。
  • calico-kubeconfig:calico所需的kubeconfig文件。
  • calico-tls目录:以tls方式连接etcd的相关文件。
[root@k8smaster01 ~]# ifconfig tunl0
tunl0: flags=193<up,running,noarp> mtu 1440
inet 10.10.190.128 netmask 255.255.255.255
tunnel txqueuelen 1000 (ipip tunnel)
rx packets 0 bytes 0 (0.0 b)
rx errors 0 dropped 0 overruns 0 frame 0
tx packets 0 bytes 0 (0.0 b)
tx errors 0 dropped 0 overruns 0 carrier 0 collisions 0
查看服务器的网络接口设置,会生产名为tunl0的接口,网络地址为10.10.190.128/32,此ip从calico-node设置的ip地址池(calico_ipv4pool_cidr="10.10.0.0/16")中进行分配的。同时,docker0对于kubernetes设置pod的ip地址将不再起作用。
[root@k8smaster01 ~]# ip route #查看路由表
042.集群网络-flannel及calico
如上可查看到不同节点的相应路由,从而通过calico就完成了node间容器网络的设置。在后续的pod创建过程中,kubelet将通过cni接口调用calico进行pod网络的设置,包括ip地址、路由规则、iptables规则等。
如果设置calico_ipv4pool_ipip="off",即不使用ipip模式,则calico将不会创建tunl0网络接口,路由规则直接使用物理机网卡作为路
由器进行转发。

2.6 运行测试

[root@k8smaster01 ~]# kubectl run nginx --replicas=2 --labels="run=load-balancer-example" --image=nginx --port=80
[root@k8smaster01 ~]# kubectl expose deployment nginx --type=nodeport --name=example-service #暴露端口
[root@k8smaster01 ~]# kubectl get service #查看服务状态
[root@k8smaster01 ~]# kubectl describe service example-service #查看信息
042.集群网络-flannel及calico
[root@k8smaster01 ~]# curl 10.97.91.153:80
042.集群网络-flannel及calico
[root@k8smaster01 ~]# kubectl get pod -o wide #查看endpoint
042.集群网络-flannel及calico
[root@k8smaster01 ~]# curl 10.10.32.129:80 #访问endpoint,与访问服务ip结果相同
[root@k8smaster01 ~]# curl 10.10.154.1:80

部署参考文档:https://docs.projectcalico.org/v3.6/getting-started/kubernetes/installation/flannel
https://github.com/projectcalico/calico/blob/master/v3.8/getting-started/kubernetes/installation/hosted/calico.yaml