Kubernetes設計和開發四大基本原則

作者介紹:Saad Ali 是來自Google的高級軟件工程師,致力於開源Kubernetes項目。他於2014年12加入該項目並負責Kubernetes存儲和volume子系統的開發。他還擔任Kubernetes存儲興趣小組的負責人,同時也是CSI(容器存儲接口)的協同開發者和maintainer。在加入Google之前,Saad Ali於微軟負責IMAP原型開發項目。

Kubernetes正在迅速成爲在分佈式系統上部署工作負載的事實標準。在這篇文章中,筆者將通過揭示其設計的一些原則,幫助你更深入地瞭解Kubernetes。

1、要聲明式而不要命令式

一旦你學會在Kubernetes開源編排引擎上部署第一個工作負載(pod),就會遇到Kubernetes的第一個原則:Kubernetes API是聲明性的而不是命令式的。

在命令式API中,你可以直接發出服務器要執行的命令,例如: “運行容器”、“停止容器”等。在聲明性API中,你聲明系統要執行的操作,系統將不斷向該狀態驅動。

可以想象成手動駕駛和自動駕駛系統。

因此,在Kubernetes中,你創建一個API對象(使用CLI或REST API)來表示你希望系統執行的操作。系統中的所有組件都會向該狀態發展,直到刪除該對象。

例如,如果要調度容器化工作負載,不是發出“運行容器”命令,而是創建描述所需狀態的API對象、pod:

創建後,此對象在API服務器上保留:

如果容器由於某種原因崩潰,系統將重新啓動容器。

要終止容器,請刪除pod對象:

爲什麼要聲明式而不要命令式?

聲明式API使系統更加健壯。

在分佈式系統中,任何組件都可能隨時出現故障。當組件恢復時,需要弄清楚要做什麼。

使用命令式API時,崩潰的組件可能在它關閉時錯過了一個調用,並且需要一些外部組件在它恢復時“趕上”。但是使用聲明式API,組件只需查看API服務器的當前狀態,即可確定它需要執行的操作(“啊,我需要確保此容器正在運行”)。

這也被描述爲“水平觸發”而不是“邊緣觸發”。在邊緣觸發系統中,如果系統錯過“事件”(“邊緣”),則必須重放事件以便系統恢復。在水平觸發系統中,即使系統錯過了“事件”(可能是因爲它已經關閉),當它恢復時,它可以查看信號的當前狀態並相應地做出響應。

因此,聲明式API使Kubernetes系統對組件故障更加健壯。

  • 2、
沒有隱藏的內部API

如果你瞭解各種Kubernetes組件的工作原理,你會遇到Kubernetes的下一個原則:控制平面是透明的,因爲沒有隱藏的內部API。

這意味着Kubernetes組件用來交互的API和你用來與Kubernetes交互的API相同。結合第一個原則(Kubernetes API是聲明式的),這意味着Kubernetes組件只能通過監控和修改Kubernetes API來交互。

讓我們通過一個簡單的例子來說明這一點。爲了啓動容器化工作負載,你可以在Kubernetes API服務器上創建一個pod對象,如上所示。

Kubernetes調度程序根據可用資源確定運行pod的最佳節點。調度程序通過爲新pod對象監控Kubernetes API服務器來完成此操作。當新的未調度的pod被創建時,調度程序將運行其算法爲這個pod查找最佳節點。在調度pod之後(已爲pod選擇了最佳節點),調度程序不會去告訴所選節點要啓動pod。請記住,Kubernetes API是聲明式的,內部組件使用相同的API。因此,調度程序更新pod對象中的NodeName字段以指示已經調度該pod。

kubelet(在節點上運行的Kubernetes代理)監控Kubernetes API(就像其他Kubernetes組件一樣)。當kubelet看到具有與自身對應的NodeName字段的pod時,它知道改pod已經被調度且必須啓動它。一旦kubelet啓動了pod,它就會繼續爲pod監控容器狀態,並且只要相應的pod對象繼續存在於API服務器中,就會一直讓容器保持運行。

刪除pod對象後,Kubelet會明白不再需要容器,並終止它。

爲什麼沒有隱藏的內部API?

讓Kubernetes組件使用相同的外部API使得Kubernetes可組合和可擴展。

