【K8S】Service服務詳解,看這一篇就夠了!!

冰河團隊發表於2020-06-19

k8s用名稱空間namespace把資源進行隔離,預設情況下,相同的名稱空間裡的服務可以相互通訊,反之進行隔離。

1.1 Service

Kubernetes中一個應用服務會有一個或多個例項(Pod,Pod可以通過rs進行多複本的建立),每個例項(Pod)的IP地址由網路外掛動態隨機分配(Pod重啟後IP地址會改變)。為遮蔽這些後端例項的動態變化和對多例項的負載均衡,引入了Service這個資源物件,如下所示:

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

根據建立Service的type型別不同,可分成4種模式:

  • ClusterIP: 預設方式。根據是否生成ClusterIP又可分為普通Service和Headless Service兩類:
    • 普通Service:通過為Kubernetes的Service分配一個叢集內部可訪問的固定虛擬IP(Cluster IP),實現叢集內的訪問。為最常見的方式。
    • Headless Service:該服務不會分配Cluster IP,也不通過kube-proxy做反向代理和負載均衡。而是通過DNS提供穩定的絡ID來訪問,DNS會將headless service的後端直接解析為podIP列表。主要供StatefulSet使用。
  • 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服務會給叢集內的服務名 ..svc.cluster.local 建立一個CNAME記錄,其值為指定的"my.database.example.com"。
當查詢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主要是指不分配Service IP,且不通過kube-proxy做反向代理和負載均衡的服務。

1.2 Port

Service中主要涉及三種Port: * port 這裡的port表示service暴露在clusterIP上的埠,clusterIP:Port 是提供給叢集內部訪問kubernetes服務的入口。

  • targetPort

containerPort,targetPort是pod上的埠,從port和nodePort上到來的資料最終經過kube-proxy流入到後端pod的targetPort上進入容器。

  • nodePort

nodeIP:nodePort 是提供給從叢集外部訪問kubernetes服務的入口。

總的來說,port和nodePort都是service的埠,前者暴露給從叢集內訪問服務,後者暴露給從叢集外訪問服務。從這兩個埠到來的資料都需要經過反向代理kube-proxy流入後端具體pod的targetPort,從而進入到pod上的容器內。

1.3 IP

使用Service服務還會涉及到幾種IP:

  • ClusterIP

Pod IP 地址是實際存在於某個網路卡(可以是虛擬裝置)上的,但clusterIP就不一樣了,沒有網路裝置承載這個地址。它是一個虛擬地址,由kube-proxy使用iptables規則重新定向到其本地埠,再均衡到後端Pod。當kube-proxy發現一個新的service後,它會在本地節點開啟一個任意埠,建立相應的iptables規則,重定向服務的clusterIP和port到這個新建的埠,開始接受到達這個服務的連線。

  • Pod IP

Pod的IP,每個Pod啟動時,會自動建立一個映象為gcr.io/google_containers/pause的容器,Pod內部其他容器的網路模式使用container模式,並指定為pause容器的ID,即:network_mode: "container:pause容器ID",使得Pod內所有容器共享pause容器的網路,與外部的通訊經由此容器代理,pause容器的IP也可以稱為Pod IP。

  • 節點IP

Node-IP,service物件在Cluster IP range池中分配到的IP只能在內部訪問,如果服務作為一個應用程式內部的層次,還是很合適的。如果這個service作為前端服務,準備為叢集外的客戶提供業務,我們就需要給這個服務提供公共IP了。指定service的spec.type=NodePort,這個型別的service,系統會給它在叢集的各個代理節點上分配一個節點級別的埠,能訪問到代理節點的客戶端都能訪問這個埠,從而訪問到服務。

 

相關文章