溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

如何深入理解Kubernetes微服務(wù)平臺(tái)

發(fā)布時(shí)間:2021-10-15 14:53:44 來(lái)源:億速云 閱讀:88 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容主要講解“如何深入理解Kubernetes微服務(wù)平臺(tái)”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“如何深入理解Kubernetes微服務(wù)平臺(tái)”吧!

Kubernetes的概念與功能

架構(gòu)師普遍有這樣的愿景:在系統(tǒng)中有ServiceA、ServiceB、ServiceC這3種服務(wù),其中ServiceA需要部署3個(gè)實(shí)例,ServiceB與ServiceC各自需要部署5個(gè)實(shí)例,希望有一個(gè)平臺(tái)(或工具)自動(dòng)完成上述13個(gè)實(shí)例的分布式部署,并且持續(xù)監(jiān)控它們。當(dāng)發(fā)現(xiàn)某個(gè)服務(wù)器宕機(jī)或者某個(gè)服務(wù)實(shí)例發(fā)生故障時(shí),平臺(tái)能夠自我修復(fù),從而確保在任何時(shí)間點(diǎn)正在運(yùn)行的服務(wù)實(shí)例的數(shù)量都符合預(yù)期。這樣一來(lái),團(tuán)隊(duì)只需關(guān)注服務(wù)開(kāi)發(fā)本身,無(wú)須再為基礎(chǔ)設(shè)施和運(yùn)維監(jiān)控的事情頭疼了。

如何深入理解Kubernetes微服務(wù)平臺(tái)

在 Kubernetes出現(xiàn)之前,沒(méi)有一個(gè)平臺(tái)公開(kāi)聲稱(chēng)實(shí)現(xiàn)了上面的愿景。Kubernetes是業(yè)界第一個(gè)將服務(wù)這個(gè)概念真正提升到第一位的平臺(tái)。在Kubernetes的世界里,所有概念與組件都是圍繞Service運(yùn)轉(zhuǎn)的。正是這種突破性的設(shè)計(jì),使Kubernetes真正解決了多年來(lái)困擾我們的分布式系統(tǒng)里的眾多難題,讓團(tuán)隊(duì)有更多的時(shí)間去關(guān)注與業(yè)務(wù)需求和業(yè)務(wù)相關(guān)的代碼本身,從而在很大程度上提高整個(gè)軟件團(tuán)隊(duì)的工作效率與投入產(chǎn)出比。

Kubernetes里的Service其實(shí)就是微服務(wù)架構(gòu)中微服務(wù)的概念,它有以下明顯特點(diǎn)。

  • 每個(gè)Service都分配了一個(gè)固定不變的虛擬IP地址——Cluster IP。

  • 每個(gè)Service都以TCP/UDP方式在一個(gè)或多個(gè)端口 (Service Port)上提供服務(wù)。

  • 客戶(hù)端訪(fǎng)問(wèn)一個(gè) Service時(shí),就好像訪(fǎng)問(wèn)一個(gè)遠(yuǎn)程的TCP/UDP服務(wù),只要與Cluster IP建立連接即可,目標(biāo)端口就是某個(gè)Service Port。

Service既然有了IP地址,就可以順理成章地采用DNS域名的方式來(lái)避免IP地址的變動(dòng)了。Kubernetes 的 DNS組件自動(dòng)為每個(gè)Service都建立了一個(gè)域名與IP的映射表,其中的域名就是Service的Name,IP就是對(duì)應(yīng)的Cluster IP,并且在Kubernetes的每個(gè)Pod(類(lèi)似于Docker'容器)里都設(shè)置了DNS Server為 Kubernetes 的 DNS Server,這樣一來(lái),微服務(wù)架構(gòu)中的服務(wù)發(fā)現(xiàn)這個(gè)基本問(wèn)題得以巧妙解決,不但不用復(fù)雜的服務(wù)發(fā)現(xiàn)API供客戶(hù)端調(diào)用,還使所有以TCP/IP方式通信的分布式系統(tǒng)都能方便地遷移到Kubernetes平臺(tái)上,僅從這個(gè)設(shè)計(jì)來(lái)看,Kubernetes就遠(yuǎn)勝過(guò)其他產(chǎn)品。

我們知道,在每個(gè)微服務(wù)的背后都有多個(gè)進(jìn)程實(shí)例來(lái)提供服務(wù),在Kubernetes平臺(tái)上,這些進(jìn)程實(shí)例被封裝在Pod中,Pod基本上等同于Docker容器,稍有不同的是,Pod其實(shí)是一組密切捆綁在一起并且“同生共死”的 Docker 容器,這組容器共享同一個(gè)網(wǎng)絡(luò)棧與文件系統(tǒng),相互之間沒(méi)有隔離,可以直接在進(jìn)程間通信。最典型的例子是Kubenetes Sky DNS Pod,在這個(gè)Pod里有4個(gè)Docker '容器。

那么,Kubernetes里的 Service 與 Pod 是如何對(duì)應(yīng)的呢?我們?cè)趺粗滥男㏄od 為某個(gè)Service提供具體的服務(wù)?下圖給出了答案——“貼標(biāo)簽”。

如何深入理解Kubernetes微服務(wù)平臺(tái)

每個(gè)Pod都可以貼一個(gè)或多個(gè)不同的標(biāo)簽(Label),而每個(gè)Service都有一個(gè)“標(biāo)簽選擇器”(Label Selector),標(biāo)簽選擇器確定了要選擇擁有哪些標(biāo)簽的對(duì)象。下面這段YAML格式的內(nèi)容定義了一個(gè)被稱(chēng)為ku8-redis-master的Service,它的標(biāo)簽選擇器的內(nèi)容為“app: ku8-redis-master",表明擁有“app= ku8-redis-master”這個(gè)標(biāo)簽的Pod都是為它服務(wù)的:

apiversion: v1 kind: Service metadata: name: ku8-redis-masterspec: ports: - port: 6379selector: app: ku8-redis-master

下面是 ku8-redis-master這個(gè) Pod 的定義,它的 labels屬性的內(nèi)容剛好匹配Service 的標(biāo)簽選擇器的內(nèi)容:

apiversion: v1kind: Pod metadata: name: ku8-redis-masterlabels: app: ku8-redis-master spec: containers: name: serverimage: redisports: -containerPort:6379 restartPolicy: Never

如果我們需要一個(gè)Service在任意時(shí)刻都有N個(gè)Pod實(shí)例來(lái)提供服務(wù),并且在其中1個(gè)Pod實(shí)例發(fā)生故障后,及時(shí)發(fā)現(xiàn)并且自動(dòng)產(chǎn)生一個(gè)新的Pod實(shí)例以彌補(bǔ)空缺,那么我們要怎么做呢?答案就是采用 Deployment/RC,它的作用是告訴Kubernetes,擁有某個(gè)特定標(biāo)簽的 Pod需要在Kubernetes集群中創(chuàng)建幾個(gè)副本實(shí)例。Deployment/RC的定義包括如下兩部分內(nèi)容。

