深入理解 iptables 的流量控制
什麼是 iptables?
在 Linux 系統中,iptables 是一個強大的防火牆工具,用於配置對 IPv4 數據包過濾規則和網絡地址轉換(NAT)。它允許系統管理員控制進入、離開或經過系統的網絡數據包的流向和處理方式,從而增強系統的安全性、穩定性和性能。
iptables 是 Linux 內核中 Netfilter 子系統的一部分,它通過在數據包經過網絡協議棧時應用規則來實現過濾和轉發。通過 iptables,用戶可以定義規則集(也稱爲表)來決定如何處理不同類型的數據包,比如允許或拒絕特定 IP 地址或端口的數據包。
iptables 支持多種不同的表和鏈,每個表和鏈都有特定的功能和用途。用戶可以根據需要創建自定義規則,或使用預定義的規則集來快速配置網絡安全策略。
在本文中,我們將介紹 iptables 的基本概念、工作原理和常見用法,以及 iptables 在 k8s 中流量轉發的相關流程。
** iptables 五鏈四表**
首先看一下 iptables 對流量控制的大體流程, 如下圖:
對流量控制,iptables 通常通過五個主要的鏈(表)來處理,分別是:
-
INPUT 鏈:處理進入本地系統的數據包。這些數據包可能是目標地址爲本地系統的或者需要被本地系統轉發的。
-
OUTPUT 鏈:處理從本地系統發出的數據包。這些數據包經過本地系統的路由和 NAT 處理後,準備發送到網絡中。
-
FORWARD 鏈:處理需要通過本地系統轉發的數據包。這些數據包既不是進入本地系統的,也不是由本地系統發出的,而是需要經過本地系統作爲路由器進行轉發的。
-
PREROUTING 鏈:在數據包經過路由之前處理。這個鏈在數據包進入本地系統之前應用,可以用於 NAT 等預處理操作。
-
POSTROUTING 鏈:在數據包離開路由之後處理。這個鏈在數據包離開本地系統之後應用,可以用於 NAT 等後處理操作。
當流量進入主機後,首先通過 prerouting 模塊判斷 是否爲本機的請求,如果流量屬於本機,則 通過 input 模塊 進入到用戶空間,然後通過 output 模塊,最後通過 postrouting 模塊轉發到網卡,如果不是本機的流量則通過 forward 將流量發送到 postrouting 轉發到網卡。
postrouting 階段結束後,iptables 將數據包發送到相應的鏈中處理。每個鏈都包含一系列規則,iptables 會按順序檢查這些規則,並根據規則的動作(接受、拒絕、轉發等)來處理數據包。
當一個規則匹配成功時,iptables 會根據規則的動作來處理數據包。常見的動作包括接受(ACCEPT)、拒絕(REJECT/DROP)、轉發(FORWARD)、重定向(REDIRECT)等。
如果沒有規則匹配成功,iptables 將根據表的默認策略來處理數據包。默認策略通常是接受或拒絕。
所以在 iptables 中主要的概念有 3 個:鏈(chain),表(table),動作(target)
在圖中出現的 prerouting,input,output,forward,postrouting。就是鏈 (chain)
其中鏈包括上面提到的五個 prerouting,input,output,forward,postrouting。表包括 filter 表,nat 表,mangle 表和 raw 表,他們分表代表什麼呢
-
filter 表:主要用於對數據包進行過濾,根據具體的規則決定是否放行該數據包 (如 DROP、ACCEPT、REJECT、LOG),所謂的防火牆其實基本上是指這張表上的過濾規則,對應內核模塊 iptables_filter;
-
nat 表:network address translation,網絡地址轉換功能,主要用於修改數據包的 IP 地址、端口號等信息 (網絡地址轉換,如 SNAT、DNAT、MASQUERADE、REDIRECT)。屬於一個流的包(因爲包的大小限制導致數據可能會被分成多個數據包) 只會經過這個表一次,如果第一個包被允許做 NAT 或 Masqueraded,那麼餘下的包都會自動地被做相同的操作,也就是說,餘下的包不會再通過這個表。對應內核模塊 iptables_nat;
-
mangle 表:拆解報文,做出修改,並重新封裝,主要用於修改數據包的 TOS(Type Of Service,服務類型)、TTL(Time To Live,生存週期) 以及爲數據包設置 Mark 標記,以實現 Qos(Quality Of Service,服務質量) 調整以及策略路由等應用,由於需要相應的路由設備支持,因此應用並不廣泛。對應內核模塊 iptables_mangle;
-
raw 表:是自 1.2.9 以後版本的 iptables 新增的表,主要用於決定數據包是否被狀態跟蹤機制處理,在匹配數據包時,raw 表的規則要優先於其他表,對應內核模塊 iptables_raw。我們最終定義的防火牆規則,都會添加到這四張表中的其中一張表中。
鏈和表有什麼關係呢,一個鏈中可以有多個表,詳細見下圖
那麼動作 (target) 又是什麼,比如,我們在過濾一個 ip 的請求的時候,是否通過,就是處理的動作,它包括以下幾種:
-
ACCEPT:允許數據包通過;
-
DROP:直接丟棄數據包,不迴應任何信息,客戶端只有當該鏈接超時後纔會有反應;
-
REJECT:拒絕數據包,會給客戶端發送一個數據包被丟棄的響應包的信息;
-
SNAT:S 指 Source,源 NAT (源地址轉換) 地址。在進入路由層面的 route 之後,出本地的網絡棧之前,改寫源地址,目標地址不變,並在本機建立 NAT 表項,當數據返回時,根據 NAT 表將目的地址數據改寫爲數據發送出去時候的源地址,併發送給主機。解決私網用戶用同一個公網 IP 上網的問題;
-
MASQUERADE:是 SNAT 的一種特殊形式,適用於動態的、臨時化變的 IP 上;
-
DNAT:D 指 Destination,目的 NAT,解決私網服務端,接收公網請求的問題。和 SNAT 相反,IP 包經過 route 之前,重新修改目標地址,源地址不變,在本機建立 NAT 表項,當數據返回時,根據 NAT 表將源地址修改爲數據發送過來時的目標地址,併發給遠程主機。可以隱藏後端服務器的真實地址;
-
REDIRECT:在本機做端口映射;
-
LOG:在 / var/log/messages 文件中記錄日誌信息,然後將數據包傳遞給下一條規則。除去最後一個 LOG,前 3 條規則匹配數據包後,該數據包不會再往下繼續匹配了,所以編寫的規則順序極其關鍵
在 iptables 中,鏈、表和動作之間的關係可以類比爲一個 API 服務開發結構。就像在 API 服務中會有各種接口,對應 iptables 中的鏈,而接口的實現則相當於 iptables
中的規則,而表則對應於數據庫的表。舉例來說,假設要實現一個規則允許 192.168.1.2 訪問 3306 端口,當請求到達時,首先會被轉發到 input 鏈進行處理,在這裏,input 鏈會去 filter 表中查看是否允許 192.168.1.2 訪問 3306 端口。在這個過程中,鏈充當了規則的集合,表用於存儲規則信息,而動作則表示了對規則的操作,類似於 API 接口的請求響應過程。
而這五鏈也是對應 netfilter 結構設計的重要部分,在 netfilter 中 的 hook 點也對應了這五鏈,分別如下
-
NF_INET_PRE_ROUTING: 這個 hook 在 IPv4 協議棧的 ip_rcv 函數或 IPv6 協議棧的 ipv6_rcv 函數中執行。所有接收數據包到達的第一個 hook 觸發點(實際上新版本 Linux 增加了 INGRESS hook 作爲最早觸發點),在進行路由判斷之前執行。
-
NF_INET_LOCAL_IN: 這個 hook 在 IPv4 協議棧的 ip_local_deliver() 函數或 IPv6 協議棧的 ip6_input() 函數中執行。經過路由判斷後,所有目標地址是本機的接收數據包到達此 hook 觸發點。
-
NF_INET_FORWARD : 這個 hook 在 IPv4 協議棧的 ip_forward() 函數或 IPv6 協議棧的 ip6_forward() 函數中執行。經過路由判斷後,所有目標地址不是本機的接收數據包到達此 hook 觸發點。
-
NF_INET_LOCAL_OUT: 這個 hook 在 IPv4 協議棧的 __ip_local_out() 函數或 IPv6 協議棧的 __ip6_local_out() 函數中執行。所有本機產生的準備發出的數據包,在進入網絡棧後首先到達此 hook 觸發點。
-
NF_INET_POST_ROUTING: 這個 hook 在 IPv4 協議棧的 ip_output() 函數或 IPv6 協議棧的 ip6_finish_output2() 函數中執行。本機產生的準備發出的數據包或者轉發的數據包,在經過路由判斷之後, 將到達此 hook 觸發點。
下面我整理了一些常用的命令。
常用命令
查看命令
一般查看命令用 -L
[root@web-01 ~]# iptable -L
-bash: iptable: command not found
You have new mail in /var/spool/mail/root
[root@web-01 ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP all -- 192.168.3.100 anywhere
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT icmp -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT)
target prot opt source destination
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
這樣我們可以查看所有的規則,那麼我們可不可以查看某一個表的內容呢,當然是可以的, 用 -t 來指定是哪一個表。
[root@web-01 ~]# iptables -L -t filter
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP all -- 192.168.3.100 anywhere
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT icmp -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT)
target prot opt source destination
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
當然也可以顯示詳細信息
[root@web-01 ~]# iptables -nvL -t filter
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP all -- * * 192.168.3.100 0.0.0.0/0
2329K 304M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
7952 700K ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
1 52 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
13181 730K REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
46 2760 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT 2508K packets, 821M bytes)
pkts bytes target prot opt in out source destination
-
n: 表示不對 IP 地址進行反查詢,加上這個參數顯示速度將會加快。
-
v: 表示輸出詳細信息,包含通過該規則的數據包數量、總字節數以及相應的網絡接口.
插入規則
iptables -t filter -I INPUT -s 192.168.3.100 -j DROP
插入 input 鏈 使用 -I。-s 爲源地址,-j 爲動作,也就是,插入 input 一條規則,當 源地址爲 192.168.3.100 是丟棄掉。DROP 和 REJECT 的區別是 DROP 直接丟棄掉,REJECT 則返回一個數據包丟棄的響應信息。
刪除規則
第一種刪除規則是,直接把 -I 參數改成 -D 比如
iptables -t filter -I INPUT -s 192.168.3.100 -j DROP
另外一種 在查詢命令後面加 --line 通過編號刪除
[root@web-01 ~]# iptables -L -t filter --line
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 192.168.3.100 anywhere
2 ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
3 ACCEPT icmp -- anywhere anywhere
4 ACCEPT all -- anywhere anywhere
5 ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
6 REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
1 REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
[root@web-01 ~]# iptables -t filter -D INPUT 1
[root@web-01 ~]# iptables -L -t filter --line
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
2 ACCEPT icmp -- anywhere anywhere
3 ACCEPT all -- anywhere anywhere
4 ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
5 REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
1 REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
iptables 如何來控制流量
那麼是如何來實現下圖中的流量控制呢?
我們一起來看兩個例子,假設一個場景,我們有幾臺機器,其中只有一臺可以上外網,需要用 NAT 的方式可以讓其餘的幾臺機器,也可以上網。
我們來模擬一下這個場景,首先準備一臺不能上網的服務器。由於我是用,本機的虛擬機模擬的,所以,將這臺服務器的網關注釋掉,也就是在這個文件中。
[root@gitlab ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0
GATEWAY 註釋掉
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
NAME=eth0
UUID=e8f82195-3fa4-4f6c-a397-527fa5af44fc
DEVICE=eth0
ONBOOT=yes
IPADDR=192.168.3.30
NETMASK=255.255.255.0
# GATEWAY=192.168.3.1
嘗試 ping 一下 baidu,即便是已經配置了 DNS 依然會找不到 service。
[root@gitlab ~]# cat /etc/resolv.conf
nameserver 114.114.114.114
[root@gitlab ~]#
[root@gitlab ~]#
[root@gitlab ~]# ping www.baidu.com
ping: www.baidu.com: Name or service not known
然後我們再準備一臺,可以上網的虛擬機。開啓內核的轉發功能,配置如下。
[root@nacos ~]# echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
[root@nacos ~]# sysctl -p
net.ipv4.ip_forward =
然後,配置 iptables 規則,允許 eth0 接口進行轉發。
# 放行Forward的數據包
iptables -I FORWARD -i eth0 -j ACCEPT
# 開啓網卡混雜模式(允許任意流向的數據包)
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
查看 iptables 的信息
[root@nacos ~]# iptables -L -t nat
...
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- anywhere anywhere
已經有 POSTROUTING 的規則了。然後,我們回到那臺不能上網的機器,配置路由。
root@gitlab ~]# route add -net 0.0.0.0/0 gw 192.168.3.20
然後,在 ping 百度
[root@gitlab ~]# ping www.baidu.com
ping: www.baidu.com: Name or service not known
[root@gitlab ~]# ping www.baidu.com
PING www.a.shifen.com (110.242.68.4) 56(84) bytes of data.
64 bytes from 110.242.68.4 (110.242.68.4): icmp_seq=1 ttl=52 time=23.1 ms
64 bytes from 110.242.68.4 (110.242.68.4): icmp_seq=2 ttl=52 time=23.0 ms
64 bytes from 110.242.68.4 (110.242.68.4): icmp_seq=3 ttl=52 time=23.4 ms
64 bytes from 110.242.68.4 (110.242.68.4): icmp_seq=4 ttl=52 time=23.1 ms
^C
--- www.a.shifen.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 12036ms
rtt min/avg/max/mdev = 23.099/23.217/23.494/0.194 ms
已經可以 ping 通了。我們再看一個例子,如果我想進行地址的轉換,比如,我有一臺服務器上面有一個數據庫,但是外網沒法訪問,用另外一臺服務器跳轉一下接口,這個需要怎麼來配置呢。
首先,先在一臺服務器上面,安裝數據庫服務。
[root@gitlab ~]# yum install mariadb-server -y
嘗試登錄
[root@gitlab ~]# systemctl status mysql
Unit mysql.service could not be found.
[root@gitlab ~]# systemctl status mariadb
● mariadb.service - MariaDB database server
Loaded: loaded (/usr/lib/systemd/system/mariadb.service; disabled; vendor preset: disabled)
Active: inactive (dead)
[root@gitlab ~]#
[root@gitlab ~]#
[root@gitlab ~]# systemctl start mariadb
[root@gitlab ~]# mysql -uroot -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 5.5.68-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
MariaDB [(none)]>
MariaDB [(none)]>
MariaDB [(none)]> exit
Bye
然後創建一個測試的數據庫
MariaDB [(none)]> create database test123;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]>
MariaDB [(none)]>
MariaDB [(none)]>
創建數據庫賬號
MariaDB [(none)]> GRANT SELECT ON*.* TO 'test'@'%' IDENTIFIED BY '123456a?';
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]>
MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
然後去另外一臺服務器,配置 iptables
首先,要保證的是,這一臺服務器可以進行正常的轉發,所以上面的例子的配置依然需要。
# 放行Forward的數據包
iptables -I FORWARD -i eth0 -j ACCEPT
# 開啓網卡混雜模式(允許任意流向的數據包)
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
然後配置它的轉發策略。
iptables -t nat -A PREROUTING -d 192.168.3.20 -p tcp --dport 13306 -j DNAT --to-destination 192.168.3.30:3306
嘗試連接
查詢
已經可以查出數據來,到這裏可能還有一些疑問,在整個配置過程中,好像沒有配置,准入的 filter 規則。但是也能通,因爲匹配的順序前面說過,先匹配 nat 表,然後再匹配 filter 表,所以,nat 表命中後,就轉發走了,這裏不用插入 filter 的規則。
當然,配置完成後,要保存配置,可以使用如下命令。
[root@nacos ~]# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[ 確定 ]
[root@nacos ~]#
他其實是保存在這個文件中 /etc/sysconfig/iptables . 當然,也可以使用 iptables-save 命令進行備份, 使用 iptables-restore 進行回放。
iptables-save > 文件名
iptables-restore < 文件名
所以保存 iptables 規則的時候,其實也可以使用這樣的命令
iptables-save > /etc/sysconfig/iptables
到現在我們會發現一個問題,在鏈,表和 動作,我們是否可以對這些內容進行更改呢,其實是可以的,我們可以自定義創建一些鏈去插入一些規則在他所相應的表。
-
-N:new, 自定義一條新的規則鏈
-
-E:重命名自定義鏈;引用計數不爲 0 的自定義鏈不能夠被重命名,也不能被刪除
-
-X:delete,刪除自定義的空的規則鏈
-
-P:Policy,設置默認策略;對 filter 表中的鏈而言,其默認策略有:ACCEPT:接受, DROP:丟棄
自定義一條新的規則鏈 chain
[root@localhost ~]# iptables -N test_chain
在 nat 表中自定義一條新的規則鏈
[root@localhost ~]# iptables -N test_chain -t nat
關聯自定義鏈 chain
[root@localhost ~]# iptables -A INPUT -s 172.31.0.0/16 -j TEST_CHAIN
自定義 chain 有什麼使用的場景呢,在 k8s 的 service 服務中,就使用這種場景,去進行負載均衡。下面我們來仔細看一下 service 是怎麼來實現的
Kubernetes service 中 iptables 如何實現流量控制
首先創建一個 三個副本的 pod。
[root@k8s-master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-9456bbbf9-jqtlq 2/2 Running 0 23h 10.233.3.8 k8s-node02 <none> <none>
nginx-deployment-9456bbbf9-k4px2 2/2 Running 0 23h 10.233.85.207 k8s-node01 <none> <none>
nginx-deployment-9456bbbf9-rdvst 2/2 Running 0 23h 10.233.235.239 k8s-master <none> <none>
[root@k8s-master ~]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubelet ClusterIP None <none> 10250/TCP,10255/TCP,4194/TCP 170d <none>
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 297d <none>
nginx-basic ClusterIP 10.97.59.135 <none> 80/TCP 23h app=nginx
每一次訪問 10.97.59.135:80 地址的時候,他都會負載到三個節點的某一個。我們可以用 iptables-save 來查看命令
[root@k8s-master ~]# iptables-save -t nat
由於輸出的文件比較多,接下來拆分出需要查看的內容
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
PREROUTING 規則的意思是,所有進來的數據包要跳轉到 KUBE-SERVICES 這個 chain 中看一下是否有匹配的規則。
OUTPUT 規則的意思是,所有離開的數據包也要去 KUBE-SERVICES 這個 chain 中看一下,是否有匹配的規則。
然後在 KUBE-SERVICES 這個 chain 中是否能找到關於 10.97.59.135 這個 ip 的信息。
-A KUBE-SERVICES -d 10.97.59.135/32 -p tcp -m comment --comment "default/nginx-basic:http cluster IP" -m tcp --dport 80 -j KUBE-SVC-WWRFY3PZ7W3FGMQW
果然是找到了,這條的意思是,所有訪問 10.97.59.135/32 這個地址的,目的端口是 80 的,跳轉到 KUBE-SVC-WWRFY3PZ7W3FGMQW 這個 chain,我們來看一下這個 chain 下面有什麼內容。
-A KUBE-SVC-WWRFY3PZ7W3FGMQW -m comment --comment "default/nginx-basic:http" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-4QU3V6S26CDI3HQO
-A KUBE-SVC-WWRFY3PZ7W3FGMQW -m comment --comment "default/nginx-basic:http" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-MT2IMDR4KXPUNLAK
-A KUBE-SVC-WWRFY3PZ7W3FGMQW -m comment --comment "default/nginx-basic:http" -j KUBE-SEP-YPGP2UQLOHOOHIPJ
這一段是什麼意思呢,就是有 0.33333333349 的概率命中 KUBE-SEP-4QU3V6S26CDI3HQO 這個 chain,有 0.50000000000 的概率命中 KUBE-SEP-MT2IMDR4KXPUNLAK 這個 chain。如果上面兩個都沒有命中,則會命中 KUBE-SEP-YPGP2UQLOHOOHIPJ 這個 chain
我們看一下 KUBE-SEP-4QU3V6S26CDI3HQO 這個 chain 包含什麼規則。
-A KUBE-SEP-4QU3V6S26CDI3HQO -p tcp -m comment --comment "default/nginx-basic:http" -m tcp -j DNAT --to-destination 10.233.235.239:80
也就是 目的地址轉發到 10.233.235.239:80。所有的三個 chain 如下:
-A KUBE-SEP-4QU3V6S26CDI3HQO -p tcp -m comment --comment "default/nginx-basic:http" -m tcp -j DNAT --to-destination 10.233.235.239:80
-A KUBE-SEP-MT2IMDR4KXPUNLAK -p tcp -m comment --comment "default/nginx-basic:http" -m tcp -j DNAT --to-destination 10.233.3.8:80
-A KUBE-SEP-YPGP2UQLOHOOHIPJ -p tcp -m comment --comment "default/nginx-basic:http" -m tcp -j DNAT --to-destination 10.233.85.207:80
正好對應的是 pod 的三個 ip 地址,所以在 k8s 爲什麼會把網絡模式會改爲 ipvs ,因爲在 pod 數逐漸變多的情況下,iptables 的這種規則效率比較低。首包,會逐個去匹配 iptables 的規則,如果有 1000 個規則,這個首包就會很慢,當首包進行分發後,雖然後面的請求會被 raw 表記錄,但是首包的很慢也是很影響性能的。
在本文中,我們深入探討了 iptables 的基礎知識和基本命令,以及如何在 Linux 系統中使用 iptables 進行流量控制和安全管理。我們還通過一個 NAT 流量轉發的例子,演示了 iptables 在網絡環境中的實際應用。
此外,我們分析了在 Kubernetes 中 iptables 是如何實現負載均衡的,探討了其工作原理和實現方式。瞭解這些知識不僅可以幫助我們更好地理解 Kubernetes 中網絡的工作機制,也可以幫助我們更好地優化和管理 Kubernetes 集羣的網絡性能。
最後,我們要強調在使用 iptables 時要謹慎小心,確保規則設置正確,以避免對網絡造成不必要的影響。iptables 是一個強大而靈活的工具,熟練掌握它將爲您的網絡管理工作帶來極大的便利和效率。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/-cwp7VXLDhWbnEQM3sc1-w