一文学会Calico网络自定义

一、确定最佳的网络选项

Calico支持多个容器网络选项,用于可伸缩性、网络性能和与现有基础设施的互操作性。

1. 值

不同的网络实现更适合不同的环境。Calico提供了几种不需要封装的基于IP路由的网络实现。如果您的部署需要封装,Calico提供覆盖网络(IP in IP或VXLAN)。Calico还支持使用其他Kubernetes网络选项来执行策略。本文档帮助您为集群选择最佳的网络选项。

2. 概念

2.1 关于calico networking

Calico提供了一些方法,允许pod连接到其他pod、主机和外部网络(例如internet)。

Calico网络:

  • 使用Calico的IP地址管理(IPAM)将IP地址分配给pods
  • 编写本地节点的路由表
  • 将路由分配给其他节点和网络设备
2.2 关于BGP

Calico支持使用边界网关协议(BGP)将路由信息共享到网络中。Calico支持节点到节点的全网格部署(有和没有路由反射器),以及BGP直接对机架(ToR)路由器顶部的现场部署;允许流量直接路由到工作负载,而不需要NAT或封装。

2.3 其它Kubernetes 网络选项

Calico可以使用许多其他Kubernetes网络选项执行网络策略强制。

  • Flannel
  • Amazon AWS VPC CNI
  • Azure CNI
  • Google cloud networking

下表显示了使用Calico时常见的网络选项。

image-20230630120304024

网络选项

3. 基本说明

本节提供更多关于Calico的内置网络选项的细节:

  • Unencapsulated, peered with physical infrastructure
  • Unencapsulated, not peered with physical infrastructure
  • IP in IP or VXLAN encapsulation
3.1 Unencapsulated, peered with physical infrastructure

Calico可以与你的路由器使用BGP对等。这提供了出色的性能和易于调试的非封装流量,以及广泛的网络拓扑和连接选项。

  • 您的集群可以跨越多个L2子网,而不需要封装
  • 集群外的资源可以直接与pod通信,而不需要NAT
  • 如果你想的话,你甚至可以把pod直接暴露在互联网上!
3.2 Unencapsulated, not peered with physical infrastructure

此选项还提供了接近主机到主机的性能级别,并允许网络直接看到流量。

当所有节点都在一个L2子网上时,如果底层网络不强制执行IP地址检查,Calico可以在节点之间路由pod流量,而不需要封装。如果您的网络由多个L2子网组成,那么您可以使用路由器在BGP上进行对等,或者使用跨子网封装来仅封装跨子网边界的流量。

如果不允许在集群外部进行工作负载访问或使用基础设施进行对等访问,就无法在pod和不属于Calico集群的目的地之间路由流量。

3.3 IP in IP or VXLAN encapsulation

如果可能,我们建议运行Calico没有网络覆盖/封装。这提供了最高的性能和最简单的网络;离开您的工作负载的包是连接到网络上的包。

但是,当运行在底层网络上时,有选择地使用覆盖(IP中的IP或VXLAN中的IP)是非常有用的,因为底层网络不容易知道工作负载IP。Calico可以对:所有的流量,没有流量,或者只对跨越子网边界的流量进行封装。

IP中的IP或VXLAN封装也可以在子网之间选择性地使用——这提供了子网中未封装的流量的性能优势,适用于织物包含多个L2网络且无法进行对等连接的环境。例如,如果您在AWS中跨多个VPC/子网使用Calico网络,Calico可以选择性地只封装在VPC/子网之间路由的流量,而不封装在每个VPC/子网中运行。

二、配置BGP路由反射及对等体

1. BGP协议配置

apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  logSeverityScreen: Info
  nodeToNodeMeshEnabled: true
  asNumber: 63400
  serviceClusterIPs:
  - cidr: 10.96.0.0/12
  serviceExternalIPs:
  - cidr: 192.168.20.99/32

2. 关闭默认的BGP node-to-node mesh

image-20230630120324478

BGP网格

缺省的节点到节点的BGP网格必须关闭,以启用其他BGP拓扑。为此,修改默认的BGP配置资源。

  • 运行下面的命令去关闭BGP full-mesh
calicoctl patch bgpconfiguration default -p '{"spec": {"nodeToNodeMeshEnabled": false}}'

2. 配置全局的 BGP 对等体

  • 下面的示例创建一个全局BGP对等点,它将每个Calico节点配置为在AS 64567中使用192.20.30.40的对等点。
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: my-global-peer
spec:
  peerIP: 192.20.30.40
  asNumber: 64567

3. 配置每节点的 BGP peer

每个节点的BGP对等点应用于集群中的一个或多个节点。您可以通过精确地指定节点的名称或使用标签选择器来选择节点。

apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: rack1-tor
spec:
  peerIP: 192.20.30.40
  asNumber: 64567
  nodeSelector: rack == ‘rack-1’

4. 配置node作为路由反射器

Calico 可以配置扮演成一个路由反射器。每个节点要充当路由反射器必须有一个集群ID——通常一个未使用的IPv4地址。

  • 配置一个节点作为路由反射器,有个集群ID 244.0.0.1, 运行如下命令:
calicoctl patch node c76085.xiodi.cn -p '{"spec": {"bgp": {"routeReflectorClusterID": "244.0.0.1"}}}'
  • 常规情况下,给这个节点打上标签,标明这个是路由反射器。允许它更容易通过BGPPeer resource选择。
kubectl label node c76085.xiodi.cn route-reflector=true
  • 现在使用标签器很容易配置路由反射器节点和非路由反射器节点。比如:
kind: BGPPeer
apiVersion: projectcalico.org/v3
metadata:
  name: peer-with-route-reflectors
spec:
  nodeSelector: all()
  peerSelector: route-reflector == 'true'
  • 针对一个节点查看BGP peering 状态
    您可以使用calicoctl查看一个特定节点的边界网关协议连接的当前状态。这是用于确认您的配置是根据需要的行为。
sudo calicoctl node status
  • 改变默认的global AS number

默认的,所有的calico 节点使用64512 autonomous system, 除非特殊指定。下面的命令把它改成64513.

calicoctl patch bgpconfiguration default -p '{"spec": {"asNumber": “64513”}}'
  • 针对特定的节点改变AS number,如下所示
calicoctl patch node node-1 -p '{"spec": {"bgp": {“asNumber”: “64514”}}}'

三、IPinIP模式

您可以配置每个IP池不同封装配置。然而,你不能一个IP池内混合封装类型。

  • Configure IP in IP encapsulation for only cross subnet traffic
  • Configure IP in IP encapsulation for all inter workload traffic
  • Configure VXLAN encapsulation for only cross subnet traffic
  • Configure VXLAN encapsulation for all inter workload traffic
  1. IPv4/6 地址支持

IP in IP和 VXLAN只支持IPv4地址。

  1. 最佳实践

Calico 只有一个选项来选择性地封装流量 ,跨越子网边界。我们建议使用IP in IPcross subnet选项把开销降到最低。

注意:切换封装模式会导到正在连接的进程中断。

  1. 针对仅跨子网的流量配置IP in IP

IP in IP封装可以选择性的执行, 并且仅用于通过子网边界的通信量 。

开启这个功能,设置ipipModeCrossSubnet

apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: ippool-ipip-cross-subnet-1
spec:
  cidr: 192.168.0.0/16
  ipipMode: CrossSubnet
  natOutgoing: true
  1. 针对workload间的流量配置IP in IP的封装
ipipMode`设置`Always
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: ippool-ipip-1
spec:
  cidr: 192.168.0.0/16
  ipipMode: Always
  natOutgoing: true

