本文將說明在安裝完Kubernetes Cluster之後,接下來必須要進行的CNI Plugin安裝建置方式,同時也透過這篇文章進行基本的CNI說明與比較。
首先我們要先知道什麼是CNI (Container Network Interface),CNI是CNCF的專案項目,包含了一些規範與相關的函式庫,專注在容器的網路連結,並在容器被刪除之後的資源分配,而Kubernetes會使用CNI來做為網路提供商與Kubernetes Pod網路之前的溝通窗口。
CNI的解決方案很多,各種CNI都有各自的特色與最佳應用場景,同時也是有各自的缺點,在規劃的時候記得針對要選用的CNI的相關內容要花點時間了解。但一座K8S並不是只能使用一個CNI,有時候因為環境的高度複雜還可以同時搭配多種CNI 聯合使用,只是對於維運來說難度就會大大提高。
本文選擇使用Calico來進行CNI的解決方案,原因是Calico基本上在性能、彈性有很多好評,並且除了提供主機與Pod之間的網路連接,還加入了網路安全與管理。此外Calico還可以與Istio整合,使用者可以透過規則的設定,描述Pod應該如何發送與接受流量來提高安全性與控制網路環境。
以下就是基本的部署Calico的流程:
※ 確認Firewall port requirements:
https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements#network-requirements
※ Method 1 : Operator based
#---------------------------------------------------------------
# Install the Tigera Calico operator
#---------------------------------------------------------------
[master01]# curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/tigera-operator.yaml -o tigera-operator.yaml
[master01]# kubectl create -f tigera-operator.yaml
#---------------------------------------------------------------
# Configuring custom resource
#---------------------------------------------------------------
[master01]# curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml -o custom-resources.yaml
[master01]# vim custom-resources.yaml
=> change the default IP pool CIDR (if needed)
[master01]# kubectl create -f custom-resources.yaml
[master01]# kubectl get pods -n calico-system
※ Method 2 : Manifest based
#------------------------------------------------------
# S1. 使用manifest安裝 (master01)
#------------------------------------------------------
[master]# wget https://docs.projectcalico.org/manifests/calico.yaml
[master]# vim calico.yaml (確認podnetwork)
# no effect. This should fall within `--cluster-cidr`.
- name: CALICO_IPV4POOL_CIDR
value: "192.168.0.0/16"
[master]# kubectl create -f calico.yaml
[master]# watch kubectl get pods -n kube-systems
以下是安裝時,碰到的問題與分析解決方式:
※ 問題 : calico-node pod not ready
※分析:
(1) 執行 “kubectl describe pod calico-node-ngznh -n kube-system” 出現:以下是安裝時,碰到的問題與分析解決方式:
kubelet (combined from similar events): Readiness probe failed: calico/node is not ready: BIRD is not ready: Error querying BIRD: unable to connect to BIRDv4 socket: dial unix /var/run/calico/bird.ctl: connect: connection refused
(2) 經搜尋文章發現可能是預設網卡的問題,透過以下方式確認:
[master]# kubectl get ds -A
[master]# kubectl get ds -n kube-system calico-node -oyaml | grep -i ip_auto -C 3
[master]# kubectl exec -ti <pod_name> -n calico-system -- bash
#/ cat /etc/calico/confd/config/bird.cfg
=> 確認router id是誰
=> 對應實體的interface
(Calico的BGP會使用實體網卡來做virtual router)
※解法:
(1) 確認節點的Firewall port是否有打開 (別懷疑,我真的找到沒開好的節點)
(2) 強迫指定網卡
[master]# kubectl delete -f calico.yaml
[master]# vim calico.yaml
>> search
- name: IP
value: "autodetect"
>> add
- name: IP_AUTODETECTION_METHOD
value: "interface=ens192" (多網卡用","分隔)
[master]# kubectl create -f calico.yaml
[master]# kubectl get pods -n kube-system
※ first-found會去找主機的第一張網卡,但預設是找"eth*",所以VM的網卡為ens就會失敗
※ 測試驗證
[master]# kubectl create -f nginx-quic.yaml
[master]# kubectl get deployment -o wide -n nginx-quic
[master]# kubectl get service -o wide -n nginx-quic
[master]# kubectl get pods -o wide -n nginx-quic
[master]# kubectl exec -it <pod> -- bash
# ping 192.168.50.66
64 bytes from 192.168.165.2: icmp_seq=1 ttl=62 time=0.652 ms
64 bytes from 192.168.165.2: icmp_seq=2 ttl=62 time=0.475 ms
64 bytes from 192.168.165.2: icmp_seq=3 ttl=62 time=0.465 ms
# curl 192.168.50.66:80
192.168.35.4:51610
[master]# curl worker02.test.example.poc:30088
[master]# curl worker03.test.example.poc:30088
[master]# curl worker01.test.example.poc:30088
Calico 也有自已的CLI 工具叫作Calicoctl,類似etcdctl,可以透過這個工具直接操作Calico的設定與相關功能。為什麼說與etcdctl類似呢,因為其原理也是透過讀寫Calico key/value datastore來進行檢視與操作。
calicoctl | Calico Documentation (tigera.io)
安裝方式也很簡單,下載Binary檔案即可。
[master]# wget https://github.com/projectcalico/calico/releases/download/v3.26.3/calicoctl-linux-amd64 -o calicoctl
[master]# chmod +x calicoctl ; cp calicoctl /usr/local/bin/
[master]# calicoctl version
Client Version: v3.26.3
Git commit: bdb7878af
Cluster Version: v3.26.1
Cluster Type: k8s,bgp,kubeadm,kdd
[master]# mkdir -p /data/calico
[master]# cd /data/calico ; vim calicoctl.cfg
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
datastoreType: 'kubernetes'
kubeconfig: '/etc/kubernetes/admin.conf'
接下來就是基本操作,其他操作方式可以到官網查尋:
(1) 確認節點狀態
[master]# calicoctl node status
(2) 取得IP Pool
[master]# calicoctl get ipPool --allow-version-mismatch
(3) 定義IP Pool
[master]# vim pool.yaml
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: pool1
spec:
cidr: 10.245.1.0/24
ipipMode: Never
natOutgoing: true
disabled: false
nodeSelector: all()
[master]# calicoctl create -f pool.yaml
[master]# calicoctl get ipPool --allow-version-mismatch
(4) 用kubectl創建
[master]# kubectl api-versions| grep calico
[master]# kubectl api-resources -o wide | grep calico | grep IPPool
[master]# vim pool.yaml
apiVersion: crd.projectcalico.org/v1 <<<
kind: IPPool
metadata:
name: pool3
spec:
cidr: 10.245.3.0/24
ipipMode: Never
natOutgoing: true
disabled: false
nodeSelector: all()
[master]# kubectl create -f pool.yaml
[master]# calicoctl get ipPool --allow-version-mismatch
(5) NetworkPolicy (allow 6379)
[master]# vim networkpolicy-test.yaml
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-tcp-6379
namespace: production
spec:
selector: role == 'database'
types:
- Ingress
- Egress
ingress:
- action: Allow
metadata:
annotations:
from: frontend
to: database
protocol: TCP
source:
selector: role == 'frontend'
destination:
ports:
- 6379
egress:
- action: Allow
[master]# calicoctl create -f networkpolicy-test.yaml
[master]# calicoctl get networkPolicy -o yaml
以下列出Calico與Flannel的一些基本比較,這二個方案似乎也是比較多人選擇的CNI,故他們之間的比較應該是比較具有參考價值。
(1) Underlay的支援:
(2) Overlay的支援:
(3) 動態QoS :
(4) 網路效能耗損:
(5) 網路安全策略:
(6) 固定IP/MAC :
以上就是針對Calico的基本說明,容器網路的世界是很複雜的,以系統的背景要去了解網路相關知識雖然會比較辛苦,但以平台的管理來說,這些知識是絕對有幫助的。
一般來說要選擇那種CNI開始,就要了解你的環境會需要到那些功能,所以對網路相關名詞的理解是必要的,以下列出幾個也許你應該了解的名詞:
本文就先介紹到這邊為止,謝謝您的耐心,你的支持鼓勵是我繼續分享的最大動力。
那我們就下期再見。
Reference: