Iptables
netfilter 無法正確替換 UDP 響應包的目標 IP
我們正在執行小型 kuberentes 集群(CentOS 7,Kuberenetes 1.13 + Flannel),經過一些調整 TCP 配置(見下文),我們注意到 DNS 無法正常工作。
我不認為我們的更改直接對我所觀察到的內容負責,kubernetes 也對此負責。我查了 IP 表,AFAIK 一切看起來都很好。我觀察到的是:
- Pod 10.23.118.10 發送 UDP(53) 包到 DNS ClusterIP 10.22.0.10
- 然後將包的目標 IP 從 ClusterIP (10.22.0.10) 更改為 DNS 伺服器 pod (10.23.118.2) (DNAT) 的 IP
- 伺服器獲取請求,對其進行處理,然後將響應發送回 10.23.118.10
- 此時 netfilter 應該在轉發包之前將源 IP 10.23.118.2 替換為 10.22.0.10,但由於某種原因它沒有這樣做
- Libc 收到包並拒絕它,因為它看到響應來自 10.23.118.2 而不是 10.22.0.10 或者我們得到 ICMP 包,說埠不可達。
奇怪的是,只有當 DNS 請求被發送到在同一台機器上執行的 pod 時才會發生這種情況。如果 DNS 請求來自其他機器上執行的 pod,則一切正常。
我想我們不是唯一看到這一點的人。你有過類似的情況嗎?我不確定這是 linux 的 netfilter 或 docker/kubernetes 中的錯誤是否會在配置橋接介面時破壞某些東西。我應該在哪裡尋找更多資訊?
這是我們嘗試應用的 TCP 配置:
net.core.somaxconn = 1000 net.core.netdev_max_backlog = 5000 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.ipv4.tcp_wmem = 4096 12582912 16777216 net.ipv4.tcp_rmem = 4096 12582912 16777216 net.ipv4.tcp_max_syn_backlog = 8096 net.ipv4.tcp_slow_start_after_idle = 0
問題似乎是 CentOS 7 預設配置。
重新載入配置
sysctl -p --system
時,它也會重新載入/usr/lib/sysctl.d/00-system.conf
。在/usr/lib/sysctl.d/00-system.conf
中,我們可以看到以下內容:# Disable netfilter on bridges. net.bridge.bridge-nf-call-ip6tables = 0 net.bridge.bridge-nf-call-iptables = 0 net.bridge.bridge-nf-call-arptables = 0
一旦完成(在網橋上禁用 netfilter),NAT-ing 將無法在
docker0
網橋上正常工作。有趣的是,一旦您重新啟動 docker 並使用 查詢系統
sysctl -a
,您可以看到以下內容:net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1
我只能假設這個設置是在啟動過程中由 docker 本身更改的。
這解釋了為什麼重新啟動 docker 通常會有所幫助。