k8s如何管理Pod(rc、rs、deployment)
是豆莢,可以把容器想像成豆莢裏的豆子,把一個或多個關系緊密的豆子包在一起就是豆莢(一個Pod)。在k8s中我們不會直接操作容器,而是把容器包裝成Pod再進行管理(關於Pod,大家可以參考第十期的分享“談談Pod在微服務中的運用”)。Pod是運行服務的基礎,那我們如何來管理Pod呢,下面我們就來聊一聊。分為這三個部分:
-
使用Replication Controller 來部署、升級Pod
-
Replica Set – 下一代Replication Controller
-
Deployment – 更加方便的管理Pod和Replica Set
先舉個例子,假設我們有一個Pod在提供線上服務,現在有如下幾個場景,大家想想如何應對:
-
節日活動,網站訪問量突增
-
遭到攻擊,網站訪問量突增
-
運行Pod的節點發生故障
第1種情況,活動前預先多啟動幾個Pod,活動結束後再結束掉多余的,雖然要啟動和結束的Pod有點多,但也能有條不紊按計劃進行
第2種情況,正在睡覺突然手機響了說網站反應特慢卡得要死,趕緊爬起來邊擴容邊查找攻擊模式、封IP等等……
第3種情況,正在休假突然手機又響了說網站上不去,趕緊打開電腦查看原因,啟動新的Pod
Pod需要手動管理,好累……能否在Pod發生問題時自動恢復呢,我們先來看下Replication Controller(以下簡稱RC)
先說RC是什麽。RC保證在同一時間能夠運行指定數量的Pod副本,保證Pod總是可用。如果實際Pod數量比指定的多就結束掉多余的,如果實際數量比指定的少就啟動缺少的。當Pod失敗、被刪除或被終結時RC會自動創建新的Pod來保證副本數量。所以即使只有一個Pod也應該使用RC來進行管理。
接下來我們看下如何創建RC,看這個定義文件rc.yaml
這個文件定義了RC的屬性,我們先關註如下字段:
spec.replicas:副本數量3
spec.selector:RC通過spec.selector來篩選要控制的Pod
spec.template:這裏寫Pod的定義(但不需要apiVersion和kind)
spec.template.metadata.labels:Pod的label,可以看到這個label與spec.selector相同
這個文件的意思是定義了一個RC對象,它的名字是hello-rc(metadata.name:hello-rc),保證有3個Pod運行(spec.replicas:3),Pod的鏡像是index.tenxcloud.com/tailnode/hello:v1.0(spec.template.spec.containers.image: index.tenxcloud.com/tailnode/hello:v1.0)關鍵在於spec.selector與spec.template.metadata.labels,這兩個字段必須相同,否則下一步創建RC會失敗。(也可以不寫spec.selector,這樣默認與spec.template.metadata.labels相同)
現在通過kubectl來創建RC:
查看結果可以看到當前RC的狀態:指定了需要3個Pod、當前實際有3個Pod、3個Pod都在運行中(圖片較大只截取部分):
如果使用的鏡像較大查看狀態可能是Waiting,這是因為正在下載鏡像,等待一段時間就好。
上面說過RC會自動管理Pod保證指定數量副本運行,我們來實驗一下,看下圖:
1.查看當前Pod,(註意NAME和AGE列)
2.刪除hello-rc-5crgq
3.再次查看Pod,發現新的Pod啟動了(註意NAME和AGE列)
到這裏我們對RC有了基本的認識,並進行了簡單的使用。
現在回到最開始的問題,如何通過RC修改Pod副本數量。其實非常簡單,只需要修改yaml文件spec.replicas字段成想要的值,然後執行kubectl replace命令(或者使用kubect edit replicationcontroller hello-rc直接修改)
執行結果看下圖:
當我們有新功能發布或修復BUG時使用滾動升級是不錯的選擇,可以使用工具kubectl rolling-update完成這個任務。對照下圖我們來看下是如何進行的
使用命令kubectl rolling-update hello-rc –image=index.tenxcloud.com/tailnode/hello:v2.0
在另一個窗口查看RC
對照兩張截圖,我們能夠看出升級步驟如下:
-
創建一個使用新版本Pod的RC,hello-rc-4f7ed44b6db1e20aa1bc681c81d63caf
-
依次增加新RC的副本數量、減少舊RC的副本數量
-
當升級成功後,刪除舊RC
-
重命名新RC為hello-rc
當Pod中只有一個容器時通過--image參數指定新的Tag,如果有多個容器或其他字段的修改時,需要使用kubectl rolling-update NAME -f FILE指定文件
如果在升級過程中出現問題(比如長時間無響應),可以CTRL+C結束再使用kubectl rolling-update hello-rc –-rollback進行回滾,但如果升級完成後出現問題(比如新版本程序出core),此命令無能為力,需要使用同樣方法“升級”為舊版本
在時速雲平臺我們能夠非常方便的使用彈性伸縮功能來調整Pod副本數量,還是舉例說明:
啟動一個能夠輸出Pod主機名和版本號的服務,看下圖當前只有一個Pod副本運行
點擊彈性伸縮,修改數量為3,同時使用下面的命令測試,從輸出結果可以看出提供服務的Pod數量變成了3個:
下面再來測試下灰度升級功能,修改目標版本為v2.0(之前是v1.0,為了便於查看效果新建有2個Pod的服務),然後查看Pod變化
第一個新Pod hello-v2.0-ywcc2已經啟動
第二個新Pod hello-v2.0-whtvh正在啟動
最後一個舊Pod hello-41ee8正在停止
升級完成,只有兩個新Pod提供服務
同時使用命令查看服務的響應如下:
k8s是一個高速發展的項目,在新的版本中官方推薦使用Replica Set和Deployment來代替RC。那麽它們優勢在哪裏,我們來看一看:
-
RC只支持基於等式的selector(env=dev或environment!=qa)但Replica Set還支持新的基於集合的selector(version in (v1.0, v2.0)或env notin (dev, qa)),這對復雜的運維管理帶來很大方便
-
使用Deployment升級Pod只需要定義Pod的最終狀態,k8s會為你執行必要的操作,雖然能夠使用命令kubectl rolling-update完成升級,但它是在客戶端與服務端多次交互控制RC完成的,所以REST API中並沒有rolling-update的接口,這為定制自己的管理系統帶來了一些麻煩。
-
Deployment擁有更加靈活強大的升級、回滾功能
Replica Set目前與RC的區別只是支持的selector不同,後續肯定會加入更多功能。Deployment使用了Replica Set,是更高一層的概念。除非需要自定義升級功能或根本不需要升級Pod,所以推薦使用Deployment而不直接使用Replica Set。
下面我們繼續來看Deployment的定義文件,與RC的定義文件基本相同(註意apiVersion還是beta版),所以不再詳細解釋各字段意思
與創建RC相同,使用命令kubectl create -f deployment.yaml –record創建Deployment,註意–record參數,使用此參數將記錄後續對創建的對象的操作,方便管理與問題追溯
使用kubectl edit deployment hello-deployment修改spec.replicas/spec.template.spec.container.image字段來完成擴容縮容與滾動升級(比kubectl rolling-update速度快很多)
修改image字段為新版本鏡像後查看Pod,在STATUS列看到正在執行升級的Pod:
使用kubectl rollout history命令查看Deployment的歷史信息
上面提到過kubectl rolling-update升級成功後不能直接回滾,不是很方便,那使用Deployment可以嗎,答案是肯定的。
首先在上面的命令加上–revision參數,查看改動詳細信息如下:
然後使用kubctl rollout undo deployment hello-deployment回滾至前一版本(使用--to-revision參數指定版本)即可。
命令kubectl describe deployment hello-deployment查看詳細信息,在Message一列看到回滾如下,詳細的信息記錄對於問題發生後的原因查找有很大幫助:
通過對比RC、Replica Set與Deployment,可以看出新的Replica Set與Deployment比RC要強大易用很多,但因為現在還是beta版本所以不建議在生產環境使用,不過相信不久的將來我們就能使用上。
k8s如何管理Pod(rc、rs、deployment)