天天看點

應用開發的先鋒:容器和Kubernetes的故事

本文介紹了容器和kubernetes的底層概念,以及它們如何給應用開發提供了新的模式。

容器就是新的程序

讓我們從計算機開聊。 當計算機啟動時,它會運作一個叫init的程式,然後init會啟動其他所需的程式:伺服器、終端、視窗管理器等。 init能做幾件有趣的事情, 例如讓一個程式開機啟動, 隔一段時間運作一個程式, 還有確定一個程式沒有失敗或者crash,如果有就重新開機它。 正在運作的程式可以看到這台機器上的所有東西: 其它在運作的程式,所有的檔案,以及網絡。

多個程序同時跑在一台計算機上。所有的程序可以自由的互相之間互動,或者與正常的資源互動。

通過将程序進行劃分, 程式員可以有一個更加簡單的模型來友善了解, 是以建立命名空間(namespace)的工具也被開發出來了。 程式或者程序隻能看到運作在同一個命名空間下的其他程序。 如果它們尋找檔案,那麼隻能看見硬碟上配置設定到這個命名空間的那一部分。 從安全的角度而言,一個命名空間裡面的某個程序被黑掉了影響的僅僅也隻是這個命名空間而已。

類似于docker和rkt這樣的工具被開發出來以後使得我們能系統化地使用這些特性。 這些工具提供了打包的功能,将一個命名空間打包成一個容器,使得我們可以很友善的将它搬到另一台機器上運作,不出意外的它會跟之前完全一緻的方式繼續運作,因為它本身的隔離特性。 事實上,通常可以很容易的将容器想象為可以完全獨立的運作的小計算機. 因為這些新的工具非常易用,它們漸漸成為一種流行的建構軟體方式。

容器就是新的程序。

應用開發的先鋒:容器和Kubernetes的故事

容器中的程序。 在這裡,一個程序僅僅能夠與所在同一個容器裡面的其他程序和資源互動。

擴充: 一個好“難題”

一台計算機的資源是有限的,而且同時僅能處理有限的資料和運作有限的程序。 當面臨增長的負載時(比如更多使用者,更大的資料集)一個簡單的應對方式是垂直擴充,也即是增加更多的處理能力和記憶體給到這台計算機,但是很快這個代價就會非常昂貴,而且本身擴充的空間也相當有限。 另一種方式就是通過增加更多的計算機來水準擴充。 這些計算機一起就組成了叢集。

為了能跑在叢集上,應用也需要以不同的方式架構。 例如,如果我們确認同一個程式的兩份拷貝可以不需要通路對方的資料就能運作,那麼我們就能放心的将它的多份拷貝放到不同的計算機上運作。

應用開發的先鋒:容器和Kubernetes的故事

水準擴充:在這裡叢集裡,三台計算機每台運作兩個容器。 一共有兩個app server的執行個體來處理大的負載。

雖然容器本身并沒有給我們任何其他的工具來建構分布式應用,但是考慮一下這個級别上的抽象能讓建構叢集的應用友善一些。容器模型所鼓勵的假設情形是:

可以有多份拷貝同時運作(架構要考慮并發性)。

容器可以在叢集中的任意一台機器上動态啟動和停止(最好是無狀态或者臨時的),而且

計算機或者程序可能會在任意的時間點失敗或者不可用但是整個系統仍然保持工作(架構要考慮失敗和恢複)。

由于在叢集裡面有這麼多的計算機要管理,我們面臨一些額外挑戰:

首先,我們需要管理計算機上的資源,比如處理能力和存儲。這意味着我們不得不有效地分發和排程程序到不同的計算機上去執行。

我們也需要“親和性”和方法将相關的程序放在一起跑,以便高效利用共享存儲;而同時“反親和性”的要求又需要保證對同一個資源有競争性的程序不能運作在同一台機器上。例如,如果我們想要将應用伺服器的程序跑兩份來服務兩倍的請求,我們可能希望他們跑在叢集裡兩台不同的伺服器上。

當許多的程序跑在不同的地方時,我們需要一種方式讓他們互相發現和溝通。我們隻需要某個程序運作所在的機器ip就可以與這個程序通信。

在隻有一台計算機的時候,隻有一個ip位址就可以了。 在有多個計算機之後,我們需要維護一個程序到ip的映射,例如像etcd這樣的分布式資料庫。 當一個程序在一台機器上啟動時,這個資訊就被加入到資料庫中。 如果程序挂掉或者機器當機,也需要将這個條目從資料庫中删除。

程式員對于開發跑在一台計算機上的應用很得心應手了。 理想狀态下,我們想要的是有一個工具能将叢集裡面所有的計算機管理起來,而展現給程式員的就像一台“巨型”的計算機。

