calico 二、配置BGP对等体

大番茄 2020年03月12日 1,470次浏览

Calico v3.11.2
Kubernetes v1.16.7

一、安装calicoctl

https://docs.projectcalico.org/v3.11/getting-started/calicoctl/install

calicoctl是管理calico对象的工具。
git下载地址:
https://github.com/projectcalico/calicoctl/releases/

下载、添加执行权限并放到PATH路径下:
https://github.com/projectcalico/calicoctl/releases/download/v3.11.2/calicoctl

配置:
https://docs.projectcalico.org/v3.11/getting-started/calicoctl/configure/
我这里是使用etcd作为calico的存储,所以需要配置calicoctl连接etcd。
calicoctl默认使用/etc/calico/calicoctl.cfg作为配置文件。
官方网站中有很多例子,根据例子写就行。
比如我这里:

apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
  datastoreType: "etcdv3"
  etcdEndpoints: "https://172.100.102.71:2379,https://172.100.102.72:2379,https://172.100.102.73:2379"
  etcdKeyFile: "/etc/calico/calico-etcd.key"
  etcdCertFile: "/etc/calico/calico-etcd.crt"
  etcdCACertFile: "/etc/calico/cacert.pem"

需要连接etcd的证书,证书也可以内置到文件里,网站中有介绍。

测试一下:

[root@k8s-master calico]# calicoctl get nodes
NAME
k8s-node1
k8s-node2
k8s-node3

查看其他信息:
查看地址池

[root@k8s-master ~]# calicoctl get ipPool
NAME                  CIDR          SELECTOR
default-ipv4-ippool   10.6.0.0/16   all()

ipam(IP Address Management)可分配的地址信息。

[root@k8s-master ~]# calicoctl ipam show
+----------+-------------+-----------+------------+--------------+
| GROUPING |    CIDR     | IPS TOTAL | IPS IN USE |   IPS FREE   |
+----------+-------------+-----------+------------+--------------+
| IP Pool  | 10.6.0.0/16 |     65536 | 5 (0%)     | 65531 (100%) |
+----------+-------------+-----------+------------+--------------+

有一些查询当前节点信息的,calicoctl会连接calico的socket,所以需要calicoctl在运行calico的节点执行。
如:

[root@k8s-master ~]# calicoctl node status
Calico process is not running.
[root@k8s-master ~]#

在calico节点就可以了:

[root@k8s-node1 ~]# calicoctl node status
Calico process is running.

IPv4 BGP status
+----------------+-------------------+-------+------------+-------------+
|  PEER ADDRESS  |     PEER TYPE     | STATE |   SINCE    |    INFO     |
+----------------+-------------------+-------+------------+-------------+
| 172.100.102.72 | node-to-node mesh | up    | 11:21:07   | Established |
| 172.100.102.73 | node-to-node mesh | up    | 2020-03-10 | Established |
+----------------+-------------------+-------+------------+-------------+

IPv6 BGP status
No IPv6 peers found.

node-to-node mesh是BGP的全互连模式。

二、配置BGP

https://docs.projectcalico.org/v3.11/networking/bgp

说明

BGP(边界网关协议)是运行于TCP上的一种自治系统的路由协议。是用于在网络中的两个路由器之间交换路由信息的标准协议。每个运行BGP的路由器都有一个或多个BGP对等体
BGP对等体: 通过BGP与其通信的其他路由器。
路由器与其他路由器建立对等关系,其实就是建立了TCP长连接,然后用BGP协议相互通信。对方路由器就是本路由器的BGP对等体,反过来也是一样,本路由器也是对方路由器的对等体。通俗讲对等关系就是邻居关系,对等体就是邻居。

BGP模式

Calico 维护的网络默认是(Node-to-Node Mesh)全互联模式,Calico集群中的所有节点之间都会相互建立连接,用于路由交换。

[root@k8s-node1 ~]# ss -tan | grep 179
LISTEN     0      8            *:179                      *:*
ESTAB      0      0      172.100.102.71:179                172.100.102.72:49409
ESTAB      0      0      172.100.102.71:179                172.100.102.73:55701

可以之间看到有两个连接。
还有上面node status显示的也一样。而其他节点也是同样。
这种情况下节点数量越多,网络中的连接数就会成倍增加,而且在100个节点左右会遇到性能瓶颈。

解决办法就是把其中的几个calico节点当做路由反射器(route reflector), 然后其他节点只需要把这几个节点当做对等体建立连接就可以。
路由器反射器会把传递过来的路由,在传递给其他节点,来实现路由交换。

在这之前先来看看对等体怎么配置。路由反射器也是需要单独配置对等体的,所以这一步是必须的。


首先需要关闭全互连模式,但是现在的BGP没有配置资源,都是默认的配置。
所以还需要创建一个BGP配置资源, 并且配置为关闭全互连模式。
https://docs.projectcalico.org/v3.11/reference/resources/bgpconfig
如:

apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  logSeverityScreen: Info
  nodeToNodeMeshEnabled: false
  asNumber: 64520

BGPConfiguration: BGPConfiguration是全局的配置资源。
nodeToNodeMeshEnabled: 就是是否开启全互连模式。
asNumber: as表示自治系统,asN自治系统编号。 默认是64512。 这里必须提供,不然asNumber好像就变成空了。
64512-65535也是私有的ASN,不能出现在公网。ASN在外网是唯一的,由IANA 地址授权委员会统一分配, 不过在内网就无所谓了。官网的例子是63400,同样没问题。
使用calicoctl get nodes -o wide可以查询节点的ASN。

[root@k8s-master ~]# calicoctl get nodes -o wide
NAME        ASN       IPV4                IPV6
k8s-node1   (64512)   172.100.102.71/24
k8s-node2   (64512)   172.100.102.72/24
k8s-node3   (64512)   172.100.102.73/24

注意: 全互连模式关闭以后, k8s集群网络就中断了。
应用文件, 与k8s的方式一样:

[root@k8s-master ~]# calicoctl apply -f bgpconfig.yaml
Successfully applied 1 'BGPConfiguration' resource(s)

应用以后, bgp之间的连接就断了,然后路由也没了,网络也断了。

[root@k8s-node1 ~]# calicoctl node status
Calico process is running.

IPv4 BGP status
No IPv4 peers found.

IPv6 BGP status
No IPv6 peers found.

如果把nodeToNodeMeshEnabled改为true再次应用,就会再次启用全互连模式,网络也会恢复。

配置对等体

https://docs.projectcalico.org/v3.11/reference/resources/bgppeer
有时候需要把指定的设备或节点添加为对等体,比如网络中的物理路由器,支持BGP的三层交换机,还有路由反射器等。

先来看一下我这里的节点信息:

[root@k8s-master ~]# calicoctl get nodes -o wide
NAME        ASN       IPV4                IPV6
k8s-node1   (64520)   172.100.102.71/24
k8s-node2   (64520)   172.100.102.72/24
k8s-node3   (64520)   172.100.102.73/24

对等体资源对象叫做BGPPeer

全局对等体

我打算把k8s-node3作为全局的对等体,让k8s-node1, k8s-node2去连。
全局对等体的意思是,全局生效,所有节点都会去把目标当做对等体去连。

apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: my-global-peer
spec:
  peerIP: 172.100.102.73
  asNumber: 64520

peerIP: 目标的地址,其他节点回去连接这个地址。
asNumber: 目标设置的asNumber。
应用:

[root@k8s-master ~]# calicoctl apply -f bgppeer.yaml
Successfully applied 1 'BGPPeer' resource(s)

查看:

[root@k8s-master ~]# calicoctl get bgppeer
NAME             PEERIP           NODE       ASN
my-global-peer   172.100.102.73   (global)   64520

在k8s-node1,k8s-node2,k8s-node3上看一下效果。


k8s-node1:

[root@k8s-node1 ~]# calicoctl node status
Calico process is running.

IPv4 BGP status
+----------------+-----------+-------+----------+-------------+
|  PEER ADDRESS  | PEER TYPE | STATE |  SINCE   |    INFO     |
+----------------+-----------+-------+----------+-------------+
| 172.100.102.73 | global    | up    | 09:42:22 | Established |
+----------------+-----------+-------+----------+-------------+

可以看到之与k8s-node3(172.100.102.73)建立了连接。

image.png
路由里也只有k8s-node3的路由信息。


k8s-node2:

[root@k8s-node2 ~]# calicoctl node status
Calico process is running.

IPv4 BGP status
+----------------+-----------+-------+----------+-------------+
|  PEER ADDRESS  | PEER TYPE | STATE |  SINCE   |    INFO     |
+----------------+-----------+-------+----------+-------------+
| 172.100.102.73 | global    | up    | 09:42:21 | Established |
+----------------+-----------+-------+----------+-------------+

image.png
这里也是只有k8s-node3的路由。


k8s-node3:

k8s-node1与k8s-node2都与k8s-node3建立了对等关系。

[root@k8s-node3 ~]# calicoctl node status
Calico process is running.

IPv4 BGP status
+----------------+---------------+-------+----------+-------------+
|  PEER ADDRESS  |   PEER TYPE   | STATE |  SINCE   |    INFO     |
+----------------+---------------+-------+----------+-------------+
| 172.100.102.71 | node specific | up    | 09:42:22 | Established |
| 172.100.102.72 | node specific | up    | 09:42:21 | Established |
+----------------+---------------+-------+----------+-------------+

IPv6 BGP status

image.png
因为k8s-node3与另外两个节点都有对等关系, 那两个节点也是k8s-node3的对等体。 所以上面有两个节点的路由。