四、vxlan两种模式解析

  1. 针对仅跨越子网的流量 ,配置VXLAN封装
  • 配置这个功能,设置vxlanMode为CrossSubnet
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: ippool-vxlan-cross-subnet-1
spec:
  cidr: 192.168.0.0/16
  vxlanMode: CrossSubnet
  natOutgoing: true
  • 针对workload间的流量 配置VXLAN的封装
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: ippool-vxlan-1
spec:
  cidr: 192.168.0.0/16
  vxlanMode: Always
  natOutgoing: true

五、通过Mtu增加网络性能

1. 确定MTU的大小

下表针对Calico环境列出了常见的MTU大小。 因为MTU是endpoints间网络路径的全局属性, 你应该设定最低MTU的MTU包可能需要的任何路径。

1.1 常见的MTU大小
Network MTU Calico MTU Calico MTU with IP-in-IP (IPv4) Calico MTU with VXLAN (IPv4)
1500 1500 1480 1450
9000 9000 8980 8950
1460(GCE) 1460 1440 1410
9001(AWS jumbo) 9001 8981 8951
1450(OpenStack VXLAN) 1450 1430 1400
1.2 针对overlay网络推荐的MTU

额外的报头用于在IP和VXLAN IP协议,降低了最小的MTU大小头。在IP使用20-byte头(IP, VXLAN使用50-byte头)。因此,我们建议如下:

  • 如果你使用在Pod网络使用VXLAN,配置MTU大小“物理网络MTU大小- 50”。
  • 假如你使用IP in IP, 配置MTU大小为“物理网络大小-20”
  • workload endpoint MTU和 tunnel MTU设置为相同的值。
1.3 针对flannel网络的MTU

当使用flannel的网络时,网络接口的MTU应该匹配flannel接口的MTU。 假如使用flannel的VXLAN, 使用上面的calico MTU with VXLAN列的大小。

2. 配置MTU针对workloads

当你设置MTU,它适用于新工作负载。MTU变化应用于现有的工作负载,必须重新启动calico nodes。

  • 编辑calico-config ConfigMap FelixConfiguration设置值。例如:
kubectl patch configmap/Calico-config -n kube-system --type merge \
  -p '{"data":{"veth_mtu": "1440"}}'

3. 针对overlay 网络配置MTU

如果您使用的是IP in IP和/或VXLAN calico overlay 网络,设置隧道MTU匹配veth MTU配置的值。

  • 编辑calico-config ConfigMap设置MTU在FelixConfiguration隧道值。例如:
# Configure the MTU to use
veth_mtu: "1440" 
  • 查看当前tunnel MTU值
ip link show

IP在IP隧道作为tunlx出现(例如,tunl0),连同MTU大小。例如:

img

mtu

六、calico网络地址转换

1. 允许workloads 访问 internet,私有IP地址

允许工作负载使用私有IP地址访问互联网,你可以用你现有NAT功能,或者你可以在Calico IPPool上开启natOutgoing。

在以下的示例中,我们创建一个Calicco IPPool,并开启natOutgoing 。Outbound NAT是在节点本地执行的。

apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: default-ipv4-ippool
spec:
  cidr: 192.168.0.0/16
  natOutgoing: true

2. 仅去nat那些指定的IP地址范围

您可以创建额外的IPPools不用于IP地址管理,防止NAT某些CIDR块。这是有用的,如果你想让节点NAT网络流量,但不是在某些内部ip范围。例如,如果您不想NAT流量10.0.0.0/8,您可以创建以下池。您必须确保集群之间的网络和10.0.0.0/8可路由。

apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: no-nat-10.0.0.0-8
spec:
  cidr: 10.0.0.0/8
  disabled: true

七、IP地址检测剖析

针对calico节点配置IP自动检测,确保路由使用正确的P地址。

1. 值

当你安装Calico在一个节点上时,一个IP地址和子网被自动检测。Calico提供几种方式去配置子网自动检测,和支持配置指定的IPs。

  • 拥有多个外部接口的主机
  • 主机接口拥有多个IP地址
  • 改变跨子网包的封装
  • 改变主机IP地址

2. 概念

2.1 自动检测节点IP地址和子网

针对节点间的路由,每个calico节点必须配置一个IPv4地址 和/或 一个IPV6地址,当安装一个calico在一个节点上时,一个节点资源使用从主机检测到的路由信息自动创建。针对一些部署,你可能想要自动的更新检测,确保节点获取正确的IP地址。

  • 在安装后默认的节点资源案例
apiVersion: projectcalico.org/v3
kind: Node
metadata:
  name: node-hostname
spec:
  bgp:
    asNumber: 64512
    ipv4Address: 10.244.0.1/24
    ipv6Address: 2000:db8:85a3::8a2e:370:7335/120
    ipv4IPIPTunnelAddr: 192.168.0.1
2.2 自动检测方法

默认的,Calico使用first-found方法,也就是说第一个接口第一个有效的IP地址(排除local interface,因为它是docker bridge).你可以使用以下方法的任一一种改变默认方法。

(1)使用一个能到达特定IP或domain的地址。

(2)使用正则的方式,去匹配接口(interface)

(3)使用正则的方式,去排除匹配的接口(skip interface)

2.3 手动配置IP地址和子网
  • 有两种方式去手动的配置IP地址和子网

(1) calico node container(start/restart),使用环境变量去设置节点的值

(2) 更新节点的资源

  • 使用环境变量和节点的资源

因为你可以通过配置环境变量和节点资源,去更改IP地址和子网,下表描述了这些值如何同步的。

If this environment variable… Is… Then…
IP/IP6 Explicitly set The specified values are used, and the Node resource is updated.
Set to autodetect The requested method is used (first-found, can-reach, interface, skip-interface), and the Node resource is updated.
Not set, but Node resource has IP/IP6 values Node resource value is used.
IP Not set, and there is no IP value in Node resource Autodetects an IPv4 address and subnet, and updates Node resource.
IP6 Not set, and there is a notIP6 value in Node resource No IP6 routing is performed on the node。

3. 动作

3.1 改变自动检测方法

由于默认的自动检测方法是first valid interface found(first-found). 去使用不同的自动检测方法,使用kubectl set env命令指定方法。

  • IPv4
kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHOD=<autodetection-method>
  • IPv6
kubectl set env daemonset/calico-node -n kube-system IP6_AUTODETECTION_METHOD=<autodetection-method>
  • 设置检测方法基于情况

(1)IP 或 domain name

kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHOD=can-reach=www.google.com

(2)包含匹配的接口

kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHOD=interface=eth.*

(3)排除匹配的接口

kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHOD=skip-interface=eth.*
3.2 针对节点手动配置IP地址和子网

在下列情况下,您可能需要配置一个特定的IP子网:

  • 主机拥有多个外部的接口
  • 主机接口拥有多个IP地址
  • 改变跨子网数据包的封装
  • 改变主机IP地址
  1. 使用环境变量配置IP和子网
kubectl set env daemonset/calico-node -n kube-system IP=10.0.2.10/24 IP6=fd80:24e2:f998:72d6::/120
  1. 使用节点资源配置IP和子网
calicoctl patch node kind-control-plane \
  --patch='{"spec":{"bgp": {"ipv4Address": "10.0.2.10/24", "ipv6Address": "fd80:24e2:f998:72d6::/120"}}}'

八、IP地址及封装模式切换
针对安装Calico到kubernetes集群中的每个节点,每个manifest包含所有需要的资源。

它安装如下的kubernetes资源:

  • 在每个主机上使用Daemonset的方式安装calico/node容器。
  • 在每个主机上使用Daemonset的方式安装Calico CNI和网络的配置。
  • 使用deployment的方式运行calico/kube-controllers
  • calico-etcd-secretssecret, 它提供到etcd存储的TLS.
  • calico-config ConfigMap. 它包含安装配置的参数。

1. 配置pod IP 范围

Calico IPAM从IP pools中分配 IP地址。

如果要修改pods使用的默认IP地址范围,那么修改calico.yaml清单中的CALICO_IPV4POOL_CIDR

2. 配置IP-in-IP

默认情况下,清单支持跨子网的IP-in-IP封装。许多用户可能希望禁用IP-in-IP封装,例如在以下情况下。

  • 他们的集群运行在正确配置的AWS VPC中。
  • 它们的所有Kubernetes节点都连接到同一个第2层网络。
  • 他们打算使用BGP peer,使他们的基础设施意识到pod IP地址。

如果要关闭IP-in-IP的封装,修改清单中的CALICO-IPV4POOL_IPIP.

3. 从IP-in-IP到VXLAN的切换

默认情况下,Calico清单支持IP-in-IP封装。如果您所在的网络阻塞了ip中的ip,比如Azure,您可能希望切换到Calico的VXLAN封装模式。要做到这一点,在安装时(以便Calico创建默认的IP池与VXLAN和没有IP-in-IP配置必须撤消):

  • 启动calico for policy and networking 清单
  • 使用CALICO_IPV4POOL_VXLAN取代CALICO_IPV4POOL_IPIP的名字。新的变量值同样保持为
    Always
  • 完全的关闭Calico的基于BGP网络:
    • 使用calico_backend: "vxlan" 代替calico_backend: "bird". 此步是关闭BIRD。
    • 从calico/node readiness/liveness check中注释掉--bird-readybird-live行。(否则关闭BIRD,将会导致readniess/liveness检查失败)
          livenessProbe:
            exec:
              command:
              - /bin/calico-node
              - -felix-live
             # - -bird-live
          readinessProbe:
            exec:
              command:
              - /bin/calico-node
              # - -bird-ready
              - -felix-ready

k8s 操作

1.取消k8s master节点不可调度

kubectl taint nodes k8s-master node-role.kubernetes.io/master:NoSchedule-

目录
Calico简介
Calico 网络Node之间通信网络
Calico网络模型主要工作组件

示例1:安装calico
calicoctl命令安装与使用
示例2:修改BGP网络

Calico简介

Calico 是一种容器之间互通的网络方案。在虚拟化平台中,比如 OpenStack、Docker 等都需要实现 workloads 之间互连,但同时也需要对容器做隔离控制,就像在 Internet 中的服务仅开放80端口、公有云的多租户一样,提供隔离和管控机制。而在多数的虚拟化平台实现中,通常都使用二层隔离技术来实现容器的网络,这些二层的技术有一些弊端,比如需要依赖 VLAN、bridge 和隧道等技术,其中 bridge 带来了复杂性,vlan 隔离和 tunnel 隧道则消耗更多的资源并对物理环境有要求,随着网络规模的增大,整体会变得越加复杂。我们尝试把 Host 当作 Internet 中的路由器,同样使用 BGP 同步路由,并使用 iptables 来做安全访问策略,最终设计出了 Calico 方案。

设计思想:Calico 不使用隧道或 NAT 来实现转发,而是巧妙的把所有二三层流量转换成三层流量,并通过 host 上路由配置完成跨 Host 转发

设计优势:

1.更优的资源利用
二层网络通讯需要依赖广播消息机制,广播消息的开销与 host 的数量呈指数级增长,Calico 使用的三层路由方法,则完全抑制了二层广播,减少了资源开销。

2.可扩展性
Calico 使用与 Internet 类似的方案,Internet 的网络比任何数据中心都大,Calico 同样天然具有可扩展性。

3.简单而更容易 debug
因为没有隧道,意味着 workloads 之间路径更短更简单,配置更少,在 host 上更容易进行 debug 调试。

4.更少的依赖
Calico 仅依赖三层路由可达。

5.可适配性
Calico 较少的依赖性使它能适配所有 VM、Container、白盒或者混合环境场景。

Calico 网络Node之间通信网络

IPIP(可跨网段通信)
从字面来理解,就是把一个IP数据包又套在一个IP包里,即把 IP 层封装到 IP 层的一个 tunnel。它的作用其实基本上就相当于一个基于IP层的网桥!一般来说,普通的网桥是基于mac层的,根本不需 IP,而这个 ipip 则是通过两端的路由做一个 tunnel,把两个本来不通的网络通过点对点连接起来。
类似vxlan 但封装开销比vxlan小 效率相对更高一些,但安全性也更差

Vxlan(可跨网段通信)
与Flannel Vxlan原理相同

BGP(二层网络通信)
边界网关协议(Border Gateway Protocol, BGP)是互联网上一个核心的去中心化自治路由协议。它通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议。BGP,通俗的讲就是讲接入到机房的多条线路(如电信、联通、移动等)融合为一体,实现多线单IP,BGP 机房的优点:服务器只需要设置一个IP地址,最佳访问路由是由网络上的骨干路由器根据路由跳数与其它技术指标来确定的,不会占用服务器的任何系统
实际上,Calico 项目提供的 BGP 网络解决方案,与 Flannel 的 host-gw 模式几乎一样。也就是说,Calico也是基于路由表实现容器数据包转发,但不同于Flannel使用flanneld进程来维护路由信息的做法,而Calico项目使用BGP协议来自动维护整个集群的路由信息。

部署推荐方案:
BGP+Vxlan

其中BGP在官方的推荐方案中 以50个节点为界区别了不同规模使用不同的部署方案

  • 小规模网络:BGP peer 一对一网络:每个节点都是有N-1条路由,小型网络适用,当节点数N变多时,路由表更新及AIP-SERVER都需要承受很大的压力 类似网络拓扑结构中的 网状拓扑结构
  • 大规模网络:BGP Reflector 路由反射器:选择一到多个节点做为Reflector,所有节点路由都汇总给Reflector,所有节点都路由都指向Reflector ,适合大型网络,类似网络拓扑结构中的星型网络

Calico网络模型主要工作组件:###

  1. Felix:运行在每一台 Host 的 agent 进程,主要负责网络接口管理和监听、路由、ARP 管理、ACL 管理和同步、状态上报等。
  2. etcd:分布式键值存储,主要负责网络元数据一致性,确保Calico网络状态的准确性,可以与kubernetes共用;
  3. BGP Client(BIRD):Calico 为每一台 Host 部署一个 BGP Client,使用 BIRD 实现,BIRD 是一个单独的持续发展的项目,实现了众多动态路由协议比如 BGP、OSPF、RIP 等。在 Calico 的角色是监听 Host 上由 Felix 注入的路由信息,然后通过 BGP 协议广播告诉剩余 Host 节点,从而实现网络互通。
  4. BGP Route Reflector:在大型网络规模中,如果仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,因为所有节点之间俩俩互联,需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,使所有 BGP Client 仅与特定 RR 节点互联并做路由同步,从而大大减少连接数。

Calico有两种运行方式,

  1. 是让calico/node独立运行于Kubernetes集群之外,但calico/kube-controllers依然需要以Pod资源运行中集群之上;
  2. 是以CNI插件方式配置Calico完全托管运行于Kubernetes集群之上,类似于我们前面曾经部署托管Flannel网络插件的方式。
    对于后一种方式,Calico提供了在线的部署清单,它分别为50节点及以下规模和50节点以上规模的Kubernetes集群使用Kubernetes API作为Dabastore提供了不同的配置清单,也为使用独立的etcd集群提供了专用配置清单。但这3种类型的配置清单中,Calico默认启用的是基于IPIP隧道的叠加网络,因而它会在所有流量上使用IPIP隧道而不是BGP路由。以下配置定义在部署清单中DaemonSet/calico-node资源的Pod模板中的calico-node容器之上。

