kubernetes基本概念 pod, service

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, 那么targetPortport相同。關(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集群?;蛘遬od集群并不在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。

  1. 環(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上。

  2. 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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容