一次網絡不通“爭吵“引發的思考

作者: 鄭明泉、余凱

為啥爭吵,吵什么?

“你到底在說什么啊,我K8s的ecs節點要訪問clb的地址不通和本地網卡有什么關系…” 氣憤語氣都從電話那頭傳了過來,這時電話兩端都沉默了。過了好一會傳來地鐵小姐姐甜美的播報聲打斷了剛剛的沉寂「乘坐地鐵必須全程佩戴口罩,下一站西湖文化廣場…」。

pod需要訪問clb的443的監聽, 但是如果是集群內(集群內后面都指的K8s的節點或者POD)訪問就會出現如下報錯Connection refused:

在這里插入圖片描述

所以就捋了一下客戶鏈路如下:

在這里插入圖片描述

具體現象是什么

無論是節點node還是pod里訪問192.168.1.200:443都是不通的,但是訪問192.168.1.200:80卻是正常的。同時集群外的ECS192.168.3.100訪問192.168.1.200:443和192.168.1.200:80都是正常的。

進一步分析看看

CLB1的IP192.168.1.200被綁定到了K8s的node節點的kube-ipvs0網卡上,這個是一張dummy 網卡,參考dummy interface。由于 SVC1 是LoadBalancer類型的,同時復用了這個CLB1,關聯endpoint是POD1192.168.1.101:80,那么就可以解釋為何訪問192.168.1.200:80是正常,是由于kube-proxy根據SVC1的配置創建ipvs規則同時掛載了可被訪問的后端服務。而集群里訪問192.168.1.200:443都是不通的,因為IP被綁定到dummy網卡后,就不會再出節點去訪問到CLB1,同時沒有443對應ipvs規則,所以直接是拒絕的。

這個時候如果節點里沒有ipvs規則(ipvs優先于監聽)但是又能訪問通的話, 可以檢查一下是否本地有監聽0.0.0.0:443的服務,那么這個時候所有網卡IP+443都能通,但是訪問的是本地服務,而不是真正的CLB后端的服務。

在這里插入圖片描述

是否有辦法解決呢

最建議的方式

最好的方式拆分, 集群內和集群外的服務分開兩個CLB使用。

阿里云svc注解的方式

SVC1使用這個注解service.beta.kubernetes.io/alibaba-cloud-loadbalancer-hostname,進行占位,這樣就不會綁定CLB的IP到kube-ipvs0的網卡上,集群內訪問CLB的IP就會出集群訪問CLB,但是需要注意如果監聽協議為TCP或UDP,集群內訪問CLB IP時將會存在回環訪問問題。詳細信息,請參見客戶端無法訪問負載均衡CLB [ 1]

需要CCM版本在 v2.3.0及以上版本才支持這個注解, 具體參考:通過Annotation配置傳統型負載均衡CLB [ 2]

在這里插入圖片描述

demo:

apiVersion: v1
kind: Service
metadata:annotations:service.beta.kubernetes.io/alibaba-cloud-loadbalancer-hostname: "${your_service_hostname}"name: nginx-svcnamespace: default
spec:ports:- name: httpport: 80protocol: TCPtargetPort: 80selector:app: nginxtype: LoadBalancer

集群內訪問 ExternalTrafficPolicy 策略有影響嗎?

我們都知道K8s的nodeport和loadbalancer模式是可以調整外部流量策略的,那么圖中的「外部策略為Local/Cluster,所有集群節點創建IPVS規則是有區別的」該如何解釋呢, 以及集群內訪問nodePort/CLBIP的時候會發生什么。

在這里插入圖片描述

以下都是針對svc的internalTrafficPolicy都是Cluster或者缺省的情況,這個ServiceInternalTrafficPolicy特性在1.22的K8s中默認開啟,具體參考service-traffic-policy [ 3]

具體到阿里云容器在不同網絡CNI情況下的數據鏈路,可以參考下面的文章:

  • 全景剖析阿里云容器網絡數據鏈路(一)—— Flannel
  • 全景剖析阿里云容器網絡數據鏈路(二)—— Terway ENI
  • 全景剖析阿里云容器網絡數據鏈路(三)—— Terway ENIIP
  • 全景剖析阿里云容器網絡數據鏈路(四)—— Terway IPVLAN+EBPF
  • 全景剖析阿里云容器網絡數據鏈路(五)—— Terway ENI-Trunking
  • 全景剖析阿里云容器網絡數據鏈路(六)—— ASM Istio

此處我們只討論ipvs TrafficPolicy Local在Kubernetes 從1.22升級到1.24的行為變化。

Kubernetes 1.24 IPVS的變化