这里可能会有点疑惑, 既然k8s-node3有两个节点的路由,为什么没有发给其他两个节点,这就是BGP的内部安全机制了。 只有把k8s-node3作为路由反射器才行。


配置指定节点可以使用的对等体

上面是全局对等体(所有节点的对等体),这里是只作为某些节点的对等体。
跟上面的配置只多了nodeSelector
先把全局的删除了:

[root@k8s-master ~]# calicoctl delete bgppeer my-global-peer
Successfully deleted 1 'BGPPeer' resource(s)

calico可以读取k8s的节点label信息,也可以自己创建label。
可以使用calicoctl get nodes k8s-node1 -o yaml查看节点信息。

所以这里直接在k8s里添加label。

[root@k8s-master ~]# kubectl label node/k8s-node1 rack=rack-3
node/k8s-node1 labeled

创建bgppeer:

apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: rack3-tor
spec:
  peerIP: 172.100.102.73
  asNumber: 64520
  nodeSelector: rack == "rack-3"

nodeSelector: 节点标签选择器,选择有rack: rack-3标签的节点使用这个对等体。
应用:

[root@k8s-master ~]# calicoctl apply -f bgppeer.yaml
Successfully applied 1 'BGPPeer' resource(s)

结果就是只有k8s-node1去连接了。 k8s-node3上也只有k8s-node1的连接。

也可以使用node参数来直接限制某个节点才可以连接对等体。


路由反射器

分两步:
1,选择节点创建为路由反射器。
2,创建BGPPeer指定路由反射器为对等体。

创建路由反射器

我这里选择k8s-node3作为路由反射器。

需要修改节点配置:
https://docs.projectcalico.org/v3.11/reference/resources/node
添加routeReflectorClusterID配置就可以了。

首先,导出k8s-node3的节点配置:

[root@k8s-master ~]# calicoctl get node k8s-node3 -o yaml > k8s-node3.yaml

文件里的annotationslabels 信息是从k8s里拿到的, 所以可以删除。当然,不删也可以,正常情况下应该都是不删的。我这里只是为了突出重点,就把没用的删了。

apiVersion: projectcalico.org/v3
kind: Node
metadata:
  name: k8s-node3
spec:
  bgp:
    ipv4Address: 172.100.102.73/24
    routeReflectorClusterID: 244.0.0.1
  orchRefs:
  - nodeName: k8s-node3
    orchestrator: k8s

主要就是routeReflectorClusterID: 路由反射器集群ID,不知道为什么使用ip地址作为ID。官网例子使用的是244.0.0.1,我这里也用这个了。
orchRefs 关联协调器,应该是与k8s集群关联的。 如果删了,那些从k8s继承过来的label与annotations之类的配置就都没了。
应用:

[root@k8s-master ~]# calicoctl apply -f k8s-node3.yaml
Successfully applied 1 'Node' resource(s)

现在路由反射器已经创建好了。现在k8s-node1与k8s-node2再把k8s-node3作为对等体,路由里就有其他节点的路由了。

如果再添加其他的节点为路由器反射器,对应节点添加routeReflectorClusterID: 244.0.0.1 配置就可以了。

路由反射器一般也都是多个节点高可用,防止一个节点挂了,网络就挂了。
这时再用上面直接指定对等体ip的方式就不够好使了。

选择路由反射器为对等体

还是创建BGPPeer, 使用peerSelector标签选择器。设置此项后,peerIPand与asNumber字段必须为空。

防止混乱删除之前的BGPPeer。

calicoctl delete bgppeer rack3-tor

为路由反射器节点添加标签:

[root@k8s-master ~]# kubectl label node k8s-node3 route-reflector=true
node/k8s-node3 labeled

添加新的BGPPeer:

apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: peer-with-route-reflectors
spec:
  nodeSelector: all()
  peerSelector: route-reflector == 'true'

这里的nodeSelector加不加都无所谓,不加就是global类型的,加了就是node specific的,只是这里的也是表示所有节点。官网的例子是加上的。

[root@k8s-master ~]# calicoctl apply -f bgppeer.yaml
Successfully applied 1 'BGPPeer' resource(s)

这样就可以了。
其他路由反射器,只要添加route-reflector标签就可以了。

[root@k8s-node1 ~]# calicoctl node status
Calico process is running.

IPv4 BGP status
+----------------+---------------+-------+----------+-------------+
|  PEER ADDRESS  |   PEER TYPE   | STATE |  SINCE   |    INFO     |
+----------------+---------------+-------+----------+-------------+
| 172.100.102.73 | node specific | up    | 12:52:07 | Established |
| 172.100.102.72 | node specific | up    | 12:53:54 | Established |
+----------------+---------------+-------+----------+-------------+

用到的资源对象

BGPConfiguration: BGP全局默认配置。
Node: BGP中单节点配置
BGPPeer: BGP中的对等配置。