K8s & K3s 對(duì)外服務(wù)暴露分析

背景簡(jiǎn)介

K8s & K3s 將外部流量引入群集有哪些不同方式环础,在何種場(chǎng)景選用那種方式缰趋,我們進(jìn)行如下探討:

  • NodePort
    NodePort在集群中的主機(jī)節(jié)點(diǎn)上為Service提供一個(gè)代理端口券腔,以允許從主機(jī)網(wǎng)絡(luò)上對(duì)Service進(jìn)行訪問。
    NodePort的流量轉(zhuǎn)發(fā)機(jī)制和Cluster IP的iptables模式類似棠涮,唯一不同之處是在主機(jī)網(wǎng)絡(luò)上開了一個(gè)“NodePort”來接受外部流量盟蚣。從上面的規(guī)則也可以看出,在創(chuàng)建Nodeport時(shí)节沦,Kube-proxy也會(huì)同時(shí)為Service創(chuàng)建Cluster IP相關(guān)的iptables規(guī)則键思。


    image

NodePort提供了一種從外部網(wǎng)絡(luò)訪問Kubernetes集群內(nèi)部Service的方法,但該方法存在下面一些限制甫贯,導(dǎo)致這種方式主要適用于程序開發(fā)吼鳞,不適合用于產(chǎn)品部署。

Kubernetes cluster host的IP必須是一個(gè)well-known IP叫搁,即客戶端必須知道該IP赖条。但Cluster中的host是被作為資源池看待的,可以增加刪除常熙,每個(gè)host的IP一般也是動(dòng)態(tài)分配的,因此并不能認(rèn)為host IP對(duì)客戶端而言是well-known IP碱茁。
客戶端訪問某一個(gè)固定的host IP的方式存在單點(diǎn)故障裸卫。假如一臺(tái)host宕機(jī)了,kubernetes cluster會(huì)把應(yīng)用 reload到另一節(jié)點(diǎn)上纽竣,但客戶端就無法通過該host的nodeport訪問應(yīng)用了墓贿。
通過一個(gè)主機(jī)節(jié)點(diǎn)作為網(wǎng)絡(luò)入口,在網(wǎng)絡(luò)流量較大時(shí)存在性能瓶頸蜓氨。

  • LoadBalancer
    Kubernetes提供了LoadBalancer聋袋。通過將Service定義為L(zhǎng)oadBalancer類型,Kubernetes在主機(jī)節(jié)點(diǎn)的NodePort前提供了一個(gè)四層的負(fù)載均衡器穴吹。該四層負(fù)載均衡器負(fù)責(zé)將外部網(wǎng)絡(luò)流量分發(fā)到后面的多個(gè)節(jié)點(diǎn)的NodePort端口上幽勒。
    下圖展示了Kubernetes如何通過LoadBalancer方式對(duì)外提供流量入口,圖中LoadBalancer后面接入了兩個(gè)主機(jī)節(jié)點(diǎn)上的NodePort港令,后端部署了三個(gè)Pod提供服務(wù)啥容。根據(jù)集群的規(guī)模锈颗,可以在LoadBalancer后面可以接入更多的主機(jī)節(jié)點(diǎn),以進(jìn)行負(fù)荷分擔(dān)咪惠。


    image

備注:LoadBalancer類型需要云服務(wù)提供商的支持击吱,Service中的定義只是在Kubernetes配置文件中提出了一個(gè)要求,即為該Service創(chuàng)建Load Balancer遥昧,至于如何創(chuàng)建則是由Google Cloud或Amazon Cloud等云服務(wù)商提供的覆醇,創(chuàng)建的Load Balancer的過程不在Kubernetes Cluster的管理范圍中。

目前WS, Azure, CloudStack, GCE 和 OpenStack 等主流的公有云和私有云提供商都可以為Kubernetes提供Load Balancer炭臭。一般來說永脓,公有云提供商還會(huì)為L(zhǎng)oad Balancer提供一個(gè)External IP,以提供Internet接入徽缚。如果你的產(chǎn)品沒有使用云提供商惜犀,而是自建Kubernetes Cluster,則需要自己提供LoadBalancer题翻。

  • Ingress
    LoadBalancer類型的Service提供的是四層負(fù)載均衡器褐鸥,當(dāng)只需要向外暴露一個(gè)服務(wù)的時(shí)候,采用這種方式是沒有問題的那婉。但當(dāng)一個(gè)應(yīng)用需要對(duì)外提供多個(gè)服務(wù)時(shí)板甘,采用該方式則要求為每一個(gè)四層服務(wù)(IP+Port)都創(chuàng)建一個(gè)外部load balancer。

