前言:
前面写了一些关于calico的文章,但感觉好像是浅尝辄止,分散在了几篇文章内,并且很多地方还是没有说的太清楚云原生|kubernetes|kubernetes的网络插件calico和flannel安装以及切换_calico换flannel_晚风_END的博客-CSDN博客
云原生|kubernetes|集群网络优化之启用ipvs_开启ipvs_晚风_END的博客-CSDN博客
那,以上文章很多地方是一笔带过的,比如,calico到底是干什么用的,BGP如何启用,BIRD如何使用,如何构造合适的网络模型?VXLAN的启用,这些内容是并没有太多涉及的。
OK,那么,本文将就以上文章的缺点修复,写一个比较完整的网络模型构建指南。
#######附:网络模型也可以狭义的认为或者说理解为网络插件,并没有严格的定义,但,这个不是重点,重点在于网络适配现有的集群,能最大化的发挥集群的作用
正文:
一,
kubernetes的网络选择
通常的,不管是二进制还是kubeadm亦或者其它的集群安装方式,在初始化集群这一步完成后,需要做得第一个事情是搭建集群内部的网络,而在网络没有搭建完成的时候,kubectl查看集群的状态是noready的,也就是说集群是不可用的,没有办法创建任何pod(在云计算里也是一样的,没有网络模型的时候,是无法创建虚拟机的)
那么,我们为什么要做这样一件事情?我们需要做哪些工作呢?
为什么?
实际上,不同公司对于网络模型有不同的设计想法。网络,尤其是ip地址的规划,一定程度上体现了公司基础设施的规划方式。比如有些公司会指定某个子网下的所有终端(服务器、NAS设备等)用于提供数据服务,这些终端设备往往也在地理上邻近。一种很常见的做法是,把不同的DC通过网段区分开。因此,可以认为网络的规划是一种业务的体现,而基础设施是服务于业务的,因此将与业务深度绑定的网络构建工作完全交给用户是一种合理的做法。
需要做得工作是哪些?
首先,是cni插件的安装
概念:
CNI用于连接容器管理系统和网络插件。提供一个容器所在的network namespace,将network interface插入该network namespace中(比如veth的一端),并且在宿主机做一些必要的配置(例如将veth的另一端加入bridge中),最后对namespace中的interface进行IP和路由的配置。
CNI的工作是从容器管理系统处获取运行时信息,包括network namespace的路径,容器ID以及network interface name,再从容器网络的配置文件中加载网络配置信息,再将这些信息传递给对应的插件,由插件进行具体的网络配置工作,并将配置的结果再返回到容器管理系统中。
现实中的具体表现:
CNI插件是可执行文件,会被kubelet调用。启动kubelet --network-plugin=cni,--cni-conf-dir 指定networkconfig配置,默认路径是:/etc/cni/net.d,并且,--cni-bin-dir 指定plugin可执行文件路径,默认路径是:/opt/cni/bin;
CNI plugin 只需要通过 CNI 库实现两类方法, 一类是创建容器时调用, 一类是删除容器时调用.
[root@k8s-master bin]# pwd /opt/cni/bin [root@k8s-master bin]# ll total 85340 -rwxr-xr-x 1 root root 2769360 Sep 15 07:11 bandwidth -rwxr-xr-x 1 root root 3099896 Sep 15 07:11 bridge -rw-r--r-- 1 root root 36336160 Jan 3 01:38 cni-plugins-linux-amd64-v1.1.1.tgz -rwxr-xr-x 1 root root 7404776 Sep 15 07:11 dhcp -rwxr-xr-x 1 root root 3191600 Sep 15 07:11 firewall -rwxr-xr-x 1 root root 3069556 Jan 3 01:41 flannel -rwxr-xr-x 1 root root 2779512 Sep 15 07:11 host-device -rwxr-xr-x 1 root root 2345824 Sep 15 07:11 host-local -rwxr-xr-x 1 root root 2863240 Sep 15 07:11 ipvlan -rwxr-xr-x 1 root root 2397136 Sep 15 07:11 loopback -rwxr-xr-x 1 root root 2893272 Sep 15 07:11 macvlan -rwxr-xr-x 1 root root 2689616 Sep 15 07:11 portmap -rwxr-xr-x 1 root root 2999880 Sep 15 07:11 ptp -rwxr-xr-x 1 root root 2537944 Sep 15 07:11 sbr -rwxr-xr-x 1 root root 2083248 Sep 15 07:11 static -rwxr-xr-x 1 root root 2461080 Sep 15 07:11 tuning -rwxr-xr-x 1 root root 2863064 Sep 15 07:11 vlan -rwxr-xr-x 1 root root 2566296 Sep 15 07:11 vrf
main插件:提供某种网络功能,比如使用的brdige,以及loopback,ipvlan,macvlan等等
meta插件:不能作为独立的插件使用,需要调用其他插件,例如flannel,或者配合其他插件使用,例如portmap
ipam插件:对所有CNI插件共有的IP管理部分的抽象,从而减少插件编写过程中的重复工作,官方提供的有dhcp和host-local两种类型
其次,就是负责具体的创建网络的网络插件
目前的网络插件包括了cisco ACI、Apstra的AOS、Big Switch Network的Big cloud Fabric、Cilium、来自华为的CNI-genie、cni-ipvlan-vpc-k8s、Contiv、Contail/Tungsten Fabric、DANM、Fannel、Google Compute Engine、Jaguar、Knitter、Kube-Router、L2 networks/linux bridge、Multus、NSX-T、Nuage Networks VCS(virtualized Cloud Services)、OpenVswitch(云计算的常用网络插件)、OVN(云计算的常用网络插件)、Project Calico、Romana、Weaver Networks等。比较流行的有Flannel,Calico,Weaver,cilium等
当然,这些插件的部署方式很多,常见的部署手法以二进制和yaml资源清单文件为主。
大体的运行机制:
以flannel为例(其它的插件运行机制是类似的):
- kubelet调用CRI接口也就是dockershim,它调用CNI插件,也就是/opt/cni/bin中的flannel程序,这个程序需要2部分参数,一部分是dockershim的CNI环境变量也就是具体动作ADD或者DEL,如果是ADD则是把容器添加到CNI网络里,ADD会有一些参数;另外一部分就是dockershim加载的JSON文件,然后/opt/cni/bin/flannel程序会对2部分参数做整合以及填充其他信息比如ipam信息也就是具体的子网信息,ipMasp信息,mtu信息,这些都是从/run/flannel/subnet.env文件中读取的,然后flannel会调用CNI的birdge插件,也就是执行/opt/cni/bin/bridge这个命令,由它来完成将容器加入CNI网络的具体操作。
- 首先,定义两个节点主机A POD-A 主机B POD-B
POD-A首先会发送给docker 0网桥
docker 0会转发给flannel0网桥
flannel0会转发给flanneld(后台进程),flanned会到ETCD中查看ETCD维护的路由表条目/信息,确认往哪去发送
flanned 会在转发给宿主机的物理网卡
物理网卡会以UDP的方式转发数据包(数据包中除了主机A和主机B的源TP和目标IP之外,还会封装POD-A和POD-B的源/目标Ip)
主机B接收到
首先解封装,发现源IP地址是找自己的(主机IP地址)
UDP 转发过来,解封装之后,发现了封装在UDP内部的POD IP(源/目标)
主机B的物理网卡就会发送给flanned进行处理
而flanned会查询ETCD中维护的路由表信息,发现是自己的pod (也能查询到找的docker-ip网段是什么网段)
flanned会发送给自己的flannel0网桥,flannel网桥再发送给对应的docker (0)网桥
docker 网桥(网关),会把这个数据包发送给对应的POD-B
当然了,calico与这个flannel是类似的机制,如果想要更加深入的理解这些插件,那么,二进制部署的方式是一个不错的方法。
#####注1:
flannel是一个纯粹的VXLAN网络模型,当然,一般也是这么用的,而calico是比flannel功能更多的一个网络插件,在kubernetes集群内的具体体现是安装有calico的k8s集群才能够有使用NetWorkPolicy也就是网络策略的能力,而flannel是不具备此能力的。
OK,下面以二进制方式部署一个flannel插件
二,
flannel的二进制部署
- 部署前的环境
网络环境:
[root@k8s-master bin]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:0c:29:4b:cc:d3 brd ff:ff:ff:ff:ff:ff
inet 192.168.123.11/24 brd 192.168.123.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe4b:ccd3/64 scope link
valid_lft forever preferred_lft forever
3: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:c7:37:fb:5c brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
集群状态:
版本是1.23.15,kubeadm部署的一主二从三节点,etcd是单实例,堆叠部署(也就是集群内部的etcd),
因此,etcd的相关证书都存放在/etc/kubernetes/pki/etcd目录下
[root@k8s-master bin]# kubectl get no -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master Ready control-plane,master 53d v1.23.15 192.168.123.11 <none> CentOS Linux 7 (Core) 5.4.228-1.el7.elrepo.x86_64 docker://20.10.7
k8s-node1 Ready <none> 53d v1.23.15 192.168.123.12 <none> CentOS Linux 7 (Core) 5.4.228-1.el7.elrepo.x86_64 docker://20.10.7
k8s-node2 Ready <none> 53d v1.23.15 192.168.123.13 <none> CentOS Linux 7 (Core) 5.4.228-1.el7.elrepo.x86_64 docker://20.10.7
- flannel二进制安装包的下载:
Releases · flannel-io/flannel · GitHub
OK,下载下来的压缩包内只有三个文件,其实只用到了flanneld这一个文件,其它的无关紧要,下载的文件是flannel-v0.21.2-linux-amd64.tar.gz(后面处理这个文件)
- etcd数据库写入网络相关设置:
由于etcd是堆叠的内部etcd,位于maser节点,因此,这一步操作在maser节点上执行:
1,
随意找一个etcdctl ,也就是etcd的客户端,最好是etcd3的,放置在/opt目录下,简化命令如下:
alias etcd_search='ETCDCTL_API=3 /opt/etcdctl --endpoints=https://192.168.123.11:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key'
2,etcd状态查询,可以看到,是正常的
[root@k8s-master bin]# etcd_search member list -w table
+------------------+---------+------------+-----------------------------+-----------------------------+------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER |
+------------------+---------+------------+-----------------------------+-----------------------------+------------+
| d9fb26556fe7b4a5 | started | k8s-master | https://192.168.123.11:2380 | https://192.168.123.11:2379 | false |
+------------------+---------+------------+-----------------------------+-----------------------------+------------+
3,
etcd写入网络配置
定义pod使用的网络是10.244.0.0,vxlan模式
etcd_search put /coreos.com/network/config '{"Network":"10.244.0.0/16","Backend":{"Type":"vxlan"}}'
4,
确认是否正确写入etcd数据库:
[root@k8s-master ~]# etcd_search get /coreos.com/network/config
/coreos.com/network/config
{"Network":"10.244.0.0/16","Backend":{"Type":"vxlan"}}
5,
创建flanneld服务的配置文件:
mkdir -p /etc/kube-flannel/
cat >/etc/kube-flannel/flannel.conf<<EOF
FLANNEL_OPTIONS="-etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt -etcd-certfile=/etc/kubernetes/pki/etcd/server.crt -etcd-keyfile=/etc/kubernetes/pki/etcd/server.key"
FLANNEL_ETCD_ENDPOINTS="https://192.168.123.11:2379"
EOF
6,
创建flanneld服务的启动脚本
cat >/etc/systemd/system/flanneld.service <<EOF
[Unit]
Description=Flanneld overlay address etcd agent
After=network.target
After=network-online.target
Wants=network-online.target
After=etcd.service
Before=containerd.service
[Service]
Type=notify
EnvironmentFile=/etc/kube-flannel/flannel.conf
ExecStart=/opt/bin/flanneld \
-etcd-endpoints=${FLANNEL_ETCD_ENDPOINTS} \
$FLANNEL_OPTIONS
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
7,
创建flanneld和cni的接口配置文件:
cat >/etc/cni/net.d/10-flannel.conflist <<EOF
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
EOF
8,
分发所有配置文件和可执行文件到从节点:
由于分发后,配置文件都是一样的,因此,证书文件也要配一份,但,slave节点一般是没有pki这个目录的,因此,整个文件夹复制
flanneld这个程序,在配置文件里的定义是/opt/bin/目录下,因此,需要建立此目录,并保证此目录下有flanneld这个程序
scp /etc/systemd/system/flanneld.service k8s-node1:/etc/systemd/system/
scp /etc/systemd/system/flanneld.service k8s-node2:/etc/systemd/system/
scp /etc/kube-flannel/flannel.conf k8s-node1:/etc/kube-flannel/
scp /etc/kube-flannel/flannel.conf k8s-node2:/etc/kube-flannel/
scp /etc/cni/net.d/10-flannel.conflist k8s-node1:/etc/cni/net.d/
scp /etc/cni/net.d/10-flannel.conflist k8s-node2:/etc/cni/net.d/
scp /opt/bin/flanneld k8s-node1:/opt/bin/
scp /opt/bin/flanneld k8s-node2:/opt/bin/
scp -r /etc/kubernetes/pki k8s-node1:/etc/kubernetes/
scp -r /etc/kubernetes/pki k8s-node2:/etc/kubernetes/
9,
启动flanneld服务:
systemctl daemon-reload&&systemctl start flanneld&&systemctl status flanneld
最终的服务状态应该是这样的:
其中9903 main.go:435] Wrote subnet file to /run/flannel/subnet.env,表示子网配置文件已经创建,该文件是由flanneld服务自动创建的
[root@k8s-master bin]# systemctl daemon-reload&&systemctl start flanneld&&systemctl status flanneld
● flanneld.service - Flanneld overlay address etcd agent
Loaded: loaded (/etc/systemd/system/flanneld.service; disabled; vendor preset: disabled)
Active: active (running) since Sat 2023-02-25 20:43:46 CST; 1h 35min ago
Main PID: 9903 (flanneld)
CGroup: /system.slice/flanneld.service
└─9903 /opt/bin/flanneld -etcd-endpoints=https://192.168.123.11:2379 -etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt -etcd-certfile=/etc/kubernetes/pki/etcd/server.crt -etcd-keyfile=/etc/kubernetes/pki/etcd/server.key
Feb 25 20:43:46 k8s-master flanneld[9903]: I0225 20:43:46.982617 9903 local_manager.go:148] Found lease (ip: 10.244.91.0/24 ipv6: ::/0) for current IP (192.168.123.11), reusing
Feb 25 20:43:46 k8s-master flanneld[9903]: I0225 20:43:46.987497 9903 main.go:407] Changing default FORWARD chain policy to ACCEPT
Feb 25 20:43:46 k8s-master systemd[1]: Started Flanneld overlay address etcd agent.
Feb 25 20:43:46 k8s-master flanneld[9903]: I0225 20:43:46.992243 9903 iptables.go:274] generated 3 rules
Feb 25 20:43:46 k8s-master flanneld[9903]: I0225 20:43:46.992284 9903 main.go:435] Wrote subnet file to /run/flannel/subnet.env
Feb 25 20:43:46 k8s-master flanneld[9903]: I0225 20:43:46.992306 9903 main.go:439] Running backend.
Feb 25 20:43:46 k8s-master flanneld[9903]: I0225 20:43:46.992414 9903 vxlan_network.go:62] watching for new subnet leases
Feb 25 20:43:46 k8s-master flanneld[9903]: I0225 20:43:46.995285 9903 local_manager.go:403] Waiting for 22h59m58.999784463s to renew lease
Feb 25 20:43:47 k8s-master flanneld[9903]: I0225 20:43:47.009344 9903 iptables.go:267] bootstrap done
Feb 25 20:43:47 k8s-master flanneld[9903]: I0225 20:43:47.033202 9903 local_manager.go:403] Waiting for 22h59m58.999603795s to renew lease
查看网络状态:
master节点:
可以看到,flanneld服务拉起了一个flannel.1 的虚拟网卡,以及两个veth网卡
[root@k8s-master bin]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:0c:29:4b:cc:d3 brd ff:ff:ff:ff:ff:ff
inet 192.168.123.11/24 brd 192.168.123.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe4b:ccd3/64 scope link
valid_lft forever preferred_lft forever
3: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:c7:37:fb:5c brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
5: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN
link/ether a6:3a:2f:6a:cd:4c brd ff:ff:ff:ff:ff:ff
inet 10.244.91.0/32 scope global flannel.1
valid_lft forever preferred_lft forever
inet6 fe80::a43a:2fff:fe6a:cd4c/64 scope link
valid_lft forever preferred_lft forever
6: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP qlen 1000
link/ether e2:5b:ab:d9:66:98 brd ff:ff:ff:ff:ff:ff
inet 10.244.91.1/24 brd 10.244.91.255 scope global cni0
valid_lft forever preferred_lft forever
inet6 fe80::e05b:abff:fed9:6698/64 scope link
valid_lft forever preferred_lft forever
7: vethb0fbcc51@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master cni0 state UP
link/ether a2:52:33:72:d7:70 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::a052:33ff:fe72:d770/64 scope link
valid_lft forever preferred_lft forever
8: veth2dd14f41@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master cni0 state UP
link/ether be:76:31:3c:f2:de brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::bc76:31ff:fe3c:f2de/64 scope link
valid_lft forever preferred_lft forever
slave1节点(slave2基本一样,不占用篇幅了):
[root@k8s-node1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:0c:29:d2:16:f8 brd ff:ff:ff:ff:ff:ff
inet 192.168.123.12/24 brd 192.168.123.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fed2:16f8/64 scope link
valid_lft forever preferred_lft forever
3: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:9a:a0:f5:cf brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
5: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN
link/ether 32:30:10:b7:75:6c brd ff:ff:ff:ff:ff:ff
inet 10.244.85.0/32 scope global flannel.1
valid_lft forever preferred_lft forever
inet6 fe80::3030:10ff:feb7:756c/64 scope link
valid_lft forever preferred_lft forever
6: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP qlen 1000
link/ether 3a:e8:b6:c4:dc:2a brd ff:ff:ff:ff:ff:ff
inet 10.244.85.1/24 brd 10.244.85.255 scope global cni0
valid_lft forever preferred_lft forever
inet6 fe80::38e8:b6ff:fec4:dc2a/64 scope link
valid_lft forever preferred_lft forever
7: veth1c6fe451@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master cni0 state UP
link/ether 8a:04:23:73:21:b3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::8804:23ff:fe73:21b3/64 scope link
valid_lft forever preferred_lft forever
8: veth6b727ae1@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master cni0 state UP
link/ether 2a:a2:8d:5a:03:a5 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::28a2:8dff:fe5a:3a5/64 scope link
valid_lft forever preferred_lft forever
OK,flannel二进制形式的部署就完成了,后面的测试pod是否能够正常创建等等就不在这里废话了。
三,
calico的安装部署
- calico的版本:
首先,应该说明一下,calico的版本是比较多得,主要是分为两种,open source(开放版)和Calico Enterprise(企业版)
Documentation archive | Calico Documentation
###注2:
企业版是带有许可证的,目前来说没见过使用,好像是有一个web管理界面,剩下的应该和开放版是一样的。
OK,calico官方推荐是yaml清单形式部署,当然,还有其它的方式,例如,从docker镜像里抽取文件的二进制方式,yum安装方式,apt安装方式等等。
那么,yaml文件一般是从calico 的官网下载,下载地址是:Documentation archive | Calico Documentation
由于版本的不同,yaml清单文件的方式也有些许不同,例如,3.14版本的安装介绍:
Quickstart for Calico on KubernetesInstall Calico on a single-host Kubernetes cluster for testing or development in under 15 minutes.https://docs.tigera.io/archive/v3.20/getting-started/kubernetes/quickstart
#####注:以上这两个quick start 是用于测试或者开发环境的yaml清单文件,如果是用于生产环境的:
Install Calico networking and network policy for on-premises deployments #生产环境的部署文档
一般是使用第一个链接内的yaml文件,反正第二个链接我是没有成功部署,网络配置存储在kubernetes api内,如果集群规模比较大,可以使用第三个链接,将网络配置存储在etcd集群内。
例如部署calico-3.25:
curl https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml -O
然后直接执行此文件即可,基本不需要修改,部署完成后,相关pod如下:
[root@k8s-master ~]# kubectl get po -A |grep calico
kube-system calico-kube-controllers-64cc74d646-th8mh 1/1 Running 0 23m
kube-system calico-node-5jdnc 1/1 Running 0 23m
kube-system calico-node-6fl6n 1/1 Running 0 23m
kube-system calico-node-cpzhn 1/1 Running 0 23m
注:
- 在k8s集群上实际部署时,Calico分为calico-node和calico-kube-controllers两个组件,它们通过Datastore读取与自身相关的资源定义完成配置
- calico-node:Calico在k8s集群中每个节点运行的代理程序,负责提供Felxi、bird4、bird6和confd等守护进程,在所有node上创建calico-node pod,这个pod包括两个容器,一个是初始化容器:calico-cni,一个是创建路由和iptables信息的calico-node(通常是daemonset控制器部署)
- calico-kube-controllers:Calico运行在k8s集群上的自定义控制器,是Calico协同k8s的插件,是监控和并同步network policy、namespaces、pods、nodes、serviceaccount等信息到calico的配置存储系统。官方文档建议的是,一个calico-kube-controllers replicas能管理200个节点,建议总共不超过20个replicas,(通常,是deployment控制器部署)
部署的时候,根据自身的网络环境,集群规模,选择合适的部署方式
下面是系统要求:
进入这个链接后,可以看到3.14可部署在kubernetes-1.16-1.18上, 在其他版本可能会正常工作,但,官方没有测试,也就是说,其他版本不一定可以使用calico-3.14。
Supported versions
We test Calico v3.14 against the following Kubernetes versions.
- 1.16
- 1.17
- 1.18
Other versions are likely to work, but we do not actively test Calico v3.14 against them.
calico的三种工作模式:
Overlay模式,Calico提供VXLAN或IP-in-IP网络模式,包括限制跨子网模式(cross-subnet),也可以称之为覆盖网络模式,
Non-overlay模式,Calico提供在L2网络或L3网络之上运行的Non-overlay网络,BGP就是此模式
IPIP模式
IPIP模式是calico的默认网络架构,其实这也是一种overlay的网络架构,但是比overlay更常用的vxlan模式相比更加轻量化。IPinIP就是把一个IP数据包又套在一个IP包里,即把 IP 层封装到 IP 层的一个 tunnel它的作用其实基本上就相当于一个基于IP层的网桥!一般来说,普通的网桥是基于mac层的,根本不需 IP,而这个 ipip 则是通过两端的路由做一个 tunnel,把两个本来不通的网络通过点对点连接起来.
BGP模式
Calico常用的模式也是它的王牌模式BGP模式,虽然说calico有BGP模式和IPIP模式但是并不是说IPIP模式就不用建立BGP连接了,IPIP模式也是需要建立BGP连接的,只不过建立BGP链接的目标比较清晰,就是对端的tunl0对应的网卡。BGP模式对于IPIP模式的优点也并不是简单的描述为“可以跨节点通信”,IPIP模式也是可以跨节点通信的,只要两个节点能互相连通就可以。而BGP的优点是可以通过指定BGP的对端Peer,一般是交换机,那么只要能接入这个交换机的host或者PC都能通过路由的方式连通calico的其他节点上的容器。也就是说BGP的可扩展的网络拓扑更灵活。
注:bird是BGP的客户端
VXLAN模式
VXLAN(Virtual eXtensible Local Area Network,虚拟扩展局域网),是由IETF定义的NVO3(Network Virtualization over Layer 3)标准技术之一,是对传统VLAN协议的一种扩展。VXLAN的特点是将L2的以太帧封装到UDP报文(即L2 over L4)中,并在L3网络中传输。
calico yaml清单文件的自定义(这里是使用VXLAN):
- name: IP
value: "autodetect"
# Enable IPIP
- name: CALICO_IPV4POOL_IPIP
value: "Never"
# Enable or Disable VXLAN on the default IP pool.
- name: CALICO_IPV4POOL_VXLAN
value: "Always"
# Enable or Disable VXLAN on the default IPv6 IP pool.
- name: CALICO_IPV6POOL_VXLAN
value: "Never"
配置解释:
CALICO_IPV4POOL_IPIP:启用IPIP隧道配置
Always:全流量使用IPIP隧道转发
Cross-SubNet:跨网段节点使用IPIP隧道转发,同一网段节点使用BGP路由直接转发
Never:不启用IPIP
CALICO_IPV4POOL_VXLAN::启用VXLAN配置
Always:全流量使用VXLAN隧道转发
Cross-SubNet:跨网段节点使用VXLAN隧道转发,同一网段节点使用BGP路由直接转发
Never:不启用VXLAN
注:IPIP不能和VXLAN同时开启,必须是一个开,一个关
如果仅使用基于VXLAN协议的覆盖网络模式(也就是纯粹的VXLAN),用不到BGP动态路由模式的话,即为了节省一点资源,可以选择完全禁用Calico基于BGP的网络:
将"calico_backend: “bird”“修改为"calico_backend: “vxlan””,这将禁用BIRD。
从calico/node的readiness/liveness检查中去掉"- -bird-ready"和"- -bird-live",以保证calico的node能够正常启动
安装完毕后的宿主机的网络状态和路由信息:
可以看到有vxlan.calico,tunl0是无IP的
[root@k8s-master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:0c:29:4b:cc:d3 brd ff:ff:ff:ff:ff:ff
inet 192.168.123.11/24 brd 192.168.123.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe4b:ccd3/64 scope link
valid_lft forever preferred_lft forever
3: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:df:f6:0f:75 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
5: cali29548c5dae8@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP
link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::ecee:eeff:feee:eeee/64 scope link
valid_lft forever preferred_lft forever
8: vxlan.calico: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN
link/ether 66:d5:cf:d3:6b:7e brd ff:ff:ff:ff:ff:ff
inet 10.244.235.192/32 scope global vxlan.calico
valid_lft forever preferred_lft forever
inet6 fe80::64d5:cfff:fed3:6b7e/64 scope link
valid_lft forever preferred_lft forever
9: cali16b3e23e8a8@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP
link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::ecee:eeff:feee:eeee/64 scope link
valid_lft forever preferred_lft forever
[root@k8s-master ~]# ip r
default via 192.168.123.2 dev ens33
10.244.36.64/26 via 10.244.36.64 dev vxlan.calico onlink
10.244.169.128/26 via 10.244.169.128 dev vxlan.calico onlink
blackhole 10.244.235.192/26 proto 80
10.244.235.193 dev cali29548c5dae8 scope link
10.244.235.194 dev cali16b3e23e8a8 scope link
169.254.0.0/16 dev ens33 scope link metric 1002
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.123.0/24 dev ens33 proto kernel scope link src 192.168.123.11
OK,如果运行在ipip模式下,网络情况和路由是这样的:
tunl0是有IP的,并且路由里有bird这个客户端
[root@k8s-master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:0c:29:4b:cc:d3 brd ff:ff:ff:ff:ff:ff
inet 192.168.123.11/24 brd 192.168.123.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe4b:ccd3/64 scope link
valid_lft forever preferred_lft forever
3: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
inet 10.244.235.192/32 scope global tunl0
valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:1d:e3:74:59 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
7: cali16b3e23e8a8@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1480 qdisc noqueue state UP
link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::ecee:eeff:feee:eeee/64 scope link
valid_lft forever preferred_lft forever
8: cali29548c5dae8@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1480 qdisc noqueue state UP
link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::ecee:eeff:feee:eeee/64 scope link
valid_lft forever preferred_lft forever
[root@k8s-master ~]# ip r
default via 192.168.123.2 dev ens33
10.244.36.64/26 via 192.168.123.12 dev tunl0 proto bird onlink
10.244.169.128/26 via 192.168.123.13 dev tunl0 proto bird onlink
blackhole 10.244.235.192/26 proto bird
10.244.235.193 dev cali16b3e23e8a8 scope link
10.244.235.194 dev cali29548c5dae8 scope link
169.254.0.0/16 dev ens33 scope link metric 1002
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.123.0/24 dev ens33 proto kernel scope link src 192.168.123.11