再次了解kubernetes
的基本概念和術(shù)語(yǔ)
1、kubernetes整體概要
在Kubernetes中绍哎,Service(服務(wù))是分布式集群架構(gòu)的一個(gè)核心,一個(gè)Service對(duì)象擁有如下特征孽查。
- 擁有一個(gè)唯一指定的名字(如mysql-server)酥馍。
- 擁有一個(gè)虛擬IP(Cluster IP、Service IP或VIP)板熊。
- 能夠提供某個(gè)遠(yuǎn)程服務(wù)的能力框全。
- 被印射到了提供這種服務(wù)能力的一組容器應(yīng)用之上。
Service的服務(wù)進(jìn)程目前都是居于Socker通信方式對(duì)外提供服務(wù)邻邮,如Redis竣况、Memcache克婶、Mysql筒严、Web Service丹泉,或是實(shí)現(xiàn)了某個(gè)具體業(yè)務(wù)的一個(gè)特定的TCP Server進(jìn)程。雖然一個(gè)Service通常由多個(gè)相關(guān)的服務(wù)進(jìn)程來(lái)提供服務(wù)鸭蛙,每個(gè)服務(wù)進(jìn)程都有一個(gè)Endpoint(ip+port)訪問(wèn)點(diǎn)摹恨,但kubernetes能夠讓我們通過(guò)Service(虛擬Cluster IP + Service Port)連接到指定的Service上面。
kubernetes內(nèi)建的透明負(fù)載均衡娶视、故障恢復(fù)機(jī)制及service創(chuàng)建后ip不變化晒哄,基于此可以向用戶提供穩(wěn)定的服務(wù)。
容器提供了強(qiáng)大的隔離功能肪获,所以有必要把Service提供服務(wù)的這組進(jìn)程放到容器中進(jìn)行隔離寝凌。為此,kubernetes設(shè)計(jì)了Pod對(duì)象孝赫,將每個(gè)服務(wù)進(jìn)程包裝到相應(yīng)的Pod中较木,使其成為Pod中運(yùn)行的一個(gè)容器(Container)。為了建立Service和Pod間的關(guān)聯(lián)聯(lián)系青柄,kubernetes首先給每個(gè)Pod貼上一個(gè)標(biāo)簽(Label)伐债,如給運(yùn)行mysql的Pod貼上name=mysql的標(biāo)簽,然后給相應(yīng)的Service定義標(biāo)簽選擇器(Label Selector)致开,如mysql的Service的標(biāo)簽選擇器的選擇條件為name=mysql峰锁,意為Service下所有包含name-=mysql的Label的Pod上。
說(shuō)到Pod双戳,簡(jiǎn)單介紹其概念虹蒋。首先,Pod運(yùn)行在一個(gè)我們稱之為節(jié)點(diǎn)(Node)的環(huán)境中飒货,這個(gè)節(jié)點(diǎn)可能是物理機(jī)或虛擬機(jī)千诬,通常一個(gè)節(jié)點(diǎn)上上面運(yùn)行幾百個(gè)Pod;其次每個(gè)Pod運(yùn)行著一個(gè)特殊的被稱之為Pause的容器膏斤,其它的容器被稱為業(yè)務(wù)容器徐绑,這些業(yè)務(wù)容器共享Pause容器的網(wǎng)絡(luò)棧和Volume掛載卷,因此它們之間的通信和數(shù)據(jù)交換效率更為高效莫辨。在設(shè)計(jì)時(shí)我們可以充分利用這一特性將一組密切相關(guān)的服務(wù)進(jìn)程放到同一個(gè)Pod中傲茄。最后需要注意的是并不是每一個(gè)Pod和它里面運(yùn)行的容器都能映射到一個(gè)Service上,只有那些提供服務(wù)的一組Pod才會(huì)被映射成一個(gè)服務(wù)沮榜。
在集群管理方面盘榨,kubernetes將集群中的機(jī)器劃分為一個(gè)Master節(jié)點(diǎn)和一群工作節(jié)點(diǎn)(Node)。其中Master節(jié)點(diǎn)運(yùn)行著集群管理的一組進(jìn)程kube-apiserver
蟆融、kube-controller-manage
草巡、kube-scheduler
。這些進(jìn)程實(shí)現(xiàn)了整個(gè)集群的資源管理型酥、Pod調(diào)度山憨、彈性收縮查乒、安全控制、系統(tǒng)控制和糾錯(cuò)等管理功能郁竟,并且全是自動(dòng)完成的玛迄。Node作為一個(gè)集群中的工作節(jié)點(diǎn),運(yùn)行真正的應(yīng)用程序棚亩,在Node上kubernetes管理的最小單元是Pod蓖议。Node運(yùn)行著kubernetes的kubelet
、kube-proxy
服務(wù)進(jìn)程讥蟆,這些服務(wù)進(jìn)程負(fù)責(zé)Pod的創(chuàng)建勒虾、啟動(dòng)、監(jiān)控瘸彤、重啟和銷毀从撼,以及實(shí)現(xiàn)軟件模式的均衡負(fù)載。
解決傳統(tǒng)的服務(wù)擴(kuò)容和服務(wù)升級(jí)兩個(gè)難題里钧栖,kubernetes集群中低零,我們只需要為擴(kuò)容的service關(guān)聯(lián)的Pod創(chuàng)建一個(gè)Replication Controller
(簡(jiǎn)稱RC),在這個(gè)RC定義文件中寫好下面幾個(gè)關(guān)鍵信息:
- 目標(biāo)Pod的定義拯杠。
- 目標(biāo)Pod需要運(yùn)行的副本數(shù)量(Replicas)掏婶。
- 要監(jiān)控目標(biāo)Pod的標(biāo)簽(Label)。
在創(chuàng)建好RC(系統(tǒng)將自動(dòng)創(chuàng)建好Pod)后潭陪,kubernetes會(huì)通過(guò)RC中定義的Label篩選出對(duì)應(yīng)的Pod實(shí)例并全自動(dòng)實(shí)時(shí)監(jiān)控其狀態(tài)和數(shù)量雄妥。
2、基本概念和術(shù)語(yǔ)
kubernetes中大部分概念如Node
依溯、Pod
老厌、Replication Controller
、Service
等都可以被看作一種資源對(duì)象黎炉,幾乎所有的資源對(duì)象都可以通過(guò)kubernetes提供的kubectl
工具(或API編程調(diào)用)執(zhí)行增刪改查等操作枝秤,并將其保存在etcd中持久化存儲(chǔ)。從這個(gè)角度來(lái)看慷嗜,kubernetes其實(shí)是一個(gè)高度自動(dòng)化的資源控制系統(tǒng)淀弹,它通過(guò)跟蹤對(duì)比保存在etcd庫(kù)里的“資源期望狀態(tài)”和當(dāng)前環(huán)境中的“實(shí)際資源狀態(tài)”的差異來(lái)實(shí)現(xiàn)自動(dòng)控制和自動(dòng)糾錯(cuò)的高級(jí)功能。
2.1 Master
kubernetes里的Master指的是集群控制節(jié)點(diǎn)庆械。每個(gè)kubernetes集群里都需要一個(gè)Master節(jié)點(diǎn)來(lái)負(fù)責(zé)整個(gè)集群的管理和控制薇溃,基本上kubernetes所有的控制命令都是發(fā)給它,它來(lái)負(fù)責(zé)具體的執(zhí)行過(guò)程缭乘,我們后面所有的執(zhí)行的命令基本上都是在Master節(jié)點(diǎn)上運(yùn)行的沐序。Master節(jié)點(diǎn)通常會(huì)占據(jù)一個(gè)獨(dú)立的服務(wù)器或虛擬機(jī),就是它的重要性體現(xiàn),一個(gè)集群的大腦策幼,如果它宕機(jī)邑时,那么整個(gè)集群將無(wú)法響應(yīng)控制命令。
Master節(jié)點(diǎn)上運(yùn)行著以下幾組關(guān)鍵進(jìn)程:
- Kubernetes API Server(kube-apiserver):提供了HTTP rest接口的關(guān)進(jìn)服務(wù)進(jìn)程垄惧,是Kubernetes里所有資源增刪改查等操作的唯一入口,也是集群管理的入口進(jìn)程绰寞。
- Kubernetes Controller Manage(kube-controller-manage):Kubernetes里所有資源對(duì)象的自動(dòng)化控制中心到逊,可以理解為資源對(duì)象的“大總管”。
- Kubernetes Scheduler(kube-scheduler):負(fù)責(zé)資源的調(diào)度(Pod調(diào)度)的進(jìn)程滤钱。
Master還啟動(dòng)了一個(gè)etcd server進(jìn)程觉壶,因?yàn)閗ubernetes里所有的資源對(duì)象的數(shù)據(jù)都是保存在etcd中的。
2.2 Node
除了Master件缸,kubernetes集群的其它機(jī)器也被稱為Node節(jié)點(diǎn)铜靶,在較早的版本也被稱為Monion。同樣的它也是一臺(tái)物理機(jī)或是虛擬機(jī)他炊。Node節(jié)點(diǎn)才是Kubernetes集群中工作負(fù)載節(jié)點(diǎn)争剿,每個(gè)Node都會(huì)被Master分配一些工作負(fù)載(Docker容器),當(dāng)某個(gè)Node宕機(jī)之后痊末,其上的工作負(fù)載會(huì)被Master自動(dòng)轉(zhuǎn)移到其它節(jié)點(diǎn)上面去蚕苇。
每個(gè)Node節(jié)點(diǎn)運(yùn)行著以下幾個(gè)關(guān)鍵進(jìn)程:
- kubelet:負(fù)責(zé)pod對(duì)應(yīng)的同期創(chuàng)建、啟動(dòng)停止等任務(wù)凿叠,同時(shí)與Master節(jié)點(diǎn)密切協(xié)作涩笤,實(shí)現(xiàn)集群管理的基本功能。
- kube-proxy:實(shí)現(xiàn)Kubernetes Service的通信與負(fù)載均衡的重要組件盒件。
- Docker-Engine(docker):docker引擎蹬碧,負(fù)責(zé)本機(jī)容器的創(chuàng)建和管理工作。
Node節(jié)點(diǎn)可以在運(yùn)行期間動(dòng)態(tài)增加到Kubernetes集群中炒刁,前提是這個(gè)節(jié)點(diǎn)已經(jīng)正確安裝恩沽、配置和啟動(dòng)的上述關(guān)鍵進(jìn)程。在默認(rèn)情況下kubenet會(huì)向Master注冊(cè)自己翔始,這也是kubernetes推薦的管理方式飒筑。一旦Node被納入集群管理范圍,kubelet進(jìn)程就會(huì)定時(shí)向Master節(jié)點(diǎn)匯報(bào)自身的情況绽昏,包括操作系統(tǒng)协屡、Docker版本、機(jī)器cpu和內(nèi)存情況及有哪些pod在運(yùn)行全谤。這樣Master可以獲知Node的資源使用情況并實(shí)現(xiàn)高效均衡的資源調(diào)度策略肤晓。而某個(gè)Node超過(guò)時(shí)間不進(jìn)行上報(bào)信息時(shí),master將會(huì)將其標(biāo)記為失聯(lián)(Not Ready),隨后會(huì)觸發(fā)資源轉(zhuǎn)移的自動(dòng)流程。
2.3 Pod
Pod是Kubernets最重要也是最基礎(chǔ)的概念补憾,其由下圖示意組成:
需求推動(dòng)發(fā)展漫萄,下面解釋為何會(huì)有pod的設(shè)計(jì)和其如此特殊的結(jié)構(gòu)。
- 一組容器作為單元的情況下盈匾,難以去對(duì)“整體”進(jìn)行簡(jiǎn)單判斷并采取有效的行動(dòng)腾务。如一個(gè)容器掛了,是算整體服務(wù)掛了削饵,還是算N/M的死亡率岩瘦。引入業(yè)務(wù)無(wú)關(guān)并且不易掛掉的
Pause
容器作為Pod的根容器,以它的狀態(tài)作為整體容器組的狀態(tài)窿撬,就簡(jiǎn)單巧妙的解決了這個(gè)問(wèn)題启昧。 - Pod多個(gè)業(yè)務(wù)容器共享Pause容器的IP族购,共享Pause容器掛接的Volume卷供鸠。這樣既簡(jiǎn)化了密切關(guān)聯(lián)業(yè)務(wù)容器之間的通信問(wèn)題,還很好地解決了它們之間文件共享的問(wèn)題旷档。
k8s為每個(gè)Pod都都分配了唯一的ip跛璧,稱之為Pod IP严里,一個(gè)Pod里的多個(gè)容器共享Pod IP地址。k8s要求底層網(wǎng)絡(luò)支持集群內(nèi)任意兩個(gè)Pod之間的TCP/IP直接通信追城,這通常采用虛擬二層網(wǎng)絡(luò)技術(shù)來(lái)實(shí)現(xiàn)田炭,如Flannel、Openswith等漓柑,牢記在k8s中教硫,一個(gè)Pod容器與另外主機(jī)上的Pod容器能夠直接通信。
Pod其實(shí)有兩種類型:普通的Pod及靜態(tài)的Pod(static Pod)辆布,后者比較特殊瞬矩,并不存放在k8s的etcd里面存儲(chǔ),而是存放在某一個(gè)具體的Node上的一個(gè)文件中锋玲,并且只在此Node上啟動(dòng)運(yùn)行景用。而普通的Pod一旦被創(chuàng)建,就會(huì)被放入到etcd中存儲(chǔ)惭蹂,隨后會(huì)被k8s Master調(diào)度到某個(gè)具體的Node上面進(jìn)行綁定(Binding)伞插,隨后該P(yáng)od被對(duì)應(yīng)的Node上的kubblet進(jìn)程實(shí)例化成一組的Docker容器并啟動(dòng)起來(lái)。默認(rèn)情況下盾碗,當(dāng)Pod里的某個(gè)容器停止時(shí)媚污,k8s會(huì)自動(dòng)檢測(cè)這個(gè)問(wèn)題并重啟啟動(dòng)這個(gè)Pod(Pod里面的所有容器),如果Pod所在的Node宕機(jī)廷雅,則會(huì)將這個(gè)Node上的所有Pod重新調(diào)度到其它節(jié)點(diǎn)上耗美。Pod京髓、容器與Node的關(guān)系如下:
k8s里的所有的資源對(duì)象都可以采用yaml或JSON格式的文件定義或描述商架,下面是某個(gè)Pod文件的資源定義文件堰怨。
apiSerdion: v1
kind: Pod
matadata:
name: myweb
labels:
name: myweb
spec:
containers:
- name: myweb
image: kubeguide/tomcat-app:v1
ports:
- containerPort: 8080
env:
- name: MYSQL_SERVICE_HOST
value: 'mysql'
- name: MYSQL_SERVICE_PORT
value: '3306'
kind為Pod表明這是一個(gè)Pod的定義;matadata的name屬性為Pod的名字蛇摸,還能定義資源對(duì)象的標(biāo)簽Label备图,這里聲明myweb擁有一個(gè)name=myweb
的標(biāo)簽。Pod里面所包含的容器組的定義則在spec中聲明赶袄,這里定義一個(gè)名字為myweb揽涮,鏡像為kubeguide/tomcat-app:v1
的容器,該容器注入了名為MYSQL_SERVICE_HOST='mysql'
和MYSQL_SERVICE_PORT='3306'
的環(huán)境變量(env關(guān)鍵字)弃鸦。Pod的IP加上這里的容器端口(containerPort)就組成了一個(gè)新的概念Endpoint(端口)绞吁,它代表Pod的一個(gè)服務(wù)進(jìn)程對(duì)外的通信地址幢痘。一個(gè)Pod也存在著具有多個(gè)Endpoint的情況唬格,比如tomcat定義pod時(shí)候,可以暴露管理端口和服務(wù)端口兩個(gè)Endpoint颜说。
我們所熟悉的Docker Volume在k8s中也有相應(yīng)的概念 - Pod Volume购岗,后者有一些幻化,比如可以用分布式系統(tǒng)GlusterFS實(shí)現(xiàn)后端存儲(chǔ)功能门粪;Pod Volume是定義在Pod之上喊积,然后被各個(gè)容器掛載到自己的文件系統(tǒng)中的。
最后是k8s中Event的概念玄妈,Event是一個(gè)事件的記錄乾吻,記錄了時(shí)間的最早產(chǎn)生時(shí)間、最后重現(xiàn)時(shí)間拟蜻、重復(fù)次數(shù)绎签、發(fā)起者、類型及導(dǎo)致此次事件的原因等總舵信息酝锅。Event通常會(huì)關(guān)聯(lián)到某個(gè)具體的資源對(duì)象上诡必,是排查故障的重要信息參考信息。Node描述信息包含Event搔扁,而Pod同樣有Event記錄爸舒。當(dāng)我們發(fā)現(xiàn)某個(gè)Pod遲遲無(wú)法創(chuàng)建時(shí),可以用kubectl describe pod name
來(lái)查看它的信息稿蹲,用來(lái)定位問(wèn)題的原因扭勉。
每個(gè)Pod都可以對(duì)其能使用的服務(wù)器上的計(jì)算資源設(shè)置限額,當(dāng)前可以設(shè)置的限額的計(jì)算資源有CPU和Memory兩種苛聘,其中CPU的資源單位為CPU(core)核數(shù)剖效,一個(gè)絕對(duì)值嫉入。
一個(gè)cpu的配額對(duì)絕大多數(shù)容器去是一個(gè)相當(dāng)大的資源配額,所以在k8s中璧尸,通常以千分之一的cpu配額為最小單位咒林,用m
來(lái)表示,即一個(gè)容器的限額為100-300m爷光,即占用0.1-0.3個(gè)cpu限額垫竞。由于它是絕對(duì)值,所以無(wú)論在1個(gè)cpu的機(jī)器還是多個(gè)cpu的機(jī)器蛀序,這個(gè)100m的配額都是一樣的欢瞪。類似的Memory配額也是一個(gè)絕對(duì)值,單位是內(nèi)存字節(jié)數(shù)徐裸。
在k8s中遣鼓,一個(gè)計(jì)算資源進(jìn)行配額限定需要設(shè)定下面兩個(gè)參數(shù):
- Request;該資源的最小申請(qǐng)量重贺,系統(tǒng)必須滿足要求骑祟。
- Limits:該資源允許最大的使用量,不能被突破气笙,當(dāng)容器視圖使用超出這個(gè)量的資源時(shí)次企,可能會(huì)被k8s殺死并重啟。
通常會(huì)把Request設(shè)置為一個(gè)比較小的數(shù)值潜圃,符合同期平時(shí)的工作負(fù)載情況下的資源要求缸棵,而把Limit設(shè)置為峰值負(fù)載情況下資源占用的最大量。如下面的設(shè)定:
spec:
containers:
- name: db
image: mysql
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
即表明mysql容器在申請(qǐng)最少0.25個(gè)cpu及64Mib的內(nèi)存谭期,在運(yùn)行過(guò)程中mysql容器所能使用的資源配額為0.5個(gè)cpu及128Mib的內(nèi)存堵第。
2.4 Label(標(biāo)簽)
Label是k8s系統(tǒng)中另一個(gè)核心的概念。一個(gè)Label是一個(gè)key=value的鍵值對(duì)隧出,其中key和value由用戶自己指定踏志。Label對(duì)象可以附加到各種資源對(duì)象上面,如Node鸳劳、Pod狰贯、Service、RC等赏廓,一個(gè)資源對(duì)象可以定義任意數(shù)量的Label涵紊,同一個(gè)Label也可以被添加到任意資源對(duì)象上去,Label通常在資源對(duì)象定義時(shí)確定幔摸,也可以通過(guò)對(duì)象創(chuàng)建之后動(dòng)態(tài)添加或刪除摸柄。
我們可以通過(guò)給指定的資源對(duì)象捆綁一個(gè)或多個(gè)不同的Label來(lái)實(shí)現(xiàn)多維度的資源分組管理功能,以便于靈活既忆、方便地進(jìn)行資源分配驱负、調(diào)度嗦玖、配置和布署等管理工作。一些常用的label如下:
- 版本控制:"release": "stable", "release": "canary"
- 環(huán)境標(biāo)簽:"environment": "dev", "environment": "qa", "environment": "production"
- 架構(gòu)標(biāo)簽:"tier": "frontend", "release": "backend", "release": "middkeware"
- 分區(qū)標(biāo)簽:"partition": "customerA"
- 質(zhì)量管控標(biāo)簽:"track": "daily", "track": "weekly"
給某個(gè)資源對(duì)象定義一個(gè)Label跃脊,隨后可以通過(guò)Label Selector(標(biāo)簽選擇器)查詢和篩選擁有某些Label的資源對(duì)象宇挫,k8s通過(guò)這種方式實(shí)現(xiàn)了類是SQL的簡(jiǎn)單通用的對(duì)象查詢方式。
當(dāng)前有兩種Label Selector
的表達(dá)式:基于等式的(Equality-based)和基于集合(Set-based)酪术。
基于等式的表達(dá)式匹配標(biāo)簽實(shí)例:
- name=redis-slave:匹配所有具有標(biāo)簽name=redis-slave的資源對(duì)象器瘪。
- env!=production: 匹配不具有標(biāo)簽name=production的資源對(duì)象。
基于集合方式的表達(dá)式匹配標(biāo)簽實(shí)例:
- name in (redis-slave, redis-master):匹配所有具有標(biāo)簽name=redis-slave或name=redis-master的資源對(duì)象绘雁。
- name not in (php-frontend):匹配不具有標(biāo)簽name=php-frontend的資源對(duì)象橡疼。
可以通過(guò)多個(gè)Label Selector表達(dá)式的組合實(shí)現(xiàn)復(fù)雜的條件選擇,多個(gè)表達(dá)式之間用“,”分隔即可庐舟,幾個(gè)條件是and的關(guān)系欣除,即同時(shí)滿足多個(gè)條件,如:
- name=redis-slave, env!=production
- name not in (php-frontend), env!=production
Label Selector在k8s中重要使用場(chǎng)景有下面幾處:
- kube-controller-manage進(jìn)程通過(guò)資源對(duì)象RC上定義的Label Selector來(lái)篩選要監(jiān)控的Pod副本的數(shù)量挪略。
- kube-proxy進(jìn)程通過(guò)Service的Label Selector來(lái)選擇對(duì)于那個(gè)的Pod历帚,自動(dòng)建立起Service對(duì)應(yīng)每個(gè)Pod的請(qǐng)求轉(zhuǎn)發(fā)路由表,從而實(shí)現(xiàn)Service的智能負(fù)載均衡機(jī)制瘟檩。
- 通過(guò)對(duì)某些Node定義特定的Label抹缕,并且Pod定義文件中使用NodeSelector這種標(biāo)簽調(diào)度策略澈蟆,kube-schedule進(jìn)程可以實(shí)現(xiàn)Pod“定向調(diào)度”的特性墨辛。
總結(jié):使用Label可以給資源對(duì)象創(chuàng)建多組標(biāo)簽,Label和Label Selector共同構(gòu)成了k8s系統(tǒng)中最核心的應(yīng)用模型趴俘,使得被管理對(duì)象能夠被精細(xì)地分組管理睹簇,同時(shí)實(shí)現(xiàn)了整個(gè)集群的高可用性。
2.5 Replication Controller(RC)
前面部分對(duì)Replication Controller(簡(jiǎn)稱RC)的定義和作用做了一些說(shuō)明寥闪,本節(jié)對(duì)RC的概念再進(jìn)行深入研究下太惠。
RC是k8s系統(tǒng)中的核心概念之一,簡(jiǎn)單來(lái)說(shuō)疲憋,它是定義了一個(gè)期望的場(chǎng)景凿渊。即聲明某種Pod的副本數(shù)量在任意時(shí)刻都符合某個(gè)預(yù)期值,所以RC的定義包含如下幾個(gè)部分:
- Pod期待的副本數(shù)(replicas)缚柳。
- 用于篩選目標(biāo)Pod的Label Selector埃脏。
- 當(dāng)Pod的副本數(shù)量小于預(yù)期數(shù)量的時(shí)候,用于創(chuàng)建新Pod的Pod模版(templates)秋忙。
下面是一個(gè)完整的RC定義的例子彩掐,即確保擁有tier=frontend
標(biāo)簽的這個(gè)Pod(運(yùn)行Tomcat容器)在整個(gè)集群中始終只有一個(gè)副本。
apiVersion: v1
kind: ReplicationController
metadata:
name: frontend
spec:
replicas: 1
selector:
tier: frontend
templete:
metadata:
labels:
app: app-demo
tier: frontend
spec:
containers:
- name: tomcat-demo
image: tomcat
imagePullPolicy: IfNotPresent
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
當(dāng)我們定義了一個(gè)RC并提交到k8s集群中以后灰追,Master節(jié)點(diǎn)上的Controller Manager組件就得到了通知堵幽,定期巡檢系統(tǒng)中當(dāng)前存活目標(biāo)的Pod狗超,并確保目標(biāo)Pod實(shí)例的數(shù)量剛好等于此RC的期望值。如果有過(guò)多的Pod副本在進(jìn)行朴下,系統(tǒng)就會(huì)停掉一些Pod努咐,否則系統(tǒng)會(huì)自動(dòng)創(chuàng)建一些Pod∨闺剩可以說(shuō)麦撵,通過(guò)RC,k8s實(shí)現(xiàn)了用戶應(yīng)用集群的高可用性溃肪,并且大大減少了系統(tǒng)管理員在傳統(tǒng)環(huán)境中完成許多的運(yùn)維工作(主機(jī)監(jiān)控免胃、應(yīng)用監(jiān)控、故障恢復(fù))惫撰。
需要注意的有幾點(diǎn):刪除RC并不會(huì)影響已經(jīng)通過(guò)該RC創(chuàng)建好的Pod羔沙。為了刪除所有的Pod,可以設(shè)置replicas為0厨钻,然后更新RC扼雏。另外,kubectl提供了stop和delete命令來(lái)一次性刪除RC和RC控制的全部Pod夯膀。
當(dāng)我們應(yīng)用升級(jí)時(shí)诗充,通常會(huì)通過(guò)Build一個(gè)新的Docker鏡像,并用新的鏡像版本來(lái)代替舊的版本方式達(dá)到目的诱建。在系統(tǒng)升級(jí)的過(guò)程中蝴蜓,我們希望是平滑的方式,如系統(tǒng)中10個(gè)對(duì)應(yīng)舊版本的Pod俺猿,最佳的方式就是就舊版本的Pod每次停止一個(gè)茎匠,同時(shí)創(chuàng)建一個(gè)新版本的Pod,在整個(gè)升級(jí)的過(guò)程中押袍,此消彼長(zhǎng)诵冒,而運(yùn)行中的Pod始終是10個(gè),幾分鐘后谊惭,當(dāng)所有的Pod都是新版本之后汽馋,升級(jí)過(guò)程完成。通過(guò)RC的機(jī)制圈盔,k8s很容易就實(shí)現(xiàn)這種高級(jí)實(shí)用的特性豹芯,被稱為“滾動(dòng)升級(jí)”(Rolling Update)。
由于Replication Controller與k8s代碼中的模塊Replication Controller同名药磺,同時(shí)這個(gè)詞又無(wú)法準(zhǔn)確表達(dá)它的本意告组,所以在k8s1.2的時(shí)候,它就升級(jí)成了另外一個(gè)新的概念 - Replica Set癌佩,官網(wǎng)解釋為“下一代的RC”木缝。與當(dāng)前RC區(qū)別在于:Replica Sets支持基于集合的Label Selector(Set-based selector)便锨,而當(dāng)前RC只支持基于等式的Label Selector(equality-based selector)。
當(dāng)前我們很少使用Replica Set我碟,它主要被Deployment這個(gè)更高層的資源對(duì)象使用放案,從而形成一整套Pod的創(chuàng)建、刪除矫俺、更新的編排機(jī)制吱殉。當(dāng)我們使用Deployment時(shí),無(wú)需關(guān)系它是如何創(chuàng)建和維護(hù)Replica Set厘托,都是自動(dòng)完成的友雳。
Replica Set與Deployment這兩個(gè)重要的資源對(duì)象逐步替換了之前RC的作用,是k8s1.3 Pod自動(dòng)擴(kuò)容(伸縮)這個(gè)告警功能實(shí)現(xiàn)的基礎(chǔ)铅匹。
最后總結(jié)RC(Replica Set)的的一些特性與作用:
- 多數(shù)情況下押赊,我們通過(guò)定義一個(gè)RC實(shí)現(xiàn)Pod的創(chuàng)建過(guò)程及副本數(shù)量的自動(dòng)控制,可以實(shí)現(xiàn)Pod的彈性收縮包斑。
- RC里包括完整的Pod定義模版流礁。
- RC通過(guò)Label Selector機(jī)制實(shí)現(xiàn)對(duì)Pod的自動(dòng)控制。
- 通過(guò)改變RC里Pod模版的鏡像版本罗丰,可以實(shí)現(xiàn)Pod的滾動(dòng)升級(jí)功能神帅。
2.6 Deployment
Deployment是k8s 1.2之后引入的新概念,引入的目的就是為了更好的解決Pod的編排問(wèn)題萌抵。為此找御,Deployment在內(nèi)部使用了Replica Set來(lái)實(shí)現(xiàn)目的,可以看作是RC的一次升級(jí)谜嫉。
Deployment典型使用場(chǎng)景有以下幾個(gè):
- 創(chuàng)建一個(gè)Deployment對(duì)象來(lái)生成對(duì)應(yīng)的Replica Set并完成Pod副本的創(chuàng)建過(guò)程萎坷。
- 檢查Deployment的狀態(tài)來(lái)看布署動(dòng)作是否完成(Pod副本的數(shù)量是否達(dá)到預(yù)期值)凹联。
- 更新Deployment以創(chuàng)建新的Pod(如鏡像升級(jí))沐兰。
- 如果當(dāng)前Deployment不穩(wěn)定,則回滾到早先的Deployment版本蔽挠。
- 掛起或恢復(fù)一個(gè)Deployment住闯。
下面是一個(gè)實(shí)例,文件名為tomcat-deployment.yaml:
apiVersion: extension/v1beta1
kind: Deployment
matadata:
name: frontend
spec:
replica: 1
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
template:
matadata:
labels:
app: app-demo
tier: frontend
spec:
containers:
- name: tomcat-demo
image: tomcat
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
命令kubectl create -f tomcat-deployment.yaml
澳淑,命令以后再嘗試比原。
2.7 Horizontal Pod Autoscaler(HPA)
之前提到過(guò),通過(guò)手工執(zhí)行kubectl scale
的命令杠巡,我們可以實(shí)現(xiàn)Pod擴(kuò)容或縮容量窘,但谷歌對(duì)k8s的定位是自動(dòng)化、智能化氢拥,即分布式系統(tǒng)要能根據(jù)當(dāng)前負(fù)載情況變化自動(dòng)觸發(fā)水平擴(kuò)展或縮容的行為蚌铜,因?yàn)檫@過(guò)程是頻繁發(fā)生锨侯、不可預(yù)料的。
k8s 1.1版本中首次發(fā)布這一特性:Horizontal Pod Autoscaling冬殃,隨后在1
2版本中HPA被升級(jí)為穩(wěn)定版本(apiVersion: autoscaling/v1)囚痴,但同時(shí)仍保留舊版本(apiVersion: extension/v1beta1),官方計(jì)劃是1.3移除舊版本审葬,1.4徹底移除舊版本的支持深滚。
Horizontal Pod Autoscaling(HPA),意味Pod的橫向自動(dòng)擴(kuò)容涣觉,與之前RC痴荐、Deployment一樣,也是k8s資源對(duì)象的一種官册。通過(guò)分析RC控制的所有目標(biāo)Pod的負(fù)載變化情況蹬昌,來(lái)確定是否需要針對(duì)性地調(diào)整目標(biāo)Pod的副本數(shù),即HPA的實(shí)現(xiàn)原理攀隔。當(dāng)前有下兩種方式作為Pod負(fù)載的度量指標(biāo)皂贩。
- CPU Utilization Percentage。
- 應(yīng)用程序自定義度量指標(biāo)昆汹,如服務(wù)每秒內(nèi)相應(yīng)的請(qǐng)求數(shù)(TPS或QPS)明刷。
CPU Utilization Percentage是一個(gè)算術(shù)平均值,即目標(biāo)Pod所有副本的CPU利用率的平均值满粗。一個(gè)Pod自身的CPU利用率是該P(yáng)od當(dāng)前CPU的使用量除以它的Pod Resquest的值辈末。如我們定義一個(gè)Pod的Pod Resquest為0.4,而當(dāng)前Pod的CPU使用量是0.2映皆,即它的CPU使用率是50%挤聘,如此我們就可以算出一個(gè)RC所控制的所有Pod副本的CPU利用率的算術(shù)平均值了。某一時(shí)刻捅彻,CPU Utilization Percentage的值超過(guò)80%组去,則意味著當(dāng)前Pod副本數(shù)量可能不支持接下來(lái)所有的請(qǐng)求,需要進(jìn)行動(dòng)態(tài)擴(kuò)容步淹,而請(qǐng)求高峰時(shí)段過(guò)去后从隆,Pod利用率又會(huì)降下來(lái),對(duì)應(yīng)Pod副本也會(huì)減少數(shù)量缭裆。
CPU Utilization Percentage 計(jì)算過(guò)程中使用到的Pod的COU的量通常是1分鐘的平均值键闺,目前通過(guò)查詢Heapster擴(kuò)展組件來(lái)得到這個(gè)值,所以需要安裝布署Heapster澈驼,這樣便增加了系統(tǒng)的復(fù)雜度和實(shí)施HPA特性的復(fù)雜度辛燥。未來(lái)的計(jì)劃是實(shí)現(xiàn)一個(gè)自身性能數(shù)據(jù)采集的模塊。
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
matadata:
name: php-apache
namespace: default
spec:
maxReplica: 10
minReplica: 1
scaleTargetRef:
kind: Deployment
name: php-apache
targetCPUUtilizationPercentage: 90
2.8 Service(服務(wù))
2.8.1 概述
Service同樣也是k8s核心資源對(duì)象之一,它即是我們常提起微服務(wù)構(gòu)架的一個(gè)“微服務(wù)”挎塌,之前我們說(shuō)的Pod畅铭、RC等資源對(duì)象其實(shí)都是為這節(jié)所說(shuō)的Service(服務(wù))做準(zhǔn)備的。
k8s的Service定義了一個(gè)服務(wù)的訪問(wèn)入口地址硕噩,前端的應(yīng)用(Pod)通過(guò)這個(gè)入口地址訪問(wèn)其背后由Pod副本組成的集群實(shí)例,Service和其后端Pod副本集群之間則是通過(guò)Label Selector來(lái)實(shí)現(xiàn)無(wú)縫對(duì)接的缭贡;RC的作用實(shí)際是保證Service的服務(wù)能力與服務(wù)質(zhì)量始終處于預(yù)期的標(biāo)準(zhǔn)炉擅。
通過(guò)分析、識(shí)別并建模系統(tǒng)中的所有服務(wù)為微服務(wù) - kubernetes Service阳惹,最終系統(tǒng)由多個(gè)提供不同業(yè)務(wù)能力而又彼此獨(dú)立的微服務(wù)單元所組成谍失,服務(wù)之間通過(guò)TCP/IP進(jìn)行通信,從而形成強(qiáng)大而又靈活的彈性網(wǎng)絡(luò)莹汤,擁有了強(qiáng)大的分布式能力快鱼、彈性擴(kuò)展能力、容錯(cuò)能力纲岭,同時(shí)程序架構(gòu)也變得靈活很多抹竹。
既然每個(gè)Pod都會(huì)被分配一個(gè)單獨(dú)的IP地址,而且每個(gè)Pod都提供了一個(gè)獨(dú)立Endpoint(Pod IP+ContainerPort)以被客戶端訪問(wèn)止潮,現(xiàn)在多個(gè)Pod副本組成了一個(gè)集群來(lái)提供服務(wù)窃判,一般的做法都是布署一個(gè)負(fù)載局衡器(軟件或硬件),為這組Pod開(kāi)啟一個(gè)對(duì)外的服務(wù)端口8000喇闸,并將這些Pod的Endpoint列表加入8000端口的轉(zhuǎn)發(fā)列表中袄琳,客戶端就可以通過(guò)負(fù)載均衡器的對(duì)外IP地址+服務(wù)器端口來(lái)訪問(wèn)此服務(wù),而客戶端的請(qǐng)求最后會(huì)被轉(zhuǎn)發(fā)到那個(gè)Pod燃乍,則由負(fù)載均衡器的算法決定唆樊。
k8s也遵循了上述做法,運(yùn)行在每個(gè)Node上的kube-proxy進(jìn)程其實(shí)就是只能的軟件負(fù)載均衡器刻蟹,它負(fù)責(zé)把對(duì)Service的請(qǐng)求轉(zhuǎn)發(fā)到后端的某個(gè)Pod上面逗旁,并在內(nèi)部實(shí)現(xiàn)服務(wù)的負(fù)載均衡和會(huì)話保持機(jī)制。但k8s發(fā)明了一種巧妙影響深遠(yuǎn)的設(shè)計(jì):Service不是共用一個(gè)負(fù)載均衡器的IP地址座咆,而是每個(gè)Service分配了一個(gè)全局唯一的虛擬IP地址痢艺,這個(gè)IP地址又被稱為Cluster IP。這樣的話,雖然Pod的Endpoint會(huì)隨著Pod的創(chuàng)建和銷毀而發(fā)生改變剧防,但是Cluster IP會(huì)伴隨Service的整個(gè)生命周期搞乏,只要通過(guò)Service的Name和Cluster IP進(jìn)行DNS域名映射,Pod的服務(wù)發(fā)現(xiàn)通過(guò)訪問(wèn)Service即可解決蚁吝。
2.8.2 k8s的服務(wù)發(fā)現(xiàn)機(jī)制
任何分布式系統(tǒng)都會(huì)有服務(wù)發(fā)現(xiàn)的基礎(chǔ)問(wèn)題,大部分的分布式系統(tǒng)通過(guò)提供特定的API接口黔帕,但這增加了系統(tǒng)的可侵入性某残。
最早k8s采用Linux環(huán)境變量去解決這個(gè)問(wèn)題国撵,即每個(gè)Service生成一些對(duì)應(yīng)的Linux變量(ENV),并在每個(gè)Pod容器在啟動(dòng)時(shí)玻墅,自動(dòng)注入這些環(huán)境變量介牙。后來(lái)k8s通過(guò)Add-On增值包的方式引入了DNS系統(tǒng),把服務(wù)名作為DNS域名澳厢,這樣程序就可以直接使用服務(wù)名來(lái)建立通信連接环础。
2.8.3 外部系統(tǒng)訪問(wèn)Service的問(wèn)題
為了更加深入的理解和掌握k8s,我們要弄明白k8s的三個(gè)IP的關(guān)鍵問(wèn)題:
- Node IP:Node節(jié)點(diǎn)的IP地址剩拢。
- Pod IP:Pod的IP地址线得。
- Cluster IP:Service的IP地址。
Node IP是k8s集群中每個(gè)節(jié)點(diǎn)物理網(wǎng)卡的IP地址徐伐,這是一個(gè)真是存在的物理網(wǎng)絡(luò)贯钩,所有屬于這個(gè)網(wǎng)絡(luò)的服務(wù)器之間都能通過(guò)這個(gè)網(wǎng)絡(luò)直接通信,不管它們中是否有部分節(jié)點(diǎn)不屬于這個(gè)k8s集群办素。這也表明了k8s集群之外的節(jié)點(diǎn)訪問(wèn)的k8s集群內(nèi)的某個(gè)節(jié)點(diǎn)或者TCP/IP服務(wù)的時(shí)候角雷,必須通過(guò)Node IP進(jìn)行通信。
Pod IP是每個(gè)Pod的IP地址性穿,它是Docker Engine根據(jù)docker0網(wǎng)橋的IP地址段進(jìn)行分配的谓罗,通常是一個(gè)虛擬的二層網(wǎng)絡(luò)。前面說(shuō)過(guò)季二,k8s要求Pod里的容器訪問(wèn)另一個(gè)Pod的容器時(shí)檩咱,就是通過(guò)Pod IP所在的虛擬二層網(wǎng)絡(luò)進(jìn)行通信的,而真實(shí)的TCP/IP流量則是通過(guò)Node IP所在的物理網(wǎng)卡流出的胯舷。這個(gè)參考docker通信相關(guān)的細(xì)節(jié)刻蚯。
最后看Service的Cluster IP,它也是一個(gè)虛擬的IP桑嘶。更像一個(gè)假的IP:
- Cluster IP僅僅作用域k8s Service這個(gè)對(duì)象炊汹,并由k8s管理和分配IP地址(來(lái)源Cluster IP地址池)。
- Cluster IP無(wú)法被ping逃顶,因?yàn)闆](méi)有一個(gè)“網(wǎng)絡(luò)實(shí)體對(duì)象”來(lái)響應(yīng)讨便。
- Cluster IP只能結(jié)合Service Port組成一個(gè)具體的通信端口,單獨(dú)的Cluster IP不具備TCP/IP通信的基礎(chǔ)以政,并且它們屬于k8s集群這樣一個(gè)封閉的空間霸褒,集群之外節(jié)點(diǎn)若想訪問(wèn)這個(gè)通信端口,需要做額外的操作盈蛮。
- 在k8s集群之內(nèi)废菱,Node IP網(wǎng)、Pod IP網(wǎng)與Cluster IP網(wǎng)之間的通信,采用的是k8s自己設(shè)計(jì)的一種編程方式的特殊的路由規(guī)則殊轴,和我們熟知的IP路由有很大的不同衰倦。
那么基于上述,我們知道:Service的Cluster IP屬于k8s集群內(nèi)部的地址旁理,無(wú)法在集群外部直接使用這個(gè)地址樊零。那么矛盾在實(shí)際中就是開(kāi)發(fā)的業(yè)務(wù)肯定是一部分提供給k8s集群外部的應(yīng)用或用戶使用的,典型的就是web孽文,那用戶如何訪問(wèn)驻襟。
采用NodePort是解決上述最直接、最常用叛溢、最有效的方法塑悼。
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
spec:
type: NodePort
ports:
- port: 8080
nodePort: 31002
selector:
tier: frontend
nodePort: 31002這個(gè)屬性表名我們手動(dòng)指定tomcat-service的NodePort為31002,否則k8s就會(huì)自動(dòng)分配一個(gè)可用的端口楷掉,這個(gè)端口我們可以直接在瀏覽器中訪問(wèn):http://<nodePort IP>:31002
厢蒜。
NodePort的實(shí)現(xiàn)方式就是在k8s集群里每個(gè)Node上為外部訪問(wèn)的Service開(kāi)啟一個(gè)對(duì)應(yīng)的TCP監(jiān)聽(tīng)端口,外部系統(tǒng)只要用任意一個(gè)Node的IP地址和具體的NodePort端口號(hào)就能訪問(wèn)這個(gè)服務(wù)烹植。在任意的Node上運(yùn)行netstat命令斑鸦,我們就能看到NodePort端口被監(jiān)聽(tīng)。
但NodePort并沒(méi)有完全解決Service的所有問(wèn)題草雕,如負(fù)載均衡的問(wèn)題巷屿。假如我們的集群中10個(gè)Node,則此時(shí)最好有一個(gè)均衡負(fù)載器墩虹,外部的請(qǐng)求只需要訪問(wèn)此負(fù)載均衡器的IP地址嘱巾,則負(fù)載均衡器負(fù)責(zé)轉(zhuǎn)發(fā)流量到后面某個(gè)Node的NodePort上面。
Load Balance組件獨(dú)立于k8s集群之外诫钓,通常是一個(gè)硬件的負(fù)載均衡器或是軟件方式實(shí)現(xiàn)的旬昭,如HAProxy或Nginx。對(duì)每個(gè)Service菌湃,我們通常配置一個(gè)對(duì)應(yīng)的Load Balance的實(shí)例來(lái)轉(zhuǎn)發(fā)流量到后端的Node上问拘,這增加了工作量即出錯(cuò)的概率。
未完惧所、待續(xù)……