一般來說详炬,同一個(gè)應(yīng)用的多個(gè)服務(wù)/資源會(huì)放在同一個(gè)域名下盐类,在這種情況下,創(chuàng)建多個(gè)Load balancer是完全沒有必要的呛谜,反而帶來了額外的開銷和管理成本在跳。另外直接將服務(wù)暴露給外部用戶也會(huì)導(dǎo)致了前端和后端的耦合,影響了后端架構(gòu)的靈活性隐岛,如果以后由于業(yè)務(wù)需求對(duì)服務(wù)進(jìn)行調(diào)整會(huì)直接影響到客戶端猫妙。為了解決該問題,可以通過使用Kubernetes Ingress來作為網(wǎng)絡(luò)入口聚凹。
Kubernetes Ingress聲明了一個(gè)應(yīng)用層(OSI七層)的負(fù)載均衡器割坠,可以根據(jù)HTTP請(qǐng)求的內(nèi)容將來自同一個(gè)TCP端口的請(qǐng)求分發(fā)到不同的Kubernetes Service,其功能包括:

  1. 按HTTP請(qǐng)求的URL進(jìn)行路由
    同一個(gè)TCP端口進(jìn)來的流量可以根據(jù)URL路由到Cluster中的不同服務(wù)妒牙,如下圖所示:


    image
  2. 按HTTP請(qǐng)求的Host進(jìn)行路由
    同一個(gè)IP進(jìn)來的流量可以根據(jù)HTTP請(qǐng)求的Host路由到Cluster中的不同服務(wù)彼哼,如下圖所示:


    image

Ingress 規(guī)則定義了對(duì)七層網(wǎng)關(guān)的要求,包括URL分發(fā)規(guī)則湘今,基于不同域名的虛擬主機(jī)敢朱,SSL證書等。Kubernetes使用Ingress Controller 來監(jiān)控Ingress規(guī)則,并通過一個(gè)七層網(wǎng)關(guān)來實(shí)現(xiàn)這些要求蔫饰,一般可以使用Nginx琅豆,HAProxy,Envoy等篓吁。

Ingress配合NodePort和LoadBalancer提供對(duì)外流量入口

雖然Ingress Controller通過七層網(wǎng)關(guān)為后端的多個(gè)Service提供了統(tǒng)一的入口茫因,但由于其部署在集群中,因此并不能直接對(duì)外提供服務(wù)杖剪。實(shí)際上Ingress需要配合NodePort和LoadBalancer才能提供對(duì)外的流量入口冻押,如下圖所示:


image

上圖描述了如何采用Ingress配合NodePort和Load Balancer為集群提供外部流量入口,從該拓?fù)鋱D中可以看到該架構(gòu)的伸縮性非常好盛嘿,在NodePort洛巢,Ingress,Pod等不同的接入層面都可以對(duì)系統(tǒng)進(jìn)行水平擴(kuò)展次兆,以應(yīng)對(duì)不同的外部流量要求稿茉。

上圖只展示了邏輯架構(gòu),下面的圖展示了具體的實(shí)現(xiàn)原理:


image

流量從外部網(wǎng)絡(luò)到達(dá)Pod的完整路徑如下:

  1. 外部請(qǐng)求先通過四層Load Balancer進(jìn)入內(nèi)部網(wǎng)絡(luò)
  2. Load Balancer將流量分發(fā)到后端多個(gè)主機(jī)節(jié)點(diǎn)上的NodePort (userspace轉(zhuǎn)發(fā))
  3. 請(qǐng)求從NodePort進(jìn)入到Ingress Controller (iptabes規(guī)則芥炭,Ingress Controller本身是一個(gè)NodePort類型的Service)
  4. Ingress Controller根據(jù)Ingress rule進(jìn)行七層分發(fā)漓库,根據(jù)HTTP的URL和Host將請(qǐng)求分發(fā)給不同的Service (userspace轉(zhuǎn)發(fā))
  5. Service將請(qǐng)求最終導(dǎo)入到后端提供服務(wù)的Pod中 (iptabes規(guī)則)

從前面的介紹可以看到,K8S Ingress提供了一個(gè)基礎(chǔ)的七層網(wǎng)關(guān)功能的抽象定義园蝠,其作用是對(duì)外提供一個(gè)七層服務(wù)的統(tǒng)一入口渺蒿,并根據(jù)URL/HOST將請(qǐng)求路由到集群內(nèi)部不同的服務(wù)上。

場(chǎng)景應(yīng)用分析

ClusterIP

ClusterIP 服務(wù)是 Kubernetes 的默認(rèn)服務(wù)彪薛。它給你一個(gè)集群內(nèi)的服務(wù)茂装,集群內(nèi)的其它應(yīng)用都可以訪問該服務(wù)。集群外部無法訪問它善延。

ClusterIP 服務(wù)的 YAML 文件類似如下:

apiVersion: v1

kind: Service
metadata:  
name: my-internal-service
selector:    
app: my-app
spec:
type: ClusterIP
ports:  
- name: http
port: 80
targetPort: 80
protocol: TC

從Internet 沒法訪問 ClusterIP 服務(wù)少态,那么為什么要討論它呢?那是因?yàn)槲覀兛梢酝ㄟ^ Kubernetes 的 proxy 模式來訪問該服務(wù)易遣!


image
# 啟動(dòng) Kubernetes proxy 模式:
kubectl proxy --port=8080
# 通過Kubernetes API况增,使用如下模式來訪問這個(gè)服務(wù):
http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>
# 要訪問上面定義的服務(wù),可以使用如下地址:
http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/
何時(shí)使用這種方式训挡?

有一些場(chǎng)景下,你得使用 Kubernetes 的 proxy 模式來訪問你的服務(wù):
由于某些原因歧强,你需要調(diào)試你的服務(wù)澜薄,或者需要直接通過筆記本電腦去訪問它們。
容許內(nèi)部通信摊册,展示內(nèi)部?jī)x表盤等肤京。

這種方式要求我們運(yùn)行 kubectl 作為一個(gè)未認(rèn)證的用戶,因此我們不能用這種方式把服務(wù)暴露到 internet 或者在生產(chǎn)環(huán)境使用。

NodePort

NodePort 服務(wù)是引導(dǎo)外部流量到你的服務(wù)的最原始方式忘分。NodePort棋枕,正如這個(gè)名字所示,在所有節(jié)點(diǎn)(虛擬機(jī))上開放一個(gè)特定端口妒峦,任何發(fā)送到該端口的流量都被轉(zhuǎn)發(fā)到對(duì)應(yīng)服務(wù)重斑。


image

NodePort 服務(wù)的 YAML 文件類似如下:

apiVersion: v1

kind: Service
metadata:  
name: my-nodeport-service
selector:    
app: my-app
spec:
type: NodePort
ports:  
- name: http
port: 80
targetPort: 80
nodePort: 30036
protocol: TC

NodePort 服務(wù)主要有兩點(diǎn)區(qū)別于普通的“ClusterIP”服務(wù)。第一肯骇,它的類型是“NodePort”窥浪。有一個(gè)額外的端口,稱為 nodePort笛丙,它指定節(jié)點(diǎn)上開放的端口值 漾脂。如果你不指定這個(gè)端口,系統(tǒng)將選擇一個(gè)隨機(jī)端口胚鸯。大多數(shù)時(shí)候我們應(yīng)該讓 Kubernetes 來選擇端口骨稿,因?yàn)槿缭u(píng)論中 thockin 所說,用戶自己來選擇可用端口代價(jià)太大姜钳。

何時(shí)使用這種方式坦冠?

這種方法有許多缺點(diǎn):
每個(gè)端口只能是一種服務(wù)
端口范圍只能是 30000-32767
如果節(jié)點(diǎn)/VM 的 IP 地址發(fā)生變化,你需要能處理這種情況傲须。

基于以上原因蓝牲,我不建議在生產(chǎn)環(huán)境上用這種方式暴露服務(wù)。如果你運(yùn)行的服務(wù)不要求一直可用泰讽,或者對(duì)成本比較敏感例衍,你可以使用這種方法。這樣的應(yīng)用的最佳例子是 demo 應(yīng)用已卸,或者某些臨時(shí)應(yīng)用佛玄。

LoadBalancer

LoadBalancer 服務(wù)是暴露服務(wù)到 internet 的標(biāo)準(zhǔn)方式。在 GKE 上累澡,這種方式會(huì)啟動(dòng)一個(gè) Network Load Balancer梦抢,它將給你一個(gè)單獨(dú)的 IP 地址,轉(zhuǎn)發(fā)所有流量到你的服務(wù)愧哟。

image
何時(shí)使用這種方式奥吩?

如果你想要直接暴露服務(wù),這就是默認(rèn)方式蕊梧。所有通往你指定的端口的流量都會(huì)被轉(zhuǎn)發(fā)到對(duì)應(yīng)的服務(wù)霞赫。它沒有過濾條件,沒有路由等肥矢。這意味著你幾乎可以發(fā)送任何種類的流量到該服務(wù)端衰,像 HTTP,TCP,UDP旅东,Websocket灭抑,gRPC 或其它任意種類。

這個(gè)方式的最大缺點(diǎn)是每一個(gè)用 LoadBalancer 暴露的服務(wù)都會(huì)有它自己的 IP 地址抵代,每個(gè)用到的 LoadBalancer 都需要付費(fèi)腾节,這將是非常昂貴的。

Ingress

