偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

新聞 架構(gòu) 分布式
架構(gòu)師普遍有這樣的愿景:在系統(tǒng)中有ServiceA、ServiceB、ServiceC這3種服務(wù),其中ServiceA需要部署3個實例,ServiceB與ServiceC各自需要部署5個實例,希望有一個平臺(或工具)自動完成上述13個實例的分布式部署,并且持續(xù)監(jiān)控它們。

 深入Kubernetes微服務(wù)平臺

Kubernetes的概念與功能

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

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

  • 每個Service都分配了一個固定不變的虛擬IP地址——Cluster IP。
  • 每個Service都以TCP/UDP方式在一個或多個端口 (Service Port)上提供服務(wù)。
  • 客戶端訪問一個 Service時,就好像訪問一個遠(yuǎn)程的TCP/UDP服務(wù),只要與Cluster IP建立連接即可,目標(biāo)端口就是某個Service Port。

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

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

那么,Kubernetes里的 Service 與 Pod 是如何對應(yīng)的呢?我們怎么知道哪些Pod 為某個Service提供具體的服務(wù)?下圖給出了答案——“貼標(biāo)簽”。

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

  1. apiversion: v1 
  2. kind: Service 
  3. metadata: 
  4. name: ku8-redis-masterspec: 
  5. ports: 
  6. - port: 6379selector: 
  7. app: ku8-redis-master 

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

  1. apiversion: v1kind: Pod 
  2. metadata: 
  3. name: ku8-redis-masterlabels: 
  4. app: ku8-redis-master 
  5. spec: 
  6. containers: 
  7. name: serverimage: redisports: 
  8. -containerPort:6379 
  9. restartPolicy: Never 

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

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

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

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

  1. apiversion :v1 
  2. kind: ReplicationControllermetadata: 
  3. name: ku8-redis-slavespec: 
  4. replicas: 2template: 
  5. metadata: 
  6. labels: 
  7. app: ku8-redis-slavespec: 
  8. containers: 
  9. name: server 
  10. image: devopsbq/redis-slave 
  11. env: 
  12. name: MASTER ADDR 
  13. value: ku8-redis-masterports: 
  14. -containerPort:6379 

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

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

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

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

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

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

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

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

Kubernetes的組成與原理

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

  • 所有資源對象的CRUD API:資源對象會被保存到Etcd中存儲并提供Query接口,比如針對Pod、Service及RC等的操作。
  • 資源對象的 Watch API:客戶端用此API來及時得到資源變化的相關(guān)通知,比如某個Service 相關(guān)的Pod實例被創(chuàng)建成功,或者某個Pod 狀態(tài)發(fā)生變化等通知,Watch API主要用于Kubernetes 中的高效自動控制邏輯。

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

  • controller manager:負(fù)責(zé)所有自動化控制事物,比如RC/Deployment的自動控制、HPA自動水平擴(kuò)容的控制、磁盤定期清理等各種事務(wù)。
  • scheduler:負(fù)責(zé)Pod 的調(diào)度算法,在一個新的Pod被創(chuàng)建后,Scheduler根據(jù)算法找到最佳 Node節(jié)點,這個過程也被稱為Pod Binding。
  • kubelet:負(fù)責(zé)本Node節(jié)點上Pod實例的創(chuàng)建、監(jiān)控、重啟、刪除、狀態(tài)更新、性能采集并定期上報 Pod 及本機(jī) Node節(jié)點的信息給Master節(jié)點,由于Pod實例最終體現(xiàn)為Docker'容器,所以Kubelet還會與Docker交互。
  • kube-proxy:為 Service的負(fù)載均衡器,負(fù)責(zé)建立Service Cluster IP 到對應(yīng)的Pod實例之間的NAT轉(zhuǎn)發(fā)規(guī)則,這是通過Linux iptables實現(xiàn)的。

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

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

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

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

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

基于Kubernetes 的 PaaS平臺

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

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