●目標(biāo)Pod的副本數(shù)量(replicas)。

●目標(biāo)Pod的創(chuàng)建模板(Template)。

下面這個(gè)例子定義了一個(gè)RC,目標(biāo)是確保在集群中任意時(shí)刻都有兩個(gè) Pod,其標(biāo)簽為“ app:ku8-redis-slave”,對(duì)應(yīng)的容器鏡像為redis slave,這兩個(gè) Pod 與ku8-redis-master構(gòu)成了Redis主從集群(一主二從):

apiversion :v1 kind: ReplicationControllermetadata: name: ku8-redis-slavespec: replicas: 2template: metadata: labels: app: ku8-redis-slavespec: containers: name: server image: devopsbq/redis-slave env: name: MASTER ADDR value: ku8-redis-masterports: -containerPort:6379

至此,上述YAML文件創(chuàng)建了一個(gè)一主二從的Redis集群,其中Redis Master被定義為一個(gè)微服務(wù),可以被其他Pod或 Service訪(fǎng)問(wèn),如下圖所示。

如何深入理解Kubernetes微服務(wù)平臺(tái)

注意上圖在 ku8-reids-slave的容器中有MASTER_ADDR的環(huán)境變量,這是Redis Master 的地址,這里填寫(xiě)的是“ku8-redis-master”,它是Redis Master Service 的名稱(chēng),之前說(shuō)過(guò):Service的名稱(chēng)就是它的DNS域名,所以Redis Slave容器可以通過(guò)這個(gè)DNS與Redis Master Service進(jìn)行通信,以實(shí)現(xiàn)Redis 主從同步功能。

Kubernetes 的核心概念就是Service、Pod 及 RC/Deployment。圍繞著這三個(gè)核心概念,Kubernetes實(shí)現(xiàn)了有史以來(lái)最強(qiáng)大的基于容器技術(shù)的微服務(wù)架構(gòu)平臺(tái)。比如,在上述Redis集群中,如果我們希望組成一主三從的集群,則只要將控制Redis Slave的 ReplicationController中的replicas改為3,或者用kubectrl scale命令行功能實(shí)現(xiàn)擴(kuò)容即可。命令如下,我們發(fā)現(xiàn),服務(wù)的水平擴(kuò)容變得如此方便:

kubectl scale --replicas=3 rc/ku8-redis-slave

不僅如此,Kubernetes還實(shí)現(xiàn)了水平自動(dòng)擴(kuò)容的高級(jí)特性——HPA ( Horizontal PodAutoscaling ),其原理是基于Pod 的性能度量參數(shù)(CPU utilization和 custom metrics)對(duì)RC/Deployment管理的Pod進(jìn)行自動(dòng)伸縮。舉個(gè)例子,假如我們認(rèn)為上述Redis Slave集群對(duì)應(yīng)的Pod也對(duì)外提供查詢(xún)服務(wù),服務(wù)期間Pod的 CPU利用率會(huì)不斷變化,在這些Pod 的CPU平均利用率超過(guò)80%后,就會(huì)自動(dòng)擴(kuò)容,直到CPU利用率下降到80%以下或者最多達(dá)到5個(gè)副本位置,而在請(qǐng)求的壓力減小后,Pod的副本數(shù)減少為1個(gè),用下面的HPA命令即可實(shí)現(xiàn)這一目標(biāo):

kubectl autoscale rc ku8-redis-slave --min=1 --max=5 --cpu-percent=80

除了很方便地實(shí)現(xiàn)微服務(wù)的水平擴(kuò)容功能,Kubernetes還提供了使用簡(jiǎn)單、功能強(qiáng)大的微服務(wù)滾動(dòng)升級(jí)功能(rolling update),只要一個(gè)簡(jiǎn)單的命令即可快速完成任務(wù)。舉個(gè)例子,假如我們要將上述Redis Slave服務(wù)的鏡像版本從devopsbq/redis-slave升級(jí)為leader/redis-slave,則只要執(zhí)行下面這條命令即可:

kubectl rolling-update ku8-redis-slave --image=leader/redis-slave

滾動(dòng)升級(jí)的原理如下圖所示,Kubernetes在執(zhí)行滾動(dòng)升級(jí)的過(guò)程中,會(huì)創(chuàng)建一個(gè)新的RC,這個(gè)新的RC使用了新的Pod鏡像,然后Kubernetes每隔一段時(shí)間就將舊RC的replicas數(shù)減少一個(gè),導(dǎo)致舊版本的Pod副本數(shù)減少一個(gè),然后將新RC的replicas數(shù)增加一個(gè),于是多出一個(gè)新版本的Pod副本,在升級(jí)的過(guò)程中 Pod副本數(shù)基本保持不變,直到最后所有的副本都變成新的版本,升級(jí)才結(jié)束。

如何深入理解Kubernetes微服務(wù)平臺(tái)

Kubernetes的組成與原理

Kubernetes集群本身作為一個(gè)分布式系統(tǒng),也采用了經(jīng)典的Master-Slave架構(gòu),如下圖所示,集群中有一個(gè)節(jié)點(diǎn)是Master節(jié)點(diǎn),在其上部署了3個(gè)主要的控制程序:API Sever、ControllerManager 及 Scheduler,還部署了Etcd進(jìn)程,用來(lái)持久化存儲(chǔ)Kubernetes管理的資源對(duì)象(如Service、Pod、RC/Deployment)等。

如何深入理解Kubernetes微服務(wù)平臺(tái)

集群中的其他節(jié)點(diǎn)被稱(chēng)為Node節(jié)點(diǎn),屬于工人(Worker 節(jié)點(diǎn)),它們都由Master 節(jié)點(diǎn)領(lǐng)導(dǎo),主要負(fù)責(zé)照顧各自節(jié)點(diǎn)上分配的Pod副本。下面這張圖更加清晰地表明了Kubernetes各個(gè)進(jìn)程之間的交互關(guān)系。

如何深入理解Kubernetes微服務(wù)平臺(tái)

從上圖可以看到,位于中心地位的進(jìn)程是API Server,所有其他進(jìn)程都與它直接交互,其他進(jìn)程之間并不存在直接的交互關(guān)系。那么,APl Server的作用是什么呢?它其實(shí)是Kubernetes的數(shù)據(jù)網(wǎng)關(guān),即所有進(jìn)入Kubernetes 的數(shù)據(jù)都是通過(guò)這個(gè)網(wǎng)關(guān)保存到Etcd數(shù)據(jù)庫(kù)中的,同時(shí)通過(guò)API Server將Eted里變化的數(shù)據(jù)實(shí)時(shí)發(fā)給其他相關(guān)的Kubernetes進(jìn)程。API Server 以REST方式對(duì)外提供接口,這些接口基本上分為以下兩類(lèi)。

  • 所有資源對(duì)象的CRUD API:資源對(duì)象會(huì)被保存到Etcd中存儲(chǔ)并提供Query接口,比如針對(duì)Pod、Service及RC等的操作。

  • 資源對(duì)象的 Watch API:客戶(hù)端用此API來(lái)及時(shí)得到資源變化的相關(guān)通知,比如某個(gè)Service 相關(guān)的Pod實(shí)例被創(chuàng)建成功,或者某個(gè)Pod 狀態(tài)發(fā)生變化等通知,Watch API主要用于Kubernetes 中的高效自動(dòng)控制邏輯。

