一句話總結(jié)Kubernetes的Headless服務(wù)
Kubernetes的概念很多,有的著實(shí)讓人費(fèi)解,比如說Headless服務(wù),聽名字就很拗口。那Headless服務(wù)是什么,使用場景是什么。一句話總結(jié):Headless服務(wù)就是一組Pod組成的只供集群內(nèi)訪問(沒有ClusterIP)的Service,一般結(jié)合StatefulSet用于部署有狀態(tài)應(yīng)用的場景。
1、Service與服務(wù)發(fā)現(xiàn)
提到Headless Service就得先說說Service和服務(wù)發(fā)現(xiàn)。
1.1、Service簡述
Service主要用于實(shí)現(xiàn)對一組Pod的訪問,Service 通過標(biāo)簽選擇器來關(guān)聯(lián) Pod 資源。Service對外暴露服務(wù)的方式有nodePort和loadbalancer。Service 根據(jù)訪問的端口將對應(yīng)的請求轉(zhuǎn)發(fā)至后端Pod的端口上。
Service對象的IP地址(ClusterIP)是虛擬IP地址,僅在 Kubernetes集群內(nèi)可訪問,外部無法訪問。一般有以下幾種方式將Service暴露給外部訪問:
- 通過hostPort方式在單一節(jié)點(diǎn)上做端口映射
- 通過Pod的hostNetwork配置讓Pod資源使用工作節(jié)點(diǎn)上的網(wǎng)絡(luò)
- 使用NodePort或LoadBalancer類型的Service
- 使用Ingress 資源
本質(zhì)上來講,一個(gè)Service 對象對應(yīng)于工作節(jié)點(diǎn)內(nèi)核之中的一組路由規(guī)則,這些規(guī)則能夠?qū)⒌竭_(dá)Service對象的ClusterIP的流量轉(zhuǎn)發(fā)至相應(yīng)Pod對象的IP地址和端口。
每個(gè)工作節(jié)點(diǎn)的kube-proxy組件通過API Server持續(xù)監(jiān)聽各個(gè)Service及其關(guān)聯(lián)的Pod對象,并將Service對象的創(chuàng)建或變動(dòng),實(shí)時(shí)寫入到當(dāng)前工作節(jié)點(diǎn)的路由規(guī)則上。客戶端、Service及Pod對象的關(guān)系如下圖所示:
1.2、Service類型
Service 一般分為3種類型:ClusterIP、NodePort、LoadBalancer。
ClusterIP
通過集群內(nèi)部IP 地址暴露服務(wù),CusterIP地址僅在集群內(nèi)部可以訪問,無法被集群外部的客戶端訪問。
NodePort
NodePort類型,將Service的端口號(hào)映射到每個(gè)Node的一個(gè)端口號(hào)上,然后分發(fā)給后端的Pod處理。這種類型的Service 既可以被集群內(nèi)部客戶端通過 CIusterIP 直接訪問,也可以在集群外部客戶端通過nodeIP:nodePort進(jìn)行訪問。
LoadBalancer
LoadBalancer類型建立在 NodePort基礎(chǔ)上,將Service映射到一個(gè)負(fù)載均衡器的IP 地址上,通常在公有云環(huán)境中使用。
客戶端通過負(fù)載均衡器的IP和Service的端號(hào)就可以訪問到具體的服務(wù),無須再通過 kube-proxy提供的負(fù)載均衡機(jī)制進(jìn)行流量轉(zhuǎn)發(fā),可以直接將流量轉(zhuǎn)發(fā)到后端 Pod上。
如果是本地搭建LoadBalancer,一般采用metallb方案,官網(wǎng)地址:https://metallb.universe.tf/,有興趣的朋友自行搭建。
2、Headless Service的概念
在某些場景中,無需對外提供訪問能力,只需要在內(nèi)部找到自己想找到的Pod資源時(shí),可以通過Headless Service來實(shí)現(xiàn)。
這種不具有ClusterIP的Service資源就是Headless Service,該 Service 的請求流量不需要 kube-proxy 處理,也不會(huì)有負(fù)載均衡和路由規(guī)則,而是由ClusterDNS的域名解析機(jī)制直接去訪問固定的Pod資源。
一般Headless會(huì)搭配著StatefulSet一起使用,下面繼續(xù)介紹。
3、StatefulSet結(jié)合Headless使用
3.1、StatefulSet概述
StatefulSet是編排有狀態(tài)應(yīng)用的控制器。所謂有狀態(tài)的應(yīng)用就是一組具有唯一持久數(shù)據(jù)和固定訪問名稱的 Pod。StatefulSet主要用來部署有狀態(tài)應(yīng)用,比如部署ZK、Kafka、MySQL、Redis等。
有狀態(tài)的資源通常由兩個(gè)組件構(gòu)成:Headless Service和StatefulSet。Headless Service用于為各個(gè)Pod資源分配唯一固定的標(biāo)識(shí),然后生成DNS 解析記錄。StatefulSet用于編排Pod 對象,并借助volumeClaimTemplate自動(dòng)為Pod資源創(chuàng)建專有的存儲(chǔ)。
數(shù)據(jù)的高可用是StatefulSet會(huì)極力保障的一個(gè)特性,不管是縮容還是擴(kuò)容的場景。StatefulSet控制器不支持并行擴(kuò)縮容機(jī)制,它一次只啟動(dòng)或者終止一個(gè)Pod 資源,避免數(shù)據(jù)錯(cuò)誤。
StatefulSet、volumeClaimTemplate、PVC、PV的關(guān)系見下圖:
3.2、StatefulSet特性
有序性
StatefulSet借助 Headless Service 為每個(gè) Pod資源分配唯一固定的標(biāo)識(shí),一般是在Pod名稱后面添加-0、-1、-2、...等等,。假設(shè)設(shè)置副本數(shù)replicas=2,啟動(dòng)時(shí),先啟動(dòng)pod-0再啟動(dòng)pod-1,停止時(shí)則以相反的順序進(jìn)行,先停止pod-1再停止pod-0。
有狀態(tài)
無狀態(tài)應(yīng)用沒有固定標(biāo)識(shí),他們不受其他Pod影響,同樣模板創(chuàng)建的任意Pod就可以替換之前的Pod。
有狀態(tài)應(yīng)用有固定的名稱和存儲(chǔ),會(huì)受到同一組內(nèi)的其他Pod的影響。Pod對象如果被替換,新的Pod仍然具有相同的標(biāo)識(shí)和相同的存儲(chǔ)。
StatefulSet使用存儲(chǔ)卷模板為每個(gè) Pod 對象創(chuàng)建專用的 PVC存儲(chǔ)卷,通過volumeClaimTemplate自動(dòng)創(chuàng)建綁定的存儲(chǔ)PVC不變。
刪除 Pod 對象并不會(huì)刪除相關(guān)的 PV 資源,如果Pod 對象由于節(jié)點(diǎn)故障等原因被重新調(diào)度到其他節(jié)點(diǎn)時(shí),之前同名Pod實(shí)例專用的 PV數(shù)據(jù)可以繼續(xù)復(fù)用。
穩(wěn)定服務(wù)發(fā)現(xiàn)
因?yàn)槭怯袪顟B(tài)的,所以想找到自己想找到的Pod,可以直接通過pod名稱.svc名稱.命名空間.svc.cluster.local訪問。
4、Yaml示例
示例部署一個(gè)Headless Service + StatefulSet,比如部署一個(gè)帶有存儲(chǔ)的nginx服務(wù)。文中使用到了volumeClaimTemplates,前提要?jiǎng)?chuàng)建一個(gè)storageClassName。后面會(huì)單獨(dú)寫一篇講解PV、PVC、StorageClass、Provisioner。
apiVersion: v1
kind: Service
metadata:
name: nginx-statefulset-svc
namespace: dev
spec:
# ClusterIP | NodePort | LoadBalancer
type: ClusterIP
# headless service 這里的clusterIP使用None
clusterIP: None
selector:
app: nginx-statefulset-tpl
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx-statefulset
namespace: dev
labels:
app: nginx-statefulset
spec:
replicas: 2
serviceName: nginx-statefulset-svc
selector:
matchLabels:
app: nginx-statefulset-tpl
template:
metadata:
labels:
app: nginx-statefulset-tpl
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
# volumeClaimTemplates是StatefulSet獨(dú)有的配置,前提要先創(chuàng)建一個(gè)storageClassName
volumeClaimTemplates:
- metadata:
name: www
spec:
resources:
requests:
storage: 200Mi
accessModes:
- ReadWriteOnce
storageClassName: nfs-client
5、總結(jié)
一句話總結(jié):Headless服務(wù)就是一組Pod組成的只供集群內(nèi)訪問(沒有ClusterIP)的Service,一般結(jié)合StatefulSet用于部署有狀態(tài)應(yīng)用的場景。
既然是Headless Service,那首先它是Service,一般的Service能被內(nèi)部和外部訪問。之所以叫Headless Service是因?yàn)橹粚?nèi)提供訪問。既然只對內(nèi)訪問,那肯定就需要提供穩(wěn)定的訪問能力了,否則就沒什么作用了。比如說擁有固定的Pod名稱和存儲(chǔ),所以一般會(huì)結(jié)合StatefulSet一起使用,用來部署有狀態(tài)的應(yīng)用。