開源容器編排系統(tǒng) Kubernetes v1.0新特性全解
Kubernetes 1.0剛剛發(fā)布,開源社區(qū)400多位貢獻(xiàn)者一年的努力,多達(dá)14000多次的代碼提交,最終達(dá)到了之前預(yù)計(jì)的milestone,并意味著這個(gè)開源容器編排系統(tǒng)可以正式在生產(chǎn)環(huán)境使用,必將推動(dòng)容器生態(tài)及周邊產(chǎn)業(yè)的進(jìn)步發(fā)展。本文主要介紹kubernetes1.0較新的功能特性,包括服務(wù)發(fā)現(xiàn)方式及較新版本對(duì)應(yīng)的設(shè)置變化,如何用DNS方式構(gòu)建內(nèi)網(wǎng)服務(wù)發(fā)現(xiàn),存儲(chǔ)支持,如何解決集群存儲(chǔ)及如何使用rbd的方式將Ceph存儲(chǔ)塊附加到Pod,監(jiān)控,如何在集群模式下搭建監(jiān)控系統(tǒng)等話題。以及介紹Kuberentes官方發(fā)布時(shí)官方提到的功能理念及未來部分的功能擴(kuò)展,包括Kubernetes產(chǎn)品經(jīng)理 Craig McLuckie所提及的Kubernetes的整體愿景等。
首先介紹 Kubernetes v1.0的部分較新的特征,包括DNS負(fù)載均衡,Kuberentes監(jiān)控和Kubernetes HA高可用性的方式等
1. DNS,負(fù)載均衡
Kubernetes服務(wù)發(fā)現(xiàn)通用兩種方式, kube-proxy和DNS, 在v1之前,Service含有字段portalip 和publicIPs, 分別指定了服務(wù)的虛擬ip和服務(wù)的出口機(jī)ip,publicIPs可任意指定成集群中任意包含kube-proxy的節(jié)點(diǎn),可多個(gè)。portalIp 通過NAT的方式跳轉(zhuǎn)到container的內(nèi)網(wǎng)地址。在v1版本中,publicIPS被約定廢除,標(biāo)記為deprecatedPublicIPs,僅用作向后兼容,portalIp也改為ClusterIp, 而在service port 定義列表里,增加了nodePort項(xiàng),即對(duì)應(yīng)node上映射的服務(wù)端口。
這樣portlist里僅僅是一個(gè)容器端口到服務(wù)端口的maping,這種方式和marathon里的方式相似。loadbalancer項(xiàng)里是提供給外部clouder provider使用的,云提供商可以通過獲取loadbanancer指定的入口ip和對(duì)應(yīng)的虛擬服務(wù)入口,來建立自定義的服務(wù)連接通道,或者通過獲取 endpoint或pod直接將訪問導(dǎo)入containter。當(dāng)然,如果loadbanancer在集群外部,需要自行解決連入集群內(nèi)網(wǎng)的問題。
DNS服務(wù)發(fā)現(xiàn),就是在Kubernetes內(nèi)網(wǎng)建立一套pod組合,對(duì)外提供DNS服務(wù)。DNS服務(wù)組本身是放在Kubernetes平臺(tái)里的,同時(shí)又給Kubernetes平臺(tái)提供服務(wù)。這個(gè)和監(jiān)控的服務(wù)組合類似,當(dāng)然也可以單獨(dú)拿出來,以standalone的方式在Kubernetes 平臺(tái)之外運(yùn)行提供服務(wù)。
DNS服務(wù)以addon的方式,需要安裝skyDNS和kube2DNS。kube2DNS會(huì)通過讀取kubernetes API獲取服務(wù)的clusterIP和port信息,同時(shí)以watch的方式檢查service的變動(dòng),及時(shí)收集變動(dòng)信息,并將對(duì)于的ip信息提交給 etcd存檔,而skyDNS通過etcd內(nèi)的DNS記錄信息,開啟53端口對(duì)外提供服務(wù)。大概的DNS的域名記錄是 servicename.namespace.tenx.domain, "tenx.domain"是提前設(shè)置的主域名。
舉例來說,如果在K8s中創(chuàng)建了一個(gè)服務(wù)“mysql-service", namespace是"tenxcloud", 這時(shí)會(huì)在skyDNS中形成記錄 mysql-service.tenxcloud.tenx.domain。在后續(xù)創(chuàng)建的pod中,如果仍然以namespace 為tenxcloud創(chuàng)建,那么在pod內(nèi)可以直接用 mysql-service 來訪問上述服務(wù),但如果在其他的namespace內(nèi)訪問,就需要加上命名空間名稱,如mysql-service.tenxcloud。實(shí)際上最終的 url是要加上端口號(hào),需要在servcie定義中給端口命名,比如mysql-service 的訪問端口是 {"name": "mysqlport" , "targetport": 3306, "protocol": "tcp"},那么對(duì)于的3306,對(duì)于的 DNS SRV記錄是 _mysqlport._tcp.mysql-service.tenxcloud。
Kubernetes 支持以 "link"方式連接跨機(jī)容器服務(wù),但link的方式依賴于服務(wù)的啟動(dòng)順序,容錯(cuò)性能較差,官方更加推薦以DNS的方式來構(gòu)建。
2. Kubernetes監(jiān)控
比較老的版本 kubernetes需要外接cadvisor,主要功能是將node主機(jī)的container metrics抓取出來。在較新的版本里,cadvior功能被集成到了kubelet組件中,kubelet在與docker交互的同時(shí),對(duì)外提供監(jiān)控服務(wù)。
kubernetes集群范圍內(nèi)的監(jiān)控主要由kubelet、heapster和storage backend(如influxdb)構(gòu)建。Heapster可以在集群范圍獲取metrics和事件數(shù)據(jù)。它可以以pod的方式運(yùn)行在 Kubernetes平臺(tái)里,也可以單獨(dú)運(yùn)行以standalone的方式。
當(dāng)以pod及服務(wù)方式運(yùn)行時(shí),heapster通過虛擬網(wǎng)訪問kube-apiserver, 獲取所有node的信息,主要是ip地址,然后通過node節(jié)點(diǎn)(ip地址)上Kubelet對(duì)外提供的服務(wù)獲取對(duì)應(yīng)pod的metrics。
Kubelet則通過內(nèi)部集成cadvisor的組件或者最終的數(shù)據(jù)。最后,heapster會(huì)將獲取的數(shù)據(jù)存儲(chǔ)到后端, 現(xiàn)階段后端存儲(chǔ)支持Influxdb 和GCM等。
簡(jiǎn)單介紹下Influxdb, 它是時(shí)序數(shù)據(jù)庫,即所有記錄都帶有時(shí)間戳屬性。主要用于實(shí)時(shí)數(shù)據(jù)采集,事件跟蹤記錄,存儲(chǔ)時(shí)間圖表原始數(shù)據(jù)等。它的查詢語言與SQL類似,又略有不同;對(duì)外提供RESTAPI接口。自帶的操作面板可以直接把數(shù)據(jù)粗略轉(zhuǎn)成曲線圖表。支持定時(shí)自動(dòng)運(yùn)行的統(tǒng)計(jì)命令,比如,定時(shí)執(zhí)行求取平均值并存到另外的表格,對(duì)于帶有時(shí)間坐標(biāo)的數(shù)據(jù)分析有很高的價(jià)值。目前在過時(shí)數(shù)據(jù)清理上略有瑕疵,不能定時(shí)自動(dòng)清除過往數(shù)據(jù),需要外接類似crontab等定時(shí)工具來處理。
Inflxudb可與Grafana結(jié)合,Grafana可將influxdb數(shù)據(jù)內(nèi)容更好的呈現(xiàn)成圖表曲線的形式,如果不需要提供對(duì)外產(chǎn)品的話,Grafana是很好的數(shù)據(jù)圖形工具。
通過設(shè)置heapster --source 來設(shè)置數(shù)據(jù)來源,--sink 參數(shù)可以設(shè)定后端存儲(chǔ)為influxdb。 heapster 抓取數(shù)據(jù)后,將分類存儲(chǔ)到多個(gè)influxdb 表格中,包括cpu、memory、network、eventlog 等,另外可以設(shè)置定時(shí)統(tǒng)計(jì)命令來處理這些raw數(shù)據(jù)。
heapster目前未到1.0版本,對(duì)于小規(guī)模的集群監(jiān)控比較方便。但對(duì)于較大規(guī)模的集群,heapster目前的cache方式會(huì)吃掉大量?jī)?nèi)存。因?yàn)橐〞r(shí)獲取整個(gè)集群的容器信息,信息在內(nèi)存的臨時(shí)存儲(chǔ)成為問題,再加上heaspter要支持api獲取臨時(shí)metrics,如果將 heapster以pod方式運(yùn)行,很容易出現(xiàn)OOM。所以目前建議關(guān)掉cache,并以standalone的方式獨(dú)立出Kubernetes平臺(tái),比如單獨(dú)運(yùn)行在一個(gè)VM上。而influxdb也要做好數(shù)據(jù)清理工作,日志及監(jiān)控信息增長(zhǎng)會(huì)給系統(tǒng)帶來很大煩惱,外接crontab運(yùn)行清除命令即可。但作為GoogleCloudPlatform的工具,heapster也有望以容器工具集項(xiàng)目的方式加入CNCF,所以建議Kubernetes監(jiān)控還是用 heapster方式來做。
3. 官方Kubernetes HA的方式
利用etcd實(shí)現(xiàn)master 選舉,從多個(gè)Master中得到一個(gè)kube-apiserver, 保證至少有一個(gè)master可用,實(shí)現(xiàn)high availability。對(duì)外以loadbalancer的方式提供入口。這種方式可以用作ha,但仍未成熟,據(jù)了解,未來會(huì)更新升級(jí)ha的功能。這里用到了kubelet的啟動(dòng)方式,--config參數(shù),設(shè)置路徑添加kubelet啟動(dòng)時(shí)刻需要做的動(dòng)作。 --config=/etc/kubernetes/manifests,可以利用其創(chuàng)建pod。
有以下幾點(diǎn):
Process watcher,保證 master運(yùn)行失敗后自動(dòng)重啟,這個(gè)是必要條件。monit的方式,或者自行解決守護(hù)問題。
可靠的冗余存儲(chǔ),使用etcd集群模式。 etcd是key value的存儲(chǔ)方式,它的角色類似于zookeeper。etcd搭建集群節(jié)點(diǎn)至少3個(gè),因?yàn)檫x舉投票最終要確定leader和follower,初始投票會(huì)假定自身都是leader,同時(shí)又都reject對(duì)方,無法形成多數(shù)的票數(shù)。3個(gè)可以形成多數(shù)對(duì)少數(shù)的情況,并且建議把投票timeout的設(shè)置成不同的時(shí)間。而5個(gè)以上較為穩(wěn)定。
多個(gè)kube-apiserver,用負(fù)載均衡的方式統(tǒng)一起來。node節(jié)點(diǎn)訪問時(shí),通過haproxy的入口,分發(fā)到不同的apiserver,而apiserver背后是相同的etcd集群。
用組件podmaster 模擬選舉。它利用etcd實(shí)現(xiàn)一個(gè)選舉算法。類似zookeeper的方式,選舉出來的kube-apiserver被啟動(dòng)并作為主出口,其他的kube-apiserver處于standby的狀態(tài)被停止。
安裝部署 kube-sheduller和kube-controller-manager,這里在每臺(tái)master機(jī)器上同時(shí)存在一套 kube-apiserver、kube-scheduller 和kube-controller-manager,并且以localhost的方式連接。這樣當(dāng)kube-apiserver被選中時(shí),同機(jī)的 kube-scheduller和kube-controoler-manager起作用,當(dāng)standby時(shí),同機(jī)的3個(gè)組件都會(huì)不可用。
也就是說,etcd集群背景下,存在多個(gè)kube-apiserver,并用pod-master保證僅是主master可用。同時(shí)kube- sheduller和kube-controller-manager也存在多個(gè),但伴隨著kube-apiserver,同一時(shí)間只能有一套運(yùn)行。
Q&A
Q1:有幾個(gè)問題:1.容器 net方式 網(wǎng)絡(luò)性能損失多少,2 .Kubernetes是怎么做到的容器自動(dòng)遷移?
A:容器是建在pod里,實(shí)際上最終用的是docker 的 網(wǎng)絡(luò)參數(shù),同pod里不用轉(zhuǎn)發(fā),是docker本身的功能,在虛擬網(wǎng)絡(luò)里,是以NAT的方式。
Q2:K8s是不是定義的一個(gè)pod的容器集群是只部署在同一個(gè)主機(jī)上?
A:到目前是,同一個(gè)pod里的containerS 是部署在同一臺(tái)主機(jī)的。
Q3:這個(gè)圖里的loadbalancer是安裝在哪里的?所有的客戶端以及kubelete會(huì)連接這個(gè)嘛?
A:loadbanlancer可以任意地方,只要能訪問到集群,會(huì)作為api的出口。
Q4:K8s中的etcd放在容器里的嗎?
A:不用放在里面,可以放進(jìn)去,也可以在外面。