91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何深入理解Kubernetes微服務平臺

發布時間:2021-10-15 14:53:44 來源:億速云 閱讀:92 作者:iii 欄目:開發技術

本篇內容主要講解“如何深入理解Kubernetes微服務平臺”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何深入理解Kubernetes微服務平臺”吧!

Kubernetes的概念與功能

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

如何深入理解Kubernetes微服務平臺

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

Kubernetes里的Service其實就是微服務架構中微服務的概念,它有以下明顯特點。

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

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

  • 客戶端訪問一個 Service時,就好像訪問一個遠程的TCP/UDP服務,只要與Cluster IP建立連接即可,目標端口就是某個Service Port。

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

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

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

如何深入理解Kubernetes微服務平臺

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

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

下面是 ku8-redis-master這個 Pod 的定義,它的 labels屬性的內容剛好匹配Service 的標簽選擇器的內容:

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

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

●目標Pod的副本數量(replicas)。

●目標Pod的創建模板(Template)。

下面這個例子定義了一個RC,目標是確保在集群中任意時刻都有兩個 Pod,其標簽為“ app:ku8-redis-slave”,對應的容器鏡像為redis slave,這兩個 Pod 與ku8-redis-master構成了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文件創建了一個一主二從的Redis集群,其中Redis Master被定義為一個微服務,可以被其他Pod或 Service訪問,如下圖所示。

如何深入理解Kubernetes微服務平臺

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

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

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

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

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

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

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

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

如何深入理解Kubernetes微服務平臺

Kubernetes的組成與原理

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

如何深入理解Kubernetes微服務平臺

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

如何深入理解Kubernetes微服務平臺

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

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

  • 資源對象的 Watch API:客戶端用此API來及時得到資源變化的相關通知,比如某個Service 相關的Pod實例被創建成功,或者某個Pod 狀態發生變化等通知,Watch API主要用于Kubernetes 中的高效自動控制邏輯。

下面是上圖中其他Kubernetes進程的主要功能。

  • controller manager:負責所有自動化控制事物,比如RC/Deployment的自動控制、HPA自動水平擴容的控制、磁盤定期清理等各種事務。

  • scheduler:負責Pod 的調度算法,在一個新的Pod被創建后,Scheduler根據算法找到最佳 Node節點,這個過程也被稱為Pod Binding。

  • kubelet:負責本Node節點上Pod實例的創建、監控、重啟、刪除、狀態更新、性能采集并定期上報 Pod 及本機 Node節點的信息給Master節點,由于Pod實例最終體現為Docker'容器,所以Kubelet還會與Docker交互。

  • kube-proxy:為 Service的負載均衡器,負責建立Service Cluster IP 到對應的Pod實例之間的NAT轉發規則,這是通過Linux iptables實現的。

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

如何深入理解Kubernetes微服務平臺

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

那么,如果某個Node'宕機,則會發生什么事情呢?假如某個Node宕機一段時間,則因為在此節點上沒有Kubelet進程定時匯報這些Pod 的狀態,因此這個Node 上的所有Pod'實例都會被判定為失敗狀態,此時Controller Manager會將這些Pod刪除并產生新的Pod實例,于是這些Pod被調度到其他 Node 上創建出來,系統自動恢復。

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

如何深入理解Kubernetes微服務平臺

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

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

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

基于Kubernetes 的 PaaS平臺

PaaS其實是一個重量級但不怎么成功的產品,受限于多語言支持和開發模式的僵硬,但近期又隨著容器技術及云計算的發展,重新引發了人們的關注,這是因為容器技術徹底解決了應用打包部署和自動化的難題。基于容器技術重新設計和實現的PaaS平臺,既提升了平臺的技術含量,又很好地彌補了之前PaaS平臺難用、復雜、自動化水平低等缺點。

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

Kubernetes 擁有如下特性。

  • Pod(容器)可以讓開發者將一個或多個容器整體作為一個“原子單元”進行部署。

  • 采用固定的Cluster IP及內嵌的DNS這種獨特設計思路的服務發現機制,讓不同的Service很容易相互關聯(Link)。

  • RC可以保證我們關注的Pod副本的實例數量始終符合我們的預期。

  • 非常強大的網絡模型,讓不同主機上的Pod能夠相互通信。

  • 支持有狀態服務與無狀態服務,能夠將持久化存儲也編排到容器中以支持有狀態服務。

  • 簡單易用的編排模型,讓用戶很容易編排一個復雜的應用。

國內外已經有很多公司采用了Kubernetes作為它們的PaaS平臺的內核,所以本節講解如何基于Kubernetes 設計和實現一個強大的 PaaS平臺。

一個 PaaS平臺應該具備如下關鍵特性。

  • 多租戶支持:這里的租戶可以是開發廠商或者應用本身。

  • 應用的全生命周期管理:比如對應用的定義、部署、升級、下架等環節的支持。

  • 具有完備的基礎服務設施:比如單點登錄服務、基于角色的用戶權限服務、應用配置服務、日志服務等,同時PaaS平臺集成了很多常見的中間件以方便應用調用,這些常見的中間件有消息隊列、分布式文件系統、緩存中間件等。

  • 多語言支持:一個好的PaaS平臺可以支持多種常見的開發語言,例如Java、Node.js、PHP、Python、C++等。

接下來,我們看看基于Kubernetes 設計和實現的PaaS平臺是如何支持上述關鍵特性的。

如何實現多租戶

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

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

