1. 程式人生 > >Kubernetes網路分析之防火牆

Kubernetes網路分析之防火牆

本篇文章將從伺服器都防火牆的變化來分析K8s和Docker網路的實現

測試機:

名稱 系統 ip
master CentOS7 192.168.245.131
slave1 CentOS7 192.168.245.132

第一步分析初始狀態linux防火牆的規則
在這裡插入圖片描述
我們可以看到,初始狀態的nat表中原始的5個鏈中的規則都轉到了這個三個鏈中,我們在看這三個鏈
在這裡插入圖片描述
仔細檢視會發現所有鏈中都是空的,linux的防火牆nat表中初始狀態沒有設定什麼規則。

我們再看filter表:
在這裡插入圖片描述
filter中的input表:

  • 第一條規則是接收所有跟蹤狀態是RELATED和ESTABLISHED的資料包
  • 第二條規則為接收所有從迴環裝置發出的資料包
  • 第三、四、五條規則為將所有的資料報一次傳送給INPUT_direct、INPUT_ZONES_SOURCE和INPUT_ZONES鏈
  • 第六條規則為拒絕所有跟蹤狀態為INVALID的資料包
  • 第七條規則為拒絕所有資料報,並用icmp-host-prohibit型別的icmp包響應
    繼續看INPUT_direct、INPUT_ZONES_SOURCE和INPUT_ZONES鏈:
    在這裡插入圖片描述

    這三條鏈中只有INPUT_ZONES鏈有規則,並且仍是將所有資料報交給IN_public鏈
    繼續看IN_public鏈:
    在這裡插入圖片描述
    同理,繼續看IN_public_log,IN_public_deny,IN_public_allow:
    在這裡插入圖片描述
    看到只有一條規則,是接收目的埠為22,並且跟蹤狀態為新建的所有tcp資料包
    小結:Linux初始狀態的filter的input鏈只允許目標埠為22新建連線的tcp資料包,以及建立連線後該連線接的後續資料包,其它的包一率拒絕
    FOWARD和INPUT鏈基本一致,不同點為FOWARD不接受埠為22新建連線的tcp資料包,但允許轉發已建立連線的資料報
    OUTPUT鏈沒有任何規則;

啟動Docker觀察防火牆規則的變化
docker的配置為
在這裡插入圖片描述
啟動docker並觀察防火牆規則變化
先看nat表:
在這裡插入圖片描述
我們可以看到在PREROUTING鏈和OUTPUT鏈分別加了一條道DOCKER鏈的規則
在看DOCKER鏈
在這裡插入圖片描述
DOCKER鏈中只有一條規則,意思是收到從docker0發出的資料報時,退出DOCKER鏈,返回父鏈(進入該鏈的鏈這裡是PREROUTING或OUTPUT),那麼在這裡意思就意味著接收。

再看filter表
在這裡插入圖片描述
我們可以看到的變化就是假了DOCKER和DOCKER-ISOLATION鏈,
在這裡插入圖片描述
並且DOCKER-ISOLATION鏈中只有一條和之前的DOCKER鏈中的一樣的規則,就是返回父鏈,繼續執行其他規則,
再看docker新加的三條規則:

  • 第一條是接收所有發往docker0的連線狀態是RELATED和ESTABLISHED的資料包,即接收所有已經和docker0建立了連線的資料包
  • 第二條是接收所有容器發往外網的資料包
  • 第三條是接收所有容器發往容器的資料包

小結:可以看到docker預設外網訪問容器的資料報都會被拒絕

我們再啟動kubernetes來觀察防火牆的變動
我們分別啟動
master: 啟動docker etcd kube-apiserver kube-controller-manager kube-scheduler
slave1: 啟動docker kubelet kube-proxy

啟動完成後就來看下防火牆的變動吧
我們發下master上的防火牆沒有任何變動,這時由於,kubernetes中的網路轉發規則設定有kube-proxy控制,所以master還得啟動一下kube-proxy

接下來我們會發現另一個問題,就是slave1無法向master註冊成功,nodes結點的狀態一直是NotReady,這是由於之前所說的linux防火牆的filter表中的規則只允許tcp:22的資料報,所以slave1發往master的註冊資料包都被過reject了。

由於這裡slave1向master中的使用的是非安全連線,埠為8080,我們不妨在filter表中加一條規則,來映證我們上面對linux防火牆的討論。執行一下命令

  iptables -t filter -I INPUT  -j ACCEPT

然後slave1就註冊成功了

好了,現在繼續分析防火牆規則的變化,先看nat鏈
在這裡插入圖片描述
可以看到兩個新面孔,我們繼續看看這兩個鏈:
在這裡插入圖片描述
在這裡插入圖片描述
KUBE_SERVICE鏈中有兩條規則:

  • 第一條是將所有目的地址是10.254.0.1(Kubernetes配置的地址)目的埠是443的tcp資料包都交給KUBE-SVC-NPX。。。這個鏈處理,
  • 第二條規則是將所有目的地址是本地的資料包交給KUBE-NODEPORTS鏈

在看這兩條鏈:
在這裡插入圖片描述
在這裡插入圖片描述
繼續往下:
在這裡插入圖片描述
該鏈有兩條規則:
第一條是繼續轉給KUBE-MARK-MASQ鏈
第二條是所有的tcp資料報都進行DNAT,裝換為192.168.245.131:6443

再看KUBE-MARK-MASQ鏈:
在這裡插入圖片描述
意思大致是對所有資料包打上標記 0x4000。

再看KUBE-POSTROUTING
在這裡插入圖片描述
表示所有資料包都要進行地址偽裝

再看filter 表:
在這裡插入圖片描述
filter表中只加了一條鏈:
在這裡插入圖片描述
並且該鏈還是空的,說明K8s並沒有對資料報做任何過濾操作

補充:還有一條鏈
在這裡插入圖片描述
會Drop掉所有標記為0x8000的資料包,這個標記是nat表中KUBE-KUBE-MARK-DROP鏈標記的資料包

我們再啟動一個service看看:
在這裡插入圖片描述
加了一條到該service的規則,並且該規則裡面加了到該service的每個pod的規則
在這裡插入圖片描述
在這裡插入圖片描述
每條規則都是對從該pod發出的資料進行IP偽裝,對發往該pod的進行ip解偽裝。

小結:從上面可以看出kubernetes的對防火牆的操作主要在nat表,對各個地址進行NAT轉換,沒有對資料報進行過濾的操作。所以K8s不會造成結點網路不通的問題,只會產生叢集中服務訪問不通的問題。

總結
如果是結點無法連通,首先看Linux主機之間是否可通,確保連線正常的情況下,分析防火牆規則
如果是主機可通但不通主機間的容器不可通,則多半是Docker產生的鏈規則導致,
如果是服務不通,則是K8s生成的服務鏈規則異常導致