Kubernetes 擁有如下特性。

  • Pod(容器)可以讓開發(fā)者將一個或多個容器整體作為一個“原子單元”進(jìn)行部署。
  • 采用固定的Cluster IP及內(nèi)嵌的DNS這種獨(dú)特設(shè)計思路的服務(wù)發(fā)現(xiàn)機(jī)制,讓不同的Service很容易相互關(guān)聯(lián)(Link)。
  • RC可以保證我們關(guān)注的Pod副本的實例數(shù)量始終符合我們的預(yù)期。
  • 非常強(qiáng)大的網(wǎng)絡(luò)模型,讓不同主機(jī)上的Pod能夠相互通信。
  • 支持有狀態(tài)服務(wù)與無狀態(tài)服務(wù),能夠?qū)⒊志没鎯σ簿幣诺饺萜髦幸灾С钟袪顟B(tài)服務(wù)。
  • 簡單易用的編排模型,讓用戶很容易編排一個復(fù)雜的應(yīng)用。

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

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

  • 多租戶支持:這里的租戶可以是開發(fā)廠商或者應(yīng)用本身。
  • 應(yīng)用的全生命周期管理:比如對應(yīng)用的定義、部署、升級、下架等環(huán)節(jié)的支持。
  • 具有完備的基礎(chǔ)服務(wù)設(shè)施:比如單點登錄服務(wù)、基于角色的用戶權(quán)限服務(wù)、應(yīng)用配置服務(wù)、日志服務(wù)等,同時PaaS平臺集成了很多常見的中間件以方便應(yīng)用調(diào)用,這些常見的中間件有消息隊列、分布式文件系統(tǒng)、緩存中間件等。
  • 多語言支持:一個好的PaaS平臺可以支持多種常見的開發(fā)語言,例如Java、Node.js、PHP、Python、C++等。

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

如何實現(xiàn)多租戶

Kubernetes通過Namespace特性來支持多租戶功能。

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

  • Calico:基于三層路由實現(xiàn)的容器網(wǎng)絡(luò)方案。
  • Weave Net:基于報文封裝的二層容器解決方案。
  • Romana:類似于Calico的容器網(wǎng)絡(luò)方案。

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

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

  1. nodeSelector: 
  2. partition: tenanta 
架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

PaaS 平臺的領(lǐng)域模型設(shè)計

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

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

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

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

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

Storm On Kubernetes 實戰(zhàn)

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

  • storm.zookeeper.servers: ZooKeeper集群的節(jié)點IP地址列表。
  • nimbus.seeds:Nimbus的IP地址。
  • supervisor.slots.ports:Supervisor 中的Worker 監(jiān)聽端口列表。

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

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

  1. apiVersion: v1kind: Servicemetadata: 
  2. name: ku8-zookeeperspec: 
  3. ports: 
  4. name: clientport: 2181selector: 
  5. app: ku8-zookeeper 

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

  1. apiversion: v1 
  2. kind: Replicationcontrollermetadata: 
  3. name: ku8-zookeeper-lspec: 
  4. replicas: 1template: 
  5. metadata: 
  6. labels: 
  7. app: ku8-zookeeperspec: 
  8. containers: 
  9. name: server 
  10. image: jplock/ zookeeper 
  11. imagePu1lPolicy: IfNotPresentports: 
  12. -containerPort: 2181 

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

  1. apiversion: v1kind: Servicemetadata: 
  2. name: nimbusspec: 
  3. selector: 
  4. app: storm-nimbusports: 
  5. -name: nimbus-rpc 
  6. port: 6627 
  7. targetPort:6627 

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

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

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

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

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

  • Storm版本新。
  • Storm整體只有一個鏡像,通過容器的command 命令參數(shù)來決定啟動的是哪種類型的節(jié)點,比如Nimbus主節(jié)點、Nimbus-ui管理器或者Supervisor 從節(jié)點。
  • 標(biāo)準(zhǔn)化的Storm進(jìn)程啟動方式,可以將conf/storm.yaml配置文件映射到容器外,因此可以采用Kubernetes 的 ConfigMap特性。

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

  1. apiversion: v1kind: Pod 
  2. metadata: 
  3. name: nimbuslabels: 
  4. app: storm-nimbusspec: 
  5. volumes: 
  6. name: config-volumeconfigMap: 
  7. name: storm-configitems: 
  8. 一key:storm-conf.yaml 
  9. path:storm.yaml 
  10. containers: 
  11. - name: nimbus 
  12. image: storm: 1.0 
  13. imagePullPolicy: IfNotPresentports: 
  14. -containerPort: 6627 
  15. command:【"storm" ,"nimbus" ]volumeMounts: 
  16. - name: config-volumemountPath: /conf 
  17. restartPolicy: Always 

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

類似地,我們定義storm-ui服務(wù),這是一個Web管理程序,提供了圖形化的Storm管理功能,因為需要在Kubernetes集群之外訪問它,所以我們通過NodePort方式映射8080端口到主機(jī)上的30010。storm-ui服務(wù)的YAML定義文件如下:

  1. apiversion: v1kind: Servicemetadata: 
  2. name: storm-uispec: 
  3. type: NodePortselector: 
  4. app:storm-uiports: 
  5. -name: web 
  6. port: 8080 
  7. targetPort: 8080nodePort:30010 

