為啥爭吵,吵什么?
Cloud Native
"你到底在說什么啊,我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后端的服務。
是否有辦法解決呢
Cloud Native
最建議的方式
最好的方式拆分, 集群內和集群外的服務分開兩個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-svc namespace: default spec: ports: - name: http port: 80 protocol: TCP targetPort: 80 selector: app: nginx type: LoadBalancer
集群內訪問ExternalTrafficPolicy
策略有影響嗎?
Cloud Native
我們都知道K8s的nodeport和loadbalancer模式是可以調整外部流量策略的,那么圖中的「外部策略為Local/Cluster,所有集群節點創建IPVS規則是有區別的」該如何解釋呢, 以及集群內訪問nodePort/CLBIP的時候會發生什么。
以下都是針對svc的internalTrafficPolicy都是Cluster或者缺省的情況,這個ServiceInternalTrafficPolicy特性在1.22的K8s中默認開啟,具體參考service-traffic-policy[3]
具體到阿里云容器在不同網絡CNI情況下的數據鏈路,可以參考下面的文章。
此處我們只討論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]。
集群外訪問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。
審核編輯:湯梓紅
-
網卡
+關注
關注
4文章
311瀏覽量
27384 -
客戶端
+關注
關注
1文章
290瀏覽量
16688 -
SVC
+關注
關注
0文章
33瀏覽量
12139 -
阿里云
+關注
關注
3文章
956瀏覽量
43043 -
kubernetes
+關注
關注
0文章
224瀏覽量
8720
原文標題:一次網絡不通"爭吵"引發的思考
文章出處:【微信號:OSC開源社區,微信公眾號:OSC開源社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論