下面是上圖中其他Kubernetes進(jìn)程的主要功能。

  • controller manager:負(fù)責(zé)所有自動(dòng)化控制事物,比如RC/Deployment的自動(dòng)控制、HPA自動(dòng)水平擴(kuò)容的控制、磁盤(pán)定期清理等各種事務(wù)。

  • scheduler:負(fù)責(zé)Pod 的調(diào)度算法,在一個(gè)新的Pod被創(chuàng)建后,Scheduler根據(jù)算法找到最佳 Node節(jié)點(diǎn),這個(gè)過(guò)程也被稱(chēng)為Pod Binding。

  • kubelet:負(fù)責(zé)本Node節(jié)點(diǎn)上Pod實(shí)例的創(chuàng)建、監(jiān)控、重啟、刪除、狀態(tài)更新、性能采集并定期上報(bào) Pod 及本機(jī) Node節(jié)點(diǎn)的信息給Master節(jié)點(diǎn),由于Pod實(shí)例最終體現(xiàn)為Docker'容器,所以Kubelet還會(huì)與Docker交互。

  • kube-proxy:為 Service的負(fù)載均衡器,負(fù)責(zé)建立Service Cluster IP 到對(duì)應(yīng)的Pod實(shí)例之間的NAT轉(zhuǎn)發(fā)規(guī)則,這是通過(guò)Linux iptables實(shí)現(xiàn)的。

在理解了Kubernetes各個(gè)進(jìn)程的功能后,我們來(lái)看看一個(gè)RC 從YAML定義到最終被部署成多個(gè)Pod 及容器背后所發(fā)生的事情。為了很清晰地說(shuō)明這個(gè)復(fù)雜的流程,這里給出一張示意圖。

如何深入理解Kubernetes微服務(wù)平臺(tái)

首先,在我們通過(guò)kubectrl create命令創(chuàng)建一個(gè)RC(資源對(duì)象)時(shí),kubectrl通過(guò)Create RC這個(gè)REST接口將數(shù)據(jù)提交到APl Server,隨后API Server將數(shù)據(jù)寫(xiě)入Etcd里持久保存。與此同時(shí),Controller Manager監(jiān)聽(tīng)(Watch)所有RC,一旦有RC被寫(xiě)入Etcd中,Controller Manager就得到了通知,它會(huì)讀取RC的定義,然后比較在RC中所控制的Pod 的實(shí)際副本數(shù)與期待值的差異,然后采取對(duì)應(yīng)的行動(dòng)。此刻,Controller Manager 發(fā)現(xiàn)在集群中還沒(méi)有對(duì)應(yīng)的Pod實(shí)例,就根據(jù)RC里的Pod模板(Template)定義,創(chuàng)建一個(gè)Pod并通過(guò)API Server保存到Etcd中。類(lèi)似地,Scheduler進(jìn)程監(jiān)聽(tīng)所有 Pod,一旦發(fā)現(xiàn)系統(tǒng)產(chǎn)生了一個(gè)新生的Pod,就開(kāi)始執(zhí)行調(diào)度邏輯,為該P(yáng)od 安排一個(gè)新家(Node),如果一切順利,該P(yáng)od就被安排到某個(gè)Node節(jié)點(diǎn)上,即Binding to a Node。接下來(lái),Scheduler進(jìn)程就把這個(gè)信息及 Pod狀態(tài)更新到Etcd里,最后,目標(biāo)Node節(jié)點(diǎn)上的Kubelet監(jiān)聽(tīng)到有新的Pod被安排到自己這里來(lái)了,就按照Pod里的定義,拉取容器的鏡像并且創(chuàng)建對(duì)應(yīng)的容器。在容器成功創(chuàng)建后,Kubelet進(jìn)程再把 Pod的狀態(tài)更新為Running 并通過(guò)API Server更新到 Etcd 中。如果此 Pod還有對(duì)應(yīng)的Service,每個(gè)Node上的Kube-proxy進(jìn)程就會(huì)監(jiān)聽(tīng)所有Service及這些Service對(duì)應(yīng)的Pod實(shí)例的變化,一旦發(fā)現(xiàn)有變化,就會(huì)在所在 Node節(jié)點(diǎn)上的 iptables 里增加或者刪除對(duì)應(yīng)的NAT轉(zhuǎn)發(fā)規(guī)則,最終實(shí)現(xiàn)了Service的智能負(fù)載均衡功能,這一切都是自動(dòng)完成的,無(wú)須人工干預(yù)。

那么,如果某個(gè)Node'宕機(jī),則會(huì)發(fā)生什么事情呢?假如某個(gè)Node宕機(jī)一段時(shí)間,則因?yàn)樵诖斯?jié)點(diǎn)上沒(méi)有Kubelet進(jìn)程定時(shí)匯報(bào)這些Pod 的狀態(tài),因此這個(gè)Node 上的所有Pod'實(shí)例都會(huì)被判定為失敗狀態(tài),此時(shí)Controller Manager會(huì)將這些Pod刪除并產(chǎn)生新的Pod實(shí)例,于是這些Pod被調(diào)度到其他 Node 上創(chuàng)建出來(lái),系統(tǒng)自動(dòng)恢復(fù)。

本節(jié)最后說(shuō)說(shuō)Kube-proxy的演變,如下圖所示。

如何深入理解Kubernetes微服務(wù)平臺(tái)

Kube-proxy一開(kāi)始是一個(gè)類(lèi)似于HAProxy的代理服務(wù)器,實(shí)現(xiàn)了基于軟件的負(fù)載均衡功能,將Client 發(fā)起的請(qǐng)求代理到后端的某個(gè)Pod 上,可以將其理解為Kubernetes Service的負(fù)載均衡器。Kube-proxy最初的實(shí)現(xiàn)機(jī)制是操控 iptables規(guī)則,將訪(fǎng)問(wèn)Cluster IP 的流量通過(guò)NAT方式重定向到本機(jī)的Kube-proxy,在這個(gè)過(guò)程中涉及網(wǎng)絡(luò)報(bào)文從內(nèi)核態(tài)到用戶(hù)態(tài)的多次復(fù)制,因此效率不高。Kube-proxy 之后的版本改變了實(shí)現(xiàn)方式,在生成 iptables規(guī)則時(shí),直接NAT 到目標(biāo)Pod地址,不再通過(guò)Kube-proxy進(jìn)行轉(zhuǎn)發(fā),因此效率更高、速度更快,采用這種方式比采用客戶(hù)端負(fù)載均衡方式效率稍差一點(diǎn),但編程簡(jiǎn)單,而且與具體的通信協(xié)議無(wú)關(guān),適用范圍更廣。此時(shí),我們可以認(rèn)為Kubernetes Service基于 iptables機(jī)制來(lái)實(shí)現(xiàn)路由和負(fù)載均衡機(jī)制,從此以后,Kube-proxy已不再是一個(gè)真正的“proxy"”,僅僅是路由規(guī)則配置的一個(gè)工具類(lèi)“代理”。

