摘要:服務(wù)本身的源碼非常簡單,只返回客戶端地址,如下所示。結(jié)果顯示用戶的訪問地址是一臺云主機(jī)的內(nèi)網(wǎng)地址,顯然不正確。重新部署服務(wù)后,再用瀏覽器訪問,可以發(fā)現(xiàn)正確獲取了瀏覽器的訪問。
如果是HTTP1.1協(xié)議,一般的反向代理或者負(fù)載均衡設(shè)備(如ULB7)支持X-Forwarded-For頭部字段,會在用戶的請求報文中加入類似X-Forwarded-For:114.248.238.236的頭部。Web應(yīng)用程序只需要解析該頭部即可獲得用戶真實(shí)IP。
如果是TCP或UDP自定義協(xié)議,可以客戶端在協(xié)議字段里定義一個大端unsigned字段來保存自身IP,服務(wù)端把該字段解析出來然后調(diào)用inet_ntoa(3)等函數(shù)獲得ipv4點(diǎn)分字符串。
如果2中協(xié)議不支持填寫自身IP,則服務(wù)端可以通過socket系統(tǒng)調(diào)用getpeername(2)來獲取對端地址。下文討論此方式。
Kubernetes Loadbalancer ULB4碰到的問題UK8S使用ULB4和ULB7來支持Loadbalancer類型的Service。對于ULB7,由于只支持HTTP協(xié)議且默認(rèn)支持X-Forwarded-For頭部,所以Web服務(wù)可以很容易獲取客戶端的真實(shí)IP。但對于使用ULB4接入的純四層協(xié)議的服務(wù)來說,可能需要使用getpeername(2)來獲取客戶端真實(shí)IP。然而由于目前kube-proxy采用Iptables模式,后端pod內(nèi)的應(yīng)用程序的網(wǎng)絡(luò)庫調(diào)用getpeername(2)會無法獲得正確的IP地址。以下例子可以說明問題。
部署一個簡單的webserver,通過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)如下所示,可以通過EIP 117.50.3.206訪問該服務(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ù)本身的源碼非常簡單,只返回客戶端地址,如下所示。
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)通過瀏覽器訪問該服務(wù),如下所示。
結(jié)果顯示用戶的訪問IP地址是一臺云主機(jī)的內(nèi)網(wǎng)IP地址,顯然不正確。
原因解釋Loadbalancer創(chuàng)建成功后,ULB4的VServer將UK8S集群中的每個Node云主機(jī)節(jié)點(diǎn)作為自身的RS節(jié)點(diǎn),RS端口為Service申明的Port值(注意不是NodePort)。ULB4將訪問流量轉(zhuǎn)發(fā)到其中一個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前,對這個包有一次SNAT操作。準(zhǔn)確地說,是一次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)然,這個 SNAT 操作只針對本Service轉(zhuǎn)發(fā)出來的包,否則普通的IP包也受到影響了,而判定IP包是否由本Service轉(zhuǎn)發(fā)出來的依據(jù)是改包上是有有個"0x4000"標(biāo)志,這個標(biāo)志則是在DNAT操作前打上去的。
由于IP請求包的源地址被修改,Pod內(nèi)的程序網(wǎng)絡(luò)庫通過getpeername(2)調(diào)用獲取到的對端地址是Node1的IP地址而不是客戶端真實(shí)的地址。
為什么需要對流出的包做SNAT操作呢?
原因比較簡單。參考下圖,當(dāng)Node1上的Pod處理完請求后,需要發(fā)送響應(yīng)包,如果沒有SNAT操作,Pod收到的請求包源地址就是client的IP地址,這時候Pod會直接將響應(yīng)包發(fā)給client的IP地址,但對于client程序來說,它明明沒有往PodIP發(fā)送請求包,卻收到來自Pod的IP包,這個包很可能會被client丟棄。而有了SNAT,Pod會將響應(yīng)包發(fā)給Node1,Node1再根據(jù)DNAT規(guī)則產(chǎn)生的conntrack記錄,將響應(yīng)包通過返回給client。
client
^
v
ulb4
^
v
node 1 <--- node 2
| ^ SNAT
| | --->
v |
endpoint
如何獲取源IP?對于Pod需要明確知道客戶端來源地址的情況,我們需要顯示地將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ù)后,再用瀏覽器訪問,可以發(fā)現(xiàn)Pod正確獲取了瀏覽器的訪問IP。
而這個機(jī)制的原理也很簡單,當(dāng)設(shè)置了externalTrafficPolicy為Local時,Node上的iptables規(guī)則會設(shè)置只將IP包轉(zhuǎn)發(fā)到在本機(jī)上運(yùn)行的Pod,如果本機(jī)上無對應(yīng)Pod在運(yùn)行,此包將被DROP。如下圖,這樣Pod可以直接使用client的源地址進(jìn)行回包而不需要SNAT操作。
client
^
v
ulb4
^ /
/ / VServer健康檢查失敗
/ v X
node 1 node 2
^ |
| |
| v
endpoint
對于其他未運(yùn)行Service對應(yīng)Pod的Node節(jié)點(diǎn)來說,ULB VServer對其健康檢查探測會因為iptables的DROP規(guī)則而失敗,這樣來自用戶的請求永遠(yuǎn)不會被發(fā)往這些節(jié)點(diǎn)上,可以確保這些請求都能被正確響應(yīng)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/126937.html
摘要:原因解釋創(chuàng)建成功后,的將集群中的每個云主機(jī)節(jié)點(diǎn)作為自身的節(jié)點(diǎn),端口為申明的值注意不是。如何獲取源對于需要明確知道客戶端來源地址的情況,我們需要顯示地將的設(shè)置成如下修改。重新部署服務(wù)后,再用瀏覽器訪問,可以發(fā)現(xiàn)正確獲取了瀏覽器的訪問。ULB屬性修改的處理方法如沒有實(shí)際需要,請避免修改ULB名稱及注釋根據(jù)cloudprovider插件使用提醒,由UK8S cloudprovider創(chuàng)建的ULB不...
摘要:詳細(xì)請見產(chǎn)品價格產(chǎn)品概念使用須知名詞解釋漏洞修復(fù)記錄集群節(jié)點(diǎn)配置推薦模式選擇產(chǎn)品價格操作指南集群創(chuàng)建需要注意的幾點(diǎn)分別是使用必讀講解使用需要賦予的權(quán)限模式切換的切換等。UK8S概覽UK8S是一項基于Kubernetes的容器管理服務(wù),你可以在UK8S上部署、管理、擴(kuò)展你的容器化應(yīng)用,而無需關(guān)心Kubernetes集群自身的搭建及維護(hù)等運(yùn)維類工作。了解使用UK8S為了讓您更快上手使用,享受UK...
摘要:提供在線升級的功能,插件升級不會影響現(xiàn)有的網(wǎng)絡(luò)。升級功能開啟后,即可看到插件版本信息,點(diǎn)擊升級即可進(jìn)行升級。年月日修復(fù)固定意外釋放導(dǎo)致不可用的問題修復(fù)搶占文件鎖超時導(dǎo)致釋放失敗的問題插件開啟后,將默認(rèn)使用其管理。 網(wǎng)絡(luò)插件 升級本篇目錄1. 網(wǎng)絡(luò)插件升級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)安裝完成,接下來通過helm客戶端在kubernetes集群中創(chuàng)建一個應(yīng)用,執(zhí)行安裝前最好先進(jìn)行應(yīng)用商店的同步,以獲得最新的應(yīng)用信息。#更新商店信息 helm repo update #查詢tomcat應(yīng)用 helm search to...
摘要:集群常見問題單個集群最多能添加多少個節(jié)點(diǎn)當(dāng)前單個集群對應(yīng)節(jié)點(diǎn)數(shù)量可查看集群節(jié)點(diǎn)配置推薦。創(chuàng)建失敗,使用發(fā)現(xiàn)報錯為,是啥原因在創(chuàng)建等資源時,都需要扮演云賬戶的身份調(diào)用來完成相關(guān)操作。集群內(nèi)可以解析,但無法聯(lián)通外網(wǎng)拉取數(shù)據(jù)失敗。集群常見問題單個集群最多能添加多少個節(jié)點(diǎn)?A:當(dāng)前單個UK8S集群對應(yīng)節(jié)點(diǎn)數(shù)量可查看集群節(jié)點(diǎn)配置推薦。UK8S完全兼容原生Kubernetes API嗎?A:完全兼容。U...
摘要:通過暴露是社區(qū)的一個開源項目,你可以通過來部署更新應(yīng)用排查應(yīng)用故障以及管理集群資源。執(zhí)行以下命令安裝,使用的鏡像已經(jīng)去掉了的證書限制。不支持的版本范圍。通過ULB暴露Kubernetes DashboardDashboard是Kubernetes社區(qū)的一個Web開源項目,你可以通過Dashboard來部署更新應(yīng)用、排查應(yīng)用故障以及管理Kubernetes集群資源。另外,Dashboard還提...
閱讀 836·2025-02-07 13:29
閱讀 644·2024-11-07 18:25
閱讀 131094·2024-02-01 10:43
閱讀 1060·2024-01-31 14:58
閱讀 1022·2024-01-31 14:54
閱讀 83215·2024-01-29 17:11
閱讀 3497·2024-01-25 14:55
閱讀 2217·2023-06-02 13:36