配置选项
在IPv4类型的地址池上启用的IPIP及其类型,支持3种可用值
Always(全局流量)、Cross-SubNet(跨子网流量)和Never3种可用值

  • name: CALICO_IPV4POOL_IPIP
    value: “Always”
  • 是否在IPV4地址池上启用VXLAN隧道协议,取值及意义与Flannel的VXLAN后端相同;但在全局流量启用VXLAN时将完全不再需要BGP网络,建议将相关的组件禁用
  • name: CALICO_ IPV4POOL_VXLAN
    value: “Never”
  • 需要注意的是,Calico分配的地址池需要同Ktbernetes集群的Pod网络的定义保持一致。Pod网络通常由kubeadm init初始化集群时使用–pod-network-cidr选项指定的网络,而Calico在其默认的配置清单中默认使用192.168.0.0/16作为Pod网络,因而部署Kubernetes集群时应该规划好要使用的网络地址,并设定此二者相匹配。对于曾经使用了flannel的默认的10.244.0.0/16网络的环境而言,我们也可以选择修改资源清单中的定义,从而将其修改为其他网络地址,它定义在DaemonSet/calico-node资源的Pod模板中的calico-node容器之上。

官网链接:

https://docs.projectcalico.org/getting-started/kubernetes/self-managed-onprem/onpremises

示例1:安装calico
wget https://docs.projectcalico.org/manifests/calico.yaml

[root@k8s-master ~]# cd /etc/kubernetes/manifests/
[root@k8s-master manifests]# cat kube-controller-manager.yaml 
...
System Info:
  Machine ID:                 32599e2a74704b2e95443e24ea15d4f6
  System UUID:                34979a62-16de-4287-b149-2d4c2d8a70fb
  Boot ID:                    f31de60e-4f89-4553-ba7a-99a46d049936
  Kernel Version:             5.4.109-1.el7.elrepo.x86_64
  OS Image:                   CentOS Linux 7 (Core)
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  docker://20.10.7
  Kubelet Version:            v1.19.9
  Kube-Proxy Version:         v1.19.9
PodCIDR:                      10.244.1.0/24  #第个节点的地址块都是由K8S分配
PodCIDRs:                     10.244.1.0/24   
Non-terminated Pods:          (17 in total)

[root@k8s-master ~]# kubectl describe node k8s-node1
System Info:
  Machine ID:                 32599e2a74704b2e95443e24ea15d4f6
  System UUID:                34979a62-16de-4287-b149-2d4c2d8a70fb
  Boot ID:                    f31de60e-4f89-4553-ba7a-99a46d049936
  Kernel Version:             5.4.109-1.el7.elrepo.x86_64
  OS Image:                   CentOS Linux 7 (Core)
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  docker://20.10.7
  Kubelet Version:            v1.19.9
  Kube-Proxy Version:         v1.19.9
PodCIDR:                      10.244.1.0/24   #每个Node Pod都是由K8S分配IP
PodCIDRs:                     10.244.1.0/24

[root@k8s-master Network]# vim calico.yaml
...
 "ipam": {
              "type": "host-local",
              "subnet": "usePodCidr"   #使用k8s ipam插件分配地址 
          },
          "policy": {
              "type": "k8s"
          },

...
- name: FELIX_WIREGUARDMTU
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: veth_mtu
            # The default IPv4 pool to create on startup if none exists. Pod IPs will be
            # chosen from this range. Changing this value after installation will have
            # no effect. This should fall within `--cluster-cidr`.
            - name: CALICO_IPV4POOL_CIDR
              value: "10.244.0.0/16"  #为了和之前的flannel 10.244.0.0/16适配
            - name: CALICO_IPV4POOL_BLOCK_SIZE  #添加这一行修改默认块大小
              value: "24"
            - name: USE_POD_CIDR  #使用K8S的分配的IP地址,不然calico和K8S分配的地址会不一样
              value: "true"
  • 安装calico
[root@k8s-master plugin]# kubectl delete -f kube-flannel.yml
podsecuritypolicy.policy "psp.flannel.unprivileged" deleted
clusterrole.rbac.authorization.k8s.io "flannel" deleted
clusterrolebinding.rbac.authorization.k8s.io "flannel" deleted
serviceaccount "flannel" deleted
configmap "kube-flannel-cfg" deleted
daemonset.apps "kube-flannel-ds" deleted

[root@k8s-master plugin]# kubectl apply -f calico.yaml 
configmap/calico-config created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/kubecontrollersconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrolebinding.rbac.authorization.k8s.io/calico-node created
daemonset.apps/calico-node created
serviceaccount/calico-node created
deployment.apps/calico-kube-controllers created
serviceaccount/calico-kube-controllers created
poddisruptionbudget.policy/calico-kube-controllers created
  • calico几个组件
[root@k8s-master ~]# ps aux|grep calico
root     10867  0.0  0.1 112816  2156 pts/1    S+   13:51   0:00 grep --color=auto calico
root     20680  0.0  2.3 1215184 35216 ?       Sl   10:27   0:06 calico-node -allocate-tunnel-addrs
root     20681  0.0  2.1 1215184 32672 ?       Sl   10:27   0:06 calico-node -monitor-addresses
root     20682  2.4  3.3 1510624 51636 ?       Sl   10:27   4:54 calico-node -felix
root     20683  0.0  2.3 1657832 35496 ?       Sl   10:27   0:09 calico-node -confd
root     20686  0.0  2.0 1214928 31628 ?       Sl   10:27   0:05 calico-node -monitor-token
  • 因为calico并没有使用k8s的ipam分配IP,所以节点会有2个IP,一个是K8S分配的IP 一个是calico分配的IP
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.54.2    0.0.0.0         UG    101    0        0 eth4
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.4.0     0.0.0.0         255.255.255.0   U     100    0        0 eth0
192.168.12.0    192.168.4.172   255.255.255.0   UG    0      0        0 tunl0  #可以看到tunl0的路由信息
192.168.51.0    192.168.4.173   255.255.255.0   UG    0      0        0 tunl0  #同时可以看到节点的IP不像之前一定是连续的
192.168.54.0    0.0.0.0         255.255.255.0   U     101    0        0 eth4
192.168.113.0   192.168.4.171   255.255.255.0   UG    0      0        0 tunl0  #隧道接口
192.168.237.0   0.0.0.0         255.255.255.0   U     0      0        0 *
192.168.237.1   0.0.0.0         255.255.255.255 UH    0      0        0 cali7c0fb624285
192.168.237.2   0.0.0.0         255.255.255.255 UH    0      0        0 caliedaf285d4ef
192.168.237.3   0.0.0.0         255.255.255.255 UH    0      0        0 cali854da94d42a


[root@k8s-master calico]# ip route list
default via 192.168.54.2 dev eth4 proto static metric 101 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
192.168.4.0/24 dev eth0 proto kernel scope link src 192.168.4.170 metric 100 
192.168.12.0/24 via 192.168.4.172 dev tunl0 proto bird onlink   #可以看到tunl0的路由信息
192.168.51.0/24 via 192.168.4.173 dev tunl0 proto bird onlink    
192.168.54.0/24 dev eth4 proto kernel scope link src 192.168.54.170 metric 101 
192.168.113.0/24 via 192.168.4.171 dev tunl0 proto bird onlink 
blackhole 192.168.237.0/24 proto bird 
192.168.237.1 dev cali7c0fb624285 scope link 
192.168.237.2 dev caliedaf285d4ef scope link 
192.168.237.3 dev cali854da94d42a scope link 
  • 192.168.51.0/24 via 192.168.4.173 dev tunl0 proto bird onlink 下面的路由表可以看到 calico会为每个节点分配网络地址段 并不是使用节点的网络地址