基于iptables 實(shí)現(xiàn)的路由和負(fù)載均衡機(jī)制雖然在性能方面比普通Proxy提升了很多,但也存在自身的固有缺陷,因?yàn)槊總€(gè)Service都會(huì)產(chǎn)生一定數(shù)量的 iptables 規(guī)則。在Service數(shù)量比較多的情況下,iptables 的規(guī)則數(shù)量會(huì)激增,對(duì)iptables的轉(zhuǎn)發(fā)效率及對(duì)Linux內(nèi)核的穩(wěn)定性都造成一定的沖擊。因此很多人都在嘗試將IPVS(IP虛擬服務(wù)器)代替iptables。Kubernetes 從 1.8版本開(kāi)始,新增了Kube-proxy對(duì)IPVS的支持,在1.11版本中正式納入 GA。與 iptables 不同, IPVS本身就被定位為L(zhǎng)inux官方標(biāo)準(zhǔn)中TCP/UDP服務(wù)的負(fù)載均衡器解決方案,因此非常適合代替iptables來(lái)實(shí)現(xiàn) Service的路由和負(fù)載均衡。

此外,也有一些機(jī)制來(lái)代替 Kube-proxy,比如Service Mesh 中的 SideCar 完全代替了Kube-proxy的功能。在 Service 都基于HTTP接口的情況下,我們會(huì)有更多的選擇方式,比如Ingress、Nginx 等。

基于Kubernetes 的 PaaS平臺(tái)

PaaS其實(shí)是一個(gè)重量級(jí)但不怎么成功的產(chǎn)品,受限于多語(yǔ)言支持和開(kāi)發(fā)模式的僵硬,但近期又隨著容器技術(shù)及云計(jì)算的發(fā)展,重新引發(fā)了人們的關(guān)注,這是因?yàn)槿萜骷夹g(shù)徹底解決了應(yīng)用打包部署和自動(dòng)化的難題?;谌萜骷夹g(shù)重新設(shè)計(jì)和實(shí)現(xiàn)的PaaS平臺(tái),既提升了平臺(tái)的技術(shù)含量,又很好地彌補(bǔ)了之前PaaS平臺(tái)難用、復(fù)雜、自動(dòng)化水平低等缺點(diǎn)。

OpenShift是由 RedHat公司于2011年推出的PaaS云計(jì)算平臺(tái),在Kubernetes推出之前,OpenShift 就已經(jīng)演變?yōu)閮蓚€(gè)版本(v1與v2),但在 Kubernetes推出之后,OpenShift的第3個(gè)版本v3放棄了自己的容器引擎與容器編排模塊,轉(zhuǎn)而全面擁抱Kubernetes。

Kubernetes 擁有如下特性。

  • Pod(容器)可以讓開(kāi)發(fā)者將一個(gè)或多個(gè)容器整體作為一個(gè)“原子單元”進(jìn)行部署。

  • 采用固定的Cluster IP及內(nèi)嵌的DNS這種獨(dú)特設(shè)計(jì)思路的服務(wù)發(fā)現(xiàn)機(jī)制,讓不同的Service很容易相互關(guān)聯(lián)(Link)。

  • RC可以保證我們關(guān)注的Pod副本的實(shí)例數(shù)量始終符合我們的預(yù)期。

  • 非常強(qiáng)大的網(wǎng)絡(luò)模型,讓不同主機(jī)上的Pod能夠相互通信。

  • 支持有狀態(tài)服務(wù)與無(wú)狀態(tài)服務(wù),能夠?qū)⒊志没鎯?chǔ)也編排到容器中以支持有狀態(tài)服務(wù)。

  • 簡(jiǎn)單易用的編排模型,讓用戶(hù)很容易編排一個(gè)復(fù)雜的應(yīng)用。

國(guó)內(nèi)外已經(jīng)有很多公司采用了Kubernetes作為它們的PaaS平臺(tái)的內(nèi)核,所以本節(jié)講解如何基于Kubernetes 設(shè)計(jì)和實(shí)現(xiàn)一個(gè)強(qiáng)大的 PaaS平臺(tái)。

一個(gè) PaaS平臺(tái)應(yīng)該具備如下關(guān)鍵特性。

  • 多租戶(hù)支持:這里的租戶(hù)可以是開(kāi)發(fā)廠(chǎng)商或者應(yīng)用本身。

  • 應(yīng)用的全生命周期管理:比如對(duì)應(yīng)用的定義、部署、升級(jí)、下架等環(huán)節(jié)的支持。

  • 具有完備的基礎(chǔ)服務(wù)設(shè)施:比如單點(diǎn)登錄服務(wù)、基于角色的用戶(hù)權(quán)限服務(wù)、應(yīng)用配置服務(wù)、日志服務(wù)等,同時(shí)PaaS平臺(tái)集成了很多常見(jiàn)的中間件以方便應(yīng)用調(diào)用,這些常見(jiàn)的中間件有消息隊(duì)列、分布式文件系統(tǒng)、緩存中間件等。

  • 多語(yǔ)言支持:一個(gè)好的PaaS平臺(tái)可以支持多種常見(jiàn)的開(kāi)發(fā)語(yǔ)言,例如Java、Node.js、PHP、Python、C++等。

接下來(lái),我們看看基于Kubernetes 設(shè)計(jì)和實(shí)現(xiàn)的PaaS平臺(tái)是如何支持上述關(guān)鍵特性的。

如何實(shí)現(xiàn)多租戶(hù)

Kubernetes通過(guò)Namespace特性來(lái)支持多租戶(hù)功能。

我們可以創(chuàng)建多個(gè)不同的Namespace資源對(duì)象,每個(gè)租戶(hù)都有一個(gè)Namespace,在不同的Namespace下創(chuàng)建的Pod、Service 與RC等資源對(duì)象是無(wú)法在另外一個(gè)Namespace下看到的,于是形成了邏輯上的多租戶(hù)隔離特性。但單純的Namespace隔離并不能阻止不同Namespace下的網(wǎng)絡(luò)隔離,如果知道其他Namespace中的某個(gè) Pod的IP地址,則我們還是可以發(fā)起訪(fǎng)問(wèn)的,如下圖所示。