以下均以kube-proxy的IPVS模式為例:

  • 當externalTrafficPolicy為Cluster模式或缺省的時候,ipvs規則里的nodePort/CLBIP后端會掛載所有的Endpoint的IP,這時候集群內訪問會丟失源IP,因為節點會做一層SNAT。
  • 當externalTrafficPolicy是Local的時候
    • 當節點上有對應service的Endpoint的時候,ipvs規則里的nodePort/CLBIP后端只掛載自己節點的Endpoint的IP,集群內訪問會保留源IP。
    • 當節點上沒有對應service的Endpoint的時候
    • 在1.24之前的版本是會掛空的后端的,集群內訪問會拒絕。
    • 在1.24之后的K8s集群里,當節點上沒有對應service的Endpoint的時候,ipvs規則里的nodePort/CLB IP后端會掛載所有的Endpoint的IP,這時候集群內訪問會丟失源IP,因為節點會做一層SNAT。社區調整了Local策略后端服務的規則掛載策略,具體參考社區PR [ 4]

https://github.com/kubernetes/kubernetes/pull/97081/commits/61085a75899a820b5eebfa71801e17423c1ca4da

集群外訪問SLB

集群外訪問SLB的話,CCM只會掛載Local類型的節點,情況跟1.24 kubernetes前一樣,這里不做過多闡述,請見上面連接。

集群外訪問NodePort

1.24 Kubernetes之前版本

  • 訪問有Endpoint的節點的NodePort,可以通,可以保留源IP

Nginx分布在cn-hongkong.10.0.4.174和cn-hongkong.10.0.2.84節點。

在這里插入圖片描述

從外部10.0.3.72節點訪問有后端pod所在節點的cn-hongkong.10.0.2.84的30479端口,可以訪問。

在這里插入圖片描述

cn-hongkong.10.0.0.140節點上是有相關的IPVS的規則的,但是只有該節點上后端Pod IP。

在這里插入圖片描述

通過conntrack表可以到,這是由于在cn-hongkong.10.0.0.140節點上,相關的鏈路被dnat,最后是由pod cn-hongkong.10.0.2.84節點上的 的nginx-7d6877d777-tzbf7 10.0.2.87返回源,所有的相關轉化都在該節點上,所以TCP四層建連可以成功。

在這里插入圖片描述

  • 訪問沒有Endpoint的節點的NodePort,不能通,因為節點上沒有相關的ipvs轉發規則

從外部10.0.3.72節點訪問無后端pod所在節點的cn-hongkong.10.0.0.140的30479端口,不可以訪問。

在這里插入圖片描述

查看該cn-hongkong.10.0.0.140節點,并沒有相關的ipvs轉發規則,所以無法進行dnat,訪問會失敗。

在這里插入圖片描述

1.24 Kubernetes版本之后(含)

訪問有Endpoint節點的NodePort,可以通,可以保留源IP

訪問沒有Endpoint節點的NodePort:

  • terway ENIIP or host網絡:不通

Nginx分布在cn-hongkong.10.0.2.77和cn-hongkong.10.0.0.171 節點。

在這里插入圖片描述

從外部10.0.3.72節點訪問無后端pod所在節點的cn-hongkong.10.0.5.168的30745端口,可以看到,訪問失敗。

在這里插入圖片描述

cn-hongkong.10.0.5.168節點上是有相關的IPVS的規則的,并且會把所有的后端Pod IP加到IPVS規則中。

在這里插入圖片描述

通過conntrack表可以到,這是由于在cn-hongkong.10.0.5.168節點上,相關的鏈路被dnat,最后是由pod cn-hongkong.10.0.2.77節點上的nginx-79fc6bc6d-8vctc 10.0.2.78返回源,源在接受這個鏈路后,會發現和自己的五元組不匹配,直接丟棄,三次握手必然失敗,所以建連失敗。

在這里插入圖片描述

  • flannel網絡:可以通,但是保留不了源IP

Nginx分布在cn-hongkong.10.0.2.86。

在這里插入圖片描述

從外部訪問cn-hongkong.10.0.4.176的31218端口,可以訪問成功。

在這里插入圖片描述

cn-hongkong.10.0.4.176記錄了src是10.0.3.72,并做了dnat為172.16.160.135,期望它返回給10.0.4.176的58825端口。

在這里插入圖片描述

后端ep所在節點cn-hongkong.10.0.2.86,conntrack表記錄了src是10.0.4.176,sport是58825。所以可以看到應用pod是記錄的源IP是10.0.4.176,丟失了源IP。

在這里插入圖片描述

集群內訪問SLB或者NodePort