[root@k8s-node1 ~]# ip route list
default via 192.168.54.2 dev eth4 proto static metric 101 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
192.168.4.0/24 dev eth0 proto kernel scope link src 192.168.4.171 metric 100 
192.168.12.0/24 via 192.168.4.172 dev tunl0 proto bird onlink 
192.168.51.0/24 via 192.168.4.173 dev tunl0 proto bird onlink 
192.168.54.0/24 dev eth4 proto kernel scope link src 192.168.54.171 metric 101 
blackhole 192.168.113.0/24 proto bird   #黑洞 代表自己网段 
192.168.237.0/24 via 192.168.4.170 dev tunl0 proto bird onlink
  • 查看目前工作模式
[root@k8s-master calico]# kubectl api-resources
NAME                              SHORTNAMES   APIGROUP                       NAMESPACED   KIND
bgpconfigurations                              crd.projectcalico.org          false        BGPConfiguration
bgppeers                                       crd.projectcalico.org          false        BGPPeer
blockaffinities                                crd.projectcalico.org          false        BlockAffinity
clusterinformations                            crd.projectcalico.org          false        ClusterInformation
felixconfigurations                            crd.projectcalico.org          false        FelixConfiguration
globalnetworkpolicies                          crd.projectcalico.org          false        GlobalNetworkPolicy
globalnetworksets                              crd.projectcalico.org          false        GlobalNetworkSet
hostendpoints                                  crd.projectcalico.org          false        HostEndpoint
ipamblocks                                     crd.projectcalico.org          false        IPAMBlock
ipamconfigs                                    crd.projectcalico.org          false        IPAMConfig
ipamhandles                                    crd.projectcalico.org          false        IPAMHandle
ippools                                        crd.projectcalico.org          false        IPPool  #calico地址池
kubecontrollersconfigurations                  crd.projectcalico.org          false        KubeControllersConfiguration
networkpolicies                                crd.projectcalico.org          true         NetworkPolicy
networksets                                    crd.projectcalico.org          true         NetworkSet


[root@k8s-master calico]# kubectl get  ippools -o yaml
....
  spec:
    blockSize: 24   #掩码长度
    cidr: 192.168.0.0/16  #地址池
    ipipMode: Always      #可以看到目前为ipip模式
    natOutgoing: true
    nodeSelector: all()
  • 访问抓包
[root@k8s-master PodControl]# kubectl get pod -o wide
NAME                              READY   STATUS    RESTARTS   AGE    IP             NODE        NOMINATED NODE   READINESS GATES
deployment-demo-fb544c5d8-r7pc8   1/1     Running   0          8m3s   192.168.51.1   k8s-node3   <none>           <none>
deployment-demo-fb544c5d8-splfr   1/1     Running   0          8m3s   192.168.12.1   k8s-node2   <none>           <none>
[root@k8s-master PodControl]# kubectl exec deployment-demo-fb544c5d8-r7pc8 -it -- /bin/sh
[root@deployment-demo-fb544c5d8-r7pc8 /]# ifconfig
eth0      Link encap:Ethernet  HWaddr 16:96:97:3F:F3:C5  
          inet addr:192.168.51.1  Bcast:192.168.51.1  Mask:255.255.255.255
          UP BROADCAST RUNNING MULTICAST  MTU:1480  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

[root@deployment-demo-fb544c5d8-r7pc8 /]# curl 192.168.12.1
iKubernetes demoapp v1.0 !! ClientIP: 192.168.51.1, ServerName: deployment-demo-fb544c5d8-splfr, ServerIP: 192.168.12.1!
[root@deployment-demo-fb544c5d8-r7pc8 /]# curl 192.168.12.1
iKubernetes demoapp v1.0 !! ClientIP: 192.168.51.1, ServerName: deployment-demo-fb544c5d8-splfr, ServerIP: 192.168.12.1!
[root@deployment-demo-fb544c5d8-r7pc8 /]# curl 192.168.12.1



[root@k8s-node2 ~]# tcpdump -i eth0 -nn ip host 192.168.4.172  and host 192.168.4.173
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
11:48:24.421003 IP 192.168.4.173 > 192.168.4.172: IP 192.168.51.1.33436 > 192.168.12.1.80: Flags [S], seq 3259804851, win 64800, options [mss 1440,sackOK,TS val 2008488248 ecr 0,nop,wscale 7], length 0 (ipip-proto-4)
11:48:24.421093 IP 192.168.4.172 > 192.168.4.173: IP 192.168.12.1.80 > 192.168.51.1.33436: Flags [S.], seq 3234480084, ack 3259804852, win 64260, options [mss 1440,sackOK,TS val 1053230437 ecr 2008488248,nop,wscale 7], length 0 (ipip-proto-4)  #可以看到(ipip-proto-4)为IPIP模式
11:48:24.422305 IP 192.168.4.173 > 192.168.4.172: IP 192.168.51.1.33436 > 192.168.12.1.80: Flags [.], ack 1, win 507, options [nop,nop,TS val 2008488250 ecr 1053230437], length 0 (ipip-proto-4)
11:48:24.422308 IP 192.168.4.173 > 192.168.4.172: IP 192.168.51.1.33436 > 192.168.12.1.80: Flags [P.], seq 1:77, ack 1, win 507, options [nop,nop,TS val 2008488250 ecr 1053230437], length 76: HTTP: GET / HTTP/1.1 (ipip-proto-4)
11:48:24.422554 IP 192.168.4.172 > 192.168.4.173: IP 192.168.12.1.80 > 192.168.51.1.33436: Flags [.], ack 77, win 502, options [nop,nop,TS val 1053230439 ecr 2008488250], length 0 (ipip-proto-4)
11:48:24.431688 IP 192.168.4.172 > 192.168.4.173: IP 192.168.12.1.80 > 192.168.51.1.33436: Flags [P.], seq 1:18, ack 77, win 502, options [nop,nop,TS val 1053230447 ecr 2008488250], length 17: HTTP: HTTP/1.0 200 OK (ipip-proto-4)
11:48:24.432638 IP 192.168.4.172 > 192.168.4.173: IP 192.168.12.1.80 > 192.168.51.1.33436: Flags [FP.], seq 18:276, ack 77, win 502, options [nop,nop,TS val 1053230449 ecr 2008488250], length 258: HTTP (ipip-proto-4)
11:48:24.433660 IP 192.168.4.173 > 192.168.4.172: IP 192.168.51.1.33436 > 192.168.12.1.80: Flags [.], ack 18, win 507, options [nop,nop,TS val 2008488261 ecr 1053230447], length 0 (ipip-proto-4)
11:48:24.437531 IP 192.168.4.173 > 192.168.4.172: IP 192.168.51.1.33436 > 192.168.12.1.80: Flags [F.], seq 77, ack 277, win 505, options [nop,nop,TS val 2008488261 ecr 1053230449], length 0 (ipip-proto-4)
11:48:24.437775 IP 192.168.4.172 > 192.168.4.173: IP 192.168.12.1.80 > 192.168.51.1.33436: Flags [.], ack 78, win 502, options [nop,nop,TS val 1053230454 ecr 2008488261], length 0 (ipip-proto-4)
IP 192.168.4.172 > 192.168.4.173: IP 192.168.12.1.80 > 192.168.51.1.33436 
  • 可以看到默认为ipip模式 也是经过封装在转发的 和Flannel很类似,但相对Flannel经过虚拟网桥CNI calico直接内核(内核的路由由 kube-proxy或IPVS生成)到在由tunl0传输想对Flannel少了一层交换机交换的过程,性能相比Flannel会快一些 但这并不是calico最佳的模式

