前面几节内容学习了容器网络接口CNI及CNI规范的一些基础知识,从本节开始学习开源虚拟网络方案Calico。 Calico是一个可用于容器、虚拟机和本机主机工作负载的开源网络和网络安全解决方案。 Calico支持广泛的平台,包括Kubernetes, OpenShift, Docker EE, OpenStack和裸金属服务。 Calico同时实现并提供了calico网络CNI插件,因此可以将Calico用作容器网络插件。 本文将回到原始时代,从零开始纯手工以二进制形式部署Calico,这样能先从整体上理解Calico的各个组件。
准备工作
三台CentOS 7.9主机如下:
192.168.100.101 node1
192.168.100.102 node2
192.168.100.103 node3关闭各个主机的防火墙,或者参考[https://docs.projectcalico.org/getting-started/bare-metal/requirements]的Network requirements网络需求部分开放相关端口及协议。 需要确保各个主机节点上已经安装了下面的依赖,这些依赖可以在文档https://github.com/projectcalico/node#linux-dependencies中找到相关的说明:
yum install -y conntrack net-tools iptables procps kmod iptables-utils ipsetcalico集群需要在每个主机节点上部署一个calico-node,在部署calico-node之前还要确保已经部署了calico的datastore服务。
calico支持etcd和kubernetes两种datastore,使用etcd存储时calico将直接连接etcd集群,使用kubernetes存储时,calico将连接k8s的api server。
既然回到了"原始时代",因此选择etcd作为calico的datastore。 这里省略etcd集群的部署过程。在本实验环境中,3个节点etcd也是部署在这三台主机上。
etcdctl version
etcdctl version: 3.4.16
API version: 3.4
export ETCDCTL_API=3
etcdctl \
--cert /etc/etcd/ssl/client.crt \
--key /etc/etcd/ssl/client.key \
--cacert /etc/etcd/ssl/ca.crt \
--endpoints https://192.168.100.101:2379,https://192.168.100.102:2379,https://192.168.100.103:2379 \
member list
9e954b89cd9805e, started, node2, https://192.168.100.102:2380, https://192.168.100.102:2379, false
1e6d17829ae1a0b0, started, node1, https://192.168.100.101:2380, https://192.168.100.101:2379, false
cff40374b94e6f44, 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的二进制文件:
docker pull calico/node:v3.19.1
docker create --name container calico/node:v3.19.1
docker cp container:/bin/calico-node calico-node
docker cp container:/usr/bin/bird bird
docker cp container:/usr/bin/bird bird6
docker cp container:/etc/calico/confd ./
docker rm container
chmod +x calico-node
chmod +x bird
chmod +x bird6将拷贝出来的calico-node, bird, bird6文件分发到各个主机节点的/usr/local/bin目录下。
将拷贝出来的confd模板配置文件夹confd分发到各个主机节点的/etc/calico下。
将etcd的客户端证书分发到各个节点的/etc/calico/ssl目录下:
ls /etc/calico/ssl
ca.crt client.crt client.key安装calicoctl
calicoctl是calico的命令行工具用来管理calico。 建议在所有节点上安装calicoctl:
cd /usr/local/bin
curl -o calicoctl -O -L "https://github.com/projectcalico/calicoctl/releases/download/v3.19.1/calicoctl"
chmod +x calicoctl创建/etc/calico/calicoctl.cfg配置文件,配置calicoctl连接calico的etcd datastore:
cat > /etc/calico/calicoctl.cfg << EOF
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
etcdEndpoints: https://192.168.100.101:2379,https://192.168.100.102:2379,https://192.168.100.103:2379
etcdKeyFile: /etc/calico/ssl/client.key
etcdCertFile: /etc/calico/ssl/client.crt
etcdCACertFile: /etc/calico/ssl/ca.crt
EOF检查配置是否成功:
calicoctl 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:
echo $HOSTNAME > /var/lib/calico/nodename
cat > /etc/calico/calico.env << EOF
NODENAME=$HOSTNAME
DATASTORE_TYPE=etcdv3
ETCD_ENDPOINTS=https://192.168.100.101:2379,https://192.168.100.102:2379,https://192.168.100.103:2379
ETCD_CA_CERT_FILE=/etc/calico/ssl/ca.crt
ETCD_CERT_FILE=/etc/calico/ssl/client.crt
ETCD_KEY_FILE=/etc/calico/ssl/client.key
CALICO_IPV4POOL_IPIP=Always
CALICO_IPV4POOL_CIDR=10.89.0.0/16
CALICO_NETWORKING_BACKEND=bird
CLUSTER_TYPE=
IP=autodetect
IP_AUTODETECTION_METHOD=interface=eth0
EOF注意上面的环境变量NODENAME是根据各个节点设置对应的节点名称,CALICO_IPV4POOL_CIDR配置的是calico IPAM的IP地址池,容器的IP地址将从此池中分配。CALICO_IPV4POOL_IPIP配置为Always表示开启是IPIP。
具体可配置的环境变量可以参考https://docs.projectcalico.org/reference/node/configuration
部署calico-felix服务:
cat > /etc/systemd/system/calico-felix.service << EOF
[Unit]
Description=Calico Felix agent
After=syslog.target network.target
[Service]
User=root
EnvironmentFile=/etc/calico/calico.env
ExecStartPre=/usr/bin/mkdir -p /var/run/calico
ExecStart=/usr/local/bin/calico-node -felix
KillMode=process
Restart=on-failure
LimitNOFILE=32000
[Install]
WantedBy=multi-user.target
EOF
systemctl enable calico-felix
systemctl start calico-felix
systemctl status calico-felix按照上面的步骤在3个节点上都完成felix的按照和启动后,还需要为每个felix节点在calico datastore中创建Node资源:
calicoctl apply -f - <<EOF
- apiVersion: projectcalico.org/v3
kind: Node
metadata:
name: node1
spec:
bgp:
ipv4Address: 192.168.100.101/24
---
- apiVersion: projectcalico.org/v3
kind: Node
metadata:
name: node2
spec:
bgp:
ipv4Address: 192.168.100.102/24
---
- apiVersion: projectcalico.org/v3
kind: Node
metadata:
name: node3
spec:
bgp:
ipv4Address: 192.168.100.103/24
EOF创建默认的IPPool:
calicoctl apply -f - <<EOF
- apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
cidr: 10.89.0.0/16
ipipMode: Always
vxlanMode: Never
natOutgoing: true
disabled: false
nodeSelector: all()
EOF部署calico confd
部署calico-confd服务:
cat > /etc/systemd/system/calico-confd.service << EOF
[Unit]
Description=Calico Confd
After=syslog.target network.target
[Service]
User=root
EnvironmentFile=/etc/calico/calico.env
ExecStartPre=/usr/bin/mkdir -p /var/run/calico
ExecStart=/usr/local/bin/calico-node -confd
KillMode=process
Restart=on-failure
LimitNOFILE=32000
[Install]
WantedBy=multi-user.target
EOF
systemctl enable calico-confd
systemctl start calico-confd
systemctl status calico-confd部署后可重启calico-felix和calico-confd,看状态是否正常,是否有错误日志。
部署bird
此时如果使用calicoctl node status命令查看calico node的状态,会打印None of the BGP backend processes (BIRD or GoBGP) are running.的信息。
calicoctl node status
Calico process is running.
None of the BGP backend processes (BIRD or GoBGP) are running.接下来部署bird服务。
cat > /etc/systemd/system/bird.service << EOF
[Unit]
Description=BIRD internet routing daemon
After=syslog.target network.target
[Service]
User=root
EnvironmentFile=/etc/calico/calico.env
ExecStartPre=/usr/bin/mkdir -p /var/run/calico
ExecStart=/usr/local/bin/bird -R -s /var/run/calico/bird.ctl -d -c /etc/calico/confd/config/bird.cfg
KillMode=process
Restart=on-failure
LimitNOFILE=32000
[Install]
WantedBy=multi-user.target
EOF
systemctl enable bird
systemctl start bird
systemctl 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信息了。
systemctl stop bird
bird -R -s /var/run/calico/bird.ctl -d -c /etc/calico/confd/config/bird.cfg &
calicoctl node status
Calico process is running.
IPv4 BGP status
+----------------+-------------------+-------+----------+-------------+
| PEER ADDRESS | PEER TYPE | STATE | SINCE | INFO |
+----------------+-------------------+-------+----------+-------------+
| 192.168.100.102 | node-to-node mesh | up | 21:47:43 | Established |
| 192.168.100.103 | node-to-node mesh | up | 21:47:43 | Established |
+----------------+-------------------+-------+----------+-------------+
INFO: 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