有別于以上所有例子主守,Ingress 事實(shí)上不是一種服務(wù)類型禀倔。相反,它處于多個(gè)服務(wù)的前端参淫,扮演著“智能路由”或者集群入口的角色救湖。

你可以用 Ingress 來做許多不同的事情,各種不同類型的 Ingress 控制器也有不同的能力涎才。

GKE 上的默認(rèn) ingress 控制器是啟動(dòng)一個(gè) HTTP(S) Load Balancer鞋既。它允許你基于路徑或者子域名來路由流量到后端服務(wù)。例如耍铜,你可以將任何發(fā)往域名 foo.yourdomain.com 的流量轉(zhuǎn)到 foo 服務(wù)邑闺,將路徑 yourdomain.com/bar/path 的流量轉(zhuǎn)到 bar 服務(wù)。


image

GKE 上用 L7 HTTP Load Balancer 生成的 Ingress 對(duì)象的 YAML 文件類似如下:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
backend:
serviceName: other
servicePort: 8080
rules:
- host: foo.mydomain.com
http:
  paths:
  - backend:
      serviceName: foo
      servicePort: 8080
- host: mydomain.com
http:
  paths:
  - path: /bar/*
    backend:
      serviceName: bar
      servicePort: 8080

何時(shí)使用這種方式棕兼?

Ingress 可能是暴露服務(wù)的最強(qiáng)大方式陡舅,但同時(shí)也是最復(fù)雜的。Ingress 控制器有各種類型伴挚,包括 Google Cloud Load Balancer靶衍, Nginx,Contour茎芋,Istio颅眶,等等。它還有各種插件田弥,比如 cert-manager涛酗,它可以為你的服務(wù)自動(dòng)提供 SSL 證書。

如果你想要使用同一個(gè) IP 暴露多個(gè)服務(wù)偷厦,這些服務(wù)都是使用相同的七層協(xié)議(典型如 HTTP)商叹,那么Ingress 就是最有用的。如果你使用本地的 GCP 集成只泼,你只需要為一個(gè)負(fù)載均衡器付費(fèi)剖笙,且由于 Ingress是“智能”的,你還可以獲取各種開箱即用的特性(比如 SSL辜妓,認(rèn)證,路由,等等)籍滴。

拓展閱讀

針對(duì)網(wǎng)絡(luò)流量的負(fù)載均衡酪夷,在實(shí)際生產(chǎn)工作中都是機(jī)其重要的角色的,我們幾乎所有的流量通信服務(wù)都是需要對(duì)外暴露孽惰,這是第一步晚岭,之后才會(huì)開始考慮鑒權(quán),負(fù)載勋功,限流等諸多問題的坦报,所以如何安全合適的暴露我們的流量是一個(gè)值得探討的話題,尤其在微服務(wù)領(lǐng)域狂鞋,當(dāng)開發(fā)人員的所有開發(fā)能力永遠(yuǎn)和 IP+Port 時(shí)片择,技術(shù)人員也應(yīng)該反思下自己的能力了,流量分析的問題是一個(gè)很大的面骚揍,也是從初級(jí)開發(fā)人員邁向高級(jí)/資深工程師的很關(guān)鍵的一步字管。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市信不,隨后出現(xiàn)的幾起案子嘲叔,更是在濱河造成了極大的恐慌,老刑警劉巖抽活,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件硫戈,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡下硕,警方通過查閱死者的電腦和手機(jī)丁逝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來卵牍,“玉大人果港,你說我怎么就攤上這事『迹” “怎么了辛掠?”我有些...
    開封第一講書人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)释牺。 經(jīng)常有香客問我萝衩,道長(zhǎng),這世上最難降的妖魔是什么没咙? 我笑而不...
    開封第一講書人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任猩谊,我火速辦了婚禮,結(jié)果婚禮上祭刚,老公的妹妹穿的比我還像新娘牌捷。我一直安慰自己墙牌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開白布暗甥。 她就那樣靜靜地躺著喜滨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撤防。 梳的紋絲不亂的頭發(fā)上虽风,一...
    開封第一講書人閱讀 52,736評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音寄月,去河邊找鬼辜膝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛漾肮,可吹牛的內(nèi)容都是我干的厂抖。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼初橘,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼验游!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起保檐,我...
    開封第一講書人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤耕蝉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后夜只,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體垒在,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年扔亥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了场躯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡旅挤,死狀恐怖踢关,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情粘茄,我是刑警寧澤签舞,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站柒瓣,受9級(jí)特大地震影響儒搭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芙贫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一搂鲫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧磺平,春花似錦魂仍、人聲如沸拐辽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽薛训。三九已至,卻和暖如春仑氛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背闸英。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工锯岖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人甫何。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓出吹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親辙喂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子捶牢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容