calicoctl命令安装与使用

calicoctl安装的2种方式
第1种方式 calicoctl

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

  • 几种方式运行calicoctl 常用方式1:直接下载2进制calicoctl 直接运行
[root@k8s-master ~]# curl -o calicoctl -O -L  "https://github.com/projectcalico/calicoctl/releases/download/v3.20.0/calicoctl"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   615  100   615    0     0    498      0  0:00:01  0:00:01 --:--:--   504
100 43.2M  100 43.2M    0     0   518k      0  0:01:25  0:01:25 --:--:--  920k

[root@k8s-master ~]# mv calicoctl /usr/bin/

[root@k8s-master ~]# chmod +x /usr/bin/calicoctl 
[root@k8s-master ~]# calicoctl  --help
Usage:
  calicoctl [options] <command> [<args>...]

    create       Create a resource by file, directory or stdin.
    replace      Replace a resource by file, directory or stdin.
    apply        Apply a resource by file, directory or stdin.  This creates a resource
                 if it does not exist, and replaces a resource if it does exists.
    patch        Patch a pre-exisiting resource in place.
    delete       Delete a resource identified by file, directory, stdin or resource type and
                 name.
    get          Get a resource identified by file, directory, stdin or resource type and
                 name.
    label        Add or update labels of resources.
    convert      Convert config files between different API versions.
    ipam         IP address management.
    node         Calico node management.
    version      Display the version of this binary.
    export       Export the Calico datastore objects for migration
    import       Import the Calico datastore objects for migration
    datastore    Calico datastore management.
  • calicoctl 命令使用
- calicoctl 默认会读取 ~/.kube/下文件加载认证信息,也可以通过配置文件指定认证信息位置

[root@k8s-master calico]# mkdir /etc/calico/^C
[root@k8s-master calico]# cd /etc/calico/
[root@k8s-master calico]# cat calicoctl.cfg 
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
  datastoreType: "kubernetes"
  kubeconfig: "/etc/kubernetes/admin.conf" #指定conf路径
[root@k8s-master calico]# 

[root@k8s-master calico]# kubectl get ippools
NAME                  AGE
default-ipv4-ippool   23h
[root@k8s-master calico]# calicoctl get ippool  #可以用calicoctl直接访问 calico资源
NAME                  CIDR             SELECTOR   
default-ipv4-ippool   192.168.0.0/16   all() 


[root@k8s-master calico]# calicoctl get ippool default-ipv4-ippool -o yaml
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  creationTimestamp: "2021-08-29T14:33:53Z"
  name: default-ipv4-ippool
  resourceVersion: "1305"
  uid: c01d73f3-c0c9-4674-b27e-725a1eaa5717
spec:
  blockSize: 24
  cidr: 192.168.0.0/16
  ipipMode: Always
  natOutgoing: true
  nodeSelector: all()
  vxlanMode: Never


[root@k8s-master calico]# calicoctl ipam --help  
Usage:
  calicoctl [options] [<args>...]

Options:
  -h --help                 Show this screen.
  -c --config=<config>      Path to the file containing connection
                            configuration in YAML or JSON format.
                            [default: /etc/calico/calicoctl.cfg]
  --context=<context>       The name of the kubeconfig context to use.
  -a
  -A --all-namespaces
     --as=<AS_NUM>
     --backend=(bird|gobgp|none)
     --dryrun
     --export
     --felix-config=<CONFIG>
  -f --filename=<FILENAME>
     --force
     --from-report=<REPORT>
     --ignore-validation
     --init-system
     --ip6-autodetection-method=<IP6_AUTODETECTION_METHOD>
     --ip6=<IP6>
     --ip-autodetection-method=<IP_AUTODETECTION_METHOD>
...

[root@k8s-master calico]# calicoctl ipam show
+----------+----------------+-----------+------------+--------------+
| GROUPING |      CIDR      | IPS TOTAL | IPS IN USE |   IPS FREE   |
+----------+----------------+-----------+------------+--------------+
| IP Pool  | 192.168.0.0/16 |     65536 | 9 (0%)     | 65527 (100%) |
+----------+----------------+-----------+------------+--------------+


[root@k8s-master calico]# calicoctl ipam show  --show-blocks  #每个地址段使用了多少个
+----------+------------------+-----------+------------+--------------+
| GROUPING |       CIDR       | IPS TOTAL | IPS IN USE |   IPS FREE   |
+----------+------------------+-----------+------------+--------------+
| IP Pool  | 192.168.0.0/16   |     65536 | 9 (0%)     | 65527 (100%) |
| Block    | 192.168.113.0/24 |       256 | 1 (0%)     | 255 (100%)   |
| Block    | 192.168.12.0/24  |       256 | 2 (1%)     | 254 (99%)    |
| Block    | 192.168.237.0/24 |       256 | 4 (2%)     | 252 (98%)    |
| Block    | 192.168.51.0/24  |       256 | 2 (1%)     | 254 (99%)    |
+----------+------------------+-----------+------------+--------------+

[root@k8s-master calico]# calicoctl ipam show  --show-config  #查看配置信息
+--------------------+-------+
|      PROPERTY      | VALUE |
+--------------------+-------+
| StrictAffinity     | false |
| AutoAllocateBlocks | true  |
| MaxBlocksPerHost   |     0 |
+--------------------+-------+
第2种方式 以kubectl插件方式运行
[root@k8s-master calico]# cp -p /usr/bin/calicoctl  /usr/bin/kubectl-calico  #把之前的文件改个名字就可以了

[root@k8s-master calico]# kubectl calico
Usage:
  kubectl-calico [options] <command> [<args>...]
Invalid option: ''. Use flag '--help' to read about a specific subcommand

[root@k8s-master calico]# kubectl calico get nodes  #和第1种方式相比加kubectl
NAME         
k8s-master   
k8s-node1    
k8s-node2    
k8s-node3    

[root@k8s-master calico]# kubectl calico ipam show
+----------+----------------+-----------+------------+--------------+
| GROUPING |      CIDR      | IPS TOTAL | IPS IN USE |   IPS FREE   |
+----------+----------------+-----------+------------+--------------+
| IP Pool  | 192.168.0.0/16 |     65536 | 9 (0%)     | 65527 (100%) |
+----------+----------------+-----------+------------+--------------+
示例2:修改BGP网络
#获取现有配置在此基础上修改

[root@k8s-master calico]# kubectl calico get ippool -o yaml > default-ipv4-ippool.yaml 

[root@k8s-master calico]# cat default-ipv4-ippool.yaml 
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: default-ipv4-ippool
spec:
  blockSize: 24
  cidr: 192.168.0.0/16
  ipipMode: CrossSubnet #跨节点子网时使用IPIP 没有跨子网使用BGP
  natOutgoing: true
  nodeSelector: all()
  vxlanMode: Never  #vxlanMode与ipipMode不能同时打开 必须有一个为Never
  
#通过ipipMode、vxlanMode不同选项可以使calico运行在纯GBP、ipip、vxlanMode或混合模式下
#如:ipipMode: Never vxlanMode: Never 为纯BGP模式  ipipMode: Never vxlanMode: CrossSubnet 为BGP+vxlan模式

[root@k8s-master calico]# calicoctl apply -f default-ipv4-ippool.yaml 
Successfully applied 1 'IPPool' resource(s)