1.24 Kubernetes之前版本

  • 有Endpoint的節點上訪問,可以通,可以保留源IP

Nginx分布在ap-southeast-1.192.168.100.209和ap-southeast-1.192.168.100.208節點,ap-southeast-1.192.168.100.210節點沒有Nginx pod。

在這里插入圖片描述

從集群任意節點(本例就在209節點)訪問有后端pod所在節點的ap-southeast-1.192.168.100.209的NodePort 31565端口,可以訪問。

在這里插入圖片描述

從有后端pod所在節點ap-southeast-1.192.168.100.209訪問SLB 8.222.252.252 的80端口,可以訪問。

在這里插入圖片描述

ap-southeast-1.192.168.100.209節點上是有NodePort 和SLB 的IPVS的規則的,但是只有該節點上后端Pod IP。

在這里插入圖片描述

通過conntrack表可以到,這是由于在ap-southeast-1.192.168.100.209 節點上,相關的鏈路被dnat,最后是由pod 在ap-southeast-1.192.168.100.209 節點上的 的nginx-7d6877d777-2wh4s 192.168.100.222返回源,所有的相關轉化都在該節點上,所以TCP四層建連可以成功。

在這里插入圖片描述

  • 沒有Endpoint的節點上訪問,不能通,因為節點上沒有相關的ipvs轉發規則

從集群任意節點(本例就在210節點)訪問沒有后端pod所在節點的ap-southeast-1.192.168.100.210 的NodePort 31565端口或者SLB,不可以訪問。

也進一步證實,集群內訪問關聯svc的SLB不出節點,即使SLB有其他監聽端口,訪問SLB其他端口也會拒絕。

在這里插入圖片描述

查看該ap-southeast-1.192.168.100.210 節點,并沒有相關的ipvs轉發規則,所以無法進行dnat,訪問會失敗。

在這里插入圖片描述

1.24 Kubernetes版本之后(含)

  • 有Endpoint節點上訪問,可以通,可以保留源IP

與上文的1.24 Kubernetes之前版本集群內訪問一致,可以參考上文描述。

  • 沒有Endpoint節點上訪問:

Nginx分布在cn-hongkong.10.0.2.77和cn-hongkong.10.0.0.171節點,所以在沒有Nginx的cn-hongkong.10.0.4.141節點上測試。

在這里插入圖片描述

分別有以下幾種情況:

  • terway或后端為hostNetwork
    • 節點訪問的通 NodePort(源 IP 是 ECS IP,不需要做 SNAT),無法保留源IP

可以看到沒有Endpoint的節點的NodePort 110.0.4.141:30745 的IPVS 的規則添加的Nginx的所有后端POD nginx-79fc6bc6d-8vctc 10.0.2.78 和 nginx-79fc6bc6d-j587w 10.0.0.172。

在這里插入圖片描述

集群內節點自身訪問沒有后端pod所在節點的cn-hongkong.10.0.4.141 的NodePort 30745/TCP端口,可以訪問。

在這里插入圖片描述

通過conntrack表可以到,在cn-hongkong.10.0.4.141節點上,相關的鏈路被dnat,最后是由后盾Nginx pod nginx-79fc6bc6d-8vctc 10.0.2.78返回源。

在這里插入圖片描述

而在nginx-79fc6bc6d-8vctc 10.0.2.78 所在的節點cn-hongkong.10.0.2.77上的conntrack表記錄的是10.04.141訪問10.0.2.78,并期望10.0.2.78直接返回10.0.4.141的的39530端口。

在這里插入圖片描述

集群內有endpoint 節點訪問沒有后端pod所在節點的ap-southeast-1.192.168.100.131 的NodePort 32292端口,不可以訪問,與上文1.24 Kubernetes版本之后(含) 集群外訪問一致,可以參考上文描述。

    • 節點訪問不通 SLB IP(源 IP 是 SLB IP,沒有人做 SNAT)

可以看到沒有Endpoint的節點的SLB IP 的IPVS 的規則添加的Nginx的所有后端POD nginx-79fc6bc6d-8vctc 10.0.2.78 和 nginx-79fc6bc6d-j587w 10.0.0.172。

在這里插入圖片描述

沒有Endpoint的節點上訪問 SLB 47.243.247.219,訪問確是超時。

在這里插入圖片描述

通過conntrack表可以到,在沒有ep的節點訪問SLB的IP,可以看到期望的是后端pod返回給SLB IP。而SLB IP 在節點上已經被kube-ipvs虛擬占位了,所以沒有做snat,造成無法訪問。

