k8s的部署架構(gòu)
kubernetes中有兩類資源泻云,分別是master和nodes,master和nodes上跑的服務(wù)如下圖狐蜕,
kube-apiserver | kubelet
kube-controller-manager |
kube-scheduler | kube-proxy
---------------------- --------------------
k8s master node (non-master)
-
master
:負(fù)責(zé)管理整個(gè)集群宠纯,例如,對(duì)應(yīng)用進(jìn)行調(diào)度(擴(kuò)縮)层释、維護(hù)應(yīng)用期望的狀態(tài)婆瓜、對(duì)應(yīng)用進(jìn)行發(fā)布等。 -
node
:集群中的宿主機(jī)(可以是物理機(jī)也可以是虛擬機(jī))贡羔,每個(gè)node上都有一個(gè)agent廉白,名為kubelet,用于跟master通信治力。同時(shí)一個(gè)node需要有管理容器的工具包蒙秒,用于管理在node上運(yùn)行的容器(docker或rkt)。一個(gè)k8s集群至少要有3個(gè)節(jié)點(diǎn)宵统。
kubelet通過master暴露的API與master通信,用戶也可以直接調(diào)用master的API做集群的管理。
k8s中的對(duì)象Objects
pod
k8s中的最小部署單元马澈,不是一個(gè)程序/進(jìn)程瓢省,而是一個(gè)環(huán)境(包括容器、存儲(chǔ)痊班、網(wǎng)絡(luò)ip:port勤婚、容器配置)。其中可以運(yùn)行1個(gè)或多個(gè)container(docker或其他容器)涤伐,在一個(gè)pod內(nèi)部的container共享所有資源馒胆,包括共享pod的ip:port和磁盤。
pod是臨時(shí)性的凝果,用完即丟棄的祝迂,當(dāng)pod中的進(jìn)程結(jié)束、node故障器净,或者資源短缺時(shí)型雳,pod會(huì)被干掉∩胶Γ基于此纠俭,用戶很少直接創(chuàng)建一個(gè)獨(dú)立的pods,而會(huì)通過k8s中的controller來對(duì)pod進(jìn)行管理浪慌。
controller通過pod templates來創(chuàng)建pod冤荆,pod template是一個(gè)靜態(tài)模板,創(chuàng)建出來之后的pod就跟模板沒有關(guān)系了权纤,模板的修改也不會(huì)影響現(xiàn)有的pod匙赞。
services
由于pod是臨時(shí)性的,pod的ip:port也是動(dòng)態(tài)變化的妖碉。這種動(dòng)態(tài)變化在k8s集群中就涉及到一個(gè)問題:如果一組后端pod作為服務(wù)提供方涌庭,供一組前端的pod所調(diào)用,那服務(wù)調(diào)用方怎么自動(dòng)感知服務(wù)提供方欧宜。這就引入了k8s中的另外一個(gè)核心概念坐榆,services.
service是通過apiserver創(chuàng)建出來的對(duì)象實(shí)例,舉例冗茸,
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
這個(gè)配置將創(chuàng)建出來一個(gè)新的Service對(duì)象席镀,名為my-service,后端是所有包含app=MyApp
的pod夏漱,目標(biāo)端口是9376豪诲,同時(shí)這個(gè)service也會(huì)被分配一個(gè)ip,被稱為集群ip挂绰,對(duì)應(yīng)的端口是80. 如果不指定targetPort
, 那么targetPort
與port
相同屎篱。關(guān)于targetPort
更靈活的設(shè)定是,targetPort
可以是一個(gè)String類型的名字,該名字對(duì)應(yīng)的真實(shí)端口值由各個(gè)后端pod自己定義交播,這樣同一組pod無需保證同一個(gè)port重虑,更加靈活。
在某種場景下秦士,可能你不想用label selector缺厉,不想通過選擇標(biāo)簽的方式來獲取所有的后端pod,如測試環(huán)境下同一個(gè)service name可能指向自己的pod隧土,而非生產(chǎn)環(huán)境中的正式pod集群提针。或者pod集群并不在k8s中維護(hù)曹傀。針對(duì)這個(gè)場景辐脖,k8s也有優(yōu)雅的方案進(jìn)行適配。就是在創(chuàng)建service的時(shí)候不指定selector的部分卖毁,而是先創(chuàng)建出來service揖曾,之后手動(dòng)綁定后端pod的ip和端口。
終于知道為什么k8s是目前風(fēng)頭最勁的服務(wù)編排技術(shù)了亥啦,它充分地做了解耦炭剪,由于google的業(yè)務(wù)復(fù)雜性,它的組件和組件之間翔脱,充分的解耦奴拦、靈活,整個(gè)系統(tǒng)松散且牢固届吁。
services組件與bns不同的一點(diǎn)错妖,bns的節(jié)點(diǎn)是自己指定了name和后端的關(guān)聯(lián)關(guān)系,而services是根據(jù)pod上的標(biāo)簽(label)自動(dòng)生成的疚沐,更靈活暂氯。ali的group就更別提了,group是隸屬于app的亮蛔,擴(kuò)展性方面更弱一些痴施。
上文說在創(chuàng)建service的時(shí)候,系統(tǒng)為service分配了一個(gè)集群虛IP和端口究流,服務(wù)使用方通過這個(gè)vip:port來訪問真實(shí)的服務(wù)提供方辣吃。這里的vip就是kube-proxy
提供出來的。
虛ip和service proxies
kube-proxy的模式
- userspace: client -> iptables -> kube-proxy -> backend pod(rr), iptables只是把虛ip轉(zhuǎn)換成kube-proxy的ip芬探,通過kube-proxy自己維護(hù)的不同端口來輪詢轉(zhuǎn)發(fā)到后端的pod上神得。
- iptables: client -> iptables -> backend pod(random),kube-proxy只是監(jiān)聽master上service的創(chuàng)建偷仿,之后動(dòng)態(tài)添加/刪除本機(jī)上的iptables規(guī)則
- ipvs: client -> ipvs ->backend pod, ipvs是一個(gè)內(nèi)核模塊
服務(wù)發(fā)現(xiàn)
服務(wù)使用方如何找到我們定義的Service? 在k8s中用了兩個(gè)方案哩簿,環(huán)境變量 && DNS宵蕉。
環(huán)境變量
每當(dāng)有service被創(chuàng)建出來之后,各個(gè)node(宿主機(jī))上的kubelet卡骂,就會(huì)把service name加到自己宿主機(jī)的環(huán)境變量中国裳,供所有Pod使用形入。環(huán)境變量的命名規(guī)則是{SERVICE_NAME}_SERVICE_HOST, ${SERVICE_NAME}SERVICE_PORT全跨,其中SERVICE_NAME是新serviceName的大寫形式,serviceName中的橫杠-會(huì)被替換成下劃線.
使用環(huán)境變量有一個(gè)隱含的創(chuàng)建順序亿遂,即服務(wù)使用方在通過環(huán)境變量訪問一個(gè)service的時(shí)候决摧,這個(gè)service必須已經(jīng)存在了卓舵。
這么簡單粗暴的方案...這樣做有個(gè)好處,就是省的自己搞名字解析服務(wù),相當(dāng)于本地的agent做了“域名劫持”第队。serviceName對(duì)應(yīng)到上文提到的,由kube-proxy
提供的vip:port
上震叙。DNS
這是官方不推薦的做法均芽,推薦用來跟k8s的外部服務(wù)進(jìn)行交互,ExternalName.
Headless services
在創(chuàng)建service的時(shí)候浦徊,用戶可以給spec.clusterIp指定一個(gè)特定的ip馏予。前提是這個(gè)ip需要是一個(gè)合法的IP,并且要在apiServer定義的service-cluster-ip-range范圍內(nèi)盔性。
當(dāng)然霞丧,如果用戶有自己的服務(wù)發(fā)現(xiàn)服務(wù),也可以不用k8s原生的service服務(wù)冕香,這時(shí)蛹尝,需要顯式地給spec.clusterIp設(shè)置None,這樣k8s就不會(huì)給service分配clusterIp了悉尾。
如果用戶將spec.cluster設(shè)置為None突那,但指定了selector,那么endpoints controller還是會(huì)創(chuàng)建Endpoints
的构眯,會(huì)創(chuàng)建一個(gè)新的DNS記錄直接指向這個(gè)service描述的后端pod愕难。否則,不會(huì)創(chuàng)建Endpoints
記錄鸵赖。 // 這塊沒看懂
發(fā)布服務(wù)务漩,服務(wù)類型
- ClusterIp: 默認(rèn)配置,給service分配一個(gè)集群內(nèi)部IP它褪,k8s集群外部不識(shí)別饵骨。
- NodePort:宿主機(jī)端口,集群外部的服務(wù)也訪問茫打,使用nodeIp:nodePort
- LoadBalancer:通過云負(fù)載均衡居触,將service暴露出去 // 沒理解
- ExternalName:將serviceName與externalName綁定妖混,讓外網(wǎng)可以訪問到。要求
kube-dns
的版本>= 1.7