最后,我們來建模Supervisor。Supervisor看似不需要被建模為Service,因為Supervisor 不會被主動調(diào)用,但實際上Supervisor節(jié)點之間會相互發(fā)起通信,因此Supervisor節(jié)點注冊到ZooKeeper 上的地址必須能被相互訪問,在 Kubernetes平臺上有兩種方式解決此問題。

第1種方式,Supervisor節(jié)點注冊到ZooKeeper上時,不用主機(jī)名(Pod名稱),而是采用Pod的P地址。

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

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

  1. apiversion: v1 
  2. kind: Servicemetadata: 
  3. name:storm-supervisorspec: 
  4. clusterIP:Noneselector: 
  5. app:storm-supervisorports: 
  6. - port: 8000 

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

  1. apiversion: v1kind: Pod 
  2. metadata: 
  3. name: storm-supervisorlabels: 
  4. app: storm-supervisorspec: 
  5. volumes: 
  6. name: config-volumeconfigMap: 
  7. name: storm-configitems: 
  8. 一key:storm-conf.yaml 
  9. path: storm.yaml 
  10. containers: 
  11. name: storm-supervisorimage: storm: 1.0 
  12. imagePullPolicy: IfNotPresent 
  13. command:["storm""supervisor" ]volumeMounts: 
  14. -name: config-volumemountPath: /conf 
  15. restartPolicy:Always 

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

下面這個截圖驗證了兩個Supervisor 節(jié)點也可以被成功注冊在集群中,我們看到每個節(jié)點都有4個Slot,這符合我們在storm.yaml中的配置。

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

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

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

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

  1. apiversion: v1 
  2. kind: Podmetadata: 
  3. name: storm-topo-examplespec: 
  4. volumes: 
  5. name:user-libhostPath: 
  6. path: /root/stormname: config-volumeconfigMap: 
  7. name:storm-configitems: 
  8. -key: storm-conf.yaml 
  9. path: storm. yaml 
  10. containers: 
  11. name: storm-topo-exampleimage: storm: 1.0 
  12. imagePullPolicy: IfNotPresent 
  13. command: [ "storm","jar""/userlib/storm-starter-topologies-1.0.3.jar"
  14. "org.apache.storm.starter.WordCountTopology""topology" ] 
  15. volumeMounts: 
  16. - name: config-volumemountPath: /conf 
  17. name:user-lib 
  18. mountPath: /userlib 
  19. restartPolicy: Never 

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

  • 將storm-starter-topologies-1.0.3.jar 放在主機(jī)的/root/storm目錄中。
  • 容器的啟動命令是storm client,提交Topology 作業(yè)。
  • Pod重啟策略為Never,因為只要提交完Topology 作業(yè)即可。

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

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

架構(gòu)解密從分布式到微服務(wù):深入Kubernetes微服務(wù)平臺

 

 

責(zé)任編輯:張燕妮 來源: 今日頭條
相關(guān)推薦

2024-05-16 07:51:55

分布式系統(tǒng)架構(gòu)

2023-09-12 22:58:51

分布式架構(gòu)微服務(wù)

2018-05-23 15:58:27

Spring Clou微服務(wù)架構(gòu)

2018-03-02 16:11:29

Spring Clou分布式服務(wù)跟蹤

2017-02-22 11:52:49

微服務(wù)分布式Java開發(fā)者

2018-04-16 14:56:56

微服務(wù)架構(gòu)分布式服務(wù)

2018-04-18 16:07:49

Spring Clou微服務(wù)分布式

2018-03-13 16:42:26

分布式服務(wù)跟蹤

2018-04-09 13:56:13

微服務(wù)架構(gòu)分布式

2018-04-02 15:01:31

微服務(wù)架構(gòu)分布式服務(wù)

2017-03-14 11:52:52

微服務(wù)架構(gòu)數(shù)據(jù)管理

2021-06-09 09:00:00

微服務(wù)架構(gòu)技術(shù)

2019-10-08 11:04:44

SOA微服務(wù)架構(gòu)

2020-06-10 10:20:24

微服務(wù)架構(gòu)WEB2.0

2024-05-17 13:48:19

2019-05-24 14:45:17

分布式微服務(wù)運(yùn)維

2025-04-11 02:30:00

2021-09-28 09:43:11

微服務(wù)架構(gòu)技術(shù)

2017-07-28 16:41:53

Spring Clou微服務(wù)架構(gòu)

2023-11-20 15:32:29

點贊
收藏

51CTO技術(shù)棧公眾號