kubernetes NodePort網絡踩坑


node節點信息:

系統:centos7.6     

內核:3.10   

IP地址:192.168.1.1

應用環境:

因為需要跑一個nginx的應用叫做http-proxy做流量轉發,公網入口是阿里雲的SLB然轉發到http-proxy的NodePor 端口上,也就是192.168.1.1:30285

spec:
  clusterIP: 172.30.253.123
  externalTrafficPolicy: Cluster
  ports:
    - name: http
      nodePort: 30285
      port: 8080
      protocol: TCP
      targetPort: 8080

剛配好一切正常,過了幾分鍾SLB開始報健康檢查錯誤,手動檢查了一下發現3、4請求之后必然會有一次timeout

排查過程:

  1. 先從公網請求一下
    $ curl proxy.public.com

    幾次請求中必然會有一次timeout

  1. 首先容器本地確定是否是nginx本身的問題
    $ curl localhost:8080 

    正常

  2. 在內網環境請求NodePort端口
    $ curl 192.168.1.1:30285

    正常,這就很詭異了

  3. 在宿主機本地抓包
    # tcpdump port 30285

    11:08:36.186722 IP 100.122.64.147.30042 > 192.168.1.1:30285: Flags [S], seq 868295361, win 28480, options [mss 1424,sackOK,TS val 1875975334 ecr 0,nop,wscale 9], length 0
    11:08:37.236652 IP 100.122.64.147.30042 > 192.168.1.1:.30285: Flags [S], seq 868295361, win 28480, options [mss 1424,sackOK,TS val 1875976384 ecr 0,nop,wscale 9], length 0
    11:08:39.284640 IP 100.122.64.147.30042 > 192.168.1.1:.30285: Flags [S], seq 868295361, win 28480, options [mss 1424,sackOK,TS val 1875978432 ecr 0,nop,wscale 9], length
    可以看到有收到來自SLB發來第一握手syn包,但是服務端沒有回應ack

  4. 在容器本地看一下syn drop
    $ netstat -s |grep LISTEN

    280 SYNs to LISTEN sockets dropped
    果然有而且在一直增加,查閱了相關資料后發現有可能是啟用了tcp_tw_recycle參數,前一段時間因time_wait確實優化過這個參數。。。果斷關掉

    # sysctl -w net.ipv4.tcp_tw_recycle=0

    然后一切正常了

為什么會這樣?

 

復習一下tcp的四次揮手:

第一次揮手:主動關閉方發送一個FIN+ACK報文,此時主動方進入FIN_WAIT1狀態,主動方停止發送數據但仍然能接收數據

第二次揮手:被動方收到FIN+ACK,發送一個ACK給對方,此時被動方進入CLOSE-WAIT狀態,被動方仍然可以給主動方發送數據

第三次揮手:主動方收到ACK后,此時主動方進入FIN_WAIT2狀態,被動方確定沒有數據要發后就會發送FIN+ACK報文

第四次揮手:主動方收到FIN+ACK,此時主動方進入TIME-WAIT狀態,發送一個ACK給被動方,方被動方進入CLOSED狀態

 

 

linux系統中的3個參數:

參數 默認狀態 作用 條件 影響 風險 建議
net.ipv4.tcp_timestamps
開啟 記錄TCP報文的發送時間 雙方都要開啟 影響客戶端服務端    開啟
net.ipv4.tcp_tw_recycle 關閉
4.1內核已刪除
把TIME-WAIT狀態超時時間設置為成rto,以實現快速回收 要啟用net.ipv4.tcp_timestamps 影響客戶端服務端 tcp_tw_recycle和tcp_timestamps同時開啟的條件下,60s內同一源ip主機的socket connect請求中的timestamp必須是遞增的,否則數據會被linux的syn處理模塊丟棄 內網環境切沒有NAT的時候看情況打開,沒什么必要就不要打開了
net.ipv4.tcp_tw_reuse 關閉 TIME-WAIT狀態1秒之后可以重用端口 要啟用net.ipv4.tcp_timestamps 影響客戶端   比如負載均衡連接后端服務器時,可以在負載均衡服務器上開啟

結論:對於服務端來說,客戶端通過SNAT上網時的timestamp遞增性無可保證,所以當服務端tcp_tw_recycle生效時會出現連接異常

 

k8s的NodePort網絡:  

service網絡的實體是kube-proxy維護iptables規則,先看一下流程

  1. 在nat主鏈攔截SERVICES自定義鏈
    # iptables -t nat  -nL PREROUTING
    KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */
    其他nat主鏈同樣有KUBE-SERVICES自定義鏈
  2. 攔截NodePort自定義鏈
    # iptables -t nat -nL KUBE-SERVICES

    KUBE-NODEPORTS all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL

  3. 攔截端口流量
    # iptables -t nat -nL KUBE-NODEPORTS

    KUBE-MARK-MASQ tcp -- 0.0.0.0/0 0.0.0.0/0 /* default/http-proxy:http1 */ tcp dpt:30285

    KUBE-SVC-NKX6PXTXGL4F5LBG  tcp  --  0.0.0.0/0            0.0.0.0/0            /* default/http-proxy:http1 */ tcp dpt:30285

  4. 攔截端口流量打標記
    # iptables -t nat -nL KUBE-MARK-MASQ

    MARK       all  --  0.0.0.0/0            0.0.0.0/0            MARK or 0x1

  5. 打標記並根據標記做SNAT
    # iptables -t nat -nL POSTROUTING

    KUBE-POSTROUTING  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes postrouting rules */

    # iptables -t nat -nL KUBE-POSTROUTING

    MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service traffic requiring SNAT */ mark match 0x1/0x1

  6. 第二步攔截端口流量到SCV自定義鏈
    # iptables -t nat -nL KUBE-SVC-NKX6PXTXGL4F5LBG

    KUBE-SEP-4DYOPOZ4UKLHEHIS  all  --  0.0.0.0/0            0.0.0.0/0            /* default/http-proxy:http1 */

    # iptables -t nat -nL KUBE-SEP-4DYOPOZ4UKLHEHIS

    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            /* default/http-proxy:http1 */ tcp to:10.128.0.74:8081

     

結論:可以看到第五步kube-proxy會做SNAT的操作,這也就不難解釋從SLB過來的流量為什么會不正常了。至於為什么要做SNAT主要是防止路由來回路徑不一致會導致tcp通信失敗,這里就不展開了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM