Docker與k8s的恩怨情仇(六)—— “容器編排”上演“終結者”大片
轉載請註明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。
在上節中,我們為大家介紹了Pod的基礎內容,Kubernetes如何站在上帝視角上處理容器和容器之間的關係。但僅僅有Pod卻還不夠,對於大部分使用者而言如何排程和管理自己的應用才是真正核心的問題,而對這一內容的解決方案才是Kubernetes最終極大殺器。
Pod間的編排管理
讓我們從一個例子出發,假設現在的使用者需求是:
以3機負載均衡的形式部署一個私有云客戶的活字格應用,應該如何實現呢?
Docker的“古典”做法
在活字格公有云版開發組之前開發的版本中,實現方法大概是這樣:使用三個不同的物理機,先把使用者的應用run成容器,然後安裝在在這三個物理機上,在三臺伺服器之外再買一個負載均衡服務,最後通過域名解析配置,將流量分別導向三個不同的服務機。
聽起來似乎也挺簡單的。
但是在現實中,我們會遇到考慮其他問題,比如: 如果我們只有兩臺伺服器呢?如果有一臺伺服器中的container掛了呢?如果兩臺伺服器CPU跑滿了呢?
這些排程方面的內容看起來很簡單,但是實現起來卻需要長時間的編碼和除錯。而且一通輸出之後,最終做出來也可能只是個Docker Swarm而已。
Kubernetes裡的容器編排
現在我們把上述需求看做是我們最終的目標,來看kubernetes是如何一步一步進行容器編排從而解決了這個問題。相信大家看完這部分內容之後,以上問題便會迎刃而解。
Kubernetes所做的容器編排核心內容其實是Pod編排,如何讓這些Pod配合起來協同工作,則是編排的核心。在上一節中我們一起了解了kubernetes所做的是將各種關係進行了抽象,這些關係本質其實是Pod之間的關係。kubernetes將Pod的關係抽象成了以下幾種,並且為這些關係定義了相對的控制器便於進行編排管理:
l 無狀態Pod副本之間的協同關係——Deployment
l 有狀態Pod副本之間的拓撲關係——StatefulSet
l 容器化守護程序——DaemonSet
l 離線業務——Job和CronJob
這些概念看起來可能讓你有些不知所云,其實這些內容只是不同上述的控制器對Pod的不同的管理方式而已。
限於篇幅和對這部分內容的理解深度,這裡我們將只分享活字格公有云版開發組中最多使用到kubernetes最常用的一種控制器——Deployment。
Deployment控制器功能介紹
我們先解釋什麼是控制器:控制器是kubernetes中管理待編排物件的程式,我們把一個物件管理另一個物件的模式稱為控制器模式。
kubernetes中的所有待編排物件都是通過控制器模式管理的。
其核心就是一個死迴圈,在迴圈中不停地判斷當前編排物件的狀態,如果不滿足預期狀態就更新它,如下的虛擬碼就是描述一個控制器的工作原理:
Deployment控制器的功能是:維護多個相同的無狀態Pod副本以規定的數量執行,並且支援水平擴充套件以及滾動更新。
有了這個控制,為了實現我們的最終需求——負載均衡中的活字格服務,這個Pod就可以通過Deployment管理。我們可以通過Deployment讓我們的Pod在kubernetes叢集中始終以3個副本的形式存在。
只需要用Deployment來編排我們定義的Pod,並且要求副本數量是3,Deployment控制迴圈中就會不停地判斷我們的Pod的副本數量是否是3,如果不是,就會觸發水平擴充套件功能進行調整,最終達到滿足期望狀態(副本數==3)。
Deployment工作原理演示
介紹了這麼多,我們從例項出發為大家演示Deployment是如何工作的。
由於活字格的映象配置過於複雜,因此這裡我們通過一個Nginx的多副本配置來感受一下Deployment控制器的控制結果。
我們可以通過以下yaml定義一個維護了3個nginx副本的deployment:
其實Kubernetes在最初的版本中只有ReplicaSet這種控制器模式,控制的是多副本Pod編排邏輯,後來出現了滾動更新邏輯,為了解決滾動更新的需求,在ReplicaSet基礎上擴展出了Deployment。
apiVersion:apps/v1
kind:Deployment
metadata:
name:sample-deployment-nginx
spec:
selector:
matchLabels:
app:sample-deployment-nginx
replicas:3
template:
metadata:
labels:
app:sample-deployment-nginx
spec:
containers:
-name:sample-nginx
image:nginx:1.9.1
ports:
-containerPort:80
這裡出現了三個特殊欄位:
1. selector:選擇器,類似於js中的選擇器,其功能就是選擇指定的pod執行,這個例項中我們指定所有app==sample-deployment-nginx的pod才會被這個Deployment所部署
2. replicas:指明這個Deployment維護的副本個數
3. template:控制器中提供了template這個語法,可以讓我們直接在控制器的yaml中直接編寫所需要編排的Pod資訊
編寫完這個sample-deployment-nginx.yaml後,執行一下:
kubectlapply-fsample-deployment-nginx.yaml
這個三副本的控制器就被成功運行了,使用該指令檢視執行結果:
kubectlgetpods-lapp=sample-deployment-nginx
可以看到3副本Pod已經成功在kubernetes中運行了
如果這時我們執行以下命令刪除podname==sample-deployment-nginx-54545f95cd-wtllm的副本
kubectldeletepodsample-deployment-nginx-54545f95cd-wtllm
可以自動生成一個新的pod來維持replicas==3:
通過上述例項,我們可以看到Deployment控制器對副本數量的控制結果,其實是ReplicaSet控制器在控制副本的數量。Deployment是ReplicaSet控制器的控制器,這種多層之間相互控制的模式在kubernetes也十分常見,其之間的關係如下圖所示:
至此,一個deployment管理pod的所有功能都已經展示完成了,可以看到kubernetes中控制器管理之間的精巧關係:多個控制器協同工作,既能保證精準控制,也能拆分程序阻塞從而提升效能。
其他控制器的介紹
當你理解了deployment控制器,就很容易理解其他控制器的工作原理。
在這裡我們簡單做個說明,為大家介紹其他控制器的控制邏輯:
l StatefulSet:控制滿足有拓撲狀態或者持久化儲存的Pod,拓撲狀態的意思就是Pod之間存在明確的先後生成關係,持久化儲存就是當副本被刪除或者修改了,其內部儲存的資料還會存在
l DaemonSet:守護程序控制器,是一個Node(伺服器節點)僅能存在一個的Pod,比如系統的日誌採集器等就應該用這種方式排程
l Job與CronJob:Job就是任務排程,一個Pod在排程完成後就結束了不會再有新的任務產生,Job用於維護一個任務Pod執行中的各種狀態正常,異常狀態重啟等。對應的CronJob就是定時任務,使用過Quartz的同學一定不陌生
總結
綜上,kubernetes中就是通過上述的各種控制器維護所有Pod的編排工作的,並且其還提供了完善的API可以讓使用者自行定義滿足自己需求的各種Pod編排控制器。但是對於deployment本文只是簡單的展示了一些常用的功能點,其內部還有滾動更新的最大資源、金絲雀釋出和灰度釋出等各種功能需要繼續細緻的學習。
本章中以活字格公有云為例,為大家介紹了k8s容器編排部分的實現。在下節中我們將繼續為大家分享,為了實現這個終極需求的另一部分——如何實現 “人與狗的交往過程”。
本文是由葡萄城技術開發團隊釋出,轉載請註明出處:葡萄城官網