Rancher Labs首席軟件工程師Alena Prokharchyk受邀在2017年12月6-8日的CNCF主辦的Kubernetes領域頂級盛會KubeCon + CloudNativeCon 2017北美峯會上進行演講,本文由演講內容整理而成。java
隨着Kubernetes愈來愈受歡迎,圍繞它的集成和監控服務的數量也在不斷增加。Golang編寫的全部此類服務的關鍵組件是kubernetes / client-go——一個用於與Kubernetes集羣API通訊的軟件包。在本文中,咱們將討論client-go使用的基本知識,以及如何爲開發人員節約編寫實際應用程序邏輯所需的時間。咱們還將展現使用該軟件包的最佳實踐,並從天天與Kubernetes進行集成工做的開發人員的角度,分享咱們已有的經驗。內容將包括:node
Kubernetes有不少受歡迎的地方。用戶喜歡它的豐富功能、穩定性和性能。對貢獻者來講,Kubernetes開源社區不只規模龐大,還易於上手、反饋迅速。而真正讓Kubernetes吸引了第三方開發者的是它的可擴展性。該項目提供了不少方式來添加新功能、擴展示有功能並且不會中斷主代碼庫。正是這些,使得Kubernetes發展成爲了一個平臺。
這裏有一些方式來擴展Kubernetes:python
上圖所示,你能夠發現每一個Kubernetes集羣組件不管是Kubelet仍是API服務器,均可以以某種方式進行擴展。今天咱們將重點介紹一種「自定義控制器」的方式,從如今起我將它稱爲Kubernetes控制器(Kubernetes Controller),或者簡單地稱爲控制器(Controller)。ios
控制器最多見的定義是:使得系統的當前狀態達到所指望的狀態的代碼。但這到底是什麼意思呢?咱們以Ingress控制器爲例。Ingress是一個Kubernetes資源,它可以對集羣中服務的外部訪問進行定義。一般採用HTTP而且有負載均衡支持。然而Kubernetes的核心代碼中並無ingress的實現。第三方控制器的實現將包含:
1.監控ingress/services/endpoint 資源的事件(建立、更新、刪除)
2.程序內部或外部的負載均衡器
3.使用負載均衡器的地址來更新Ingress
「所指望的狀態」在Ingress這裏指的是IP地址指向運行着的負載均衡器,該均衡器由用戶根據ingress規範定義的規則實現。而且由外部Ingress控制器負責將ingress資源轉移到這一狀態。
對相同的資源,控制器的實現以及部署他們的方式也可能會有所不一樣。你能夠選擇nginx控制器並將其部署到集羣中的每一個節點上做爲守護進程集(Daemon Set),也能夠選擇在Kubernetes集羣外部運行ingress控制器而且對F5編程做爲負載均衡器。這裏沒有嚴格的規定,Kubernetes就是如此靈活。nginx
這裏有幾種得到Kubernetes集羣及其資源相關信息的方法,你可使用Dashboard、kubectl或者使用對Kubernetes API的編程式訪問來實現。Client-go全部用Go語言編寫的工具中使用最爲普遍的庫,還有許多其餘語言的版本(java、python等)。若是你還沒本身寫過控制器,我推薦你首先去嘗試go/client-go。Kubernetes是用Go編寫的,並且我發現使用和主項目相同的語言來開發插件會更加方便。git
要熟悉相關的平臺和工具,最好的辦法就是去實踐,去實現一些東西。咱們從簡單入手,先實現一個以下的控制器:
1.監控Kubernetes節點
2.當節點上的鏡像佔用存儲空間時進行警報,而且能夠更改
這部分的實現,源碼能夠在這裏找到:https://github.com/alena1108/...github
做爲一名開發者,我和Rancher Labs的同事們更願意使用輕便簡易的工具,在這裏我將分享3個我最喜歡的工具,它們將幫助咱們完成第一個項目。
1.go-skel – Go語言的微服務skeleton,只需執行run ./skel.sh test123便可,它會爲新的go項目test123建立skeleton。
2.trash – Go語言的供應商管理工具。實際上這兒有不少依賴項管理工具,可是在臨時依賴項管理方面,trash使用起來很是出色,並且簡單。
3.dapper – 在一致性環境中對任何現有構建工具進行封裝的一種工具docker
爲了方便使用client-go的代碼,咱們必需要將其設置爲項目的依賴項。將它添加到vendor.conf文件中:編程
接着運行trash。它會將vendor.conf中定義的全部依賴項都拉到項目的vendor文件夾中。在這裏須要確保client-go與你集羣對應的Kubernetes版本是兼容的。api
在建立與Kubernetes API通訊的客戶端以前,咱們必需要先決定如何運行咱們的工具:是在Kubetnetes集羣內部仍是外部。當應用程序在集羣內部運行時,對它進行容器化,部署成爲Kubernetes pod。它還提供了一些額外的功能:你能夠選擇部署它的方式(Deamon set運行在每一個節點上,或者做爲n個副本的部署),配置針對它的健康檢查等等。當應用程序在集羣外部運行時,就須要本身來管理它。下面的配置可讓咱們的工具變得更靈活,而且支持基於config flag定義客戶端的兩種方式:
咱們將在調試應用程序時使用集羣外部運行的方式,這樣你不須要每次都構建鏡像而且將其從新部署成Kubernetes pod。在測試好應用程序後,咱們就能夠構建鏡像並將其部署到集羣中。
正如在截圖中看到的那樣,正在構建配置,並將其傳遞到kubernetes.NewForConfig來生成客戶端。
咱們的工具須要監控節點。在實現邏輯流程以前,咱們先來熟悉使用client-go執行CRUD操做:
上面的截圖展現了:
1.List節點minikube,是通過FieldSelector過濾器實現的
2.用新的標註來更新節點
3.使用gracePerios=10秒指令刪除節點—意思是從該命令執行後10秒纔會執行刪除操做
上面全部的步驟都是使用咱們以前建立的用戶集(clientset)進行的。
咱們還須要節點上鏡像的相關信息;它能夠經過訪問相應的字段來檢索:
如今咱們知道了如何從Kubernetes APIs中獲取節點並從中獲得鏡像信息。那麼咱們該如何監控鏡像大小的變化呢?最簡單的方法是週期性輪詢節點,計算當前的鏡像存儲容量,並將其和先前輪詢的結果比較。這裏的不足之處在於:不管節點是否發生變化,咱們執行的列表調用都會獲取全部的節點,這可能會很費資源——特別是當輪詢間隔很短的時候。而咱們真正想要實現的是—在節點發生變化時獲得通知,只有在這以後才執行咱們的邏輯流程。這些就是client-go的Informer來作的。
在這個例子中,咱們通過watchList指令爲節點對象建立Informer來監控節點,設置對象類型爲api.Node和30秒的同步週期來週期性地輪詢節點,不管節點是否發生改變——這種方式在更新事件出於某種緣由發生終止時能夠很好的進行撤回。在最後一個參數,咱們傳遞了2個回調函數——handleNodeAdd和handleNodeUpdate。這些回調函數具備實際的邏輯,而且在節點上的鏡像佔用存儲發生改變時觸發。NewInformer返回2個對象——controller和store。一旦controller啓動,將會開始對node.update和node.add的監控,而且調用回調函數。這部分代碼的存儲區位於內存緩存中,由informer負責更新,另外你能夠在緩存區中獲取節點對象而不用直接調用Kubernetes APIs:
咱們的項目中只有一個控制器,使用常規的Informer就足夠了。不過,若是將來你的項目最終同一個對象擁有了多個控制器,我建議你使用SharedInformer。這樣一來你不用再一個一個爲每一個控制器配上Informer,只須要註冊一個Shared informer便可,而且讓每一個控制器註冊本身的一組回調函數,返回共享緩存,這能夠減小內存佔用:
是時候來部署和測試代碼了!對於第一次運行,咱們只須要建立一個go的二進制文件而且在集羣外模式下運行它便可:
如要更改消息輸出,那麼使用鏡像部署一個pod,該鏡像是沒有在當前節點顯示的鏡像。
在基本的功能經過測試以後,接下來就是按照集羣模式嘗試運行它了。爲此咱們必須先建立鏡像,定義它的Dockerfile:
並使用docker build建立一個鏡像,該命令將生成一個可用在Kubernetes中部署pod的鏡像。如今你的應用程序能夠做爲一個pod運行在Kubernetes集羣上了。這裏是一個部署定義的例子,在以前的截圖中,我使用了該例部署咱們的應用程序:
在本文中咱們作了以下工做:
1.建立go項目
2.爲項目添加client-go包的依賴項
3.建立用於和Kubernetes api通訊的客戶端
4.定義一個用於監控節點對象改變,而且一旦發生就執行回調函數的Informer
5.在回調函數中實現一個實際的邏輯
6.在集羣外運行二進制文件來測試代碼,並把它部署到集羣中
http://mp.weixin.qq.com/s/4-c...
http://mp.weixin.qq.com/s/2qZ...
http://mp.weixin.qq.com/s/prP...
http://mp.weixin.qq.com/s/FJ2...
如若轉載,請註明出處謝謝!微信號:RancherLabs