Kubernetes – Google分布式容器技術初體驗
Kubernetes是Google開源的容器集群管理系統。前幾天寫的 分布式服務框架的4項特性中提到一個良好的分布式服務框架需要實現。
"服務的配置管理。包括服務發現、負載均衡及服務依賴管理。
服務之間的調度及生命周期管理。"
由于Kubernetes包含了上述部分特性,加上最近Google新推出的Container Engine也是基于Kubernetes基礎上實現,因此最近對Kubernetes進行了一些嘗試與體驗。
運行環境
Kubernetes目前處于一個快速迭代的階段,同時它的相關生態圈(比如docker,etcd)也在快速發展,這也意味沒有適合新手使用非常順暢的版本,網上的各種文檔(也包括官方文檔)和當前***的發布版會有不同程度滯后或不適用的情況,因此在使用時可能會碰到各種細節的障礙,而且這些新版本碰到的問題,很有可能在網上也搜索不到解決方案。
Kubernetes設計上并未綁定Google Cloud平臺,但由于以上原因,為了減少不必要的障礙,初次嘗試建議使用GCE作為運行環境(盡管GCE是一個需要收費的環境)。默認的cluster啟動腳本會創建5個GCE instance,測試完需要自己及時主動刪除。為了避免浪費,可以將minions減少,同時instance類型選擇f1-micro。費用方面一個f1-micro instance運行1個月大約50元人民幣,因此用GCE來測試Kubernetes,如果僅是測試時候開啟的話,并不會產生太多費用。
Pods及Replication Controller
Kubernetes的基本單元是pods,用來定義一組相關的container。Kubernetes的優點是可以通過定義一個replicationController來將同一個模塊部署到任意多個容器中,并且由Kubernetes自動管理。比如定義了一個apache pod,通過replicationController設置啟動100個replicas,系統就會在pod創建后自動在所有可用的minions中啟動100個apache container。并且輕松的是,當container或者是所在的服務器不可用時,Kubernetes會自動通過啟動新的container來保持100個總數不變,這樣管理一個大型系統變得輕松和簡單。
Service 微服務
在解決部署問題之后,分布式服務中存在的一大難題是服務發現(或者叫尋址),用戶訪問的前端模塊需要訪問系統內部的后端資源或者其他各種內部的服務,當一個內部服務通過replicationController動態部署到不同的節點后,而且還存在前文提到的動態切換的功能,前端應用如何來發現并訪問這些服務?Kubernetes的另外一個亮點功能就是service,service是一個pod服務池的代理抽象,目前的實現方法是通過一個固定的虛擬IP及端口來定義,并且通過分布在所有節點上的proxy來實現內部服務對service的訪問。
Kubernetes自身的配置是保存在一個etcd(類似ZooKeeper)的分布式配置服務中。服務發現為什么不通過etcd來實現?Tim的判斷更多的是為了Kubernetes上的系統和具體的配置服務解耦。由于服務發現屬于各個系統內部的業務邏輯,因此如果使用etcd將會出現業務代碼的邏輯中耦合了etcd,這樣可能會讓很多架構師望而卻步。
盡管沒有耦合etcd,部署在Kubernetes中的服務需要通過container中的環境變量來獲得service的地址。環境變量雖然簡單,但它也存在很多弊端,如存在不方便動態更改等問題。另外service目前的實現是將虛擬IP通過iptables重定向到最終的pod上,作者也提到iptables定向的局限性,不適合作為大型服務(比如上千個內部service一起運作時)的實現。
由于service定位是系統內部服務,因此默認情況下虛擬IP無法對外提供服務,但Kubernetes當前版本并沒直接提供暴露公網IP及端口的能力,需要借助云服務(比如GCE)的load balancer來實現。
小結
總的看來Kubernetes提供的能力非常令人激動,pod、replicationController以及service的設計非常簡單實用。但如果立即將服務遷移到Kubernetes,還需要面對易變的環境。另外盡管Kubernetes提供health check的機制,但service生產環境所需的苛刻的可用性還未得到充分的驗證。Service發現盡管不跟Kubernetes的內部實現解耦,但利用環境變量來實現復雜系統的服務發現也存在一些不足。
#p#
安裝說明
Kubernetes cluster簡單安裝說明如下,需要嘗試的朋友可參考。
前提準備
一個64 bit linux環境,***在墻外的,避免訪問google cloud出現超時或reset等問題;另外創建Google Cloud帳號,確保創建instances以及Cloud Storage功能可用;
安裝步驟
1. 安裝go語言環境(可選,如果需要編譯代碼則需要)
2. 安裝Google cloud sdk
$ curl https://sdk.cloud.google.com | bash
$ gcloud auth login
按提示完成授權及登錄
3. 安裝 etcd 二進制版本(V0.4.6), 解壓后將其目錄加入PATH
4. 安裝 kubernetes***的relase binary版本(V0.5.1)
修改 cluster/gce/config-default.sh,主要是修改以下字段以便節約資源。
- MASTER_SIZE=f1-micro
- MINION_SIZE=f1-micro
- NUM_MINIONS=3
在kubernetes目錄運行
$ cluster/kube-up.sh
執行成功后會顯示 done
5. 測試pod
以上腳本啟動了examples/monitoring 下面定義的service,如果嘗試啟動其它自己的pods,比如啟動一個tomcat集群
- {
- "id": "tomcatController",
- "kind": "ReplicationController",
- "apiVersion": "v1beta1",
- "desiredState": {
- "replicas": 2,
- "replicaSelector":{"name": "tomcatCluster"},
- "podTemplate":{
- "desiredState": {
- "manifest": {
- "version": "v1beta1",
- "id": "tomcat",
- "containers": [{
- "name": "tomcat",
- "image": "tutum/tomcat",
- "ports": [
- {"containerPort":8080,"hostPort":80}
- ]
- }]
- }
- },
- "labels": {"name": "tomcatCluster"}}
- },
- "labels": {
- "name": "tomcatCluster",
- }
- }
其中pod的tomcat image可以通過Docker Hub Registry https://registry.hub.docker.com/ 搜索及獲取
$ cluster/kubectl.sh create -f tomcat-pod.json
創建成功后通過 cluster/kubectl.sh get pods 來查看它所在minion及ip,可以通過curl或瀏覽器來訪問(請開啟GCE防火墻端口設置)。
再定義一個 service
- {
- "id": "tomcat",
- "kind": "Service",
- "apiVersion": "v1beta1",
- "port": 8080,
- "containerPort": 8080,
- "labels": {
- "name": "tomcatCluster"
- },
- "selector": {
- "name": "tomcatCluster"
- }
- }
保存為 tomcat-service.json
$ cluster/kubectl.sh create -f tomcat-service.json
檢查service啟動后的ip及端口,由于service是內部ip,可以在GCE上通過curl來測試及驗證。
$ cluster/kubectl.sh get services
6. 關閉cluster
cluster/kube-down.sh
作者簡介:楊衛華(Tim Yang),新浪微博技術總監,負責設計新浪微博基礎平臺架構,解決新浪微博發展中遇到的各種技術瓶頸,并致力于打造業界***的開放平臺。業余關注新技術在互聯網系統中的應用。