Kubernetes 网络插件 Calico (重要)
适用范围
本文档测试范围:
软件 | 版本 |
---|---|
Kubernetes | v1.14.x,v1.15.x,v1.16.x |
calico | v3.13.4 |
概述
Calico 是一种开源网络和网络安全解决方案,适用于容器,虚拟机和基于主机的本机工作负载。Calico 支持广泛的平台,包括 Kubernetes,docker,OpenStack 和裸机服务。Calico 后端支持多种网络模式。
- BGP 模式:将节点做为虚拟路由器通过 BGP 路由协议来实现集群内容器之间的网络访问。
- IPIP 模式:在原有 IP 报文中封装一个新的 IP 报文,新的 IP 报文中将源地址 IP 和目的地址 IP 都修改为对端宿主机 IP。
- cross-subnet:Calico-ipip 模式和 calico-bgp 模式都有对应的局限性,对于一些主机跨子网而又无法使网络设备使用 BGP 的场景可以使用 cross-subnet 模式,实现同子网机器使用 calico-BGP 模式,跨子网机器使用 calico-ipip 模式。
calico 切换 BGP 模式
部署完成后默认使用 calico-ipip 的模式,通过在节点的路由即可得知,通往其他节点路由通过 tunl0 网卡出去
修改为 BGP 网络模式,在 system 项目中修改 calico-node daemonset
修改CALICO_IPV4POOL_IPIP
改为 off,添加新环境变量FELIX_IPINIPENABLED
为 false
修改完成后对节点进行重启,等待恢复后查看主机路由,与 ipip 最大区别在于去往其他节点的路由,由 Tunnel0 走向网络网卡。
calico 切换 cross-subnet 模式
Calico-ipip 模式和 calico-bgp 模式都有对应的局限性,对于一些主机跨子网而又无法使网络设备使用 BGP 的场景可以使用 cross-subnet 模式,实现同子网机器使用 calico-BGP 模式,跨子网机器使用 calico-ipip 模式。
部署集群网络选择 calico 网络插件
默认部署出来是 calico 的 ip-in-ip 的模式 查看宿主机网卡,会发现多了个 tunl0 网卡,这个是建立 ip 隧道的网卡
去其他主机的路由都是走 tunl0 网卡出去
切换到 cross-subnet 模式
kubectl edit ipPool/default-ipv4-ippool
将 ipipMode 改为 crossSubnet
在 UI 将 calico-node 的 POD 删了重建
重启检查 calico 网络
可以看见同子网的主机出口走的是 bgp,不同子网主机走的是 tunl0 网卡走 ipip 模式
创建应用测试跨主机网络,在不同主机上互相 ping 测试,看看跨主机网络是否正常。
配置 Route reflector
安装 calicoctl
安装方式有以下几种
- Single host 上面 binary 安装
- Single host 上面 continer 安装
- 作为 k8s pod 运行
实际经验:
Binary 方式在集群里面的一台 worker 节点安装(比如 RR),calicoctl 会检测 bird/felix 的运行状态。在非 calico node 节点运行只能使用部分命令,不能运行 calico node 相关命令。
通过配置 calicoctl 来对 calico 进行控制,通常情况下建议将
curl -O -L https://github.com/projectcalico/calicoctl/releases/download/v3.13.3/calicoctl
配置可执行权限
chmod +x calicoctl
复制的/usr/bin/目录
cp calicoctl /usr/bin/
配置 calicoctl 连接 Kubernetes 集群
export CALICO_DATASTORE_TYPE=kubernetes
export CALICO_KUBECONFIG=~/.kube/config
calicoctl node status
calico node-to-node mesh
默认情况下 calico 采用 node-to-node mesh 方式 ,为了防止 BGP 路由环路,BGP 协议规定在一个 AS(自治系统)内部,IBGP 路由器之间只能传一跳路由信息,所以在一个 AS 内部,IBGP 路由器之间为了学习路由信息需要建立全互联的对等体关系,但是当一个 AS 规模很大的时候,这种全互联的对等体关系维护会大量消耗网络和 CPU 资源,所以这种情况下就需要建立路由反射器以减少 IBGP 路由器之间的对等体关系数量。
Route reflector 角色介绍
早期 calico 版本提供专门的 route reflector 镜像,在新版本 calico node 内置集成 route reflector 功能。Route reflector 可以是以下角色:
- 集群内部的 node 节点
- 集群外部节点运行 calico node
- 其他支持 route reflector 的软件或者设备。
这里以一个集群内部的 node 节点为例:
关闭 node-to-node mesh
cat <<EOF | calicoctl apply -f -
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
name: default
spec:
logSeverityScreen: Info
nodeToNodeMeshEnabled: false
asNumber: 63400
EOF
设置 Route reflector
配置 Route reflector 支持多种配置方式如:1、支持配置全局 BGP peer,。2、支持针对单个节点进行配置 BGP Peer。也可以将 calico 节点充当 Route reflector 这里以配置 calico 节点充当 Router reflector 为例。
配置节点充当 BGP Route Reflector
可将 Calico 节点配置为充当路由反射器。为此,要用作路由反射器的每个节点必须具有群集 ID-通常是未使用的 IPv4 地址。
要将节点配置为集群 ID 为 244.0.0.1 的路由反射器,请运行以下命令。这里将节点名为 rke-node4 的节点配置为 Route Reflector,若一个集群中要配置主备 rr,为了防止 rr 之间的路由环路,需要将集群 ID 配置成一样
calicoctl patch node rke-node4 -p '{"spec": {"bgp": {"routeReflectorClusterID": "244.0.0.1"}}}'
给节点打上对应的 label 标记该节点以表明它是 Route Reflector,从而允许 BGPPeer 资源选择它。
kubectl label node rke-node4 route-reflector=true
创建 BGPPeer
export CALICO_DATASTORE_TYPE=kubernetes
export CALICO_KUBECONFIG=~/.kube/config
cat <<EOF | calicoctl apply -f -
kind: BGPPeer
apiVersion: projectcalico.org/v3
metadata:
name: peer-with-route-reflectors
spec:
nodeSelector: all()
peerSelector: route-reflector == 'true'
EOF
查看 BGP 节点状态
node 上查看,peer type 由 node-to-node mesh 变为 node specific
Route Reflector 上节点查看,节点已正常建立连接
设置 veth 网卡 mtu
通常,通过使用最高 MTU 值(不会在路径上引起碎片或丢包)来实现最高性能。对于给定的流量速率,最大带宽增加,CPU 消耗可能下降。对于一些支持 jumbo frames 的网络设备,可以配置 calico 支持使用。
下表列举了,常见几种 MTU 配置下 calico 对应的网卡 mtu 的配置
IPIP 和 VXLAN 协议中的 IP 中使用的额外报文头,通过头的大小减小了最小 MTU。(IP 中的 IP 使用 20 字节的标头,而 VXLAN 使用 50 字节的标头)。
如果在 Pod 网络中的任何地方使用 VXLAN,请将 MTU 大小配置为“物理网络 MTU 大小减去 50”。如果仅在 IP 中使用 IP,则将 MTU 大小配置为“物理网络 MTU 大小减去 20” 。
将工作负载端点 MTU 和隧道 MTU 设置为相同的值
配置方法:
升级集群
配置网卡 MTU,此时通过 system 项目下 calico-config 文件可以看见对应的 mtu 设置
创建 workload 查看 POD 网卡 MTU 为 9001
设置全局 AS 号
默认情况下,除非已为节点指定每个节点的 AS,否则所有 Calico 节点都使用 64512 自治系统。可以通过修改默认的 BGPConfiguration 资源来更改所有节点的全局默认值。以下示例命令将全局默认 AS 编号设置为 64513。
cat <<EOF | calicoctl apply -f -
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
name: default
spec:
logSeverityScreen: Info
nodeToNodeMeshEnabled: false
asNumber: 64513
EOF
设置单个主机和 AS 号
例如,以下命令将名为 node-1 的节点更改为属于 AS 64514。
calicoctl patch node node-1 -p '{"spec": {"bgp": {“asNumber”: “64514”}}}'
修改节点地址范围
此操作建议在部署完集群后立刻进行。
默认情况下 calico 在集群层面分配一个 10.42.0.0/16 的 CIDR 网段,在这基础上在单独为每个主机划分一个单独子网采用 26 位子网掩码对应的集群支持的节点数为 2^10=1024 节点,单个子网最大支持 64 个 POD,当单个子网对应 IP 消耗后,calico 会重新在本机上划分一个新的子网如下,在集群对端主机可以看见对应的多个 CIDR 路由信息。
注意:块大小将影响节点 POD 的 IP 地址分配和路由条目数量,如果主机在一个 CIDR 中分配所有地址,则将为其分配一个附加 CIDR。如果没有更多可用的块,则主机可以从分配给其他主机的 CIDR 中获取地址。为借用的地址添加了特定的路由,这会影响路由表的大小。
将块大小从默认值增加(例如,使用/24 则为每个块提供 256 个地址)意味着每个主机更少的块,会减少路由。但是对应的集群可容纳主机数也对应减少为 2^8。
从默认值减小 CIDR 大小(例如,使用/28 为每个块提供 16 个地址)意味着每个主机有更多 CIDR,因此会有更多路由。
calico 允许用户修改对应的 IP 池和集群 CIDR
创建和替换步骤
注意:删除 Pod 时,应用程序会出现暂时不可用
- 添加一个新的 IP 池。
- 注意:新 IP 池必须在同一群集 CIDR 中。
- 禁用旧的 IP 池(注意:禁用 IP 池只会阻止分配新的 IP 地址。它不会影响现有 POD 的联网)
- 从旧的 IP 池中删除 Pod。
- 验证新的 Pod 是否从新的 IP 池中获取地址。
- 删除旧的 IP 池。
定义 ippool 资源
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: my-ippool
spec:
blockSize: 24
cidr: 192.0.0.0/16
ipipMode: Always
natOutgoing: true
修改对应的 blockSize 号
创建新的
calicoctl apply -f pool.yaml
将旧的 ippool 禁用
calicoctl patch ippool default-ipv4-ippool -p '{"spec": {"disabled": “true”}}'
创建 workload 测试
根据节点标签定义对应的 ippool
Calico 能够进行配置,为不同拓扑指定 IP 地址池。例如可能希望某些机架、地区、或者区域能够从同一个 IP 池中获取地址。这对于降低路由数量或者配合防火墙策略的要求会很有帮助。
给节点配置对应 label
kubectl label nodes kube-node-0 rack=0
kubectl label nodes kube-node-1 rack=1
通过标签定义对应的节点 IPpool
calicoctl create -f -<<EOF
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: rack-0-ippool
spec:
cidr: 192.168.0.0/24
ipipMode: Always
natOutgoing: true
nodeSelector: rack == "0"
EOF
calicoctl create -f -<<EOF
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: rack-1-ippool
spec:
cidr: 192.168.1.0/24
ipipMode: Always
natOutgoing: true
nodeSelector: rack == "1"
EOF
关闭 SNAT
默认情况下,calico 访问集群外网络是通过 SNAT 成宿主机 ip 方式,在一些金融客户环境中为了能实现防火墙规则,需要直接针对 POD ip 进行进行规则配置,所以需要关闭 natOutgoing
kubectl edit ippool/default-ipv4-ippool
将 natOutgoing: true
修改为natOutgoing: false
此时,calico 网络访问集群外的 ip 源 ip 就不会 snat 成 宿主机的 ip 地址。
固定 POD IP
固定单个 ip
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-test
spec:
selector:
matchLabels:
app: nginx
replicas: 1 # tells deployment to run 1 pods matching the template
template:
metadata:
labels:
app: nginx
annotations:
"cni.projectcalico.org/ipAddrs": "[\"10.42.210.135\"]"
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
固定多个 ip,只能通过 ippool 的方式
cat ippool1.yaml
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: pool-1
spec:
blockSize: 31
cidr: 10.21.0.0/31
ipipMode: Never
natOutgoing: true
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-test
spec:
selector:
matchLabels:
app: nginx
replicas: 1 # tells deployment to run 1 pods matching the template
template:
metadata:
labels:
app: nginx
annotations:
"cni.projectcalico.org/ipv4pools": "[\"pool-1\"]"
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
链接:https://www.bladewan.com/2020/11/18/calico_ops