
一、Calico 是什么
calico 是容器網絡的一種解決方案,也是當前最流行的方案之一。和其他虛擬網絡最大的不同是,它沒有采用 overlay 網絡做報文的轉發(fā),提供了純 3 層的網絡模型。三層通信模型表示每個容器都通過 IP 直接通信,中間通過路由轉發(fā)找到對方。在這個過程中,容器所在的節(jié)點類似于傳統的路由器,提供了路由查找的功能。
要想路由工作能夠正常,每個虛擬路由器(容器所在的主機節(jié)點)必須有某種方法知道整個集群的路由信息,calico 采用的是BGP 路由協議,全稱是 Border Gateway Protocol。
除了能用于 docker 這樣的容器外,它還能集成到容器集群平臺 OpenShift/kubernetes、公有云平臺 AWS、GCE 等, 而且也能很容易地集成到 openstack 等 Iaas 平臺。
二、Calico網絡方式
2.1 IPIP模式
從字面來理解,就是把一個IP數據包又套在一個IP包里,即把 IP 層封裝到 IP 層的一個 tunnel,看起來似乎是浪費,實則不然。它的作用其實基本上就相當于一個基于IP層的網橋!一般來說,普通的網橋是基于mac層的,根本不需 IP,而這個 ipip 則是通過兩端的路由做一個 tunnel,把兩個本來不通的網絡通過點對點連接起來。ipip 的源代碼在內核 net/ipv4/ipip.c 中可以找到。
2.2 BGP模式
邊界網關協議(Border Gateway Protocol, BGP)是互聯網上一個核心的去中心化自治路由協議。它通過維護IP路由表或‘前綴’表來實現自治系統(AS)之間的可達性,屬于矢量路由協議。BGP不使用傳統的內部網關協議(IGP)的指標,而使用基于路徑、網絡策略或規(guī)則集來決定路由。因此,它更適合被稱為矢量性協議,而不是路由協議。BGP,通俗的講就是講接入到機房的多條線路(如電信、聯通、移動等)融合為一體,實現多線單IP,BGP 機房的優(yōu)點:服務器只需要設置一個IP地址,最佳訪問路由是由網絡上的骨干路由器根據路由跳數與其它技術指標來確定的,不會占用服務器的任何系統。
根據路由規(guī)則的同步方式,BGP模式也有兩種方式,mesh模式與RR模式。
2.2.1 mesh 模式
mesh 模式又稱為全互聯模式,就是一個 BGP Speaker 需要與其它所有的 BGP Speaker 建立 bgp 連接(形成一個bgp mesh)。BGP Speaker越多,將會消耗越多的連接。所以它只能支持小規(guī)模集群,一般50-100為上限。
2.2.2 RR模式
RR模式,就是在網絡中指定一個或多個 BGP Speaker 作為反射路由(Router Reflector),RR與所有的 BGP Speaker 建立 bgp 連接。每個BGP Speaker只與RR建立連接,交換路由信息就能獲得全網的路由信息。Calico 中通過Global Peer來實現RR模式。
默認情況下,每個 calico 節(jié)點會和集群中其他所有節(jié)點建立 BGP peer 連接,也就是說這是一個 O(n^2) 的增長趨勢。在集群規(guī)模比較小的情況下,這種模式是可以接受的,但是當集群規(guī)模擴展到百個節(jié)點、甚至更多的時候,這樣的連接數無疑會帶來很大的負擔。為了解決集群規(guī)模較大情況下 BGP client 連接數膨脹的問題,calico 引入了 RR(Router Reflector) 的功能。
RR 的基本思想是選擇一部分節(jié)點(一個或者多個)作為 Global BGP Peer,它們和所有的其他節(jié)點互聯來交換路由信息,其他的節(jié)點只需要和 Global BGP Peer 相連就行,不需要之間再兩兩連接。更多的組網模式也是支持的,不管怎么組網,最核心的思想就是所有的節(jié)點能獲取到整個集群的路由信息。
三、Calico組件和架構
calico 的工作有:
- 分配和管理 IP
- 配置上容器的 veth pair 和容器內默認路由
- 根據集群網絡情況實時更新節(jié)點上路由表
完成以上所有的功能,除了 etcd 保存了數據外,還在每個節(jié)點運行 了calico-node 容器。calico/node 這個容器運行了多個組件:
- libnetwork plugin
- BIRD
- confd
- felix
下圖為Calico各組件之間的相互關系圖。