如何深入理解Kubernetes微服務(wù)平臺(tái)

針對(duì)多租戶(hù)的網(wǎng)絡(luò)隔離問(wèn)題,Kubernetes增加了Network Policy這一特性,我們簡(jiǎn)單地將它類(lèi)比為網(wǎng)絡(luò)防火墻,通過(guò)定義Network Policy資源對(duì)象,我們可以控制一個(gè)Namespace(租戶(hù))下的Pod被哪些Namespace訪(fǎng)問(wèn)。假如我們有兩個(gè)Namespace,分別為tenant2、tenant3,各自擁有一些Pod,如下圖所示。

如何深入理解Kubernetes微服務(wù)平臺(tái)

假如我們需要實(shí)現(xiàn)這些網(wǎng)絡(luò)隔離目標(biāo): tenant3里擁有role:db標(biāo)簽的Pod只能被tenant3(本Namespace中)里擁有role:frontend標(biāo)簽的Pod訪(fǎng)問(wèn),或者被tenent2里的任意Pod訪(fǎng)問(wèn),則我們可以定義如下圖所示的一個(gè)Network Policy資源對(duì)象,并通過(guò)kubectrl工具發(fā)布到Kubernetes集群中生效即可。

如何深入理解Kubernetes微服務(wù)平臺(tái)

需要注意的是,Kubernetes Network Policy需要配合特定的CNI網(wǎng)絡(luò)插件才能真正生效,目前支持Network Policy 的CNI 插件主要有以下幾種。

  • Calico:基于三層路由實(shí)現(xiàn)的容器網(wǎng)絡(luò)方案。

  • Weave Net:基于報(bào)文封裝的二層容器解決方案。

  • Romana:類(lèi)似于Calico的容器網(wǎng)絡(luò)方案。

Network Policy目前也才剛剛起步,還有很多問(wèn)題需要去研究和解決,比如如何定義Service的訪(fǎng)問(wèn)策略?如果Service訪(fǎng)問(wèn)策略與Pod訪(fǎng)問(wèn)策略沖突又該如何解決﹖此外,外部服務(wù)的訪(fǎng)問(wèn)策略又該如何定義?總之,在容器領(lǐng)域,相對(duì)于計(jì)算虛擬化、存儲(chǔ)虛擬化來(lái)說(shuō),網(wǎng)絡(luò)虛擬化中的很多技術(shù)才剛剛起步。

Kubernetes 的 Namespace是從邏輯上隔離不同租戶(hù)的程序,但多個(gè)租戶(hù)的程序還是可能被調(diào)度到同一個(gè)物理機(jī)(Node)上的,如果我們希望不同租戶(hù)的應(yīng)用被調(diào)度到不同的Node 上,從而做到物理上的隔離,則可以通過(guò)集群分區(qū)的方式來(lái)實(shí)現(xiàn)。具體做法是我們先按照租戶(hù)將整個(gè)集群劃分為不同的分區(qū)(Partition),如下圖所示,對(duì)每個(gè)分區(qū)里的所有 Node 都打上同樣的標(biāo)簽,比如租戶(hù) a(tanenta)的標(biāo)簽為partition=tenant,租戶(hù) b( tanentb)的標(biāo)簽為partition= tenantb,我們?cè)谡{(diào)度Pod 的時(shí)候可以使用nodeSelector屬性來(lái)指定目標(biāo)Node的標(biāo)簽,比如下面的寫(xiě)法表示Pod需要被調(diào)度到租戶(hù) a的分區(qū)節(jié)點(diǎn)上:

nodeSelector: partition: tenanta

如何深入理解Kubernetes微服務(wù)平臺(tái)

Kubernetes 分區(qū)與租戶(hù)可以有多種對(duì)應(yīng)的設(shè)計(jì),上面所說(shuō)的一個(gè)分區(qū)一個(gè)租戶(hù)的設(shè)計(jì)是一種典型的設(shè)計(jì),也可以將租戶(hù)分為大客戶(hù)與普通客戶(hù),每個(gè)大客戶(hù)都有一個(gè)單獨(dú)的資源分區(qū),而普通客戶(hù)可以以N個(gè)為一組,共享同一個(gè)分區(qū)的資源。

PaaS 平臺(tái)的領(lǐng)域模型設(shè)計(jì)

我們知道,微服務(wù)架構(gòu)下的一個(gè)應(yīng)用通常是由多個(gè)微服務(wù)所組成的,而我們的Kubernetes通常會(huì)部署多個(gè)獨(dú)立的應(yīng)用,因此,如果用 Kubernetes建模微服務(wù)應(yīng)用,則我們需要在 PaaS平臺(tái)的領(lǐng)域模型中設(shè)計(jì)出 Application這個(gè)領(lǐng)域?qū)ο螅粋€(gè)Application包括多個(gè)微服務(wù),并且最終在發(fā)布(部署)時(shí)會(huì)生成對(duì)應(yīng)的Pod、Deployment 及 Service對(duì)象,如下圖所示。

如何深入理解Kubernetes微服務(wù)平臺(tái)

如下所示是有更多細(xì)節(jié)的領(lǐng)域模型圖,Kubernetes中的 Node、Namespace分別被建模為K8sNode與TanentNS,分區(qū)則被建模為ResPartition對(duì)象,每個(gè)分區(qū)都可以包括1到N個(gè)TanentNS,即一個(gè)或多個(gè)租戶(hù)(Tanent〉使用。每個(gè)租戶(hù)都包括一些用戶(hù)賬號(hào)(User),用來(lái)定義和維護(hù)本租戶(hù)的應(yīng)用(Application)。為了分離權(quán)限,可以使用用戶(hù)組(User Group)的方式,同時(shí)可以增加標(biāo)準(zhǔn)的基于角色的權(quán)限模型。

如何深入理解Kubernetes微服務(wù)平臺(tái)

上圖中的Service領(lǐng)域?qū)ο蟛⒉皇荎ubernetes Service,而是包括了Kubernetes Service及相關(guān)RC/Deployment的一個(gè)“復(fù)合結(jié)構(gòu)”。在Service領(lǐng)域?qū)ο笾兄话吮匾娜繉傩?,在部署?yīng)用時(shí)會(huì)生成對(duì)應(yīng)的Kubernetes Service和RC/Deployment實(shí)例。下圖給出了Service的定義界面(原型)。

如何深入理解Kubernetes微服務(wù)平臺(tái)

我們?cè)诮缑嫔贤瓿蓪?duì)一個(gè)Application的定義后,就可以發(fā)布應(yīng)用了。在發(fā)布應(yīng)用的過(guò)程中,先要選擇某個(gè)分區(qū),然后程序調(diào)用Kubernetes的 API接口,創(chuàng)建此 Application相關(guān)的所有Kubernetes資源對(duì)象,然后查詢(xún)Pod的狀態(tài)即可判斷是否發(fā)布成功及失敗的具體原因。下面給出了Application從定義到發(fā)布的關(guān)鍵模塊的設(shè)計(jì)示意圖。