如何深入理解Kubernetes微服務平臺

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

如何深入理解Kubernetes微服務平臺

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

如何深入理解Kubernetes微服務平臺

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

  • Calico:基于三層路由實現的容器網絡方案。

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

  • Romana:類似于Calico的容器網絡方案。

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

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

nodeSelector: partition: tenanta

如何深入理解Kubernetes微服務平臺

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

PaaS 平臺的領域模型設計

我們知道,微服務架構下的一個應用通常是由多個微服務所組成的,而我們的Kubernetes通常會部署多個獨立的應用,因此,如果用 Kubernetes建模微服務應用,則我們需要在 PaaS平臺的領域模型中設計出 Application這個領域對象,一個Application包括多個微服務,并且最終在發布(部署)時會生成對應的Pod、Deployment 及 Service對象,如下圖所示。

如何深入理解Kubernetes微服務平臺

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

如何深入理解Kubernetes微服務平臺

上圖中的Service領域對象并不是Kubernetes Service,而是包括了Kubernetes Service及相關RC/Deployment的一個“復合結構”。在Service領域對象中只包括了必要的全部屬性,在部署應用時會生成對應的Kubernetes Service和RC/Deployment實例。下圖給出了Service的定義界面(原型)。

如何深入理解Kubernetes微服務平臺

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

如何深入理解Kubernetes微服務平臺

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

如何深入理解Kubernetes微服務平臺

PaaS 平臺的基礎中間件

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

如何深入理解Kubernetes微服務平臺

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

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

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

如何深入理解Kubernetes微服務平臺

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

如何深入理解Kubernetes微服務平臺

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

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

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

Storm On Kubernetes 實戰

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

  • storm.zookeeper.servers: ZooKeeper集群的節點IP地址列表。

  • nimbus.seeds:Nimbus的IP地址。

  • supervisor.slots.ports:Supervisor 中的Worker 監聽端口列表。

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

首先,定義ZooKeeper對應的Service,Service名稱為ku8-zookeeper,關聯的標簽為app=ku8-zookeeper 的Pod:

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

其次,定義ZooKeeper對應的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

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

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

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

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

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

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

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

  • Storm版本新。

  • Storm整體只有一個鏡像,通過容器的command 命令參數來決定啟動的是哪種類型的節點,比如Nimbus主節點、Nimbus-ui管理器或者Supervisor 從節點。

  • 標準化的Storm進程啟動方式,可以將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

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

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

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

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

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

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

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

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

storm-supervisor 這個節點對應的 Pod定義如下,需要注意Pod 的名稱為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

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

如何深入理解Kubernetes微服務平臺

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

如何深入理解Kubernetes微服務平臺

至此,Storm集群在Kubernetes 上的建模和部署已經順利完成了。接下來我們看看如何在Storm集群中提交之前學習過的WordCountTopology作業并且觀察它的運行情況。

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

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

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

上述定義有如下關鍵點。

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

  • 容器的啟動命令是storm client,提交Topology 作業。

  • Pod重啟策略為Never,因為只要提交完Topology 作業即可。

創建上述 Pod以后,我們查看該Pod 的日志,如果看到下面這段輸出,則表明WordCountTopology的拓撲作業已經被成功提交到Storm集群中了。

如何深入理解Kubernetes微服務平臺

接下來,我們進入Storm UI去看看作業的執行情況。下圖是WordCountTopology的匯總信息,狀態為Active,運行了8分鐘,占用了3個Worker進程,總共運行了28個Task。

如何深入理解Kubernetes微服務平臺

在成功提交到Storm集群后,我們可以進入Supervisor節點(Pod)查看拓撲作業的日志輸出,作業的日志輸出在目錄/log/workers-artifacts下,每個拓撲作業都有一個單獨的文件夾存放日志,我們搜索WordCountTopology 的最后一個 Bolt——統計發送Tuple的日志,可以看到如下結果,即每個Word(字)都被統計輸出了。

如何深入理解Kubernetes微服務平臺

下面這個界面給出了WordCountTopology 的詳細信息,分別顯示了拓撲里所有Spout的相關信息,例如生成了幾個Task、總共發送了多少個Tuple、失敗了多少個,以及所有 Bolt 的相關信息,例如處理了多少個 Tuple、處理的延時等統計信息,有助于我們分析Topology 作業的性能瓶頸和改進的可能性。

如何深入理解Kubernetes微服務平臺

除了上面的列表信息,Storm UI還提供了展示Stream運行情況的拓撲圖,如下圖所示,我們看到數據流從spout節點發出,經過 split 節點處理時用了3.13ms,然后抵達count節點,count節點的處理耗時為0.06ms。

如何深入理解Kubernetes微服務平臺

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

如何深入理解Kubernetes微服務平臺

到此,相信大家對“如何深入理解Kubernetes微服務平臺”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

汾西县| 平阴县| 登封市| 灌阳县| 响水县| 寿光市| 繁昌县| 嘉峪关市| 湛江市| 公安县| 昌平区| 安龙县| 盱眙县| 胶南市| 万山特区| 开原市| 广宁县| 平定县| 原阳县| 广元市| 保山市| 洛扎县| 当雄县| 大英县| 古丈县| 桂林市| 闵行区| 新宁县| 龙江县| 阿克苏市| 姚安县| 竹溪县| 旅游| 改则县| 淮阳县| 万全县| 游戏| 凤凰县| 恭城| 衡阳市| 雷山县|