在這里插入圖片描述

  • flannel并且后端為普通pod,可以訪問通,但是保留不了源IP

Nginx分布在cn-hongkong.10.0.2.86。

在這里插入圖片描述

在cn-hongkong.10.0.4.176訪問SLB 47.242.86.39 是可以訪問成功的。

在這里插入圖片描述

cn-hongkong.10.0.4.176節點的conntrack表可以看到是src和dst都是47.242.86.39,但是期望的是 nginx pod172.16.160.135 返回給 10.0.4.176 的54988端口,47.242.86.39 snat成10.0.4.176。

在這里插入圖片描述

后端ep所在節點cn-hongkong.10.0.2.86,conntrack表記錄了src是10.0.4.176,sport是54988。所以可以看到應用pod是記錄的源IP是10.0.4.176,丟失了源IP。

在這里插入圖片描述

相關鏈接:

[1] 客戶端無法訪問負載均衡CLB

https://help.aliyun.com/document_detail/55206.htm

[2] 通過Annotation配置傳統型負載均衡CLB

https://www.yuque.com/r/goto?url=https%3A%2F%2Fhelp.aliyun.com%2Fzh%2Fack%2Fack-managed-and-ack-dedicated%2Fuser-guide%2Fadd-annotations-to-the-yaml-file-of-a-service-to-configure-clb-instances

[3] service-traffic-policy

https://kubernetes.io/zh-cn/docs/concepts/services-networking/service-traffic-policy/

[4] 社區PR

https://github.com/kubernetes/kubernetes/pull/97081/commits/61085a75899a820b5eebfa71801e17423c1ca4da

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/40730.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/40730.shtml
英文地址,請注明出處:http://en.pswp.cn/news/40730.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

iview默認樣式覆蓋

scoped 屬性是 HTML5 中的新屬性。 當style標簽擁有scoped屬性時,它的css樣式只能用于當前的Vue組件,可以使組件的樣式不相互污染。 如果一個項目的所有style標簽都加上了scoped屬性,相當于實現了樣式的模塊化。 1、全頁面覆蓋 不添加scoped…

【一】ubuntu20.04上搭建containerd版( 1.2.4 以上)k8s及kuboard V3

k8s 部署全程在超級用戶下進行 sudo su本文請根據大綱順序閱讀! 一、配置基礎環境(在全部節點執行) 1、安裝docker 使用apt安裝containerd 新版k8s已經棄用docker轉為containerd,如果要將docker改為containerd詳見&#xff1a…

對dubbo的DubboReference.check的參數進行剖析

背景 在使用dubbo的時候,發現當消費者啟動的時候,如果提供者沒有啟動,即使提供者后來啟動了,消費者也調不通提供者提供的接口了。 注冊中心使用都是nacos dubbo版本是3.0.4 例子 接口 public interface DemoService {String…

“深入解析JVM內部機制:探秘Java虛擬機的奧秘“

標題:深入解析JVM內部機制:探秘Java虛擬機的奧秘 摘要:本文將深入解析JVM(Java虛擬機)的內部機制,從字節碼執行到垃圾回收,逐步揭示Java程序運行的奧秘。通過理論分析和示例代碼,讀…

thinkphp5.1 trace 不顯示sql語句

config/app.php app_debug > true,//線上環境為 false // 應用Trace app_trace > true,//線上環境為 false config/database.php debug > true, config/log.php close > false, thinkphp5.1x 設計非常奇怪 必須開啟…

使用dockerfile手動構建JDK11鏡像運行容器并校驗

Docker官方維護鏡像的公共倉庫網站 Docker Hub 國內無法訪問了,大部分鏡像無法下載,準備逐步構建自己的鏡像庫。【轉載aliyun官方-容器鏡像服務 ACR】Docker常見問題 阿里云容器鏡像服務ACR(Alibaba Cloud Container Registry)是面…

內網穿透-外遠程連接中的RabbitMQ服務

文章目錄 前言1.安裝erlang 語言2.安裝rabbitMQ3. 內網穿透3.1 安裝cpolar內網穿透(支持一鍵自動安裝腳本)3.2 創建HTTP隧道 4. 公網遠程連接5.固定公網TCP地址5.1 保留一個固定的公網TCP端口地址5.2 配置固定公網TCP端口地址 前言 RabbitMQ是一個在 AMQP(高級消息隊列協議)基…

Linux:shell腳本:基礎使用(4)《正則表達式-grep工具》

正則表達式定義: 使用單個字符串來描述,匹配一系列符合某個句法規則的字符串 正則表達式的組成: 普通字符串: 大小寫字母,數字,標點符號及一些其他符號 元字符:在正則表達式中具有特殊意義的專用字符 正則表…

python中__main__的解釋

源自于:https://zhuanlan.zhihu.com/p/340997807 Python程序運行時是從模塊頂行開始,最頂層(沒有被縮進)的代碼都會被執行,所以Python中并不需要一個統一的main()作為程序的入口。 __name__是Python的內置變量&#…

藍橋杯嵌入式省一教程:(三)按鍵掃描與定時器中斷

在第一講中曾經提到,GPIO有輸入輸出兩種模式。在點亮LED時,我們已經使用了GPIO輸出模式,在按鍵識別中,我們將要使用GPIO輸入模式。首先來看看按鍵的電路原理圖(下圖在選手資源數據包——CT117E-M4產品手冊中&#xff0…

Android CCodec (二十) CCodec Native服務實現分析

1、C2解碼服務registerAsService注冊流程 google實現CCodec的vendor默認解碼服務代碼路徑是在frameworks/av/media/codec2/hidl/services/vendor.cpp中,而其注冊的是HIDL服務,本文就對HIDL服務注冊做簡要分析。首先看下vendor.cpp中的代碼注冊流程。 int main(int /* argc *…

高等數學教材重難點題型總結(三)微分中值定理和導數的應用

第三章,微分中值定理的證明題等,非常重要,需要牢牢掌握 1.證明中值定理對某函數在給定區間上的正確性 2.與中值定理有關的證明題 3.微分中值定理應用于求證不等式 4.洛必達法則求極限 5.洛必達的經典錯誤反例 6.按某項實現多項式冪展開 7.求帶…

以 Java NIO 的角度理解 Netty

文章目錄 前言Java NIO 工作原理Selector 的創建ServerSocketChannel 的創建ServerSocketChannel 注冊 Selector對事件的處理總結 前言 上篇文章《Netty 入門指南》主要涵蓋了 Netty 的入門知識,包括 Netty 的發展歷程、核心功能與組件,并且通過實例演示…

rabbitmq的發布確認

生產者將信道設置成 confirm 模式,一旦信道進入 confirm 模式, 所有在該信道上面發布的 消息都將會被指派一個唯一的 ID (從 1 開始),一旦消息被投遞到所有匹配的隊列之后,broker 就會發送一個確認給生產者(包含消息的唯一 ID)&…

AI巨浪下,數據技術如何驅動智能未來?

引言 數據技術是大數據時代的核心驅動力,也是推動各行各業數字化轉型和智能化升級的關鍵因素。隨著云計算、人工智能、區塊鏈等新興技術的不斷發展和融合,數據技術也呈現出多模態、混合處理、自動化管理等新的趨勢和特點。 8 月 19 日(周六&…

域名和ip的關系

域名和ip的關系 一:什么是域名 域名,簡稱域名、網域,是由一串用點分隔的名字組成的上某一臺計算機或計算機組的名稱,用于在數據傳輸時標識 計算機的電子方位(有時也指地理位置)。網域名稱系統,有時也簡稱為域名…

【寶藏系列】嵌入式 C 語言代碼優化技巧【超詳細版】

【寶藏系列】嵌入式 C 語言代碼優化技巧【超詳細版】 文章目錄 【寶藏系列】嵌入式 C 語言代碼優化技巧【超詳細版】前言整形數除法和取余數合并除法和取余數通過2的冪次進行除法和取余數取模的一種替代方法使用數組下標全局變量使用別名變量的生命周期分割變量類型局部變量指針…

Centos下的tcpdump抓包用法

先查一下是否安裝, 無的話裝一下 (版本低的用yum install) : rpm -qa tcpdump dnf install tcpdump 1. 列出能抓包的網卡: tcpdump -D | --list-interfaces 2. 在eth0網卡上抓來源為10.1.1.1 的包, 只抓一個包 (-n這里是不解析DNS) : tcpdump -i eth0 -n src 10.1.1.1 -…

STM32 F103C8T6學習筆記3:串口配置—串口收發—自定義Printf函數

今日學習使用STM32 C8T6的串口,我們在經過學習筆記2的總結歸納可知,STM32 C8T6最小系統板上有三路串口,如下圖: 今日我們就著手學習如何配置開通這些串口進行收發,這里不講串口通信概念與基礎,可以自行網上…

一文讀懂HTML

文章目錄 HTML的歷史HTML的作用HTML的基本語言 HTML的歷史 HTML(HyperText Markup Language)的歷史可以追溯到20世紀90年代早期,它是互聯網發展的重要里程碑之一。以下是HTML的歷史概述: 早期階段(1980年代末 - 1990年…