如何深入理解Kubernetes微服務(wù)平臺(tái)

我們知道Kubernetes是基于容器技術(shù)的微服務(wù)架構(gòu)平臺(tái),每個(gè)微服務(wù)的二進(jìn)制文件都被打包成標(biāo)準(zhǔn)的Docker鏡像,因此應(yīng)用的全生命周期管理過(guò)程的第一步,就是從源碼到Docker鏡像的打包,而這個(gè)過(guò)程很容易實(shí)現(xiàn)自動(dòng)化,我們既可以通過(guò)編程方式實(shí)現(xiàn),也可以通過(guò)成熟的第三方開(kāi)源項(xiàng)目實(shí)現(xiàn),這里推薦使用Jenkins。下圖是Jenkins實(shí)現(xiàn)鏡像打包流程的示意圖,考慮到Jenkins的強(qiáng)大和用戶(hù)群廣泛,很多PaaS平臺(tái)都集成了Jenkins 以實(shí)現(xiàn)應(yīng)用的全生命周期管理功能。

如何深入理解Kubernetes微服務(wù)平臺(tái)

PaaS 平臺(tái)的基礎(chǔ)中間件

一個(gè)完備的PaaS平臺(tái)必須集成和提供一些常見(jiàn)的中間件,以方便應(yīng)用開(kāi)發(fā)和托管運(yùn)行。首先,第1類(lèi)重要的基礎(chǔ)中間件是 ZooKeeper,ZooKeeper非常容易被部署到Kubernetes集群中,在Kubernetes 的 GitHub上有一個(gè)YAML參考文件。ZooKeeper除了給應(yīng)用使用,也可以作為PaaS平臺(tái)面向應(yīng)用提供的“集中配置服務(wù)”的基礎(chǔ)組成部分,如下圖所示。

如何深入理解Kubernetes微服務(wù)平臺(tái)

此外,考慮到很多開(kāi)源分布式系統(tǒng)都采用了ZooKeeper來(lái)管理集群,所以我們也可以部署一個(gè)標(biāo)準(zhǔn)命名的ZooKeeper Service,以供這些集群共享使用。

第2類(lèi)重要的中間件就是緩存中間件了,比如我們之前提到的Redis 及 Memcache,它們也很容易被部署到Kubernetes集群中,作為基礎(chǔ)服務(wù)提供給第三方應(yīng)用使用。在Kubernetes的入門(mén)案例中有一個(gè)GuestBook例子,演示了在PHP頁(yè)面中訪(fǎng)問(wèn)Redis主從集群的方法,即使是復(fù)雜的Codis集群,也可以被成功部署到Kubernetes集群中。此外,RedHat 的J2EE內(nèi)存緩存中間件Infinispan也有Kubernetes集群部署的案例。

第3類(lèi)重要的中間件是消息隊(duì)列中間件,不管是經(jīng)典的ActiveMQ、RabbitMQ還是新一代的Kafka,這些消息中間件也很容易被部署到Kubernetes集群中提供服務(wù)。下圖是一個(gè)3節(jié)點(diǎn)的RabbitMQ集群在Kubernetes平臺(tái)上的建模示意圖。為了組成RabbitMQ集群,我們定義了3個(gè)Pod,每個(gè)Pod都對(duì)應(yīng)一個(gè)Kubernetes Service,從而映射到3個(gè)RabbitMQ Server 實(shí)例,此外,我們定義了一個(gè)單獨(dú)的Service,名為 ku8-rabbit-mq-server,此 Service對(duì)外提供服務(wù),并且對(duì)應(yīng)到上述3個(gè)Pod 上,于是每個(gè)Pod都有兩個(gè)標(biāo)簽。

如何深入理解Kubernetes微服務(wù)平臺(tái)

第4類(lèi)重要的中間件是分布式存儲(chǔ)中間件,目前在Kubernetes集群上可以使用Ceph集群提供的塊存儲(chǔ)服務(wù)及GlusterFS提供的分布式文件存儲(chǔ)服務(wù),其中 GlusterFS被RedHat的OpenShift平臺(tái)建議為文件存儲(chǔ)的標(biāo)配存儲(chǔ)系統(tǒng),下面是這種方案的示意圖。

如何深入理解Kubernetes微服務(wù)平臺(tái)

在 RedHat的方案中,GlusterFS集群被部署在獨(dú)立的服務(wù)器集群上,這適用于較大的集群規(guī)模及對(duì)性能和存儲(chǔ)要求高的場(chǎng)景。在機(jī)器有限的情況下,我們也可以把Kubernetes集群的每個(gè)Node節(jié)點(diǎn)都當(dāng)作一個(gè)GlusterFS的存儲(chǔ)節(jié)點(diǎn),并采用DaemonSet的調(diào)度方式將GlusterFS部署到Kubernetes集群上,具體的部署方式在Kubernetes 的 GitHub網(wǎng)站中有詳細(xì)的說(shuō)明文檔,以Pod方式部署GlusterFS集群也使得GlusterFS 的部署和運(yùn)維都變得非常簡(jiǎn)單。

提供全文檢索能力的ElasticSearch集群也很容易被部署到Kubernetes中,前面提到的日志集中收集與查詢(xún)分析的三件套ELK目前基本上全部以Pod的方式部署,以實(shí)現(xiàn)Kubernetes集群日志與用戶(hù)應(yīng)用日志的統(tǒng)一收集、查詢(xún)、分析等功能。

在當(dāng)前熱門(mén)的大數(shù)據(jù)領(lǐng)域中,很多系統(tǒng)也都能以容器化方式部署到Kubernetes集群中,比如Hadoop、HBase、Spark 及 Storm等重量級(jí)集群。下一節(jié)將給出 Storm On Kubernetes 的建模方案,并且將其部署到Kubernetes集群中,最后提交第6章的WordCountTopology 作業(yè)并且觀(guān)察運(yùn)行結(jié)果。

Storm On Kubernetes 實(shí)戰(zhàn)

通過(guò)第6章的學(xué)習(xí),我們知道一個(gè) Storm集群是由ZooKeeper、Nimbus (Master)及一些Supervisor (Slave)節(jié)點(diǎn)組成的,集群的配置文件默認(rèn)保存在 conf/storm.yaml中,最關(guān)鍵的配置參數(shù)如下。

  • storm.zookeeper.servers: ZooKeeper集群的節(jié)點(diǎn)IP地址列表。

  • nimbus.seeds:Nimbus的IP地址。

  • supervisor.slots.ports:Supervisor 中的Worker 監(jiān)聽(tīng)端口列表。