#在来看路由信息 已经没有之前的tunl0 直接从节点网络出去
[root@k8s-master calico]# ip route list
default via 192.168.54.2 dev eth4 proto static metric 101 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
192.168.4.0/24 dev eth0 proto kernel scope link src 192.168.4.170 metric 100 
192.168.12.0/24 via 192.168.4.172 dev eth0 proto bird 
192.168.51.0/24 via 192.168.4.173 dev eth0 proto bird     #已经没有之前的tunl0隧道
192.168.54.0/24 dev eth4 proto kernel scope link src 192.168.54.170 metric 101 
192.168.113.0/24 via 192.168.4.171 dev eth0 proto bird 
blackhole 192.168.237.0/24 proto bird 
192.168.237.1 dev cali7c0fb624285 scope link 
192.168.237.2 dev caliedaf285d4ef scope link 
192.168.237.3 dev cali854da94d42a scope link 
[root@k8s-master calico]# 

抓包测试

[root@k8s-master ~]# kubectl get pod -o wide
NAME                              READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
deployment-demo-fb544c5d8-r7pc8   1/1     Running   0          10h   192.168.51.1   k8s-node3   <none>           <none>
deployment-demo-fb544c5d8-splfr   1/1     Running   0          10h   192.168.12.1   k8s-node2   <none>           <none>

#从节点3访问节点3 
[root@k8s-master calico]# kubectl exec deployment-demo-fb544c5d8-r7pc8 -it -- /bin/sh
[root@deployment-demo-fb544c5d8-r7pc8 /]# curl 192.168.12.1
iKubernetes demoapp v1.0 !! ClientIP: 192.168.51.1, ServerName: deployment-demo-fb544c5d8-splfr, ServerIP: 192.168.12.1!
[root@deployment-demo-fb544c5d8-r7pc8 /]# curl 192.168.12.1
iKubernetes demoapp v1.0 !! ClientIP: 192.168.51.1, ServerName: deployment-demo-fb544c5d8-splfr, ServerIP: 192.168.12.1!

#直接抓Pod IP的包 因为没有封装 所以是Pod IP直接通信 没有外层IP

[root@k8s-node2 ~]# tcpdump -i eth0 -nn ip host 192.168.51.1  and host 192.168.12.1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
22:11:54.704770 IP 192.168.51.1.33464 > 192.168.12.1.80: Flags [S], seq 4075444778, win 64800, options [mss 1440,sackOK,TS val 2045898534 ecr 0,nop,wscale 7], length 0
22:11:54.705866 IP 192.168.12.1.80 > 192.168.51.1.33464: Flags [S.], seq 402120893, ack 4075444779, win 64260, options [mss 1440,sackOK,TS val 1090640722 ecr 2045898534,nop,wscale 7], length 0
22:11:54.706670 IP 192.168.51.1.33464 > 192.168.12.1.80: Flags [.], ack 1, win 507, options [nop,nop,TS val 2045898537 ecr 1090640722], length 0
22:11:54.707077 IP 192.168.51.1.33464 > 192.168.12.1.80: Flags [P.], seq 1:77, ack 1, win 507, options [nop,nop,TS val 2045898537 ecr 1090640722], length 76: HTTP: GET / HTTP/1.1
22:11:54.707132 IP 192.168.12.1.80 > 192.168.51.1.33464: Flags [.], ack 77, win 502, options [nop,nop,TS val 1090640723 ecr 2045898537], length 0
22:11:54.737231 IP 192.168.12.1.80 > 192.168.51.1.33464: Flags [P.], seq 1:18, ack 77, win 502, options [nop,nop,TS val 1090640754 ecr 2045898537], length 17: HTTP: HTTP/1.0 200 OK
22:11:54.738439 IP 192.168.51.1.33464 > 192.168.12.1.80: Flags [.], ack 18, win 507, options [nop,nop,TS val 2045898568 ecr 1090640754], length 0
22:11:54.739117 IP 192.168.12.1.80 > 192.168.51.1.33464: Flags [P.], seq 18:155, ack 77, win 502, options [nop,nop,TS val 1090640755 ecr 2045898568], length 137: HTTP
22:11:54.739630 IP 192.168.12.1.80 > 192.168.51.1.33464: Flags [FP.], seq 155:276, ack 77, win 502, options [nop,nop,TS val 1090640756 ecr 2045898568], length 121: HTTP
22:11:54.739810 IP 192.168.51.1.33464 > 192.168.12.1.80: Flags [.], ack 155, win 506, options [nop,nop,TS val 2045898570 ecr 1090640755], length 0


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

IPv4 BGP status  #可以看到已经BGP模式了 这里看到是除去自己其它的3个节点
+---------------+-------------------+-------+----------+-------------+
| PEER ADDRESS  |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+---------------+-------------------+-------+----------+-------------+
| 192.168.4.171 | node-to-node mesh | up    | 02:27:59 | Established |
| 192.168.4.172 | node-to-node mesh | up    | 02:27:58 | Established |
| 192.168.4.173 | node-to-node mesh | up    | 02:27:58 | Established |
+---------------+-------------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.
  • 到目前为止 如果是小规模的集群 比如50台以下 就可以直接使用了
  • 如果是大规模集群 部署reflector路由反射器,避免过多的路由表更新 减轻AIP-SERVER压力
#把maseter配置成reflector节点

[root@k8s-master calico]# cat reflector-node.yaml 
apiVersion: projectcalico.org/v3
kind: Node
metadata:
  labels:
    route-reflector: true
  name: k8s-master   #节点名
spec:
  bgp:
    ipv4Address: 192.168.4.170/24  #Master IP
    ipv4IPIPTunnelAddr: 192.168.237.0  #tunl0网络地址
    routeReflectorClusterID: 1.1.1.1  #ID信息 如果有多个node 不能和其它重复就行


[root@k8s-master calico]# calicoctl apply -f reflector-node.yaml 
Successfully applied 1 'Node' resource(s)
  • 配置所有节点与reflector节点通信
[root@k8s-master calico]# cat bgppeer-demo.yaml
kind: BGPPeer
apiVersion: projectcalico.org/v3
metadata:
  name: bgppeer-demo
spec:
  nodeSelector: all()   #所有节点
  peerSelector: route-reflector=="true" #与有这个标签的节点通信
  
[root@k8s-master calico]# calicoctl apply -f bgppeer-demo.yaml 
Successfully applied 1 'BGPPeer' resource(s)
[root@k8s-master calico]# calicoctl node status
Calico process is running.

IPv4 BGP status
+---------------+-------------------+-------+----------+-------------+
| PEER ADDRESS  |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+---------------+-------------------+-------+----------+-------------+
| 192.168.4.171 | node-to-node mesh | up    | 02:27:59 | Established |#之前的mesh工作模式还在
| 192.168.4.172 | node-to-node mesh | up    | 02:27:58 | Established |
| 192.168.4.173 | node-to-node mesh | up    | 02:27:58 | Established |
| 192.168.4.171 | node specific     | start | 14:36:40 | Idle        |#基于reflector工作模式
| 192.168.4.172 | node specific     | start | 14:36:40 | Idle        |
| 192.168.4.173 | node specific     | start | 14:36:40 | Idle        |
+---------------+-------------------+-------+----------+-------------+

IPv6 BGP status

#关掉mesh 点对点的工作模式

[root@k8s-master calico]# cat  default-bgpconfiguration.yaml 
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  logSeverityScreen: Info
  nodeToNodeMeshEnabled: false  #是赤允许点对点通信
  asNumber : 63400

[root@k8s-master calico]# calicoctl apply -f default-bgpconfiguration.yaml 
Successfully applied 1 'BGPConfiguration' resource(s)
[root@k8s-master calico]# calicoctl node status
Calico process is running.

IPv4 BGP status
+---------------+---------------+-------+----------+-------------+
| PEER ADDRESS  |   PEER TYPE   | STATE |  SINCE   |    INFO     |
+---------------+---------------+-------+----------+-------------+
| 192.168.4.171 | node specific | up    | 14:45:26 | Established |
| 192.168.4.172 | node specific | up    | 14:45:26 | Established |
| 192.168.4.173 | node specific | up    | 14:45:26 | Established |
+---------------+---------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

