Kubernetes從部署到運維詳解
Kubernetes是Google開源的Docker容器集群編排管理系統,為容器化的應用提供自動部署,彈性伸縮,資源調度,負載均衡和服務發現等應用云平臺所需的管理功能體系。Kubernetes 的靈感源于谷歌過去15年在生產環境中運行容器的管理經驗,集合了社區中先進的理念和實戰技術。
Kubernetes對計算資源進行了更高層次的抽象,通過將容器進行細致的組合,將最終的應用服務交給用戶。Kubernetes在模型建立之初就考慮了容器跨機連接的要求,支持多種網絡解決方案,同時在Service層次構建集群范圍的SDN網絡。其目的是將服務發現和負載均衡放置到容器可達的范圍,這種透明的方式便利了各個服務間的通信,并為微服務架構的實踐提供了平臺基礎。而在Pod層次上,作為Kubernetes可操作的最小對象,其特征更是對微服務架構的原生支持。
一.架構及部署 Architecture
Kubernetes是2014年6月開源的,采用Golang的語言開發,每一個組件互相之間使用的是Master API的方式,Kubernetes的架構模式是用Master-slave模式,并且支持多種聯機網絡,支持多種分布式存儲架構。
Master的核心組件是API server,對外提供REST API服務接口。kubernetes所有的信息都存儲在分布式系統ETCD中. Scheduler是kubernetes的調度器,用于調度集群的主機資源。Controller用于管理節點注冊以及容器的副本個數等控制功能。
在Node上的核心組件是kubelet,它是任務執行者,會跟apiserver進行交互,獲取資源調度信息。 kubelet會根據資源和任務的信息和調度狀態與Docker去交互,調用Docker的API, 創建、刪除與管理容器,而kube-Proxy可以根據從API里獲取的信息以及整體的Pod架構狀態組成虛擬NAT網絡。
快速部署過程
在最新更新的kubernetes 1.4版本中,社區開發了專用的部署組件kubeadm, 用來完成kubernetes集群整體的部署過程。Kubeadm是對以往手動或腳本部署的簡化,集成了manifest配置、參數設置、認證設置、集群網絡部署以及安全證書的獲取。需要注意的是kubeadm目前默認從gcr.io的鏡像中心獲取鏡像,若需使用其他鏡像源,需要更改源碼編譯出定制版本。
Ubuntu 16.04環境的使用過程如下:
設定部署主機資源
1)在所有節點上(包括master和node)部署基礎運行環境
部署內容包括docker, kubelet, kubeadm, kubectl kubernetes-cni
運行如下命令:
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - # cat <<EOF > /etc/apt/sources.list.d/kubernetes.list deb http://apt.kubernetes.io/ kubernetes-xenial main EOF # apt-get update # apt-get install -y docker.io kubelet kubeadm kubectl kubernetes-cni
2)部署Master
在Master上運行 kubeadm init, 運行結束后,可獲得集群的token,以及提示在node上運行的命令:
3)添加節點
在master上的kubeadm init的輸出中獲取相應的參數并在Node上運行:
4)部署網絡
kubernete集群需要可以跨主機的網絡解決方案,使得位于不同主機的pod可以相互通信。目前有多種類似的解決方案,例如weave network, calico 或者 Canal。當前使用的是weave net
關于網絡,對于隔離要求較高的場景需求,采用calico是比較合適的選擇。calico會幫助容器在主機間搭建純二層的網絡,在每個主機上維護一個路由表,用來獲取目標容器所在主機的可達路徑,以及本機容器的路有項。利用iptables的防火墻機制去做隔離。容器之間跨主機進行交互時,IP包從容器出發,經過本地路有表選路,通過目標網段所在主機的路有項,到達目標主機,然后在目標主機內,進入路有選路前,先經由iptables隔離規則(可設置)進行判斷決定是否丟棄或返回,然后再經路有選路到目標容器,最終到達目標容器。整個過程沒有任何封包解包的過程,傳輸效率較高。
隔離規則可以設定在同一用戶名下的哪些容器可以被隔離成一組,被隔離的容器間可通信,而與其它容器不可通信。或者設置規則來組成更加豐富的隔離效果。
部署組件詳解
在kubernetes 1.4版本利用kubeadm部署過程中,安裝的插件包括kube-discovery,kube-proxy和kube-dns,分別負責部署階段配置的分發, NAT網絡和集群系統的dns服務。值得注意的是kube-proxy不再通過manifest來運行,是通過插件用demonset的方式來部署。
1)kubeadm
在kubeadm init運行階段,首先創建驗證token以及靜態pod文件(manifest的文件),以及運行所需的證書和kubeconfig。完成這些工作后,kubeadm會等待apiserver的啟動并正常運行,以及等待首個節點的接入。
由于master節點啟動kubelet來運行manifest文件,并且在kubelet.conf中設置了需要連接當前主機為master,因此此master 也會作為node節點接入,并且master作為節點運行也為kube-discovery提供運行的必須環境。
當節點加入并且apiserver運行正常后,將標示master的角色,kubeadm.alpha.kubernetes.io/role=master。
2)Kube-discovery
隨后在部署運行kube-discovery時,在kube-discovery所運行的pod上設置node的親和性,并將它限制成為必須在master上運行的pod。由于kube-discovery的主要功能是證書及token等配置的管理與分發,并且后續的節點加入時只需要一個簡單的master ip信息,因此將kube-discovery限制到了master節點運行,以此統一服務的入口。
這些通過在pod的annotations來實現
requiredDuringSchedulingIgnoredDuringExecution表示在調度過程中需要滿足的條件,和后面的nodeSelectorTerms在一起類似于nodeselector。這樣設置即可將pod限制到master主機中。
3)Kube-dns
從kubernetes 1.3開始,kube-dns已經不再使用etcd+skydns+kube2sky的方式。而是使用了dns緩存及轉發工具dnsmasq,以及利用skydns庫和本地內存緩存組合而成的kube-dns。
Kube-dns將從kubernetes master中監聽變動的service和endpoint信息,并建立從service ip 到service name的域名映射(對于無service的,將會建立pod ip和相應域名的映射)。Kube-dns將這些信息存放在本地的內存緩沖中,并監聽127.0.0.1:10053提供服務。
Dnsmasq是簡單的域名服務、緩存和轉發工具,這里利用它的轉發功能將kube-dns的dns服務轉接到外部,參數–server=127.0.0.1:10053。
二.運維管理 租戶資源管理Namespace(命名空間)
namespace 是kubernete用來做租戶管理的對象。每個租戶獨享自己的邏輯空間,包括replication controller、 pod、 service、 deployment、configmap等。
常用的查看方式:
kubectl get <resource type> <resource name> --namespace=<namespace> 或查看所有namespace的某類資源 kubectl get <resource type> <resource name> --all-namespaces 例如:查看所有的pod,并希望看到所部署的節點位置 kubectl get pod –all-namespaces –o wide 查看namespace為 test的replication controller,以及labet kubectl get rc –namespace=test –show-labels
配置管理ConfigMap
當服務運行在容器中時,需要訪問外部的變量,或者需要根據環境的不同更改配置文件,比如,DB以傳統的方式運行在容器云之外,當服務啟動時,需要初始化包含DB信息的配置文件。當需要切換db時,就需要更改配置文件, 當容器中有服務在運行時, 并不推薦登陸到容器內進行文件配置更改。
合理的方式是利用kubernetes的配置管理,將配置信息寫入到ConfigMap, 并掛載到對應的pod中。
例如golang程序golang-sample需要訪問配置文件db.json,內容如下:
{ "dbType": "mysql", "host": "192.168.1.22", "user": "tenxcloud", "password": "password", "port": "3306", "connectionLimit": 200, "connectTimeout": 20000, "database": "sample" }
將db.json寫入config.yaml中:
apiVersion: v1 data: db.json: |- { "dbType": "mysql", "host": "192.168.1.22", "user": "tenxcloud", "password": "password", "port": "3306", "connectionLimit": 200, "connectTimeout": 20000, "database": "sample" } kind: ConfigMap metadata: name: config-sample namespace: sample
創建configmap對象:
kubectl create –f config.yaml
在 pod中添加對應的volume
apiVersion: v1 kind: Pod metadata: labels: name: golang-sample name: golang-sample namespace: sample spec: containers: - image: inde.tenxcloud.com/sample/golang-sample:latest volumeMounts: - mountPath: /usr/src/app/config/db/ name: configmap-1 volumes: - configMap: items: - key: db.json path: db.json name: config-sample name: configmap-1
當pod創建運行后,服務在pod容器內只需要讀取固定位置的配置文件, 當配置需要改變時, 更新ConfigMap并重新分發到pod內,這樣重啟容器后,容器內所掛載的配置也會相應更新。當需要pod容器同時使用一個ConfigMap 時,更新ConfigMap內容的同時,可以批量更新容器的配置。
主機運維管理
對于運維操作來說,kubectl是一個很便利的命令行工具,首先可以對各種資源進行操作,比如添加、獲取、刪除,通過更多命令參數得到指定的信息。
獲取資源列表及詳細信息的方式可通過kubectl get 來進行,具體的操作運行kubectl get –help即可。
實踐使用過程中,對節點的運維操作會影響到應用的使用和資源的調度,比如由于配置升級需要對節點主機進行重啟,需要考慮已經運行在其上的容器的狀況,用戶的希望是對資源池的操作盡量少的影響容器應用,同時資源池的變動和上層的容器服務解藕。
當需要對主機進行維護升級時,首先將節點主機設置成不可調度模式:
kubectl cordon[nodeid]
然后需要將主機上正在運行的容器驅趕到其它可用節點:
kubectl drain [nodeid]
當容器遷移完畢后,運維人員可以對該主機進行操作,配置升級性能參數調優等等。當對主機的維護操作完畢后, 再將主機設置成可調度模式:
kubectl uncordon [nodeid]
這樣新創建的容器即可以分配到該主機,可以通過kubectl patch 對資源對象進行實時修改,比如為service增加端口,為pod修改容器鏡像版本。Annotation 可以幫助用戶更好的設置kubernete自定義插件。用戶可以在自建組件中獲取資源中對應的annotation以此進行操作。通過kubectl label可以方便的對資源打標簽,比如對node打標簽,然后容器調度時可指定分配到對應標簽的主機。
Kubernetes作為容器集群管理工具,為應用平臺提供了基于云原生的微服務支持,其活躍的社區吸引了廣大開發者的熱情關注,刺激了容器周邊生態的快速發展,同時為眾多互聯網企業采用容器集群架構升級內部IT平臺設施,構建高效大規模計算體系提供了技術基礎。
來自:http://www.iteye.com/news/31929