如果由於某種原因,Kubernetes的默認組件(例如,調度程序)不足以滿足你的需求,你可以將其關閉並將其替換爲自己的使用相同API的組件。

此外,如果你需要的功能尚不可用,則可以使用公共API輕鬆編寫組件以擴展Kubernetes功能。

  • 3、
在用戶所在的位置滿足他們

Kubernetes API允許存儲工作負載可能感興趣的信息。例如,Kubernetes API可用於存儲祕密或配置映射。祕密可以是你在容器鏡像中不想要的任何敏感數據,包括密碼、證書等。配置映射可以包含應獨立於容器鏡像的配置信息,例如應用程序啓動和其他類似參數。

由於上面定義的沒有隱藏的內部API的第二個原則,可以修改在Kubernetes上運行的應用程序以直接從Kubernetes API服務器獲取祕密或配置映射信息。但這意味着你需要修改應用程序以意識到它是在Kubernetes中運行。

這就是Kubernetes的第三個原則:在用戶所在的位置滿足他們。也就是說,Kubernetes不應要求重寫要在Kubernetes上運行的應用程序。

例如,許多應用程序接受祕密和配置信息作爲文件或環境變量。因此,Kubernetes支持將祕密和配置映射作爲文件或環境變量注入pod。

爲什麼要這麼做?
通過進行設計選擇,最大限度地減少在Kubernetes上部署工作負載的障礙,Kubernetes可以輕鬆地運行現有工作負載,而無需重寫或大幅改變它們。

  • 4、
工作負載可移植性

一旦在Kubernetes上運行無狀態工作負載,下一步自然就是嘗試在Kubernetes上運行有狀態工作負載。Kubernetes提供了一個功能強大的卷插件系統,可以將許多不同類型的持久存儲系統與Kubernetes工作負載一起使用。

例如,用戶可以輕鬆地請求將Google Cloud Persistent Disk安裝到特定路徑的pod中:

創建此pod時,Kubernetes將自動負責將指定的GCE PD掛載到pod被調度到的節點,並將其掛載到指定的容器中。然後,容器可以在容器或pod的生命週期之外寫入GCE PD被掛載到持久數據的路徑。

此方法的問題在於pod定義(pod YAML)直接引用Google Cloud Persistent Disk。如果此pod已部署在非Google Cloud Kubernetes集羣上,則無法啓動(因爲GCE PD無法使用)。

這是另一個Kubernetes原則的用武之地:工作負載定義應該可以跨集羣移植。用戶應該能夠使用相同的工作負載定義文件(例如相同的pod yaml)來跨不同的集羣可以部署工作負載。

理想情況下,上面指定的pod甚至應該可以在沒有GCE PD的集羣上運行。爲了實現這一目標,Kubernetes引入了PersistentVolumeClaim(PVC)和PersistentVolume(PV)API對象。這些對象將存儲實現與存儲使用分離。

PersistentVolumeClaim對象用作用戶以與實現無關的方式請求存儲的方法。例如,用戶可以創建PVC對象來請求100 GB的ReadWrite存儲,而不是請求特定的GCE PD:

Kubernetes系統將此請求與來自包含PersistentVolume對象的可用磁盤池中的卷匹配,或自動配置新卷以滿足請求。無論哪種方式,用於Kubernetes集羣部署工作負載的對象都可以跨集羣實現移植。

爲什麼要有工作負載可移植性?

這種工作負載可移植性原則突出了Kubernetes的核心優勢:與操作系統使應用程序開發人員不必擔心底層硬件的細節一樣,Kubernetes將分佈式系統應用程序開發人員從底層集羣的細節中解放出來。使用Kubernetes,分佈式系統應用程序開發人員不必被鎖定到特定的集羣環境。針對Kubernetes部署的應用程序可以輕鬆地部署到本地和雲環境中的各種集羣,而無需對應用程序或部署腳本進行特定於環境的更改(Kubernetes端點除外)。

  • 5、
結論

由於這些原則,Kubernetes更強大,可擴展,可移植且易於遷移。這就是Kubernetes迅速成爲在分佈式系統上部署工作負載的行業標準的原因。

本文轉移K8S技術社區-Kubernetes設計和開發四大基本原則

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章