目錄html
重點了解Flannel
, Calico
, Canal
, kube-router
mysql
首先,flannel會利用Kubernetes API或者etcd用於存儲整個集羣的網絡配置,其中最主要的內容爲設置集羣的網絡地址空間,例如,設定整個集羣內全部容器的IP都取自網段「10.1.0.0/16」。接着,flannel會在每一個主機中運行flanneld做爲agent,它會爲所在主機從集羣的網絡地址空間中,獲取一個小的網段subnet,本主機內全部容器的IP地址都將從中分配。而後,flanneld再將本主機獲取的subnet以及用於主機間通訊的Public IP,一樣經過kubernetes API或者etcd存儲起來。最後,flannel利用各類backend mechanism,例如udp,vxlan等等,跨主機轉發容器間的網絡流量,完成容器間的跨主機通訊。 你們都知道Kubernetes是經過CNI標準對接網絡插件的,可是當你去看Flannel(coreos/flannel)的代碼時,並無發現它實現了CNI的接口。若是你玩過其餘CNI插件,你會知道還有一個二進制文件用來供kubele調用,而且會調用後端的網絡插件。對於Flannel(coreos/flannel)來講,這個二進制文件是什麼呢? 這個二進制文件就對應宿主機的/etc/cni/net.d/flannel |
如今,咱們來簡單看一下,若是上方Machine A中IP地址爲10.1.15.2/24的容器要與下方Machine B中IP地址爲10.1.16.2/24的容器進行通訊,封包是如何進行轉發的。從上文可知,每一個主機的flanneld會將本身與所獲取subnet的關聯信息存入etcd中,例如,subnet 10.1.15.0/24所在主機可經過IP 192.168.0.100訪問,subnet 10.1.16.0/24可經過IP 192.168.0.200訪問。反之,每臺主機上的flanneld經過監聽etcd,也可以知道其餘的subnet與哪些主機相關聯。以下圖,Machine A上的flanneld經過監聽etcd已經知道subnet 10.1.16.0/24所在的主機能夠經過Public 192.168.0.200訪問,並且熟悉docker橋接模式的同窗確定知道,目的地址爲10.1.16.2/24的封包一旦到達Machine B,就能經過cni0網橋轉發到相應的pod,從而達到跨宿主機通訊的目的。 所以,flanneld只要想辦法將封包從Machine A轉發到Machine B就OK了,而上文中的backend就是用於完成這一任務。不過,達到這個目的的方法是多種多樣的,因此咱們也就有了不少種backend。在這裏咱們舉例介紹的是最簡單的一種方式`hostgw`:由於`Machine A和Machine B處於同一個子網內`,它們本來就能直接互相訪問。所以最簡單的方法是:在Machine A中的容器要訪問Machine B的容器時,咱們能夠將Machine B當作是網關,當有封包的目的地址在subnet 10.1.16.0/24範圍內時,就將其直接轉發至B便可。而這經過下圖中那條紅色標記的路由就能完成,對於Machine B同理可得。由此,在知足仍有subnet能夠分配的條件下,咱們能夠將上述方法擴展到任意數目位於同一子網內的主機。而任意主機若是想要訪問主機X中subnet爲S的容器,只要在本主機上添加一條目的地址爲R,網關爲X的路由便可。
Network,全局CIDR格式的IPv4網絡,字符串格式,必選 SubnetLen,子網,默認爲24位 SubnetMin,分配給節點的起始子網 SubnetMax,分配給節點的最大子網 Backend,flannel要使用的後端
[root@master bin]# cat /run/flannel/subnet.env FLANNEL_NETWORK=10.244.0.0/16 FLANNEL_SUBNET=10.244.0.1/24 FLANNEL_MTU=1450 FLANNEL_IPMASQ=true
hostgw是最簡單的backend,它的原理很是簡單,直接添加路由,將目的主機當作網關,直接路由原始封包。例如,咱們從etcd中監聽到一個EventAdded事件:subnet爲10.1.15.0/24被分配給主機Public IP 192.168.0.100,hostgw要作的工做很是簡單,在本主機上添加一條目的地址爲10.1.15.0/24,網關地址爲192.168.0.100,輸出設備爲上文中選擇的集羣間交互的網卡便可。對於EventRemoved事件,刪除對應的路由便可。
當有一個EventAdded到來時,flanneld如何進行配置的,以及封包是如何在flannel網絡中流動的。 |
如上圖所示,當主機B加入flannel網絡時,和其餘全部backend同樣,它會將本身的subnet 10.1.16.0/24和Public IP 192.168.0.101寫入etcd中,和其餘backend不同的是,它還會將vtep設備flannel.1的mac地址也寫入etcd中。linux
以後,主機A會獲得EventAdded事件,並從中獲取上文中B添加至etcd的各類信息。這個時候,它會在本機上添加三條信息:nginx
路由信息:全部通往目的地址10.1.16.0/24的封包都經過vtep設備flannel.1設備發出,發往的網關地址爲10.1.16.0,即主機B中的flannel.1設備。sql
fdb信息:MAC地址爲MAC B的封包,都將經過vxlan首先發往目的地址192.168.0.101,即主機Bdocker
arp信息:網關地址10.1.16.0的地址爲MAC Bshell
如今有一個容器網絡封包要從A發往容器B,和其餘backend中的場景同樣,封包首先經過網橋轉發到主機A中。此時經過,查找路由表,該封包應當經過設備flannel.1發往網關10.1.16.0。經過進一步查找arp表,咱們知道目的地址10.1.16.0的mac地址爲MAC B。到如今爲止,vxlan負載部分的數據已經封裝完成。因爲flannel.1是vtep設備,會對經過它發出的數據進行vxlan封裝(這一步是由內核完成的,至關於udp backend中的proxy),那麼該vxlan封包外層的目的地址IP地址該如何獲取呢?事實上,對於目的mac地址爲MAC B的封包,經過查詢fdb,咱們就能知道目的主機的IP地址爲192.168.0.101。 最後,封包到達主機B的eth0,經過內核的vxlan模塊解包,容器數據封包將到達vxlan設備flannel.1,封包的目的以太網地址和flannel.1的以太網地址相等,三層封包最終將進入主機B並經過路由轉發達到目的容器。 |
虛擬網絡數據幀添加到VxLAN首部後,封裝在物理網絡UDP報文中,到達目地主機後,去掉物理網絡報文頭部及VxLAN首部,再將報文交付給目的終端後端
VxLAN後端使用隧道網絡轉發會致使必定和流量開銷,VxLAN DirectRouting模式,經過添加必要的路由信息使用節點的二層網絡直接發送Pod通訊報文,僅在跨IP網絡時,才啓用隧道方式。這樣,在不跨IP網絡時,性能基本接近二層物理網絡api
已經建立的flannel的網絡配置修改後不會生效, 只能刪掉flannel, 修改yaml文件後從新建立, 因此必定要提早肯定好網絡配置 |
curl https://docs.projectcalico.org/v3.9/manifests/canal.yaml -O kubectl apply -f canal.yaml
kubectl create namespace dev kubectl create namespace prod
apiVersion: v1 kind: Pod metadata: name: pod-demo spec: containers: - name: myapp image: ikubernetes/myapp:v1
kubectl explain networkpolicy.spec.ingress
NetworkPolicy屬於名稱空間級別 參數: from,源地址對象列表,多個項目間邏輯關係爲或,若爲空,表示匹配一切源地址;若至少有一個值,則僅容許列表中流量經過 ports,可被訪問的端口對象列表,多個項目間爲邏輯或,若爲空,表示匹配Pod的全部端口;若至少有一個值,則僅容許訪問指定的端口 |
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-policy spec: podSelector: {} policyTypes: - Ingress
沒有定義Ingress規則, 可是寫到了policyTypes裏, 就表示默認拒絕入方向訪問, 沒有寫Egress, 表示默認容許出方向訪問 |
[root@master networkpolicy]# kubectl apply -f deny-all.yaml -n dev networkpolicy.networking.k8s.io/deny-all-policy created
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-all-ingress spec: podSelector: {} # 匹配全部Pod ingress: - {} # 定義爲空, 表示容許訪問 policyTypes: ["Ingress"]
僅定義from將默認容許本地Pod全部端口;僅定義ports將默認容許全部源端點;同時定義from和ports時,是邏輯與關係 多個from之間是邏輯或關係 多個ports之間是邏輯或關係 from與ports間是邏輯與關係 from下ipBlock、namespaceSelector、podSelector同時使用多個時,爲邏輯或關係 |
# 爲pod打標籤 [root@master manifests]# kubectl label pod myapp -n dev app=myapp --overwrite pod/myapp labeled [root@master manifests]# kubectl get pod -n dev --show-labels NAME READY STATUS RESTARTS AGE LABELS myapp 1/1 Running 0 29m app=myapp
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-myapp-ingress name: default spec: podSelector: # 該規則只在當前的namespace下,攜帶app: myapp標籤的pod生效。限制請求的類型包括Ingress和Egress matchLabels: app: myapp policyTypes: ["Ingress"] ingress: - from: - ipBlock: # 網絡地址塊 cidr: 10.244.0.0/16 # 容許某個網段訪問 except: # 排除某個網段或ip訪問(只拒絕掉10.244.1.5) - 10.244.1.5/32 - podSelector: # 攜帶了app: myapp標籤的pod能夠訪問 matchLabels: app: myapp ports: - protocol: TCP port: 80
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-egress spec: podSelector: {} policyTypes: ["Egress"]
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-tomcat-egress spec: podSelector: matchLabels: app: tomcat policyTypes: ["Egress"] egress: - to: - podSelector: matchLabels: app: nginx - ports: - protocol: TCP port: 80 - to: - podSelector: matchLabels: app: mysql ports: - protocol: TCP port: 3306
對app=tomcat的Pod,限制只能訪問app=nginx的80端口和app=mysql的3306端口 |
隔離名稱空間,應該放行與kube-system名稱空間中Pod的通訊,以實現監控和名稱解析等各類管理功能tomcat
kubectl explain networkpolicy.spec.ingress.from.namespaceSelector.matchExpressions kubectl explain networkpolicy.spec.egress.to.namespaceSelector.matchExpressions
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: namespace-deny-all namespace: default spec: policyTypes: ["Ingress","Egress"] podSelector: {} --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: namespace- namespace: default spec: policyTypes: ["Ingress","Egress"] podSelector: {} ingress: - from: - namespaceSelector: matchExpressions: - key: name operator: In values: ["default","kube-system"] egress: - to: - namespaceSelector: matchExpressions: - key: name operator: In values: ["default","kube-system"]
https://pdf.us/2019/03/27/3129.html
https://my.oschina.net/jxcdwangtao/blog/1624486
https://www.cnblogs.com/YaoDD/p/7681811.html
https://www.cnblogs.com/xzkzzz/p/9952716.html