k8s~k8s里的服務Service
k8s用命名空間namespace把資源(yuan)進行隔離,默認情況下,相同的命名空(kong)間里的服(fu)務(wu)可以相互通(tong)訊,反(fan)之進行隔離。
服務Service
1.1 Service
Kubernetes中一個(ge)應(ying)用(yong)服務會有一個(ge)或多個(ge)實(shi)例(Pod,Pod可以通過rs進行(xing)多復本的建立(li)),每個(ge)實(shi)例(Pod)的IP地址由網絡插件動態隨機分配(Pod重啟后IP地址會改變)。為(wei)屏蔽這(zhe)些后端(duan)實(shi)例的動態變化(hua)和對多實(shi)例的負載均衡,引入了Service這(zhe)個(ge)資源對象(xiang),如下所示:
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
labels:
app: nginx
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector: #service通過selector和pod建立關聯
app: nginx
根據(ju)創建Service的type類型不同,可分成(cheng)4種(zhong)模式:
ClusterIP: 默認方式。根據是否生成ClusterIP又可分為普通Service和Headless Service兩類:- 普通Service:通過為Kubernetes的Service分配一個集群內部可訪問的
固定虛擬IP(Cluster IP),實現集群內的訪問。為最常見的方式。 - Headless Service:該服務不會分配Cluster IP,也不通過kube-proxy做反向代理和負載均衡。而是通過DNS提供穩定的絡ID來訪問,DNS會將headless service的后端直接解析為podIP列表。主要供StatefulSet使用。
- 普通Service:通過為Kubernetes的Service分配一個集群內部可訪問的
NodePort:除了使用Cluster IP之外,還通過將service的port映射到集群內每個節點的相同一個端口,實現通過nodeIP:nodePort從集群外訪問服務。LoadBalancer:和nodePort類似,不過除了使用一個Cluster IP和nodePort之外,還會向所使用的公有云申請一個負載均衡器(負載均衡器后端映射到各節點的nodePort),實現從集群外通過LB訪問服務。ExternalName:是 Service 的特例。此模式主要面向運行在集群外部的服務,通過它可以將外部服務映射進k8s集群,且具備k8s內服務的一些特征(如具備namespace等屬性),來為集群內部提供服務。此模式要求kube-dns的版本為1.7或以上。這種模式和前三種模式(除headless service)最大的不同是重定向依賴的是dns層次,而不是通過kube-proxy。
比如,在service定義中指定externalName的值"my.database.example.com":
此時k8s集群內的DNS服務會給集群內的服務名
當查詢k8s集群內的服務my-service.prod.svc.cluster.local時,集群的 DNS 服務將返回映射的CNAME記錄"foo.bar.example.com"。
備注:
前3種模式,定義服務的時候通過selector指定服務對應的pods,根據pods的地址創建出endpoints作為服務后端;Endpoints Controller會watch Service以及pod的變化,維護對應的Endpoint信息。kube-proxy根據Service和Endpoint來維護本地的路由規則。當Endpoint發生變化,即Service以及關聯的pod發生變化,kube-proxy都會在每個節點上更新iptables,實現一層負載均衡。
而ExternalName模式則不指定selector,相應的也就沒有port和endpoints。
ExternalName和ClusterIP中的Headles Service同屬于Headless Service的兩種情況。Headless Service主要是指(zhi)不(bu)分配Service IP,且不(bu)通(tong)過(guo)kube-proxy做反向代理和負載均衡的服務。
1.2 Port
Service中主要涉及三種Port: * port 這里的port表示service暴露在clusterIP上的端口,clusterIP:Port 是提供給集群內部訪問kubernetes服(fu)務的入口。
-
targetPort
containerPort,targetPort是pod上的端(duan)口,從port和nodePort上到(dao)來(lai)的數據最終經過kube-proxy流入到(dao)后(hou)端(duan)pod的targetPort上進入容器(qi)。 -
nodePort
nodeIP:nodePort 是提供給(gei)從集(ji)群(qun)外(wai)部訪(fang)問(wen)kubernetes服務的入口。
總(zong)的(de)(de)(de)(de)來(lai)說,port和nodePort都是service的(de)(de)(de)(de)端口,前者暴(bao)露給從(cong)集群(qun)內訪問(wen)服(fu)務(wu),后者暴(bao)露給從(cong)集群(qun)外訪問(wen)服(fu)務(wu)。從(cong)這兩個端口到(dao)來(lai)的(de)(de)(de)(de)數據都需要經過(guo)反向代理kube-proxy流入(ru)后端具體pod的(de)(de)(de)(de)targetPort,從(cong)而進入(ru)到(dao)pod上的(de)(de)(de)(de)容器內。
1.3 IP
使用Service服務還會涉及(ji)到幾(ji)種(zhong)IP:
-
ClusterIP
Pod IP 地(di)(di)址是(shi)實際存在于某個(ge)(ge)網卡(可(ke)以(yi)是(shi)虛(xu)擬設備(bei))上的,但clusterIP就不一(yi)樣了,沒有網絡設備(bei)承載這個(ge)(ge)地(di)(di)址。它是(shi)一(yi)個(ge)(ge)虛(xu)擬地(di)(di)址,由kube-proxy使(shi)用iptables規(gui)則(ze)重(zhong)新定向到(dao)(dao)其本地(di)(di)端口(kou),再均衡到(dao)(dao)后端Pod。當kube-proxy發(fa)現一(yi)個(ge)(ge)新的service后,它會在本地(di)(di)節點打開一(yi)個(ge)(ge)任意端口(kou),創建(jian)相應(ying)的iptables規(gui)則(ze),重(zhong)定向服務的clusterIP和port到(dao)(dao)這個(ge)(ge)新建(jian)的端口(kou),開始接(jie)受到(dao)(dao)達這個(ge)(ge)服務的連(lian)接(jie)。 -
Pod IP
Pod的(de)IP,每個(ge)Pod啟動時(shi),會自(zi)動創建一個(ge)鏡像為gcr.io/google_containers/pause的(de)容(rong)(rong)器(qi),Pod內部其他容(rong)(rong)器(qi)的(de)網絡模式使(shi)用container模式,并指(zhi)定為pause容(rong)(rong)器(qi)的(de)ID,即:network_mode: "container:pause容(rong)(rong)器(qi)ID",使(shi)得(de)Pod內所有容(rong)(rong)器(qi)共(gong)享pause容(rong)(rong)器(qi)的(de)網絡,與外部的(de)通信經由此容(rong)(rong)器(qi)代(dai)理,pause容(rong)(rong)器(qi)的(de)IP也可以稱為Pod IP。 -
節點IP
Node-IP,service對(dui)象在(zai)(zai)Cluster IP range池中分配到(dao)的(de)(de)IP只能在(zai)(zai)內部訪問,如果服務作為一個(ge)(ge)應用程序內部的(de)(de)層次(ci),還(huan)是很合適(shi)的(de)(de)。如果這個(ge)(ge)service作為前端服務,準備為集群外的(de)(de)客戶提供業務,我們就(jiu)需要給(gei)(gei)這個(ge)(ge)服務提供公共(gong)IP了。指定service的(de)(de)spec.type=NodePort,這個(ge)(ge)類型的(de)(de)service,系統會給(gei)(gei)它在(zai)(zai)集群的(de)(de)各(ge)個(ge)(ge)代(dai)理節點上分配一個(ge)(ge)節點級別(bie)的(de)(de)端口(kou),能訪問到(dao)代(dai)理節點的(de)(de)客戶端都能訪問這個(ge)(ge)端口(kou),從(cong)而(er)訪問到(dao)服務。