從上述關(guān)鍵配置信息及Storm集群的工作原理來(lái)看,我們首先需要將ZooKeeper建模為Kubernetes Service,以便提供一個(gè)固定的域名地址,使得Nimbus 與Supervisor能夠訪(fǎng)問(wèn)它。下面是ZooKeeper 的建模過(guò)程(為了簡(jiǎn)單起見(jiàn),我們只建模一個(gè)ZooKeeper節(jié)點(diǎn))。

首先,定義ZooKeeper對(duì)應(yīng)的Service,Service名稱(chēng)為ku8-zookeeper,關(guān)聯(lián)的標(biāo)簽為app=ku8-zookeeper 的Pod:

apiVersion: v1kind: Servicemetadata: name: ku8-zookeeperspec: ports: name: clientport: 2181selector: app: ku8-zookeeper

其次,定義ZooKeeper對(duì)應(yīng)的RC:

apiversion: v1 kind: Replicationcontrollermetadata: name: ku8-zookeeper-lspec: replicas: 1template: metadata: labels: app: ku8-zookeeperspec: containers: name: server image: jplock/ zookeeper imagePu1lPolicy: IfNotPresentports: -containerPort: 2181

接下來(lái),我們需要將Nimbus也建模為Kubernetes Service,因?yàn)镾torm客戶(hù)端需要直接訪(fǎng)問(wèn)Nimbus服務(wù)以提交拓?fù)淙蝿?wù),所以在conf/storm.yaml中存在nimbus.sceds參數(shù)。由于Nimbus在6627端口上提供了基于Thrift的 RPC服務(wù),因此對(duì)Nimbus服務(wù)的定義如下:

apiversion: v1kind: Servicemetadata: name: nimbusspec: selector: app: storm-nimbusports: -name: nimbus-rpc port: 6627 targetPort:6627

考慮到在storm.yaml配置文件中有很多參數(shù),所以為了實(shí)現(xiàn)任意參數(shù)的可配置性,我們可以用Kubernetes的Config Map資源對(duì)象來(lái)保存storm.yaml,并映射到Nimbus(以及 Supervisor)節(jié)點(diǎn)對(duì)應(yīng)的Pod實(shí)例上。下面是在本案例中使用的storm.yaml 文件(storm-conf.yaml)的內(nèi)容:

storm.zookeeper.servers: [ku8-zookeeper] nimbus.seeds: [nimbus]storm.log.dir: "log" storm. local.dir: "storm-data"supervisor.slots.ports: -6700 670167026703

將上述配置文件創(chuàng)建為對(duì)應(yīng)的ConfigMap ( storm-config),可以執(zhí)行下面的命令:

kubelet create configmap storm-config --from-file=storm-conf.yaml

然后,storm-config 就可以被任意Pod 以 Volume方式掛載到容器內(nèi)的任意指定路徑上了。接下來(lái),我們可以繼續(xù)建模 Nimbus服務(wù)對(duì)應(yīng)的Pod。在從Docker Hub上搜尋相關(guān) Storm鏡像并進(jìn)行分析后,我們選擇了Docker 官方提供的鏡像storm:1.0。相對(duì)于其他Storm鏡像來(lái)說(shuō),官方維護(hù)的這個(gè)鏡像有以下優(yōu)點(diǎn)。

  • Storm版本新。

  • Storm整體只有一個(gè)鏡像,通過(guò)容器的command 命令參數(shù)來(lái)決定啟動(dòng)的是哪種類(lèi)型的節(jié)點(diǎn),比如Nimbus主節(jié)點(diǎn)、Nimbus-ui管理器或者Supervisor 從節(jié)點(diǎn)。

  • 標(biāo)準(zhǔn)化的Storm進(jìn)程啟動(dòng)方式,可以將conf/storm.yaml配置文件映射到容器外,因此可以采用Kubernetes 的 ConfigMap特性。

采用storm:1.0鏡像定義Nimbus Pod的YAML文件如下:

apiversion: v1kind: Pod metadata: name: nimbuslabels: app: storm-nimbusspec: volumes: name: config-volumeconfigMap: name: storm-configitems: 一key:storm-conf.yaml path:storm.yaml containers: - name: nimbus image: storm: 1.0 imagePullPolicy: IfNotPresentports: -containerPort: 6627 command:【"storm" ,"nimbus" ]volumeMounts: - name: config-volumemountPath: /conf restartPolicy: Always

這里我們需要關(guān)注兩個(gè)細(xì)節(jié):第1個(gè)細(xì)節(jié)是ConfigMap 的使用方法,首先要把之前定義的ConfigMap ——storm-config映射為Pod的一個(gè)Volume,然后在容器中將此Volume掛接到某個(gè)具體的路徑上;第2個(gè)細(xì)節(jié)是容器的參數(shù) command,上面的command: [ "storm" , "nimbus"]表示此容器啟動(dòng)的是nimus進(jìn)程。

類(lèi)似地,我們定義storm-ui服務(wù),這是一個(gè)Web管理程序,提供了圖形化的Storm管理功能,因?yàn)樾枰贙ubernetes集群之外訪(fǎng)問(wèn)它,所以我們通過(guò)NodePort方式映射8080端口到主機(jī)上的30010。storm-ui服務(wù)的YAML定義文件如下:

apiversion: v1kind: Servicemetadata: name: storm-uispec: type: NodePortselector: app:storm-uiports: -name: web port: 8080 targetPort: 8080nodePort:30010

最后,我們來(lái)建模Supervisor。Supervisor看似不需要被建模為Service,因?yàn)镾upervisor 不會(huì)被主動(dòng)調(diào)用,但實(shí)際上Supervisor節(jié)點(diǎn)之間會(huì)相互發(fā)起通信,因此Supervisor節(jié)點(diǎn)注冊(cè)到ZooKeeper 上的地址必須能被相互訪(fǎng)問(wèn),在 Kubernetes平臺(tái)上有兩種方式解決此問(wèn)題。

第1種方式,Supervisor節(jié)點(diǎn)注冊(cè)到ZooKeeper上時(shí),不用主機(jī)名(Pod名稱(chēng)),而是采用Pod的P地址。

第2種方式,用Headless Service模式,每個(gè)Supervisor節(jié)點(diǎn)都被建模為一個(gè)HeadlessService,并且確保Supervisor節(jié)點(diǎn)的容器名稱(chēng)(主機(jī)名)與Headless Service的名稱(chēng)一樣,此時(shí)Supervisor節(jié)點(diǎn)注冊(cè)到ZooKeeper 上的地址就跟Headless Service名稱(chēng)一樣了,Supervisor節(jié)點(diǎn)之間都能用對(duì)方的Headless Service的域名進(jìn)行通信。

其中,第1種方式需要修改Supervisor的啟動(dòng)腳本和對(duì)應(yīng)的參數(shù)才能進(jìn)行,實(shí)現(xiàn)起來(lái)比較麻煩,第②種方式無(wú)須修改鏡像就能實(shí)現(xiàn),所以我們采用了第﹖種方式建模。下面是某個(gè)Supervisor節(jié)點(diǎn)的Service定義,注意 clusterIP: None的特殊寫(xiě)法:

apiversion: v1 kind: Servicemetadata: name:storm-supervisorspec: clusterIP:Noneselector: app:storm-supervisorports: - port: 8000

storm-supervisor 這個(gè)節(jié)點(diǎn)對(duì)應(yīng)的 Pod定義如下,需要注意Pod 的名稱(chēng)為storm-supervisor,并且command的值為[ "storm", "supervisor"]:

apiversion: v1kind: Pod metadata: name: storm-supervisorlabels: app: storm-supervisorspec: volumes: name: config-volumeconfigMap: name: storm-configitems: 一key:storm-conf.yaml path: storm.yaml containers: name: storm-supervisorimage: storm: 1.0 imagePullPolicy: IfNotPresent command:["storm", "supervisor" ]volumeMounts: -name: config-volumemountPath: /conf restartPolicy:Always

我們可以定義多個(gè)Supervisor 節(jié)點(diǎn),比如在本案例中定義了兩個(gè)Supervisor節(jié)點(diǎn)。在成功部署到Kubernetes集群后,我們通過(guò)Storm UI的30010端口進(jìn)入Storm的管理界面,可以看到如下界面。

如何深入理解Kubernetes微服務(wù)平臺(tái)

下面這個(gè)截圖驗(yàn)證了兩個(gè)Supervisor 節(jié)點(diǎn)也可以被成功注冊(cè)在集群中,我們看到每個(gè)節(jié)點(diǎn)都有4個(gè)Slot,這符合我們?cè)趕torm.yaml中的配置。

如何深入理解Kubernetes微服務(wù)平臺(tái)

至此,Storm集群在Kubernetes 上的建模和部署已經(jīng)順利完成了。接下來(lái)我們看看如何在Storm集群中提交之前學(xué)習(xí)過(guò)的WordCountTopology作業(yè)并且觀(guān)察它的運(yùn)行情況。

首先,我們可以去 https:/ljar-download.com/下載編譯好的 WordCountTopology 作業(yè)的JAR文件
storm-starter-topologies-1.0.3.jar,然后通過(guò)Storm Client工具將該Topology作業(yè)提交到Storm集群中,提交作業(yè)的命令如下:

storm jar/userlib/storm-starter-topologies-1.0.3.jar org.apache.storm.starter.ordcountTopology topology

由于在storm:1.0鏡像中已經(jīng)包括了Storm Client 工具,所以最簡(jiǎn)便的方式是定義一個(gè)Pod,然后把下載下來(lái)的
storm-starter-topologies-1.0.3.jar作為Volume映射到Pod里的/userlib/目錄下。將容器的啟動(dòng)命令設(shè)置為上述提交作業(yè)的命令即可實(shí)現(xiàn),下面是此Pod 的YAML定義:

apiversion: v1 kind: Podmetadata: name: storm-topo-examplespec: volumes: name:user-libhostPath: path: /root/stormname: config-volumeconfigMap: name:storm-configitems: -key: storm-conf.yaml path: storm. yaml containers: name: storm-topo-exampleimage: storm: 1.0 imagePullPolicy: IfNotPresent command: [ "storm","jar", "/userlib/storm-starter-topologies-1.0.3.jar", "org.apache.storm.starter.WordCountTopology", "topology" ] volumeMounts: - name: config-volumemountPath: /conf name:user-lib mountPath: /userlib restartPolicy: Never

上述定義有如下關(guān)鍵點(diǎn)。

  • 將storm-starter-topologies-1.0.3.jar 放在主機(jī)的/root/storm目錄中。

  • 容器的啟動(dòng)命令是storm client,提交Topology 作業(yè)。

  • Pod重啟策略為Never,因?yàn)橹灰峤煌闠opology 作業(yè)即可。

創(chuàng)建上述 Pod以后,我們查看該P(yáng)od 的日志,如果看到下面這段輸出,則表明WordCountTopology的拓?fù)渥鳂I(yè)已經(jīng)被成功提交到Storm集群中了。

如何深入理解Kubernetes微服務(wù)平臺(tái)

接下來(lái),我們進(jìn)入Storm UI去看看作業(yè)的執(zhí)行情況。下圖是WordCountTopology的匯總信息,狀態(tài)為Active,運(yùn)行了8分鐘,占用了3個(gè)Worker進(jìn)程,總共運(yùn)行了28個(gè)Task。

如何深入理解Kubernetes微服務(wù)平臺(tái)

在成功提交到Storm集群后,我們可以進(jìn)入Supervisor節(jié)點(diǎn)(Pod)查看拓?fù)渥鳂I(yè)的日志輸出,作業(yè)的日志輸出在目錄/log/workers-artifacts下,每個(gè)拓?fù)渥鳂I(yè)都有一個(gè)單獨(dú)的文件夾存放日志,我們搜索WordCountTopology 的最后一個(gè) Bolt——統(tǒng)計(jì)發(fā)送Tuple的日志,可以看到如下結(jié)果,即每個(gè)Word(字)都被統(tǒng)計(jì)輸出了。

如何深入理解Kubernetes微服務(wù)平臺(tái)

下面這個(gè)界面給出了WordCountTopology 的詳細(xì)信息,分別顯示了拓?fù)淅锼蠸pout的相關(guān)信息,例如生成了幾個(gè)Task、總共發(fā)送了多少個(gè)Tuple、失敗了多少個(gè),以及所有 Bolt 的相關(guān)信息,例如處理了多少個(gè) Tuple、處理的延時(shí)等統(tǒng)計(jì)信息,有助于我們分析Topology 作業(yè)的性能瓶頸和改進(jìn)的可能性。

如何深入理解Kubernetes微服務(wù)平臺(tái)

除了上面的列表信息,Storm UI還提供了展示Stream運(yùn)行情況的拓?fù)鋱D,如下圖所示,我們看到數(shù)據(jù)流從spout節(jié)點(diǎn)發(fā)出,經(jīng)過(guò) split 節(jié)點(diǎn)處理時(shí)用了3.13ms,然后抵達(dá)count節(jié)點(diǎn),count節(jié)點(diǎn)的處理耗時(shí)為0.06ms。

如何深入理解Kubernetes微服務(wù)平臺(tái)

Storm 的 Topology 作業(yè)一旦運(yùn)行起來(lái)就不會(huì)停止,所以你會(huì)看到下面界面中的Tuple 的統(tǒng)計(jì)數(shù)字在不斷增加,因?yàn)閃ordCountTopology的 Spout 節(jié)點(diǎn)在不斷生成Tuple,所以如果我們需要停止作業(yè),則可以單擊圖中的 Deactvate按鈕掛起作業(yè),或者終止作業(yè)。

如何深入理解Kubernetes微服務(wù)平臺(tái)

到此,相信大家對(duì)“如何深入理解Kubernetes微服務(wù)平臺(tái)”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI