- Service資源概述
- 創建Service資源
- 向Service物件請求服務
- Service會話粘性
- 服務發現
- 服務暴露
- Ingress和Ingress Controller
- Ingress資源
- Ingress控制器
Service資源概述
Service是Kubernetes的核心資源型別之一,它通過規則定義出由多個Pod物件組合而成的邏輯集合,以及訪問這組Pod的策略,
由Deployment等控制器管理的Pod物件在中斷或擴縮容后,Pod組合的IP地址都會發生變化,而引入Service資源后,就可以基于標簽選擇器將一組Pod定義成一個邏輯組合,并通過自己的IP地址和埠調度代理請求至組內的Pod物件之上,它向客戶端隱藏了真實的、處理用戶請求的Pod資源,使得客戶端的請求看上去就像是由Service直接處理并進行回應的一樣,而且Service與Pod物件之間通過標簽選擇器以松耦合的方式關聯,它可以先于Pod物件創建而不會發生錯誤,
創建Service資源
Service資源基本的配置清單:
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
spec:
selector:
app: myapp
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
Service資源myapp-svc通過標簽選擇器關聯至標簽為“app=myapp”的各Pod物件,它會自動創建名為myapp-svc的Endpoints資源物件,并自動配置一個ClusterIP,暴露的埠由port欄位進行指定,后端各Pod物件的埠則由targetPort給出,
分別查看service和endpoint的狀態:
kubectl get svc myapp-svc
kubectl get endpoints myapp-svc
向Service物件請求服務
Service資源的默認型別為ClusterIP,它僅能接收來自于集群中的Pod物件中的客戶端程式的訪問請求,所以為了測驗,會創建一個專用的Pod物件,利用其互動式介面來訪問service資源,
kubectl run cirros-$RANDOM --rm -it --image=cirros -- sh
啟動了一個運行CirrOS容器的Pod,CirrOS是設計用來進行云計算環境測驗的Linux微型發行版,它自帶HTTP客戶端工具curl等,
在容器的互動式介面訪問ClusterIP:Port
/ # curl http://10.105.246.145:80
Hello MyApp | Version: v1 | <a href="https://www.cnblogs.com/zhixin9001/p/hostname.html">Pod Name</a>
Kubernetes集群默認的Service代理模式為iptables,而且使用隨機調度演算法,因此Service會將客戶端請求隨機調度至與其關聯的某個后端Pod資源上,
Service會話粘性
Service資源還支持Session affinity(會話粘性)機制,它能夠將來自同一個客戶端的請求始終轉發至同一個后端的Pod物件,適用于需要基于客戶端身份保存某些私有資訊,并根據這些私有資訊追蹤用戶的活動等一類的需求,
Service資源通過spec.sessionAffinity和spec.sessionAffinityConfig兩個欄位配置粘性會話:
- sessionAffinity欄位用于定義要使用的粘性會話的型別,它僅支持使用“None”和“ClientIP”兩種屬性值,?
- None:不使用sessionAffinity,默認值,?
- ClientIP:基于客戶端IP地址識別客戶端身份,把來自同一個源IP地址的請求始終調度至同一個Pod物件,
- sessionAffinityConfig用于配置其會話保持的時長,其可用的時長范圍為“1~86400”,默認為10800秒
但是Service資源的Session affinity機制僅能基于客戶端IP地址識別客戶端身份,它會把經由同一個NAT服務器進行源地址轉換的所有客戶端識別為同一個客戶端,調度粒度粗糙且效果不佳,因此實踐中并不推薦使用此種方法實作粘性會話,
服務發現
Service為Pod中的服務類應用提供了一個穩定的訪問入口,但Pod客戶端中的應用如何得知某個特定Service資源的IP和埠呢,這就需要借助服務發現機制來進行,
服務發現機制的基本實作,一般是事先部署好一個網路位置較為穩定的服務注冊中心(也稱為服務總線),服務提供者(服務端)向注冊中心注冊自己的位置資訊,并在變動后及時予以更新,服務消費者則周期性地從注冊中心獲取服務提供者的最新位置資訊從而“發現”要訪問的目標服務資源,
在K8S中可以基于CoreDNS進行服務發現,甚至也可以使用簡單的環境變數方式,
服務暴露
Service的IP地址默認僅在集群內可達,集群外部想訪問服務,需要首先進行服務的暴露,
Service的型別
Service有四種類似ClusterIP、NodePort、LoadBalancer和ExternalName
- ClusterIP:通過集群內部IP地址暴露服務,此地址僅在集群內部可達,而無法被集群外部的客戶端訪問;
- NodePort:建立在ClusterIP型別之上,其在每個Node的IP地址的某靜態埠(NodePort)暴露服務,NodePort的路由目標為ClusterIP,簡單來說,NodePort型別就是在作業節點的IP地址上選擇一個埠用于將集群外部的用戶請求轉發至目標Service的ClusterIP和Port,這種型別的Service既可如ClusterIP一樣受到集群內部客戶端Pod的訪問,也會受到集群外部客戶端通過套接字NodeIP:NodePort進行的請求;
- LoadBalancer:建構在NodePort型別之上,其通過cloud provider提供的負載均衡器將服務暴露到集群外部,LoadBalancer型別的Service會指向關聯至Kubernetes集群外部的某個負載均衡設備,該設備通過作業節點之上的NodePort向集群內部發送請求流量,這種Service的優勢在于,能夠把來自于集群外部客戶端的請求調度至所有節點(或部分節點)的NodePort之上,而不是依賴于客戶端自行決定連接至哪個節點,從而避免了因客戶端指定的節點故障而導致的服務不可用;
- ExternalName:通過將Service映射至由externalName欄位的內容指定的主機名來暴露服務,此主機名需要被DNS服務決議至CNAME型別的記錄,這種型別并非定義由Kubernetes集群提供的服務,而是把集群外部的某服務以DNS CNAME記錄的方式映射到集群內,從而讓集群內的Pod資源能夠訪問外部的Service的一種實作方式,這種型別的Service沒有ClusterIP和NodePort,也沒有標簽選擇器用于選擇Pod資源,
NodePort
NodePort型的Service資源,其配置清單與前面默認的ClusterIP型別類似,只是要顯式地在spec下指定type: NodePort
此外還可以指定Node埠,但必須在30000-32767之間,而且推薦使用集群自動分配的埠以避免埠的沖突,
LoadBalancer
NodePort型別的Service資源雖然能夠于集群外部訪問得到,但外部客戶端必須得事先得知NodePort和集群中至少一個節點的IP地址,且選定的節點發生故障時,客戶端還得自行選擇請求訪問其他的節點,此外有時節點并不允許外界訪問,LoadBalancer型別可將請求流量調度至各節點的NodePort之上,
創建LoadBalancer型別需要指定type: LoadBalancer,
ExternalName
ExternalName型別的Service資源用于將集群外部的服務發布到集群中以供Pod中的應用程式訪問,需要指定type: ExternalName和externalName,比如externalName: redis.ilinux.io,externalName屬性定義了一個CNAME記錄用于回傳外部真正提供服務的主機的別名,而后通過CNAME記錄值獲取到相關主機的IP地址,
spec:
type: ExternalName
externalName: redis.ilinux.io
服務創建后通過serviceName訪問相應的服務,ClusterDNS會將此名稱以CNAME格式決議為spec.externalName欄位中的名稱,而后通過DNS服務將其決議為相應的主機的IP地址,
Ingress和Ingress Controller
在Kubernetes中,Service資源和Pod資源的IP地址僅能用于集群網路內部的通信,所有的網路流量都無法穿透邊界路由器以實作集群內外通信,Kubernetes提供了兩種內建的云端負載均衡機制(cloud loadbalancing)用于發布公共應用:
- 一種是作業于傳輸層的Service資源,它實作的是“TCP負載均衡器”,無論是iptables還是ipvs模型的Service資源都配置于Linux內核中的Netfilter之上進行四層調度,是一種型別更為通用的調度器,支持調度HTTP、MySQL等應用層服務,
但由于作業于傳輸層而功能有局限,比如不支持基于URL的請求調度機制,而且Kubernetes也不支持為其配置任何型別的健康檢查, - 另一種便是Ingress資源,它實作的是“HTTP(S)負載均衡器”,屬于應用層負載均衡機制的一種,它提供了諸如可自定義URL映射和TLS卸載等功能,并支持多種型別的后端服務器健康狀態檢查機制,
Ingress是Kubernetes API的標準資源型別之一,它其實就是一組基于DNS名稱(host)或URL路徑把請求轉發至指定的Service資源的規則,用于將集群外部的請求流量轉發至集群內部完成服務發布,它僅是一組路由規則的集合,Ingress控制器根據這些規則來匹配并路由請求流量,
Ingress資源
Ingress資源是基于HTTP虛擬主機或URL的轉發規則,Ingress資源的定義方式舉例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: www.ilinux.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-svc
port:
number: 80
spec欄位下主要嵌套如下三個欄位
- rules,用于定義當前Ingress資源的轉發規則串列;未由rules定義規則,或者沒有匹配到任何規則時,所有流量都會轉發到由backend定義的默認后端,?
- backend,默認的后端用于服務那些沒有匹配到任何規則的請求;定義Ingress資源時,至少應該定義backend或rules兩者之一;此欄位用于讓負載均衡器指定一個全域默認的后端,backend物件的定義由兩個必選的內嵌欄位組成:serviceName和servicePort,分別用于指定流量轉發的后端目標Service資源的名稱和埠,?
- tls,TLS配置,目前僅支持通過默認埠443提供服務;如果要配置指定的串列成員指向了不同的主機,則必須通過SNI TLS擴展機制來支持此功能,
Ingress資源型別
單Service資源型Ingress
暴露單個Service的方法可以使用NodePort、LoadBalancer,也可以使用Ingress來暴露服務,只需要為Ingress指定“default backend”,這樣Ingress控制器會為其分配一個IP地址接入請求流量,并將它們轉至指定的后段service,如:
spec:
backend:
serviceName: my-svc
servicePort: 80
基于URL路徑進行流量分發
Ingress也支持基于URL路徑進行流量分發,如:
spec:
rules:
- host: www.ilinux.io
http:
paths:
- path: /web
backend:
service:
name: myapp-svc-web
port:
number: 80
- path: /api
backend:
service:
name: myapp-svc-api
port:
number: 80
上面定義的規則會將對www.ilinux.io/web的請求轉發到前端service myapp-svc-web,而將www.ilinux.io/api請求轉發到后段service myapp-svc-api,
基于主機名稱的虛擬主機
如果服務按照域名進行劃分,可以將Ingress基于虛擬主機定義如下:
spec:
rules:
- host: web.ilinux.io
...
- host: api.ilinux.io
TLS型別的Ingress資源
如果需要以HTTPS發布Service資源,也可以配置TLS協議的Ingress資源,但需要基于一個含有私鑰和證書的Secret物件,這在后面的章節會涉及到,在Ingress資源中參考此Secret即可讓Ingress控制器加載并配置為HTTPS服務:
spec:
tls:
- secretName: ilinuxSecret
backend:
...
Ingress控制器
Ingress控制器自身是運行于Pod中的容器應用,一般是Nginx或Envoy一類的具有代理及負載均衡功能的守護行程,它監視著來自于API Server的Ingress物件狀態,并以其規則生成相應的應用程式專有格式的組態檔并通過多載或重啟守護行程而使新配置生效,例如,對于Nginx來說,Ingress規則需要轉換為Nginx的配置資訊,
既然Ingress控制器實際上也是Pod資源,那么也需要接入外部流量,這可以使用NodePort或LoadBalancer型別的Service物件為其接入集群外部的請求流量;或者借助于DaemonSet控制器,將Ingress控制器的Pod資源各自以單一實體的方式運行于集群的所有或部分作業節點之上,并配置這類Pod物件以hostPort或hostNetwork的方式在當前節點接入外部流量,
以部署ingress-nginx并通過專用的Service接入流量為例:
首先apply在線的mandatory.yaml來部署ingress-nginx所需的全部資源,它們的namespace:為ingress-nginx:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.1/deploy/mandatory.yaml
然后定義專用的NodePort型Service資源,注意其selector要與nginx-ingress-controller的selector保持一致:
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: NodePort
selector:
app.kubernetes.io/name: ingress-nginx
ports:
- port: 80
name: http
nodePort: 30080
- port: 443
name: https
nodePort: 30443
然后就可以通過這個NodePort型Serviced的IP:30002訪問了,或者也可以根據ingress指定的host名稱配置etc/hosts,比如對于如下的ingress配置:
spec:
rules:
- host: tomcat.ilinux.io
sudo vim /etc/hosts,添加一行
127.0.0.1 tomcat.ilinux.io
然后也就可以通過tomcat.ilinux.io:30002訪問了,
學習資料
《Kubernetes實戰進階》 馬永亮著
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/285968.html
標籤:其他
上一篇:某資料庫管理軟體離線注冊分析
