摘要:服務(wù)本身的源碼非常簡(jiǎn)單,只返回客戶端地址,如下所示。結(jié)果顯示用戶的訪問(wèn)地址是一臺(tái)云主機(jī)的內(nèi)網(wǎng)地址,顯然不正確。重新部署服務(wù)后,再用瀏覽器訪問(wèn),可以發(fā)現(xiàn)正確獲取了瀏覽器的訪問(wèn)。
如果是HTTP1.1協(xié)議,一般的反向代理或者負(fù)載均衡設(shè)備(如ULB7)支持X-Forwarded-For頭部字段,會(huì)在用戶的請(qǐng)求報(bào)文中加入類(lèi)似X-Forwarded-For:114.248.238.236的頭部。Web應(yīng)用程序只需要解析該頭部即可獲得用戶真實(shí)IP。
如果是TCP或UDP自定義協(xié)議,可以客戶端在協(xié)議字段里定義一個(gè)大端unsigned字段來(lái)保存自身IP,服務(wù)端把該字段解析出來(lái)然后調(diào)用inet_ntoa(3)等函數(shù)獲得ipv4點(diǎn)分字符串。
如果2中協(xié)議不支持填寫(xiě)自身IP,則服務(wù)端可以通過(guò)socket系統(tǒng)調(diào)用getpeername(2)來(lái)獲取對(duì)端地址。下文討論此方式。
Kubernetes Loadbalancer ULB4碰到的問(wèn)題UK8S使用ULB4和ULB7來(lái)支持Loadbalancer類(lèi)型的Service。對(duì)于ULB7,由于只支持HTTP協(xié)議且默認(rèn)支持X-Forwarded-For頭部,所以Web服務(wù)可以很容易獲取客戶端的真實(shí)IP。但對(duì)于使用ULB4接入的純四層協(xié)議的服務(wù)來(lái)說(shuō),可能需要使用getpeername(2)來(lái)獲取客戶端真實(shí)IP。然而由于目前kube-proxy采用Iptables模式,后端pod內(nèi)的應(yīng)用程序的網(wǎng)絡(luò)庫(kù)調(diào)用getpeername(2)會(huì)無(wú)法獲得正確的IP地址。以下例子可以說(shuō)明問(wèn)題。
部署一個(gè)簡(jiǎn)單的webserver,通過(guò)Loadbalancer ULB4外網(wǎng)模式接入。
apiVersion: v1
kind: Service
metadata:
name: ucloud-nginx
labels:
app: ucloud-nginx
annotations:
service.beta.kubernetes.io/ucloud-load-balancer-type: "outer"
service.beta.kubernetes.io/ucloud-load-balancer-vserver-method: "source"
spec:
type: LoadBalancer
ports:
- protocol: "TCP"
port: 80
targetPort: 12345
selector:
app: ucloud-nginx
---
apiVersion: v1
kind: Pod
metadata:
name: test-nginx
labels:
app: ucloud-nginx
spec:
containers:
- name: nginx
image: uhub.service.ucloud.cn/uk8s/uk8s-helloworld:stable
ports:
- containerPort: 12345
部署完畢后,Service狀態(tài)如下所示,可以通過(guò)EIP 117.50.3.206訪問(wèn)該服務(wù)。
# kubectl get svc ucloud-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ucloud-nginx LoadBalancer 172.17.179.247 117.50.3.206 80:43832/TCP 112s
服務(wù)本身的源碼非常簡(jiǎn)單,只返回客戶端地址,如下所示。
package main
import (
"fmt"
"io"
"log"
"net/http"
"net/http/httputil"
)
func main() {
log.Println("Server hello-world")
http.HandleFunc("/", AppRouter)
http.ListenAndServe(":12345", nil)
}
func AppRouter(w http.ResponseWriter, r *http.Request) {
dump, _ := httputil.DumpRequest(r, false)
log.Printf("%q
", dump)
io.WriteString(w, fmt.Sprintf("Guest come from %v
", r.RemoteAddr))
return
}
在外網(wǎng)通過(guò)瀏覽器訪問(wèn)該服務(wù),如下所示。
結(jié)果顯示用戶的訪問(wèn)IP地址是一臺(tái)云主機(jī)的內(nèi)網(wǎng)IP地址,顯然不正確。
原因解釋Loadbalancer創(chuàng)建成功后,ULB4的VServer將UK8S集群中的每個(gè)Node云主機(jī)節(jié)點(diǎn)作為自身的RS節(jié)點(diǎn),RS端口為Service申明的Port值(注意不是NodePort)。ULB4將訪問(wèn)流量轉(zhuǎn)發(fā)到其中一個(gè)RS后,RS根據(jù)本機(jī)上kube-proxy生成的iptables規(guī)則將流量DNAT到后端Pod中,如下所示。
圖中ULB4先將流量轉(zhuǎn)發(fā)到Node1中,Node1中根據(jù)iptables DNAT規(guī)則,將流量轉(zhuǎn)發(fā)給Node2中的Pod。 需要注意的是,Node1將IP包轉(zhuǎn)發(fā)到Node2前,對(duì)這個(gè)包有一次SNAT操作。準(zhǔn)確地說(shuō),是一次MASQUERADE操作,規(guī)則如下。
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE
這條規(guī)則將源地址改成Node1的本機(jī)地址,即10.9.31.26。當(dāng)然,這個(gè) SNAT 操作只針對(duì)本Service轉(zhuǎn)發(fā)出來(lái)的包,否則普通的IP包也受到影響了,而判定IP包是否由本Service轉(zhuǎn)發(fā)出來(lái)的依據(jù)是改包上是有有個(gè)"0x4000"標(biāo)志,這個(gè)標(biāo)志則是在DNAT操作前打上去的。
由于IP請(qǐng)求包的源地址被修改,Pod內(nèi)的程序網(wǎng)絡(luò)庫(kù)通過(guò)getpeername(2)調(diào)用獲取到的對(duì)端地址是Node1的IP地址而不是客戶端真實(shí)的地址。
為什么需要對(duì)流出的包做SNAT操作呢?
原因比較簡(jiǎn)單。參考下圖,當(dāng)Node1上的Pod處理完請(qǐng)求后,需要發(fā)送響應(yīng)包,如果沒(méi)有SNAT操作,Pod收到的請(qǐng)求包源地址就是client的IP地址,這時(shí)候Pod會(huì)直接將響應(yīng)包發(fā)給client的IP地址,但對(duì)于client程序來(lái)說(shuō),它明明沒(méi)有往PodIP發(fā)送請(qǐng)求包,卻收到來(lái)自Pod的IP包,這個(gè)包很可能會(huì)被client丟棄。而有了SNAT,Pod會(huì)將響應(yīng)包發(fā)給Node1,Node1再根據(jù)DNAT規(guī)則產(chǎn)生的conntrack記錄,將響應(yīng)包通過(guò)返回給client。
client
^
v
ulb4
^
v
node 1 <--- node 2
| ^ SNAT
| | --->
v |
endpoint
如何獲取源IP?對(duì)于Pod需要明確知道客戶端來(lái)源地址的情況,我們需要顯示地將Service的spec.externalTrafficPolicy設(shè)置成Local,如下修改。
apiVersion: v1
kind: Service
metadata:
name: ucloud-nginx
labels:
app: ucloud-nginx
annotations:
service.beta.kubernetes.io/ucloud-load-balancer-type: "outer"
service.beta.kubernetes.io/ucloud-load-balancer-vserver-method: "source"
spec:
type: LoadBalancer
ports:
- protocol: "TCP"
port: 80
targetPort: 12345
selector:
app: ucloud-nginx
externalTrafficPolicy: Local
重新部署服務(wù)后,再用瀏覽器訪問(wèn),可以發(fā)現(xiàn)Pod正確獲取了瀏覽器的訪問(wèn)IP。
而這個(gè)機(jī)制的原理也很簡(jiǎn)單,當(dāng)設(shè)置了externalTrafficPolicy為L(zhǎng)ocal時(shí),Node上的iptables規(guī)則會(huì)設(shè)置只將IP包轉(zhuǎn)發(fā)到在本機(jī)上運(yùn)行的Pod,如果本機(jī)上無(wú)對(duì)應(yīng)Pod在運(yùn)行,此包將被DROP。如下圖,這樣Pod可以直接使用client的源地址進(jìn)行回包而不需要SNAT操作。
client
^
v
ulb4
^ /
/ / VServer健康檢查失敗
/ v X
node 1 node 2
^ |
| |
| v
endpoint
對(duì)于其他未運(yùn)行Service對(duì)應(yīng)Pod的Node節(jié)點(diǎn)來(lái)說(shuō),ULB VServer對(duì)其健康檢查探測(cè)會(huì)因?yàn)閕ptables的DROP規(guī)則而失敗,這樣來(lái)自用戶的請(qǐng)求永遠(yuǎn)不會(huì)被發(fā)往這些節(jié)點(diǎn)上,可以確保這些請(qǐng)求都能被正確響應(yīng)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/126937.html
摘要:原因解釋創(chuàng)建成功后,的將集群中的每個(gè)云主機(jī)節(jié)點(diǎn)作為自身的節(jié)點(diǎn),端口為申明的值注意不是。如何獲取源對(duì)于需要明確知道客戶端來(lái)源地址的情況,我們需要顯示地將的設(shè)置成如下修改。重新部署服務(wù)后,再用瀏覽器訪問(wèn),可以發(fā)現(xiàn)正確獲取了瀏覽器的訪問(wèn)。ULB屬性修改的處理方法如沒(méi)有實(shí)際需要,請(qǐng)避免修改ULB名稱(chēng)及注釋根據(jù)cloudprovider插件使用提醒,由UK8S cloudprovider創(chuàng)建的ULB不...
摘要:詳細(xì)請(qǐng)見(jiàn)產(chǎn)品價(jià)格產(chǎn)品概念使用須知名詞解釋漏洞修復(fù)記錄集群節(jié)點(diǎn)配置推薦模式選擇產(chǎn)品價(jià)格操作指南集群創(chuàng)建需要注意的幾點(diǎn)分別是使用必讀講解使用需要賦予的權(quán)限模式切換的切換等。UK8S概覽UK8S是一項(xiàng)基于Kubernetes的容器管理服務(wù),你可以在UK8S上部署、管理、擴(kuò)展你的容器化應(yīng)用,而無(wú)需關(guān)心Kubernetes集群自身的搭建及維護(hù)等運(yùn)維類(lèi)工作。了解使用UK8S為了讓您更快上手使用,享受UK...
摘要:提供在線升級(jí)的功能,插件升級(jí)不會(huì)影響現(xiàn)有的網(wǎng)絡(luò)。升級(jí)功能開(kāi)啟后,即可看到插件版本信息,點(diǎn)擊升級(jí)即可進(jìn)行升級(jí)。年月日修復(fù)固定意外釋放導(dǎo)致不可用的問(wèn)題修復(fù)搶占文件鎖超時(shí)導(dǎo)致釋放失敗的問(wèn)題插件開(kāi)啟后,將默認(rèn)使用其管理。 網(wǎng)絡(luò)插件 升級(jí)本篇目錄1. 網(wǎng)絡(luò)插件升級(jí)2. 網(wǎng)絡(luò)插件更新紀(jì)要UK8S 提供的 CNI (Container Network Interface)基于 UCloud VPC 網(wǎng)絡(luò)實(shí)...
摘要:更新商店信息查詢應(yīng)用安裝商店應(yīng)用安裝商店應(yīng)用執(zhí)行了安裝商店應(yīng)用的命令后,我們看到了系統(tǒng)返回給我們了安裝的詳細(xì)信息。安裝應(yīng)用安裝商店應(yīng)用按照前文helm工具已經(jīng)安裝完成,接下來(lái)通過(guò)helm客戶端在kubernetes集群中創(chuàng)建一個(gè)應(yīng)用,執(zhí)行安裝前最好先進(jìn)行應(yīng)用商店的同步,以獲得最新的應(yīng)用信息。#更新商店信息 helm repo update #查詢tomcat應(yīng)用 helm search to...
摘要:集群常見(jiàn)問(wèn)題單個(gè)集群最多能添加多少個(gè)節(jié)點(diǎn)當(dāng)前單個(gè)集群對(duì)應(yīng)節(jié)點(diǎn)數(shù)量可查看集群節(jié)點(diǎn)配置推薦。創(chuàng)建失敗,使用發(fā)現(xiàn)報(bào)錯(cuò)為,是啥原因在創(chuàng)建等資源時(shí),都需要扮演云賬戶的身份調(diào)用來(lái)完成相關(guān)操作。集群內(nèi)可以解析,但無(wú)法聯(lián)通外網(wǎng)拉取數(shù)據(jù)失敗。集群常見(jiàn)問(wèn)題單個(gè)集群最多能添加多少個(gè)節(jié)點(diǎn)?A:當(dāng)前單個(gè)UK8S集群對(duì)應(yīng)節(jié)點(diǎn)數(shù)量可查看集群節(jié)點(diǎn)配置推薦。UK8S完全兼容原生Kubernetes API嗎?A:完全兼容。U...
摘要:通過(guò)暴露是社區(qū)的一個(gè)開(kāi)源項(xiàng)目,你可以通過(guò)來(lái)部署更新應(yīng)用排查應(yīng)用故障以及管理集群資源。執(zhí)行以下命令安裝,使用的鏡像已經(jīng)去掉了的證書(shū)限制。不支持的版本范圍。通過(guò)ULB暴露Kubernetes DashboardDashboard是Kubernetes社區(qū)的一個(gè)Web開(kāi)源項(xiàng)目,你可以通過(guò)Dashboard來(lái)部署更新應(yīng)用、排查應(yīng)用故障以及管理Kubernetes集群資源。另外,Dashboard還提...
閱讀 1583·2025-02-07 13:29
閱讀 1008·2024-11-07 18:25
閱讀 131502·2024-02-01 10:43
閱讀 1374·2024-01-31 14:58
閱讀 1149·2024-01-31 14:54
閱讀 83576·2024-01-29 17:11
閱讀 3877·2024-01-25 14:55
閱讀 2395·2023-06-02 13:36