重学容器20: 以二进制形式部署容器网络组件Calico 3.x
2021-07-07
前面几节内容学习了容器网络接口CNI及CNI规范的一些基础知识,从本节开始学习开源虚拟网络方案Calico。 Calico是一个可用于容器、虚拟机和本机主机工作负载的开源网络和网络安全解决方案。 Calico支持广泛的平台,包括Kubernetes, OpenShift, Docker EE, OpenStack和裸金属服务。 Calico同时实现并提供了calico网络CNI插件,因此可以将Calico用作容器网络插件。 本文将回到原始时代,从零开始纯手工以二进制形式部署Calico,这样能先从整体上理解Calico的各个组件。
准备工作 #
三台CentOS 7.9主机如下:
1192.168.100.101 node1
2192.168.100.102 node2
3192.168.100.103 node3
关闭各个主机的防火墙,或者参考[https://docs.projectcalico.org/getting-started/bare-metal/requirements]的Network requirements网络需求部分开放相关端口及协议。 需要确保各个主机节点上已经安装了下面的依赖,这些依赖可以在文档https://github.com/projectcalico/node#linux-dependencies中找到相关的说明:
1yum install -y conntrack net-tools iptables procps kmod iptables-utils ipset
calico集群需要在每个主机节点上部署一个calico-node
,在部署calico-node
之前还要确保已经部署了calico的datastore服务。
calico支持etcd
和kubernetes
两种datastore,使用etcd存储时calico将直接连接etcd集群,使用kubernetes存储时,calico将连接k8s的api server。
既然回到了"原始时代",因此选择etcd作为calico的datastore。 这里省略etcd集群的部署过程。在本实验环境中,3个节点etcd也是部署在这三台主机上。
1etcdctl version
2etcdctl version: 3.4.16
3API version: 3.4
4
5export ETCDCTL_API=3
6etcdctl \
7 --cert /etc/etcd/ssl/client.crt \
8 --key /etc/etcd/ssl/client.key \
9 --cacert /etc/etcd/ssl/ca.crt \
10 --endpoints https://192.168.100.101:2379,https://192.168.100.102:2379,https://192.168.100.103:2379 \
11member list
129e954b89cd9805e, started, node2, https://192.168.100.102:2380, https://192.168.100.102:2379, false
131e6d17829ae1a0b0, started, node1, https://192.168.100.101:2380, https://192.168.100.101:2379, false
14cff40374b94e6f44, started, node3, https://192.168.100.103:2380, https://192.168.100.103:2379, false
接下来需要准备calico-node的二进制文件。 因为当前版本的calico推荐以容器方式部署,且更多的场景是将calico部署在kubernetes集群内并作为kubernetes pod网络插件, 所以calico官方目前只提供了calico-node的容器镜像,而并未提供二进制文件。
需要从容器镜像中将二进制文件拷贝出来。
当前nerdctl(v0.10)还未提供类似docker cp
命令,这里单独找一台安装了docker的机器,使用docker cp
命令拷贝calico-node的二进制文件:
1docker pull calico/node:v3.19.1
2docker create --name container calico/node:v3.19.1
3docker cp container:/bin/calico-node calico-node
4docker cp container:/usr/bin/bird bird
5docker cp container:/usr/bin/bird bird6
6docker cp container:/etc/calico/confd ./
7docker rm container
8chmod +x calico-node
9chmod +x bird
10chmod +x bird6
将拷贝出来的calico-node
, bird
, bird6
文件分发到各个主机节点的/usr/local/bin目录下。
将拷贝出来的confd模板配置文件夹confd
分发到各个主机节点的/etc/calico下。
将etcd的客户端证书分发到各个节点的/etc/calico/ssl目录下:
1ls /etc/calico/ssl
2ca.crt client.crt client.key
安装calicoctl #
calicoctl是calico的命令行工具用来管理calico。 建议在所有节点上安装calicoctl:
1cd /usr/local/bin
2curl -o calicoctl -O -L "https://github.com/projectcalico/calicoctl/releases/download/v3.19.1/calicoctl"
3chmod +x calicoctl
创建/etc/calico/calicoctl.cfg配置文件,配置calicoctl连接calico的etcd datastore:
1cat > /etc/calico/calicoctl.cfg << EOF
2apiVersion: projectcalico.org/v3
3kind: CalicoAPIConfig
4metadata:
5spec:
6 etcdEndpoints: https://192.168.100.101:2379,https://192.168.100.102:2379,https://192.168.100.103:2379
7 etcdKeyFile: /etc/calico/ssl/client.key
8 etcdCertFile: /etc/calico/ssl/client.crt
9 etcdCACertFile: /etc/calico/ssl/ca.crt
10EOF
检查配置是否成功:
1calicoctl get nodes
当前还没有部署calico node,上面的命令没有错误输出说明calicoctl配置成功。
部署calico node #
每个主机节点都是一个calico node,每个calico node上需要部署以下3个组件:
- felix: 每个calico node上都要运行一个felix组件,该组件负责配置路由及ACL等信息,并确保该主机上endpoints(接入到calico网络中的网卡称为endpoint)的连通性。felix从
calico-node
二进制文件启动。 - bird: 每个calico node上都要运行一个bird,bird从felix获取路由,并分发给网络上其他的BGP peers。简单理解bird就是BGP守护进程负责将路由信息分发给其他节点。bird从
bird
二进制文件启动。 - confd: 每个calico node上都要运行一个confd,confd监听calico datastore中的配置变化并更新bird的配置文件。confd从
calico-node
二进制文件启动。
部署calico felix #
创建calico的环境变量配置文件/etc/calico/calico.env:
1echo $HOSTNAME > /var/lib/calico/nodename
2cat > /etc/calico/calico.env << EOF
3NODENAME=$HOSTNAME
4DATASTORE_TYPE=etcdv3
5ETCD_ENDPOINTS=https://192.168.100.101:2379,https://192.168.100.102:2379,https://192.168.100.103:2379
6ETCD_CA_CERT_FILE=/etc/calico/ssl/ca.crt
7ETCD_CERT_FILE=/etc/calico/ssl/client.crt
8ETCD_KEY_FILE=/etc/calico/ssl/client.key
9CALICO_IPV4POOL_IPIP=Always
10CALICO_IPV4POOL_CIDR=10.89.0.0/16
11CALICO_NETWORKING_BACKEND=bird
12CLUSTER_TYPE=
13IP=autodetect
14IP_AUTODETECTION_METHOD=interface=eth0
15EOF
注意上面的环境变量NODENAME
是根据各个节点设置对应的节点名称,CALICO_IPV4POOL_CIDR
配置的是calico IPAM的IP地址池,容器的IP地址将从此池中分配。CALICO_IPV4POOL_IPIP
配置为Always
表示开启是IPIP。
具体可配置的环境变量可以参考https://docs.projectcalico.org/reference/node/configuration
部署calico-felix服务:
1cat > /etc/systemd/system/calico-felix.service << EOF
2[Unit]
3Description=Calico Felix agent
4After=syslog.target network.target
5
6[Service]
7User=root
8EnvironmentFile=/etc/calico/calico.env
9ExecStartPre=/usr/bin/mkdir -p /var/run/calico
10ExecStart=/usr/local/bin/calico-node -felix
11KillMode=process
12Restart=on-failure
13LimitNOFILE=32000
14
15[Install]
16WantedBy=multi-user.target
17EOF
18
19systemctl enable calico-felix
20systemctl start calico-felix
21systemctl status calico-felix
按照上面的步骤在3个节点上都完成felix的按照和启动后,还需要为每个felix节点在calico datastore中创建Node
资源:
1calicoctl apply -f - <<EOF
2- apiVersion: projectcalico.org/v3
3 kind: Node
4 metadata:
5 name: node1
6 spec:
7 bgp:
8 ipv4Address: 192.168.100.101/24
9
10---
11- apiVersion: projectcalico.org/v3
12 kind: Node
13 metadata:
14 name: node2
15 spec:
16 bgp:
17 ipv4Address: 192.168.100.102/24
18
19---
20- apiVersion: projectcalico.org/v3
21 kind: Node
22 metadata:
23 name: node3
24 spec:
25 bgp:
26 ipv4Address: 192.168.100.103/24
27
28EOF
创建默认的IPPool:
1calicoctl apply -f - <<EOF
2- apiVersion: projectcalico.org/v3
3 kind: IPPool
4 metadata:
5 name: default-ipv4-ippool
6 spec:
7 cidr: 10.89.0.0/16
8 ipipMode: Always
9 vxlanMode: Never
10 natOutgoing: true
11 disabled: false
12 nodeSelector: all()
13EOF
部署calico confd #
部署calico-confd服务:
1cat > /etc/systemd/system/calico-confd.service << EOF
2[Unit]
3Description=Calico Confd
4After=syslog.target network.target
5
6[Service]
7User=root
8EnvironmentFile=/etc/calico/calico.env
9ExecStartPre=/usr/bin/mkdir -p /var/run/calico
10ExecStart=/usr/local/bin/calico-node -confd
11KillMode=process
12Restart=on-failure
13LimitNOFILE=32000
14
15[Install]
16WantedBy=multi-user.target
17EOF
18
19systemctl enable calico-confd
20systemctl start calico-confd
21systemctl status calico-confd
部署后可重启calico-felix和calico-confd,看状态是否正常,是否有错误日志。
部署bird #
此时如果使用calicoctl node status
命令查看calico node的状态,会打印None of the BGP backend processes (BIRD or GoBGP) are running.
的信息。
1calicoctl node status
2Calico process is running.
3
4None of the BGP backend processes (BIRD or GoBGP) are running.
接下来部署bird服务。
1cat > /etc/systemd/system/bird.service << EOF
2[Unit]
3Description=BIRD internet routing daemon
4After=syslog.target network.target
5
6[Service]
7User=root
8EnvironmentFile=/etc/calico/calico.env
9ExecStartPre=/usr/bin/mkdir -p /var/run/calico
10ExecStart=/usr/local/bin/bird -R -s /var/run/calico/bird.ctl -d -c /etc/calico/confd/config/bird.cfg
11KillMode=process
12Restart=on-failure
13LimitNOFILE=32000
14
15[Install]
16WantedBy=multi-user.target
17EOF
18
19systemctl enable bird
20systemctl start bird
21systemctl status bird
通过查看bird的状态和日志,calico已经建立了node to node的mesh。
而此时运行calicoctl node status
命令查看calico node的状态,仍然会打印None of the BGP backend processes (BIRD or GoBGP) are running.
的信息,可是bird已经启动了啊,查看当前calicoctl
的源码发现https://github.com/projectcalico/calicoctl/blob/4cfe90c44c1f085004d5213e29c01d96a2f85090/calicoctl/commands/node/status.go#L80,第80行就是calicoctl打印node status的逻辑if psContains([]string{"bird"}, processes) || psContains([]string{"bird6"}, processes)
通过检查bird进程是否存在再决定是否打印,而第115行func psContains(proc []string, procList []*process.Process) bool
函数的实现中判断是进程启动命令里需要等于bird
,这里bird的systemd中是/usr/local/bin/bird
,因此psContains返回false。
于是,在一个节点上停掉bird的systemd服务,直接bird -R -s /var/run/calico/bird.ctl -d -c /etc/calico/confd/config/bird.cfg
手动启动后,再使用calicoctl node status
查看节点状态,即可以正常打印IPv4 BGP status
信息了。
1systemctl stop bird
2bird -R -s /var/run/calico/bird.ctl -d -c /etc/calico/confd/config/bird.cfg &
3calicoctl node status
4
5Calico process is running.
6
7IPv4 BGP status
8+----------------+-------------------+-------+----------+-------------+
9| PEER ADDRESS | PEER TYPE | STATE | SINCE | INFO |
10+----------------+-------------------+-------+----------+-------------+
11| 192.168.100.102 | node-to-node mesh | up | 21:47:43 | Established |
12| 192.168.100.103 | node-to-node mesh | up | 21:47:43 | Established |
13+----------------+-------------------+-------+----------+-------------+
14
15INFO: BIRDv6 process: 'bird6' is not running.
通过上面的分析,说明是由于calicoctl内部代码实现的问题,导致calicoctl node status
不支持以二进制部署并以systemd启动的bird。
因为这只是一个状态查看的命令,实际上我们已经完成了calico node的集群部署。
总结 #
本节我们完成了calico node集群的纯手工二进制部署,下节内容将在各个节点上部署calico cni插件, 并在两个主机节点上各启动一个连接到calico网络的containerd容器,测试两个容器网络是否是打通的。
参考 #
- https://docs.projectcalico.org/getting-started/bare-metal/installation/binary
- https://github.com/projectcalico/node
- https://docs.projectcalico.org/reference/architecture/overview
- https://docs.projectcalico.org/reference/node/configuration
- https://docs.projectcalico.org/getting-started/clis/calicoctl/configure/overview