前言
不知道一直在玩k8的朋友有沒有發現一個問題,開啟了
ipvs
之後,
service
開啟
NodePort
之後,在主控端壓根找不到該監聽端口,本篇文章将帶着大家解開這層面紗。
iptable回顧
四表五鍊的處理順序是先作用鍊,再作用表!!!
四表五鍊的處理順序是先作用鍊,再作用表!!!
四表五鍊的處理順序是先作用鍊,再作用表!!!
鍊的通路順序是:
- 資料包到達網卡時,首先經過
鍊,進行預路由處理。PREROUTING
- 然後,在經過
鍊後,根據路由規則确定目标位址和接口,選擇目标主機或者進行轉發。PREROUTING
- 如果資料包是發往本地主機的,那麼接下來會經過INPUT鍊,進行輸入資料包的處理。
- 如果資料包是轉發的,那麼接下來會經過
鍊,進行資料包的轉發處理。FORWARD
- 如果資料包是由本地主機發出的,那麼接下來會經過
鍊,進行輸出資料包的處理。OUTPUT
- 最後,資料包離開網卡之前,會經過
鍊,進行後路由處理。POSTROUTING
每條鍊上有什麼表呢?
- PREROUTING鍊:
- raw表:用于處理連接配接跟蹤之前的資料包,可以修改資料包的源位址。
- mangle表:用于處理資料包的特殊修改,如修改TTL(生存時間)字段、标記資料包等。
- INPUT鍊:
- mangle表:用于處理資料包的特殊修改。
- nat表:用于網絡位址轉換,通常用于
(目标位址轉換)和DNAT
(源位址轉換)。MASQUERADE
- FORWARD鍊:
- mangle表:用于處理資料包的特殊修改。
- filter表:用于過濾資料包,決定是否允許資料包通過路由轉發。
- OUTPUT鍊:
- raw表:用于處理連接配接跟蹤之前的資料包,可以修改資料包的源位址。
- mangle表:用于處理資料包的特殊修改。
- nat表:用于網絡位址轉換,通常用于
(源位址轉換)。SNAT
- POSTROUTING鍊:
- mangle表:用于處理資料包的特殊修改。
- nat表:用于網絡位址轉換,通常用于
(源位址轉換)和SNAT
(源位址轉換)。MASQUERADE
這些表的作用是在五個主要的鍊上進行資料包處理和轉換。根據規則的配置,
iptables
可以對資料包進行源位址轉換、目标位址轉換、标記、過濾等操作,進而實作網絡流量的控制和管理。每個鍊上可以同時使用多個表,可以根據需求組合不同的規則來實作複雜的網絡處理邏輯。
kube-proxy定義的鍊條
除了
iptable
本身的四表五鍊之外,
kube-proxy
也自定義了一系列鍊條,這裡我們隻基于
NodePort
并且開啟
ipvs
的
kube-proxy
進行讨論
[root@openeuler-controlplane-jtzv-0 ~]# iptables -nL -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
cali-PREROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* cali:6gwbT8clXdHdC1b1 */
KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */
CNI-HOSTPORT-DNAT all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
......
Chain KUBE-SERVICES (2 references)
target prot opt source destination
KUBE-MARK-MASQ all -- !10.233.64.0/18 0.0.0.0/0 /* Kubernetes service cluster ip + port for masquerade purpose */ match-set KUBE-CLUSTER-IP dst,dst
KUBE-NODE-PORT all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-CLUSTER-IP dst,dst
......
Chain KUBE-NODE-PORT (1 references)
target prot opt source destination
KUBE-MARK-MASQ tcp -- 0.0.0.0/0 0.0.0.0/0 /* Kubernetes nodeport TCP port for masquerade purpose */ match-set KUBE-NODE-PORT-TCP dst
.....
在這裡我們可以看到一條鍊 PREROUTING ➡️ KUBE-SERVICES ➡️ KUBE-NODE-PORT
KUBE-NODE-PORT
鍊條的内容解析如下
- 鍊名稱:
。KUBE-NODE-PORT
- 目标:
,表示如果規則比對成功,則執行名為KUBE-MARK-MASQ
的目标規則。KUBE-MARK-MASQ
- 協定:
,表示該規則僅處理 TCP 協定的流量。tcp
- 源位址 (
):source
,表示任何源位址都會被比對。0.0.0.0/0
- 目标位址 (
):destination
,表示任何目标位址都會被比對。0.0.0.0/0
- 注釋 (
):對該規則的簡要說明,用于辨別該規則的用途。/* Kubernetes nodeport TCP port for masquerade purpose */
該規則使用了
match-set
來比對集合
KUBE-NODE-PORT-TCP
中的目标端口(NodePort)。當外部請求到達 NodePort 時,該規則會将流量标記為
KUBE-MARK-MASQ
,以便進行後續的
MASQUERADE
處理。
在 Kubernetes 中,是一個
KUBE-MARK-MASQ
鍊的标記,它用于标記要進行源位址轉換(
iptables
)的資料包。
MASQUERADE
是一種
MASQUERADE
Network Address Translation (NAT)
技術,它允許修改資料包的源 IP 位址,以便傳回的資料包能夠正确傳回給發起請求的用戶端。
具體來說,當請求從 Kubernetes 叢集中的
(服務暴露在主控端上的端口)到達時,
NodePort
鍊的規則會比對該請求,并将其标記為
KUBE-NODE-PORT
。然後,
KUBE-MARK-MASQ
鍊的規則将對這些标記的資料包進行
KUBE-MARK-MASQ
MASQUERADE
處理,将它們的源 IP 位址替換為主控端的 IP 位址,以確定響應的資料包能夠正确傳回到請求的用戶端。
這個過程確定了外部請求能夠正确路由到
叢集中的
Kubernetes
和
Service
,并在傳回時正确傳回給請求的用戶端。這是實作
Pod
的
Kubernetes Service
類型所必需的一部分。
NodePort
既然使用了
march-set
,我們不妨先看看
ipset
[root@openeuler-controlplane-jtzv-0 ~]# ipset list |grep KUBE-NODE-PORT-TCP -A 12
Name: KUBE-NODE-PORT-TCP
Type: bitmap:port
Revision: 3
Header: range 0-65535
Size in memory: 8296
References: 1
Number of entries: 4
Members:
30000
30090
31037
31428
可以看到我們的目标
NodePort(31037)
工作在
ipvs
鍊(核心空間)利用
input
(使用者空間)定義的轉發規則對資料包進行校驗,或者說此時
ipvsadm
鍊不再生效了,
INPUT
會攔截進入本機的資料包,并根據負載均衡的規則将其轉發給後端的真實伺服器(
IPVS
)處理
Real Server
我們可以通過
ipvsadm -S -n
映射内容,到這一步基本就已經知道原因了,可以看到你的
NodeIP:NodePort
映射到
PodIP
,往下分析無非就是走完這個鍊條,本篇文章就不再展開贅述了。