Kubernetes 多租戶隔離利器 Calico
快,關注這個公眾號,一起漲知識
本文 介紹了一個數據中心網路方案Calico,包括其優勢、架構、效能分析、工作原理,以及分析了生態雲Kubernetes版應用引擎在Calico中的policy設定策略。
背景
小米生態雲旨在為小米生態鏈企業及合作伙伴提供雲端計算、大資料、人工智慧、安全及合規等一站式雲服務和整體解決方案。生態雲上有一款基於Kubernetes研發的新版應用引擎已經為幾十家企業提供服務,每家企業的資料保護最為重要,為此我們探討了諸多方案的可行性,最終使用Calico網路方案。
Calico簡介
Calico是純3層的資料中心網路方案,它是目前Kubernetes networkpolicy概念的最佳實現方案之一,利用虛擬路由代理虛擬交換,每一臺虛擬路由通過BGP協議傳播可達資訊(路由)到剩餘資料中心。
Calico優勢
1. 支援Kubernetes networkpolicy概念
2. 容器間網路三層隔離,無需要擔心arp風暴
3. 自由控制的policy規則
4. 網路拓撲直觀易懂,擴充套件性強
5. 通過iptables和kernel包轉發,效率高,損耗低
Calico架構圖
Calico包括如下重要元件:Felix,Etcd,BGP Client,BGP Route Reflector。Felix 、BGPClient 部署在node節點,BGPRouteReflector部署在Master,下面分別說明一下這些元件。
Felix: 主要負責路由配置以及ACLS規則的配置以及下發,它存在在每個node節點上。
Etcd: 分散式鍵值儲存,主要負責網路元資料一致性,確保Calico網路狀態的準確性,一般與Kubernetes共用。
BGP Client(BIRD): 負責把Felix在各node上設定的路由資訊廣播到Calico網路( 通過BGP協議)。
BGP Route Reflector: 集中式的路由分發。
Calico原理
如下圖所示:原網路通過路由表和iptables,再經過資料中心路由,最終到達目地網路路由,最後分配到目地容器。
Kubernetes版應用引擎的設定策略
因為企業使用者會在Kubernetes版應用引擎中建立多個namespace,故不能使用基於namespace的policy策略,我們使用label的方式進行policy的自定義。
以A公司為例子:
實驗環境所用的3個namespace是:ami-a、ami-b、bmi三個
1. 新建namespace並打標籤org=ami、org=bmi
kubectl create -f - <<EOF apiVersion: v1 kind: Namespace metadata: name: ami-a labels: org: org-ami #為namespace ami-a打org=ami EOF kubectl create -f - <<EOF apiVersion: v1 kind: Namespace metadata: name: ami-b labels: org: org-ami #為namespace ami-b 打org=ami EOF kubectl create -f - <<EOF apiVersion: v1 kind: Namespace metadata: name: bmi labels: org: org-bmi #為namespace bmi 打org=bmi EOF
2.Calico預設策略是相同子網的pod互相訪問是通的,不管namespace是否相同。
為此我們需要先建一個全域性策略來禁業pod IP訪問。然後再單獨為ami和bmi建立policy。
(1)全域性禁業策略如下:
kubectl create -f - <<EOF - apiVersion: v1 kind: policy metadata: name: cluster-policy.deny-private-egress spec: egress: - action: deny destination: nets: - 192.168.0.0/16 #禁止192.168.0.0/16 段訪問source: {} - action: deny destination: nets: - 172.16.0.0/12 #禁止172.16.0.0/12 段訪問source: {} order: 900selector: has(calico/k8s_ns) && calico/k8s_ns != 'kube-system' && calico/k8s_ns != 'app-engine' && calico/k8s_ns != 'healthspace' EOF
(2)單獨為ami和bmi建立策略如下:
calicoctl create -f - <<EOF - apiVersion: v1 kind: policy metadata: name: ami.allow-access-from-same-rog spec: egress: - action: allow destination: selector: k8s_ns/label/org == 'org-ami' #允許label org=ami的出口互相訪問source: selector: k8s_ns/label/org == 'org-ami'ingress: - action: allow destination: {} source: selector: k8s_ns/label/org == 'org-ami' #允許label org=ami的入口互相訪問order: 800selector: k8s_ns/label/org == 'org-ami' EOF calicoctl create -f - <<EOF - apiVersion: v1 kind: policy metadata: name: bmi.allow-access-from-same-rog spec: egress: - action: allow destination: selector: k8s_ns/label/org == 'org-bmi' #允許label org=bmi的出口互相訪問source: selector: k8s_ns/label/org == 'org-bmi'ingress: - action: allow destination: {} source: selector: k8s_ns/label/org == 'org-bmi' #允許label org=bmi的入口互相訪問order: 800selector: k8s_ns/label/org == 'org-bmi' EOF
order越小代表執行策略越靠前,Calico執行的是聚合策略。
通過這樣的配置 即使namespace不同,但只要label相同,網路就會互通,我們為每家企業提供不同的label,這樣就達到我們目地。
3.讓我們來驗證一下
(1)我們新建了三個namespace別分是:
ami-a label org-ami
ami-b label org-ami
bmi label org-bmi
兩個ami label相同,bmi單獨一個label。
建立完成後,使用命令kubectl get namespace ns -o yaml 分別看下建立後的namespace label。
(2)分別在每個namespace中建一個container ,使用kubectl create -f .建立三個container。
建立完成的pod IP如下:
(3)PING測試
登陸ami-a的nginx pod 去PING ami-b的pod IP看是否通:
結果是通的。
登陸ami-b的nginx pod 去PING ami-a的pod IP看是否通:
結果也是通的。
登陸 ami-a中nginx pod 去PING bmi的pod IP是否相通:
結果顯示不通。
以上結果驗證了我們使用Calico做的policy策略得以生效,並滿足我們的需求。
Calico效能
Calico是基於Golang開發,CNI網路模型,併發效能好,且policy也是基於iptables,建立各種ACLS,iptables又是基於核心轉發,再加上不像flannel有對包進行加解密的操作,節省了CPU的資源。
經過網上測試和內部測試,結論:效能僅次於物理連線。
1. 網上各網路元件測試結果:
2. 內部Calico和flannel 對比測試:
總結
Calico之所以能大規模應用,主要是其良好的效能,並且policy的配置足夠靈活,可以滿足大部分公有云廠商的需求。Calico不光可以應用於Kubernetes,還可以應用於像openstack、VM等其他雲管理平臺。
唯一的不足就是當node過多(幾萬臺級),維護的路由表就會過大,全表掃描會有效能問題(目前生態雲還未有),如果出現效能問題可以改成IPVS的方式。
更多policy配置檔案可以點選左下方 “ 閱讀原文 ” ,檢視官方文件。