1. 介紹
Kubernetes(k8s)是自動(dòng)化容器操作的開(kāi)源平臺(tái),這些操作包括部署,調(diào)度和節(jié)點(diǎn)集群間擴(kuò)展。
Kubernetes組件組成:
1 Kubectl
客戶端命令行工具,將接受的命令格式化后發(fā)送給kube-apiserver,作為整個(gè)系統(tǒng)的操作入口。
2 kube-apiserver
作為整個(gè)系統(tǒng)的控制入口,以REST API服務(wù)提供接口,提供了資源操作的唯一入口,并提供認(rèn)證、授權(quán)、訪問(wèn)控制、API注冊(cè)和發(fā)現(xiàn)等機(jī)制。
3 kube-controller-manager
用來(lái)執(zhí)行整個(gè)系統(tǒng)中的后臺(tái)任務(wù),包括節(jié)點(diǎn)狀態(tài)狀況、Pod個(gè)數(shù)、Pods和Service的關(guān)聯(lián)等。負(fù)責(zé)維護(hù)集群的狀態(tài),比如故障檢測(cè)、自動(dòng)擴(kuò)展、滾動(dòng)更新等。
4 kube-scheduler
負(fù)責(zé)節(jié)點(diǎn)資源管理,接受來(lái)自kube-apiserver創(chuàng)建Pods任務(wù),并分配到某個(gè)節(jié)點(diǎn)。
5 etcd
etcd 集群的主數(shù)據(jù)庫(kù),保存了整個(gè)集群的狀態(tài),負(fù)責(zé)節(jié)點(diǎn)間的服務(wù)發(fā)現(xiàn)和配置共享。
6 kube-proxy
運(yùn)行在每個(gè)計(jì)算節(jié)點(diǎn)上,負(fù)責(zé)Pod網(wǎng)絡(luò)代理。定時(shí)從etcd獲取到service信息來(lái)做相應(yīng)的策略。負(fù)責(zé)為Service提供cluster內(nèi)部的服務(wù)發(fā)現(xiàn)和負(fù)載均衡。
7 kubelet
運(yùn)行在每個(gè)計(jì)算節(jié)點(diǎn)上,作為agent,接受分配該節(jié)點(diǎn)的Pods任務(wù)及管理容器,周期性獲取容器狀態(tài),反饋給kube-apiserver。負(fù)責(zé)維護(hù)容器的生命周期,負(fù)責(zé)管理pods和它們上面的容器,images鏡像、volumes、etc。同時(shí)也負(fù)責(zé)Volume(CVI)和網(wǎng)絡(luò)(CNI)的管理。
8 DNS
一個(gè)可選的DNS服務(wù),用于為每個(gè)Service對(duì)象創(chuàng)建DNS記錄,這樣所有的Pod就可以通過(guò)DNS訪問(wèn)服務(wù)了。
2 相關(guān)概念
2.1 Pod
Pod是在K8s集群中運(yùn)行部署應(yīng)用或服務(wù)的最小單元,它是可以支持多容器的。Pod的設(shè)計(jì)理念是支持多個(gè)容器在一個(gè)Pod中共享網(wǎng)絡(luò)地址和文件系統(tǒng),可以通過(guò)進(jìn)程間通信和文件共享這種簡(jiǎn)單高效的方式組合完成服務(wù).比如你運(yùn)行一個(gè)操作系統(tǒng)發(fā)行版的軟件倉(cāng)庫(kù),一個(gè)Nginx容器用來(lái)發(fā)布軟件,另一個(gè)容器專(zhuān)門(mén)用來(lái)從源倉(cāng)庫(kù)做同步,這兩個(gè)容器的鏡像不太可能是一個(gè)團(tuán)隊(duì)開(kāi)發(fā)的,但是他們一塊兒工作才能提供一個(gè)微服務(wù);這種情況下,不同的團(tuán)隊(duì)各自開(kāi)發(fā)構(gòu)建自己的容器鏡像,在部署的時(shí)候組合成一個(gè)微服務(wù)對(duì)外提供服務(wù)
2.2副本復(fù)制器(RC)
通過(guò)監(jiān)控運(yùn)行中的Pod來(lái)保證集群中運(yùn)行指定數(shù)目的Pod副本。少于指定數(shù)目,RC就會(huì)啟動(dòng)運(yùn)行新的Pod副本;多于指定數(shù)目,RC就會(huì)殺死多余的Pod副本
2.3副本集(Replica Set,RS)
RS是新一代RC,提供同樣的高可用能力,區(qū)別主要在于RS后來(lái)居上,能支持更多種類(lèi)的匹配模式。副本集對(duì)象一般不單獨(dú)使用,而是作為Deployment的理想狀態(tài)參數(shù)使用
2.4部署(Deployment)
部署是一個(gè)比RS應(yīng)用模式更廣的API對(duì)象,支持動(dòng)態(tài)擴(kuò)展??梢詣?chuàng)建一個(gè)新的服務(wù),更新一個(gè)新的服務(wù),也可以是滾動(dòng)升級(jí)一個(gè)服務(wù)。滾動(dòng)升級(jí)一個(gè)服務(wù),實(shí)際是創(chuàng)建一個(gè)新的RS,然后逐漸將新RS中副本數(shù)增加到理想狀態(tài),將舊RS中的副本數(shù)減小到0的復(fù)合操作【逐步升級(jí)新得副本,剔除舊的副本】;
總結(jié):RC、RS和Deployment只是保證了支撐服務(wù)的微服務(wù)Pod的數(shù)量
2.5服務(wù)(Service)
RC、RS和Deployment只是保證了支撐服務(wù)的微服務(wù)Pod的數(shù)量,但是沒(méi)有解決如何訪問(wèn)這些服務(wù)的問(wèn)題。一個(gè)Pod只是一個(gè)運(yùn)行服務(wù)的實(shí)例,隨時(shí)可能在一個(gè)節(jié)點(diǎn)上停止,在另一個(gè)節(jié)點(diǎn)以一個(gè)新的IP啟動(dòng)一個(gè)新的Pod,因此不能以確定的IP和端口號(hào)提供服務(wù)。要穩(wěn)定地提供服務(wù)需要服務(wù)發(fā)現(xiàn)和負(fù)載均衡能力。服務(wù)發(fā)現(xiàn)完成的工作,是針對(duì)客戶端訪問(wèn)的服務(wù),找到對(duì)應(yīng)的的后端服務(wù)實(shí)例。在K8s集群中,客戶端需要訪問(wèn)的服務(wù)就是Service對(duì)象。
每個(gè)Service會(huì)對(duì)應(yīng)一個(gè)集群內(nèi)部有效的虛擬IP,集群內(nèi)部通過(guò)虛擬IP訪問(wèn)一個(gè)服務(wù)。在K8s集群中微服務(wù)的負(fù)載均衡是由Kube-proxy實(shí)現(xiàn)的。Kube-proxy是K8s集群內(nèi)部的負(fù)載均衡器。它是一個(gè)分布式代理服務(wù)器,在K8s的每個(gè)節(jié)點(diǎn)上都有一個(gè);這一設(shè)計(jì)體現(xiàn)了它的伸縮性優(yōu)勢(shì),需要訪問(wèn)服務(wù)的節(jié)點(diǎn)越多,提供負(fù)載均衡能力的Kube-proxy就越多,高可用節(jié)點(diǎn)也隨之增多。與之相比,我們平時(shí)在服務(wù)器端做個(gè)反向代理做負(fù)載均衡,還要進(jìn)一步解決反向代理的負(fù)載均衡和高可用問(wèn)題。
3 PodIP、ClusterIP和外部IP
3.1 Pod IP
Kubernetes的最小部署單元是Pod。利用Flannel作為不同HOST之間容器互通技術(shù)時(shí),由Flannel和etcd維護(hù)了一張節(jié)點(diǎn)間的路由表。Flannel的設(shè)計(jì)目的就是為集群中的所有節(jié)點(diǎn)重新規(guī)劃IP地址的使用規(guī)則,從而使得不同節(jié)點(diǎn)上的容器能夠獲得“同屬一個(gè)內(nèi)網(wǎng)”且”不重復(fù)的”IP地址,并讓屬于不同節(jié)點(diǎn)上的容器能夠直接通過(guò)內(nèi)網(wǎng)IP通信。
每個(gè)Pod啟動(dòng)時(shí),會(huì)自動(dòng)創(chuàng)建一個(gè)鏡像為gcr.io/google_containers/pause:0.8.0的容器,容器內(nèi)部與外部的通信經(jīng)由此容器代理,該容器的IP也可以稱(chēng)為Pod IP。
Pod IP 地址是實(shí)際存在于某個(gè)網(wǎng)卡(可以是虛擬設(shè)備)上的,但Service Cluster IP就不一樣了,沒(méi)有網(wǎng)絡(luò)設(shè)備為這個(gè)地址負(fù)責(zé)。它是由kube-proxy使用Iptables規(guī)則重新定向到其本地端口,再均衡到后端Pod的。
就拿上面我們提到的圖像處理程序?yàn)槔?。?dāng)我們的Service被創(chuàng)建時(shí),Kubernetes給它分配一個(gè)地址10.0.0.1。這個(gè)地址從我們啟動(dòng)API的service-cluster-ip-range參數(shù)(舊版本為portal_net參數(shù))指定的地址池中分配,比如–service-cluster-ip-range=10.0.0.0/16。假設(shè)這個(gè)Service的端口是1234。集群內(nèi)的所有kube-proxy都會(huì)注意到這個(gè)Service。當(dāng)proxy發(fā)現(xiàn)一個(gè)新的service后,它會(huì)在本地節(jié)點(diǎn)打開(kāi)一個(gè)任意端口,建相應(yīng)的iptables規(guī)則,重定向服務(wù)的IP和port到這個(gè)新建的端口,開(kāi)始接受到達(dá)這個(gè)服務(wù)的連接。
當(dāng)一個(gè)客戶端訪問(wèn)這個(gè)service時(shí),這些iptable規(guī)則就開(kāi)始起作用,客戶端的流量被重定向到kube-proxy為這個(gè)service打開(kāi)的端口上,kube-proxy隨機(jī)選擇一個(gè)后端pod來(lái)服務(wù)客戶。這個(gè)流程如下圖所示:
根據(jù)Kubernetes的網(wǎng)絡(luò)模型,使用Service Cluster IP和Port訪問(wèn)Service的客戶端可以坐落在任意代理節(jié)點(diǎn)上。外部要訪問(wèn)Service,我們就需要給Service外部訪問(wèn)IP。
Service對(duì)象在Cluster IP range池中分配到的IP只能在內(nèi)部訪問(wèn),如果服務(wù)作為一個(gè)應(yīng)用程序內(nèi)部的層次,還是很合適的。如果這個(gè)Service作為前端服務(wù),準(zhǔn)備為集群外的客戶提供業(yè)務(wù),我們就需要給這個(gè)服務(wù)提供公共IP了。
外部訪問(wèn)者是訪問(wèn)集群代理節(jié)點(diǎn)的訪問(wèn)者。為這些訪問(wèn)者提供服務(wù),我們可以在定義Service時(shí)指定其spec.publicIPs,一般情況下publicIP 是代理節(jié)點(diǎn)的物理IP地址。和先前的Cluster IP range上分配到的虛擬的IP一樣,kube-proxy同樣會(huì)為這些publicIP提供Iptables 重定向規(guī)則,把流量轉(zhuǎn)發(fā)到后端的Pod上。有了publicIP,我們就可以使用load balancer等常用的互聯(lián)網(wǎng)技術(shù)來(lái)組織外部對(duì)服務(wù)的訪問(wèn)了。
spec.publicIPs在新的版本中標(biāo)記為過(guò)時(shí)了,代替它的是spec.type=NodePort,這個(gè)類(lèi)型的service,系統(tǒng)會(huì)給它在集群的各個(gè)代理節(jié)點(diǎn)上分配一個(gè)節(jié)點(diǎn)級(jí)別的端口,能訪問(wèn)到代理節(jié)點(diǎn)的客戶端都能訪問(wèn)這個(gè)端口,從而訪問(wèn)到服務(wù)。
3.4 Endpoint地址保持
Pod的endpointd地址會(huì)隨著pod的銷(xiāo)毀和重新創(chuàng)建而發(fā)生改變,因?yàn)樾碌膒od的ip地址和舊的pod的地址不同,service一旦創(chuàng)建,kubernetes會(huì)自動(dòng)為它分配一個(gè)可用cluster ip,而且在service的整個(gè)生命周期內(nèi),它的cluster ip不會(huì)發(fā)生改變。解決endpoint地址不發(fā)生改變的方法:只需要service的name與service的cluster ip地址做一個(gè)dns域名映射就可以解決。
3.5 namespace(命名空間)
Namespace(命名空間)是kubernetes系統(tǒng)中的一個(gè)重要概念,namespace在很多情況下用于實(shí)現(xiàn)多租戶的資源隔離。Namespace通過(guò)將集群內(nèi)部的資源對(duì)象“分配”到不同的namespace中,形成邏輯上分組的不同項(xiàng)目、小組或用戶組,便于不同的分組在共享使用整個(gè)集群的資源的同時(shí)還能被分別管理。如果不特別指明namespace,用戶創(chuàng)建的pod、rc、service都將被系統(tǒng)創(chuàng)建到這個(gè)默認(rèn)名為default的namespace中。當(dāng)我們給每個(gè)租戶創(chuàng)建一個(gè)namespace來(lái)實(shí)現(xiàn)多租戶的資源隔離,還能結(jié)合kubernetes的資源配額管理,限定不同租戶能占用的資源,例如cpu使用量,內(nèi)存使用量等。
3.6 mysql-rc.yaml詳解
apiVersion: V1
king: ReplicationController????? ---副本控制器rc
metadata:
?? name: mysql?????????????????? --- rc的名稱(chēng),全局唯一
spec:
?? replics :1??????????????????? --- pod副本期待數(shù)量
?? selector:
????? app: mysql?????????????? --- 符合目標(biāo)的pod擁有此標(biāo)簽
template:??????????????? ---根據(jù)此模板創(chuàng)建pod的副本(實(shí)例)
?? metadata:
????? labels:
??????? app: mysql?? --pod副本擁有的標(biāo)簽,對(duì)應(yīng)rc的selector
?? spec:
????? containers:???? -- pod內(nèi)容器的定義部分
name: mysql?? -- 容器的名稱(chēng)
image: mysql? -- 容器對(duì)應(yīng)的docker image
ports:
- containerPort: 3306? -- 容器暴露的端口號(hào)
env:??? -- 注入到容器內(nèi)的環(huán)境變量
- name: MYSQL_ROOT_PASSWORD
? Value: “123456”
Kind屬性:用來(lái)表示此資源對(duì)象的類(lèi)型,比如這里是replication,表示這是一個(gè)rc,Spec一節(jié)中是rc的相關(guān)屬性定義,比如spec.selector是rc的pod標(biāo)簽(label)選擇器,即監(jiān)控和管理?yè)碛羞@些標(biāo)簽的pod實(shí)例,確保當(dāng)前集群上始終有且僅有replicas哥pod實(shí)例在運(yùn)行,這里我們?cè)O(shè)置replicas=1表示只能運(yùn)行一個(gè)mysql pod實(shí)例。
3.7 mysql-svc.yaml
apiVersion: v1
kind: Service? --表明是kubernetes service
metadata:
?? name: mysql? -- service的全局唯一名稱(chēng)
spec:
? ports:
- port: 3306?? --service提供服務(wù)的端口號(hào)
? selector:
??? app: mysql???? -- services對(duì)應(yīng)的pod擁有這里定義的標(biāo)簽
metadata.name是service的服務(wù)名(servicename)
port屬性定義了service的端口
spec.selector確定了哪些pod副本(實(shí)例)對(duì)應(yīng)到本地服務(wù)
3.8 myweb-rc.yaml
king: ReplicationController
metadata:
?? name: myweb
spec:
?? replicas: 5
?? selector:
????? app: myweb
?? template:
?? ? metadata:
????? ? labels:
????????? app: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’
該配置文件中的rc對(duì)應(yīng)的tomcat容器里引用了MYSQL_SERVICE_HOST=mysql這個(gè)環(huán)境變量,而mysql是我們之前定義的mysql服務(wù)的服務(wù)名
3.9 myweb-svc.yaml
apiVersion: V1
kind: Service
metadata:
?? name: myweb
spec:
?? type: NodePort
ports:
? - port: 8080
??? nodePort: 30001
?selector:
??? app: myweb
該配置文件中的type=nodeport和nodeport=30001這兩個(gè)屬性表示,表明此service開(kāi)啟了nodeport方式的外網(wǎng)訪問(wèn)模式