概述

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 模式。

img

calico 切换 BGP 模式

img

部署完成后默认使用 calico-ipip 的模式,通过在节点的路由即可得知,通往其他节点路由通过 tunl0 网卡出去

img

修改为 BGP 网络模式,在 system 项目中修改 calico-node daemonset

img

img

修改CALICO_IPV4POOL_IPIP改为 off,添加新环境变量FELIX_IPINIPENABLED为 false

img

修改完成后对节点进行重启,等待恢复后查看主机路由,与 ipip 最大区别在于去往其他节点的路由,由 Tunnel0 走向网络网卡。

img

calico 切换 cross-subnet 模式

Calico-ipip 模式和 calico-bgp 模式都有对应的局限性,对于一些主机跨子网而又无法使网络设备使用 BGP 的场景可以使用 cross-subnet 模式,实现同子网机器使用 calico-BGP 模式,跨子网机器使用 calico-ipip 模式。

部署集群网络选择 calico 网络插件

img

默认部署出来是 calico 的 ip-in-ip 的模式 查看宿主机网卡,会发现多了个 tunl0 网卡,这个是建立 ip 隧道的网卡

img

去其他主机的路由都是走 tunl0 网卡出去

img

切换到 cross-subnet 模式

kubectleditipPool/default-ipv4-ippool

将 ipipMode 改为 crossSubnet

img

在 UI 将 calico-node 的 POD 删了重建

img

重启检查 calico 网络

img

可以看见同子网的主机出口走的是 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-Lhttps://github.com/projectcalico/calicoctl/releases/download/v3.13.3/calicoctl

配置可执行权限

chmod+xcalicoctl

复制的/usr/bin/目录

cpcalicoctl/usr/bin/

配置 calicoctl 连接 Kubernetes 集群

exportCALICO_DATASTORE_TYPE=kubernetes exportCALICO_KUBECONFIG=~/.kube/config calicoctlnodestatus

img

calico node-to-node mesh

默认情况下 calico 采用 node-to-node mesh 方式 ,为了防止 BGP 路由环路,BGP 协议规定在一个 AS(自治系统)内部,IBGP 路由器之间只能传一跳路由信息,所以在一个 AS 内部,IBGP 路由器之间为了学习路由信息需要建立全互联的对等体关系,但是当一个 AS 规模很大的时候,这种全互联的对等体关系维护会大量消耗网络和 CPU 资源,所以这种情况下就需要建立路由反射器以减少 IBGP 路由器之间的对等体关系数量。

img

Route reflector 角色介绍

早期 calico 版本提供专门的 route reflector 镜像,在新版本 calico node 内置集成 route reflector 功能。Route reflector 可以是以下角色:

  • 集群内部的 node 节点
  • 集群外部节点运行 calico node
  • 其他支持 route reflector 的软件或者设备。

这里以一个集群内部的 node 节点为例:

关闭 node-to-node mesh

cat<<EOF|calicoctlapply-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 配置成一样

calicoctlpatchnoderke-node4-p'{"spec":{"bgp":{"routeReflectorClusterID":"244.0.0.1"}}}'

给节点打上对应的 label 标记该节点以表明它是 Route Reflector,从而允许 BGPPeer 资源选择它。

kubectllabelnoderke-node4route-reflector=true

创建 BGPPeer

exportCALICO_DATASTORE_TYPE=kubernetes exportCALICO_KUBECONFIG=~/.kube/config cat<<EOF|calicoctlapply-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

img

Route Reflector 上节点查看,节点已正常建立连接

img

设置 veth 网卡 mtu

通常,通过使用最高 MTU 值(不会在路径上引起碎片或丢包)来实现最高性能。对于给定的流量速率,最大带宽增加,CPU 消耗可能下降。对于一些支持 jumbo frames 的网络设备,可以配置 calico 支持使用。

下表列举了,常见几种 MTU 配置下 calico 对应的网卡 mtu 的配置

img

IPIP 和 VXLAN 协议中的 IP 中使用的额外报文头,通过头的大小减小了最小 MTU。(IP 中的 IP 使用 20 字节的标头,而 VXLAN 使用 50 字节的标头)。

如果在 Pod 网络中的任何地方使用 VXLAN,请将 MTU 大小配置为“物理网络 MTU 大小减去 50”。如果仅在 IP 中使用 IP,则将 MTU 大小配置为“物理网络 MTU 大小减去 20” 。

将工作负载端点 MTU 和隧道 MTU 设置为相同的值

配置方法:

升级集群

img

配置网卡 MTU,此时通过 system 项目下 calico-config 文件可以看见对应的 mtu 设置

img

创建 workload 查看 POD 网卡 MTU 为 9001

img

设置全局 AS 号

默认情况下,除非已为节点指定每个节点的 AS,否则所有 Calico 节点都使用 64512 自治系统。可以通过修改默认的 BGPConfiguration 资源来更改所有节点的全局默认值。以下示例命令将全局默认 AS 编号设置为 64513。

cat<<EOF|calicoctlapply-f- apiVersion:projectcalico.org/v3 kind:BGPConfiguration metadata: name:default spec: logSeverityScreen:Info nodeToNodeMeshEnabled:false asNumber:64513 EOF

设置单个主机和 AS 号

例如,以下命令将名为 node-1 的节点更改为属于 AS 64514。

calicoctlpatchnodenode-1-p'{"spec":{"bgp":{“asNumber”:“64514”}}}'

修改节点地址范围

此操作建议在部署完集群后立刻进行。

默认情况下 calico 在集群层面分配一个 10.42.0.0/16 的 CIDR 网段,在这基础上在单独为每个主机划分一个单独子网采用 26 位子网掩码对应的集群支持的节点数为 2^10=1024 节点,单个子网最大支持 64 个 POD,当单个子网对应 IP 消耗后,calico 会重新在本机上划分一个新的子网如下,在集群对端主机可以看见对应的多个 CIDR 路由信息。

img

注意:块大小将影响节点 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 号

创建新的

calicoctlapply-fpool.yaml

将旧的 ippool 禁用

calicoctlpatchippooldefault-ipv4-ippool-p'{"spec":{"disabled":“true”}}'

创建 workload 测试

根据节点标签定义对应的 ippool

Calico 能够进行配置,为不同拓扑指定 IP 地址池。例如可能希望某些机架、地区、或者区域能够从同一个 IP 池中获取地址。这对于降低路由数量或者配合防火墙策略的要求会很有帮助。

给节点配置对应 label

kubectllabelnodeskube-node-0rack=0 kubectllabelnodeskube-node-1rack=1

通过标签定义对应的节点 IPpool

calicoctlcreate-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 calicoctlcreate-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

kubectleditippool/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#tellsdeploymenttorun1podsmatchingthetemplate 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 的方式

catippool1.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#tellsdeploymenttorun1podsmatchingthetemplate template: metadata: labels: app:nginx annotations: "cni.projectcalico.org/ipv4pools":"[\"pool-1\"]" spec: containers: -name:nginx image:nginx:1.7.9 ports: -containerPort:80
/lib/modules
/var/run/calico
/var/lib/calico
/run/xtables.lock
/opt/cni/bin
/etc/cni/net.d
/var/log/calico/cni
/var/lib/cni/networks
/var/run/nodeagent
/usr/libexec/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds


rm -rf /var/lib/cni
rm -rf /etc/cni/net.d

rm /var/lib/cni/ -rf && rm -f /etc/cni/net.d/*
systemctl restart  docker containerd kubelet