3.1 libnetwork plugin
libnetwork-plugin 是 calico 提供的 docker 網絡插件,主要提供的是 IP 管理和網絡管理的功能。
默認情況下,當網絡中出現第一個容器時,calico 會為容器所在的節(jié)點分配一段子網(子網掩碼為 /26,比如192.168.196.128/26),后續(xù)出現在該節(jié)點上的容器都從這個子網中分配 IP 地址。這樣做的好處是能夠縮減節(jié)點上的路由表的規(guī)模,按照這種方式節(jié)點上 2^6 = 64 個 IP 地址只需要一個路由表項就行,而不是為每個 IP 單獨創(chuàng)建一個路由表項。節(jié)點上創(chuàng)建的子網段可以在etcd 中 /calico/ipam/v2/host/<node_name>/ipv4/block/ 看到。
calico 還允許創(chuàng)建容器的時候指定 IP 地址,如果用戶指定的 IP 地址不在節(jié)點分配的子網段中,calico 會專門為該地址添加一個 /32 的網段。
3.2 BIRD
BIRD(BIRD Internet Routing Daemon) 是一個常用的網絡路由軟件,支持很多路由協議(BGP、RIP、OSPF等)。它會在每臺宿主機上運行,calico 用它在實現主機間傳播路由信息。
BIRD 對應的配置文件在 /etc/calico/confd/config/ 目錄。
3.3 confd
confd是一個簡單的配置管理工具。bird 的配置文件會根據用戶設置的變化而變化,因此需要一種動態(tài)的機制來實時維護配置文件并通知 bird 使用最新的配置,這就是 confd 的工作。它會監(jiān)聽 etcd 的數據,用來更新 bird 的配置文件,并重新啟動 bird 進程讓它加載最新的配置文件。confd 的工作目錄是 /etc/calico/confd,里面有三個目錄:
- conf.d:confd 需要讀取的配置文件,每個配置文件告訴 confd 模板文件在什么,最終生成的文件應該放在什么地方,更新時要執(zhí)行哪些操作等
- config:生成的配置文件最終放的目錄
- templates:模板文件,里面包括了很多變量占位符,最終會替換成 etcd 中具體的數據
具體的配置文件很多,以下是一個例子:
/ # cat /etc/calico/confd/conf.d/bird.toml
[template]
src = "bird.cfg.mesh.template"
dest = "/etc/calico/confd/config/bird.cfg"
prefix = "/calico/bgp/v1"
keys = ["/host","/global"]
check_cmd = "bird -p -c {{.src}}"
reload_cmd = "pkill -HUP bird || true"
它會監(jiān)聽 etcd 的 /calico/bgp/v1 路徑,一旦發(fā)現更新,就用其中的內容更新模板文件 bird.cfg.mesh.template,把新生成的文件放在 /etc/calico/confd/config/bird.cfg,文件改變之后還會運行 reload_cmd 指定的命令重啟 bird 程序。
3.4 felix
felix 負責最終網絡相關的配置,也就是容器網絡在 linux 上的配置工作,比如:
- 更新節(jié)點上的路由表項
- 更新節(jié)點上的 iptables 表項
它的主要工作是從 etcd 中讀取網絡的配置,然后根據配置更新節(jié)點的路由和 iptables,felix 的代碼在 http://github.com/calico/felix。
四、部署Calico BGP RR模式
4.1 安裝Calico BGP網絡插件
在之前的文章中已經分享過Calico BGP網絡插件的部署過程。Openshift開啟Calico BGP 與 OVS性能PK
安裝完成后,Calico BGP默認使用的是Mesh模式。
4.2 開啟RR模式
4.2.1 開啟單RR部署(單個主機節(jié)點作為RR)
- 關閉當前Calico Mesh模式
[root@master calico]# cat << EOF | calicoctl create -f -
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
name: default
spec:
logSeverityScreen: Info
nodeToNodeMeshEnabled: false
asNumber: 63400
- 設置指定Node為RR,比如選擇infra01_node為RR,“添加router-reflector標簽,設置routeReflectorClusterID”。
[root@master calico]# calicoctl get node infra01_node --export -o yaml > infra01_node.yaml
[root@master calico]# cat infra01_node.yaml
apiVersion: projectcalico.org/v3
kind: Node
metadata:
labels:
i-am-a-route-reflector: "true"
name: infra01_node
spec:
bgp:
ipv4Address: 192.168.0.3/16
routeReflectorClusterID: 224.0.0.1
[root@master calico]# calico apply -f infra01_node.yaml
- 配置BGPPeer資源,告訴Node節(jié)點路由反射器。
[root@master calico]# cat << EOF | calicoctl create -f -
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
name: peer-to-rrs
spec:
nodeSelector: !has(i-am-a-route-reflector)
peerSelector: has(i-am-a-route-reflector)
- 查看bgppeer
[root@master1 calico]# calicoctl get bgppeers
NAME PEERIP NODE ASN
peer-to-rrs (global) 0
- 通過netstat命令查看節(jié)點間calico-node的連接
[root@master1 calico]# netstat -natp | grep bird
可以看到非RR節(jié)點只與RR節(jié)點建立連接,而RR節(jié)點與所有節(jié)點建立連接。
4.2.2 多RR節(jié)點部署(多個主機節(jié)點作為RR)
當只有一個RR節(jié)點時,會有一定的風險。當該節(jié)點出現異常時,所有節(jié)點將無法獲取路由,這將會影響到整個OpenShift集群的網絡。所以需要考慮RR節(jié)點的高可用,一種最簡單的方式就是設置多個RR節(jié)點。下面演示如何添加一個新RR節(jié)點。
- 參考4.2.1,選擇infra02_node作為新的RR節(jié)點。與infra01_node設置同樣的routeReflectorClusterID值。
- 額外添加一條新的BGPPeer資源
[root@master calico]# cat << EOF | calicoctl create -f -
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
name: rr-mesh
spec:
nodeSelector: has(i-am-a-route-reflector)
peerSelector: has(i-am-a-route-reflector)
- 查看bgppeer
[root@master1 calico]# calicoctl get bgppeers
NAME PEERIP NODE ASN
peer-to-rrs (global) 0
rr-mesh has(i-am-a-route-reflector) 0
以上配置后,每個非RR節(jié)點會與所有RR節(jié)點建立連接,同時RR節(jié)點之間建立連接,RR節(jié)點間是一個雙活的配置。
4.2.3 硬件設備RR節(jié)點部署(硬件交換機作為RR節(jié)點)
前提:硬件交換機支持BGP協議。
- 查看硬件交換機對應vlan IP。
/ Display current-configuration interface vlan 16
interface Vlanif16
ip address 192.168.16.251 255.255.255.0
vrrp vrid 84 virtual-ip 192.168.16.253
vrrp vrid 84 priority 150
vrrp vrid 84 preempt-mode timer delay 20
vrrp vrid 84 track interface XGigabitEthernet0/0/1 reduced 30
vrrp vrid 84 track interface XGigabitEthernet0/0/2 reduced 30
- 在OpenShift集群關閉Calico mesh模式,并設置ASNumber。
[root@master calico]# cat << EOF | calicoctl create -f -
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
name: default
spec:
logSeverityScreen: Info
nodeToNodeMeshEnabled: false
asNumber: 63400
- 在OpenShift集群創(chuàng)建與硬件交換機的BGPPeer配置。
[root@master calico]# cat << EOF | calicoctl create -f -
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
name: bgppeer-global
spec:
peerIP: 192.168.16.251
asNumber: 63400
- 硬件交換機和NODE 在AS號63400 中,通過IBGP建立了對等體
/ bgp 63400
router-id 192.168.16.11
peer 192.168.16.1 as-number 63400
peer 192.168.16.2 as-number 63400
peer 192.168.16.3 as-number 63400
- 硬件交換機的192.168.16.251 作為RR和NODE建立了BGP
/ ipv4-family unicast
undo synchronization
peer 192.168.16.1 enable
peer 192.168.16.1 reflect-client
peer 192.168.16.2 enable
peer 192.168.16.2 reflect-client
peer 192.168.16.3 enable
peer 192.168.16.3 reflect-client
- 在硬件交換機上查看bgp peer信息
/ display bgp peer
BGP local router ID : 192.168.16.11
Local AS number : 63400
Total number of peers : 3 Peers in established state : 3
Peer V AS MsgRcvd MsgSent OutQ Up/Down State PrefRcv
192.168.16.1 4 63400 26 29 0 00:19:34 Established 1
192.168.16.2 4 63400 26 29 0 00:19:34 Established 1
192.168.16.3 4 63400 22 22 0 00:16:27 Established 1
BGP狀態(tài)為established 表示已建立狀態(tài)。
- 在硬件交換機上查看路由信息
/ display bgp routing-table
BGP Local router ID is 192.168.16.11
Total Number of Routes: 3
Network NextHop MED LocPrf PrefVal Path/Ogn
*>i 10.200.0.0/24 192.168.16.3 100 0 i
*>i 10.200.1.0/24 192.168.16.2 100 0 i
*>i 10.200.2.0/24 192.168.16.1 100 0 i
并能通過NODE學到POD的地址段,從192.168.16.1學到10.200.2.0/24的路由,192.168.16.2學到10.200.1.0/24的路由,192.168.16.3學到10.200.0.0/24的路由。
五、Calico BGP管理工具calicoctl
管理calico網絡需要使用calicoctl工具,該工具的配置可參考OpenShift/Kubernetes集群 Calico BGP管理工具calicoctl配置
- 查看calico節(jié)點狀態(tài)
$ calicoctl node status
- 查看ip池
$ calicoctl get ipPool
- 查看node信息
$ calicoctl get node -o wide
$ calicoctl get node infra01_node -o yaml
- 創(chuàng)建新的資源
$ calicoctl create -f resource.yaml
補充
OpenShift Calico BGP網絡模式下默認使用的是etcd存儲,同時訪問etcd的證書保存secret calico-etcd-secrets中。
$ oc get secret | grep calico-etcd-secrets
calico-etcd-secrets Opaque 3 205d
如果calico的存儲etcd使用的正是OpenShift集群的etcd集群,那么當etcd的證書有更新時,請務必更新calico證書的內容,也就是更新該secret的內容,否則集群網絡將無法為新的POD分配網絡。
$ oc project kube-system
$ oc create secret generic calico-etcd-secrets \
--from-file=etcd-ca=/etc/etcd/ca.crt \
--from-file=etcd-cert=/etc/etcd/server.crt \
--from-file=etcd-key=/etc/etcd/server.key -o yaml \
--dry-run | oc apply -f -
參考文章
calico官方部署文檔
calico官方配置案例
Calico官方架構文檔
docker 容器網絡方案:calico 網絡模型
在私有云上運行Calico:IP互連網絡結構
k8s使用calico網絡
calico網絡原理、組網方式和使用
Calico配置雙RR架構