爲什麼我們這麼期待Kubernetes?

Kubernetes的目標用一張被很多人引用過的圖來說明最好:

Kubernetes的目標是讓你可以像管理牲畜一樣管理你的服務,而不是像寵物一樣,同時提高資源的利用率,讓碼農關注在應用開發本身,高可用的事情就交給Kubernetes吧。這個圖本來是openstack提出的,但純粹IaaS層的解決方案實現不了這個目標,於是有了Kubernetes。

Kubernetes和Borg系出同門,基本是Borg的開源改進版本,引用Google Borg論文裏的說法:

it (1) hides the details of resource management and failure handling so its users can focus on application development instead; (2) operates with very high reliability and availability, and supports applica- tions that do the same; and (3) lets us run workloads across tens of thousands of machines effectively

我們如何驗證是否達到這個目標了呢?
隨機關掉一臺機器,看你的服務能否正常
減少的應用實例能否自動遷移並恢復到其他節點
服務能否隨着流量進行自動伸縮

我們從一個簡單的多層應用的架構改進來探討下:

說明:
mysql應該是一主多從的架構,這裏爲了簡單進行了省略
service後面也會依賴數據庫等資源,這裏爲了簡單進行了省略
箭頭表示調用和依賴關係

具體分析一下爲了達到我們的目標,需要做到改進:
Loadbalancer要調用後端應用服務節點,後端應用服務節點掛了或者遷移增加節點,都要變更Loadbalancer的配置。這樣明顯達不到目標,於是計劃將Loadbalancer改造成Smart Loadbalancer,通過服務發現機制,應用實例啓動或者銷燬時自動註冊到一個配置中心(etcd/zookeeper),Loadbalancer監聽應用配置的變化自動修改自己的配置。

Web應用對後端資源的依賴,比如Mysql和Memcached,對應資源的ip一般是寫到配置文件的。資源節點變更或者增加都要變更應用配置。
Mysql計劃該成域名訪問方式,而不是ip。爲了避免dns變更時的延遲問題,需要在內網架設私有dns。高可用採用MHA方案,然後配合服務發現機制自動修改dns。

Memcached計劃參照couchbase的方式,通過服務發現機制,使用SmartClient,客戶端應用監聽配置中心的節點變化。難點可能在於對Memcached的改造(可以參考couchbase)。另外也可以通過增加一層代理的機制實現。

應用節點遷移時依賴的系統和基礎庫不一樣如何處理?部署方式不一樣如何處理?磁盤路徑,監聽端口等衝突怎麼辦?這個可以通過Docker這樣的容器技術,將應用部署運行的方式進行標準化,操作系統和基礎庫的依賴允許應用自定義,對磁盤路徑以及端口的依賴通過Docker運行參數動態注入,而不需要變更應用配置。Docker的自定義變量以及參數,需要提供標準化的配置文件。

服務遷移問題 每種服務都需要一個master調度中心,來監控實例狀態,確定要不要進行遷移,負責統一調度。並且每個服務器節點上要有個agent來執行具體的操作,監控該節點上的應用。另外還要提供接口以及工具去操作。
網絡以及端口衝突的問題比較麻煩 需要引入類似SDN的解決方案。
內存,cpu,以及磁盤等硬件資源,原來的習慣是購買服務器的時候就根據服務器的上的應用類型進行規劃,如果應用和硬件解耦,這種方式需要淘汰。但必須有一種調度機制讓應用遷移的時候可進行篩選。

總結一下,通過分析得出,要達到目標,關鍵是解耦,應用進程和資源(包括 cpu,內存,磁盤,網絡)的解耦,服務依賴關係的解耦。

我們上面的改造機制基本是按照個案進行設計,Kubernetes的則是要提供一套全面通用的機制。

然後,我們看看Kubernetes對以上問題的解決方案:

先上一張Kubernetes官方的架構圖

調度中心master,主要有四個組件構成:
etcd 作爲配置中心和存儲服務(架構圖中的Distributed Watchable Storage),保存了所有組件的定義以及狀態,Kubernetes的多個組件之間的互相交互也主要通過etcd。

kube-apiserver 提供和外部交互的接口,提供安全機制,大多數接口都是直接讀寫etcd中的數據。
kube-scheduler 調度器,主要幹一件事情:監聽etcd中的pod目錄變更,然後通過調度算法分配node,最後調用apiserver的bind接口將分配的node和pod進行關聯(修改pod節點中的nodeName屬性)。scheduler在Kubernetes中是一個plugin,可以用其他的實現替換(比如mesos)。有不同的算法提供,算法接口如下:

kube-controller-manager 承擔了master的主要功能,比如和CloudProvider(IaaS)交互,管理node,pod,replication,service,namespace等。基本機制是監聽etcd /registry/events下對應的事件,進行處理。具體的邏輯需要專門文章分析,此處不進行詳解。

節點上的agent,主要有兩個組件:
kubelet 主要包含容器管理,鏡像管理,Volume管理等。同時kubelet也是一個rest服務,和pod相關的命令操作都是通過調用接口實現的。比如:查看pod日誌,在pod上執行命令等。pod的啓動以及銷燬操作依然是通過監聽etcd的變更進行操作的。但kubelet不直接和etcd交互,而是通過apiserver提供的watch機制,應該是出於安全的考慮。kubelet提供插件機制,用於支持Volume和Network的擴展。

kube-proxy 主要用於實現Kubernetes的service機制。提供一部分SDN功能以及集羣內部的智能LoadBalancer。前面我們也分析了,應用實例在多個服務器節點之間遷移的一個難題是網絡和端口衝突問題。Kubernetes爲每個service分配一個clusterIP(虛擬ip)。不同的service用不同的ip,所以端口也不會衝突。Kubernetes的虛擬ip是通過iptables機制實現的。每個service定義的端口,kube-proxy都會監聽一個隨機端口對應,然後通過iptables nat規則做轉發。比如Kubernetes上有個dns服務,clusterIP:10.254.0.10,端口:53。應用對10.254.0.10:53的請求會被轉發到該node的kube-proxy監聽的隨機端口上,然後再轉發給對應的pod。如果該服務的pod不在當前node上,會先在kube-proxy之間進行轉發。當前版本的kube-proxy是通過tcp代理實現的,性能損失比較大(具體參看後面的壓測比較),1.2版本中已經計劃將kube-proxy完全通過iptables實現(https://github.com/kubernetes/kubernetes/issues/3760)
Pods Kubernetes將應用的具體實例抽象爲pod。每個pod首先會啓動一個google_containers/pause docker容器,然後再啓動應用真正的docker容器。這樣做的目的是爲了可以將多個docker容器封裝到一個pod中,共享網絡地址。

Replication Controller 控制pod的副本數量,高可用就靠它了。
Services service是對一組pods的抽象,通過kube-proxy的智能LoadBalancer機制,pods的銷燬遷移不會影響services的功能以及上層的調用方。Kubernetes對service的抽象可以將底層服務和上層服務的依賴關係解耦,同時實現了和Docker links類似的環境變量注入機制(https://github.com/kubernetes/kubernetes/blob/release-1.0/docs/user-guide/services.md#environment-variables),但更靈活。如果配合dns的短域名解析機制,最終可實現完全解耦。

Label key-value格式的標籤,主要用於篩選,比如service和後端的pod是通過label進行篩選的,是弱關聯的。
Namespace Kubernetes中的namespace主要用來避免pod,service的名稱衝突。同一個namespace內的pod,service的名稱必須是唯一的。
Kubectl Kubernetes的命令行工具,主要是通過調用apiserver來實現管理。

Kube-dns dns是Kubernetes之上的應用,通過設置Pod的dns searchDomain(由kubelet啓動pod時進行操作),可以實現同一個namespace中的service直接通過名稱解析(這樣帶來的好處是開發測試正式環境可以共用同一套配置)。主要包含以下組件,這幾個組件是打包到同一個pod中的。
etcd skydns依賴,用於存儲dns數據

skydns 開源的dns服務
kube2sky 通過apiserver的接口監聽kube內部變更,然後調用skydns的接口操作dns
Networking Kubernetes的理念裏,pod之間是可以直接通訊的(http://kubernetes.io/v1.1/docs/admin/networking.html),但實際上並沒有內置解決方案,需要用戶自己選擇解決方案: Flannel,OpenVSwitch,Weave 等。我們測試用的是Flannel,比較簡單。
配置文件 Kubernetes 支持yaml和json格式的配置文件,主要用來定義pod,replication controller,service,namespace等。

Kubernates 可能帶來的改變
降低分佈式應用開發運維的複雜度 縱觀當前的各種分佈式架構,hadoop,storm等,都是master-workers模式,框架很大一部分功能在節點的管理,處理程序的調度上,如果基於Kubernetes來實現類似功能,這些基本都可以交給Kubernetes完成,框架只需要負責核心數據的流轉以及收集邏輯。當然,當前Kubernetes的pod還未像Borg一樣直接支持batch job,但按照Kubernetes和Borg的關係,將來應該會支持(http://blog.kubernetes.io/2015/04/borg-predecessor-to-kubernetes.html)。
更完備的CI/CD(持續集成/持續交付)工具 CI是code-deploy的關鍵工具,但當前由於受限於部署環境的不一致,CI可做的事情有限,大多數還依賴用戶的自定義腳本。有了Kubernetes這樣的標準環境後,以後此類工具可以覆蓋測試環境部署,集成測試,上線部署等環節,實現標準化的交付工作流。
Kubernetes之上的分佈式存儲 Kubernetes官方提供了一個在Kubernetes上部署cassandra的例子,只需要重寫一個基於Kubernetes apiserver的SeedProvider,就可以避免靜態配置seed ip,享受Kubernetes帶來的scale-out能力。再如前面我們提到的memcached的高可用例子,如果基於Kubernetes實現一個memcached的smart client,只需要改下客戶端即可,非常簡單。個人認爲以後在Kubernetes上的支持多租戶的分佈式存儲會更加流行。只要解決了存儲服務的scale-out問題,應用的scale-out一般不會有太大問題。Hypernetes就是一個實現了多租戶的Kubernetes版本。
企業應用的分發 當前SaaS(on-demand)比較流行的一個很大的原因是原來的on-premise應用的部署運維成本太高,如果Kubernetes等分佈式操作系統得到廣泛應用,on-premise的成本降低,on-premise以及託管雲模式對SaaS的格局也會帶來影響。這也是我們這樣的創業公司關注Kubernetes的原因之一。
對IaaS的影響 當前的IaaS平臺的組件逐漸有閉源的趨勢,比如AWS嘗試用Aurora替代Mysql,阿里雲用KVStore替換Redis。用戶主要關心的是服務的可靠性,自己運維的時候可能會傾向於開源方案,但如果使用雲廠商的服務,就不太關心。按照這樣的趨勢,隨着IaaS的普及,會對整個開源的生態產生影響。但有了Kubernetes這樣的平臺,IaaS廠商主要爲Kubernetes提供運行的基礎環境,Kubernetes接管上面的應用和服務,這樣在IaaS廠商之間遷移也很容易。
微服務 微服務最近很熱,但這個概念其實不新。主要一直受限於運維的複雜度,沒有普及。如果運維繫統跟不上,服務拆太細,很容易出現某個服務器的角落裏部署着一個很古老的不常更新的服務,後來大家竟然忘記了,最後服務器遷移的時候給丟了,用戶投訴才發現。而隨着Docker以及Kubernetes這樣的工具和平臺逐漸成熟,微服務的時代也到來了。 在Kubernetes上的微服務治理框架可以一攬子解決微服務的rpc,監控,容災問題,個人覺得可以期待。
發佈了581 篇原創文章 · 獲贊 707 · 訪問量 202萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章