這個方向上的一個進展是coreos的fleet項目,它的基本思想就是像一台計算機上的init程序那樣延伸做整個叢集的init。

google 貢獻的kubernetes項目則讓我們更加接近我們想要一台”巨型”計算機的模型。

kubernetes:pod就是新的計算機

kubernetes做的第一件事情就是拿走你的所有計算機,然後還回給你一個”巨型”計算機--一個kubernetes的叢集。

一個kubernetes的pod指定一組需要運作docker或者rkt容器。

之前我們描述的是一個叢集裡面不同計算機上跑着不同程序,現在我們看到的是kubernetes叢集裡面的不同pod裡跑着不同程序。

應用開發的先鋒:容器和Kubernetes的故事

一個kubernetes叢集圍繞着pod也就是容器組建構了一個模型. 這些pod基于資源和”親和度”的限制被動态配置設定到底層節點上。

之前,我們考慮的是什麼程序需要在一台機器上一起運作。 現在,我們考慮将哪些程序組構造成什麼pod;pod已經成為一種優美的方式來對一個應用的一個功能單元構造模型。我們甚至可以直接使用社群構造的pod,直接将他們跑起來,例如日志和監控。

一個pod裡面的所有程序跑在同一台機器上,這樣解決了類似挂載磁盤這樣的資源共享的問題。 背後是kubernetes将pod配置設定到不同的計算節點也就是kubernetes node上,我們可以給pod或者node設定發生的條件例如資源限制、親和性等。

計算機就是資源的集合:計算能力、記憶體、磁盤和網絡接口。與之類似,一個pod可以從底層的資源池中配置設定一定量的資源. 它也會有自己的網卡和pod所在的虛拟網絡的ip。

是以,pod就是新的計算機。

如果我們需要某個特定功能進行擴充,我們隻需要在叢集中多跑幾個這個pod的拷貝。 當硬體不足,我們就往叢集裡面增加更多的計算和存儲。 通過将資源與它所承載的功能解耦,排程器可以保證所有的可用資源會被盡可能高效利用。

kubernetes複制控制器用來保證任意時間某個pod的一定數量的拷貝在運作。 就像一個分布式的init,如果一個pod挂了: 起因可能是裡面的一個程序失敗了,或者pod 的依賴挂了,或者它所在的節點down了; kubernetes會探測到并在另一個可用的節點上啟動一個新的拷貝。

一個kubernetes的service會跟蹤叢集裡某種特定type的pod的所有執行個體。 例如,我們有一個ap server service,它會跟蹤cluster裡面所有的app server的pod。service是一個非常簡便的抽象;我們的應用可以非常快的找到某種類型服務的所有功能單元然後将工作分發給他們。

應用開發的先鋒:容器和Kubernetes的故事

 一個完整的kubernetes叢集圖

pod被動态配置設定到節點上。 每一種pod對應的服務都有服務發現和負載均衡,同時也描繪了pod和服務的虛拟網絡。

kubernetes既是一個在叢集裡面管理和排程程序的架構,也是一種建構應用的新的思維模型,基于的是pod裡面的程序分組和service所提供的服務發現。

整個生态以及未來發展

管理一台計算機已經是一個難題了。 管理一大群互相通訊的機器更是複雜得多. 感謝發明了像docker、kubernetes這樣非凡工具的好心人,我們現在有了容器這樣的簡單模型,也有工具将叢集管理起來就像一台計算機。 建構可擴充的應用也從沒像現在這樣如此簡單。

容器和叢集管理軟體業也影響了人們建構應用的方式。 他們創造了新的模式和抽象,很多的可能性仍在探索中, 例如, 使用容器來建構可重用的應用元件或者庫可能也會很有意思。 在hasura,我們正為資料庫、搜尋、使用者管理、檔案管理等等建立元件,建構應用就隻需将它們快速組裝起來。

總的來說,在追求創造更簡模型的道路上我們已經前進了一大步。 當今的所有軟體本質就是運作代碼,執行功能。 從這個角度,我們做的所有的事情僅僅是管理這些功能:将它們分組,運作它們的多份拷貝,找到并與它們互動,然後處理失敗的情況。 由此推出一個邏輯結論, 或許某一天我們會有這樣一個系統,我們隻需要描述我們需要的功能,餘下的交給系統按照描述完成即可。 那确實是求之不得啊!

akshaya acharya

akshaya上司着hasuar的平台工程團隊。 他曾經在intellectual ventures的一個咨詢團隊與靈活開發團隊一起工作過,也曾經作為tech mentor在mest、ghana工作過。

本文轉自d1net(轉載)