k8s之網絡插件flannel及基於Calico的網絡策略


1.k8s網絡通信

a.容器間通信:同一個pod內的多個容器間的通信,通過lo即可實現;

b.pod之間的通信:pod ip <---> pod ip,pod和pod之間不經過任何轉換即可通信;

c.pod和service通信:pod ip <----> cluster ip(即service ip)<---->pod ip,它們通過iptables或ipvs實現通信,ipvs取代不了iptables,因為ipvs只能做負載均衡,而做不了nat轉換;

d.Service與集群外部客戶端的通信.

kubectl get configmap -n kube-system
kubectl get configmap kube-proxy  -o yaml  -n kube-system
看到mode是空的,把它改為ipvs就可以
k8s靠CNI接口接入其他插件來實現網絡通訊.目前比較流行的插件有flannet、callco、canel.

這些插件使用的解決方案有如下方式:

a.虛擬網橋:虛擬網卡,多個容器共用一個虛擬網卡進行通信;

b.多路復用:MacVLAN,多個容器共用一個物理網卡進行通信;

c.硬件交換:SR-LOV,一個物理網卡可以虛擬出多個接口,這個性能最好.

CNI插件存放位置
cat /etc/cni/net.d/10-flannel.conflist
flanel只支持網絡通訊,但是不支持網絡策略;
callco網絡通訊和網絡策略都支持;canel:flanel+callco
可以部署flanel提供網絡通訊,再部署一個callco只提供網絡策略,而不用canel. 
mtu:是指一種通信協議的某一層上面所能通過的最大數據包大小.

通過ifconfig可以看到flannel.1的地址是10.244.1.0,子網掩碼是255.255.255.255,mtu是1450,正常mtu是1500,mtu要留出一部分做封裝疊加,額外開銷使用.

  兩個節點上的pod可以借助flannel隧道進行通信,默認使用VxLAN協議,有額外開銷,所以性能有點低;

  flannel第二種協議叫host-gw(host gateway),即Node節點把自己的網絡接口當做pod的網關使用,從而使不同節點上的node進行通信,性能比VxLAN高,因為它沒有額外開銷,不過有個缺點,就是各node節點必須在同一個網段中;

  如果兩個pod所在節點在同一個網段中,可以讓VxLAN也支持host-gw的功能,即直接通過物理網卡的網關路由轉發,而不用隧道flannel疊加,從而提高了VxLAN的性能,這種flannel的功能叫directrouting,如果不在同一網段,則使用VxLAN疊加隧道.

network:flannel使用CIDR格式的網絡地址,用於為pod配置網絡功能.

kubectl get configmap -n kube-system kube-flannel-cfg -o json -n kube-system
1)10.244.0.0/16--->
master: 10.244.0.0./24
node01: 10.244.1.0/24
....
node255: 10.244.255.0/24
可以支持256個節點

2)SubnetLen:把network切分為子網供各節點使用時,使用多長的掩碼進行切分,默認為24位;

3)SubnetMin:指明子網中的地址段最小多少可以分給子網使用,比如可以限制10.244.10.0/24,這樣0~9就不讓用;

4)SubnetMax:表示最多使用多少個,比如10.244.100.0/24;

5)Backend:Vxlan,host-gw,udp(最慢)

kubectl edit configmap kube-flannel-cfg -n kube-system

{
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan",
        "Directrouting": true # 加一行這個
      }
}
# 不要通過這種方式修改配置,應該在第一次安裝flannel時就加上這一行,否則就需要卸載掉已安裝的flannel,
修改下載好的配置文件,重新apply,才能實現同網段通過物理網卡實現網絡通信.
route -n
10.244.1.0      10.244.1.0      255.255.255.0   UG    0      0        0 flannel.1
10.244.2.0      10.244.2.0      255.255.255.0   UG    0      0        0 flannel.1
# 沒改之前,同一網段的不同節點通信是靠疊加網絡,改完生效之后,這兩個節點通信就是host-gw-用網卡通信
route -n
10.244.1.0      10.0.0.20       255.255.255.0   UG    0      0        0 eth0
10.244.2.0      10.0.0.30       255.255.255.0   UG    0      0        0 eth0

2.Calico演示

安裝文檔:https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/flannel

# 和k8s使用同一套API數據存儲
kubectl apply -f \
https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/rbac.yaml
kubectl apply -f \
https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/canal.yaml

Egress:出站,表示pod自己是客戶端,訪問別人;

Ingress:入站,表示Pod自己是目標,別人來訪問自己;通常,客戶端的端口是隨機的,服務端的端口是固定的;

Network Policy:用來控制哪些pod和外部或內部進行通信;

podSelector:pod選擇器;  policyTypes:用來控制Ingres和Egres哪個生效.

創建兩個名稱空間,一個是測試,一個是生產

kubectl create namespace dev
kubectl create namespace prod
mkdir networkpolicy && cd networkpolicy/
cat ingress-def.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
spec:
  podSelector: {}
  policyTypes: 
  - Ingress

# pod選擇器設置為空,表示選擇所有pod,即控制整個名稱空間
# 只寫了ingress生效,又把podSelector設置為空,表示拒絕其它名稱空間訪問,拒絕所有入站請求
# 沒有加egress,所以默認egress是允許本名稱空間所有pod出站
kubectl apply -f ingress-def.yaml -n dev
# 在dev名稱空間創建一個pod
cat pod-a.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
kubectl apply -f pod-a.yaml -n dev
# 拒絕任何入站請求
curl 10.244.2.2
# 將ingress設置為空,表示允許所有入站訪問
cat ingress-def.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
spec:
  podSelector: {}
  ingress:
  - {}
  policyTypes:
  - Ingress

# 給dev名稱空間里面的pod1打個標簽app=myapp 
cat allow-netpol-demo.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-myapp-ingress
spec:
  podSelector:
    matchLabels:
      app: myapp
  ingress:
  - from:
    - ipBlock:
        cidr: 10.244.0.0/16
        except:
        - 10.244.1.2/32 
    ports:
    - protocol: TCP
      port: 80

# cidr:指定網段,允許從10.244.0.0/16網段訪問指定標簽的pod
# except:排除某些地址
kubectl apply -f allow-netpol-demo.yaml -n dev
kubectl get netpol -n dev

egress出站規則

cat egress-def.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
spec:
  podSelector:
  policyTypes:
  - Egress
kubectl apply -f egress-def.yaml -n prod
# ping其他名稱空間的容器沒反應,是因為網絡策略deny-all-egress起了作用
kubectl exec pod1 -it  -n prod -- /bin/sh
# 允許所有egress出站
cat egress-def.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
spec:
  podSelector: {}
  egress:
  - {}
  policyTypes:
  - Egress

 

參考博客:http://blog.itpub.net/28916011/viewspace-2215295/

參考博客:http://blog.itpub.net/28916011/viewspace-2215383/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM