我所理解的 Kubernetes
前言
搞kubernetes(簡稱k8s)大約5個月的時間了,這期間因功能需要閱讀并修改過部分源碼,對k8s的設計理念有了簡單的認識。今天就給大家說一說自己的一些認識,認識不深的地方歡迎大家指正。
在正式內容之前,先簡單介紹下本人對k8s做的一些功能支持:
-
自實現對接公司LVS的負載均衡控制器(lb-controoller);
-
自實現對接公司Qbus的日志收集控制器(log-controller);
-
修改RollingUpdate邏輯,讓滾動更新更加可控,業務升級更加平滑;
以上三個功能都是我們在構建容器化平臺過程中,為適配公司現有生態而進行的一系列擴展。
我理解的K8S
先來看看k8s的架構圖和各個組件
按角色劃分
按照角色劃分,k8s和絕大多數分布式系統一樣,分為Master和Slave兩類。其中Master是整個系統的控制中心,是大腦;而Slave呢是分布在各個節點的工作單元,是神經元。
按功能劃分
按照功能劃分,k8s是由很多松耦合的功能組件構成。
etcd 組件
是k8s系統的資源(數據)存儲的地方,是整個k8s的基石,也是k8s很多功能的設計之源。做為一個高可用強一致性的服務發現存儲倉庫,etcd本身非常好的提供了數據的持久化存儲和服務發現的支持。在云計算時代,如何讓服務快速透明地接入到計算集群中,如何讓共享配置信息快速被集群中的所有機器發現是迫切要解決的問題,也是最最核心的問題。etcd很好的解決了這個問題。
kube-apiserver組件
是k8s 的入口,也是整個k8s除了etcd外最最基礎、最最核心的組件。它是整個k8s系統和生態的樞紐和消息總線。沒有kube-apiserver整個k8s系統將會土崩瓦解,無法運轉。
從功能實現角度來看,kube-apiserver是對etcd的一個包裝,通過對etcd的進一步包裝,實現兩大功能。一是對外提供查詢資源對象的接口;二是提供k8s中資源注冊與發現的框架。
第一點大家都能很輕松的理解,這么大的系統,肯定是要提供一個統一的數據查詢接口;第二點大家不深入去看k8s各個組件工作機制和源碼實現的話,不一定能夠體會得到。資源注冊與發現框架是整個k8s架構設計的靈魂。所有k8s的組件,除了etcd外,都是圍繞k8s的這一機制去擴展實現的。比如下面將要介紹的kube-controller-manager、kube-scheduler、kubelet、kube-proxy,還有我們自己實現的lb-controller和log-controller。
基于etcd實現的資源的注冊和發現框架是整個k8s生態的靈魂。
服務的注冊與發現相信大家都很了解了,那資源的注冊與發現和它有啥區別嗎?
然而并沒有。服務也可以看成是一種資源。服務發現解決的是分布式系統中最常見的問題之一,即在同一個分布式集群中的進程或服務,要如何才能找到對方并建立連接。本質上來說,服務發現就是想要了解集群中是否有進程在監聽udp或tcp端口,并且通過名字就可以查找和連接。而對于資源發現而言就是想要了解集群中是否存在某資源,并且通過名字就可以查找和監聽資源狀態的變化。
接下來我們看看k8s中其它組件是如何利用k8s的資源注冊與發現機制實現與k8s完美對接的。
kube-controller-manager
kube-controller-manager 是 k8s 多種資源控制器的集合。像ReplicationController、ReplicaSetController、DeploymentController、ConfigMapController等等。通過這些控制器實現對各種資源的CRUD操作。 這些控制器通過k8s資源注冊與發現框架(其中最核心的就是list/watch機制)來注冊和發現自己關心的資源狀態變化(如:ReplicationController關心RC和POD資源、ReplicaSetController關心RS和POD資源等)。通過感知資源狀態的變化,對這些資源進行相應的處理,使得資源狀態最終達到規定的狀態。
這里以ReplicaSetController為例進行簡單闡述。
ReplicaSetController是k8s中用來管理POD的控制器,所以主要關心RS本身和POD資源的狀態變化。在啟動時便會通過apiserver的list/watch機制注冊并監聽所關心的資源。當用戶創建ReplicaSet資源時,ReplicaSetController監聽到該對象的創建事件,將通過apiserver獲取RS對象,根據對象的資源描述(POD、POD副本數等)去創建相應副本數的POD。當RS中的POD因某種原因掛掉時,ReplicaSetController也會監聽到,并重新創建1個新的POD,保證存活POD數不變。
kube-scheduler
kube-scheduler 是k8s資源調度組件,負責pod資源落到哪個或哪些node的調度。按照之前對OpenStack調度的理解來看,本以為對于kube-scheduler而言也是接收apiserver的請求然后去做各種資源是否滿足需求的處理,但是實際上它并不是直接接收apiserver的請求,而是基于k8s的資源注冊與發現框架來發現pod創建事件的,然后將pod入隊列等待資源運算處理,最終返回可用的node,并將pod與之綁定。
kubelet
k8s是一個分布式的集群管理系統,在每個節點(node)上都要運行一個 agent 對容器進行生命周期的管理,這個 agent 程序就是 kubelet。簡單地說,kubelet 的主要功能就是定時從某個地方獲取節點上 pod/Container 的期望狀態(運行什么容器、運行的副本數量、網絡或者存儲如何配置等等),并調用對應的容器平臺接口達到這個狀態。 上面說的定時從某個地方獲取就是指的通過k8s資源注冊與發現框架從apiserver中獲取。
kube-proxy
service是一組pod的服務抽象,相當于一組pod的LB,負責將請求分發給對應的pod。service會為這個LB提供一個IP,一般稱為cluster IP。kube-proxy的作用主要是負責service的實現,是service的控制器。它主要關心service、endpoint資源的狀態變化,kube-proxy通過k8s資源注冊與發現框架從apiserver中獲取期望的狀態,并調用對應的接口使其達到這個狀態。
lb-controller(自研)
截止到1.7.0版本,kubernetes 還沒有實現對四層代理的支持,而我司大部分使用的是基于LVS的四層代理,為了實現 kubernetes 與我司 LVS 的對接我們實現了自己的負載均衡控制器lb-controller。lb-controller 主要是利用k8s資源注冊與發現框架,從apiserver中獲取pod增刪事件,根據不同的事件做出不同的操作。對于增pod,會將該pod掛載到 LVS 中與其關聯的 vip 下;對于刪pod,會將該pod從LVS中的vip下卸載。從而實現動態感知pod變化并更新rs的功能。
log-controller (自研)
對于kubernetes中應用的日志,我們是通過公司現有的Qbus日志收集系統收集走的。Qbus是我司基于Kafka、logstash和Qconf實現的一套日志收集系統,已被公司絕大部分業務使用。對于要收集日志的機器而言,會在上面部署一個loogstash的agent,負責讀取日志并上傳給Qbus。
logstash的配置是人工參與處理的。對于虛擬機和物理機這種不會頻繁變更的計算資源,人工參與配置是可以接受的,但是對于k8s中pod這類生命周期端,頻繁變更的資源而言,再通過人工去處理的話,運維人員會瘋掉的。為了解決這個問題,我們基于k8s資源注冊與發現框架實現了對pod資源的自發現。動態的感知到pod的增刪,從而實現自動化的去配置logstash的功能,大大提高了生產效率。
為了k8s的開發者和用戶更加方便擴展k8s的功能,k8s提供了資源注冊和發現的客戶端庫的client-go,通過client-go可以很方便的連接到apiserver并監聽資源狀態的變化。向下屏蔽了很多細節,開發者和用戶只關心實現資源狀態變化后的處理邏輯就可以了。
總結
通過上面的介紹,我相信你已經對k8s的整體架構有了一個更清晰的認識。這里希望大家能根據自己的K8S實踐,來對比上述的分析進行理解。希望能有更多的思想火花,歡迎留言交流。
來自:http://mp.weixin.qq.com/s/h8YH_yAdZ5eDX9nvD8fCNA