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/