1. 程式人生 > 其它 >入門Kubernetes-Service

入門Kubernetes-Service

一、前言

 前一篇文章通過 Deployment 實現了Pod中服務實現滾動更新/回滾等操作;在真實應用場景中,需要將一組Pod提供給外部訪問。而且Pod生命週期是短暫的,在 Pod 的生命週期過程中,比如它建立或銷燬, IP 地址都會發生變化。不能使用傳統的部署方式使用IP方式訪問。

 所以需要將Deployment 建立的Pod組統一提供一個訪問入口,需要提供給外部的使用者去呼叫的。此時就需要服務發現。那麼在k8s中怎麼實現呢?—Service

二、服務-Service

 1、Service 的定義

  Service是 k8s 的核心資源型別之一,Service是將執行在一組Pods上的應用程式公開為網路服務的抽象方法。

  Service資源基於標籤選擇器將一組Pod定義成一個邏輯組合,並通過自己的IP地址和埠排程代理請求到組內的Pod物件

  

 2、Service 的工作方式

  在 k8s 叢集中,每個 Node 執行一個kube-proxy程序。kube-proxy負責為 Service 實現了一種 VIP(虛擬 IP)的形式,而不是ExternalName的形式。

  kube-proxy 這個元件始終監視著apiserver中有關service的變動資訊,獲取任何一個與service資源相關的變動狀態,通過watch監視,一旦有service資源相關的變動和建立,kube-proxy都要轉換為當前節點上的能夠實現資源排程規則(例如:iptables、ipvs)  

  • userspace 代理模式

  kube-proxy 會監視 Kubernetes 控制平面對 Service 物件和 Endpoints 物件的新增和移除操作。 對每個 Service,它會在本地 Node 上開啟一個埠(隨機選擇)。 任何連線到“代理埠”的請求,都會被代理到 Service 的後端Pods中的某個上面(如Endpoints所報告的一樣)。 使用哪個後端 Pod,是 kube-proxy 基於SessionAffinity來確定的。

  最後,它配置 iptables 規則,捕獲到達該 Service 的clusterIP(是虛擬 IP) 和Port的請求,並重定向到代理埠,代理埠再代理請求到後端Pod。

  預設情況下,使用者空間模式下的 kube-proxy 通過輪轉演算法選擇後端。

  

  • iptables 代理模式

  這種模式,kube-proxy會監視 Kubernetes 控制節點對 Service 物件和 Endpoints 物件的新增和移除。 對每個 Service,它會配置 iptables 規則,從而捕獲到達該 Service 的clusterIP和埠的請求,進而將請求重定向到 Service 的一組後端中的某個 Pod 上面。 對於每個 Endpoints 物件,它也會配置 iptables 規則,這個規則會選擇一個後端組合。

  預設的策略是,kube-proxy 在 iptables 模式下隨機選擇一個後端。

  使用 iptables 處理流量具有較低的系統開銷,因為流量由 Linux netfilter 處理, 而無需在使用者空間和核心空間之間切換。 這種方法也可能更可靠。

  如果 kube-proxy 在 iptables 模式下執行,並且所選的第一個 Pod 沒有響應, 則連線失敗。 這與使用者空間模式不同:在這種情況下,kube-proxy 將檢測到與第一個 Pod 的連線已失敗, 並會自動使用其他後端 Pod 重試。

  你可以使用 Pod就緒探測器驗證後端 Pod 可以正常工作,以便 iptables 模式下的 kube-proxy 僅看到測試正常的後端。 這樣做意味著你避免將流量通過 kube-proxy 傳送到已知已失敗的 Pod。

  

  • ipvs 代理模式

  在ipvs模式下,kube-proxy 監視 Kubernetes 服務和端點,呼叫netlink介面相應地建立 IPVS 規則, 並定期將 IPVS 規則與 Kubernetes 服務和端點同步。 該控制迴圈可確保IPVS 狀態與所需狀態匹配。訪問服務時,IPVS 將流量定向到後端Pod之一。

  IPVS代理模式基於類似於 iptables 模式的 netfilter 掛鉤函式, 但是使用雜湊表作為基礎資料結構,並且在核心空間中工作。 這意味著,與 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向通訊的延遲要短,並且在同步代理規則時具有更好的效能。 與其他代理模式相比,IPVS 模    式還支援更高的網路流量吞吐量。

  IPVS 提供了更多選項來平衡後端 Pod 的流量。 這些是:

    • rr:輪替(Round-Robin)
    • lc:最少連結(Least Connection),即開啟連結數量最少者優先
    • dh:目標地址雜湊(Destination Hashing)
    • sh:源地址雜湊(Source Hashing)
    • sed:最短預期延遲(Shortest Expected Delay)
    • nq:從不排隊(Never Queue)

  

 3、Service的使用

  a、服務型別:建立Service物件,指定型別為NodePort

apiVersion: v1
kind: Service           # 定義Kubernetes資源的型別為Service
metadata:
  name: k8sdemoweb-service     # 定義資源的名稱
spec:
  selector:             # 指定對應的Pod
    app: k8demosweb     # 指定Pod的標籤為k8sweb
  ports:
  - protocol: TCP       # 協議型別
    port: 80            # 指定Service訪問的埠
    targetPort: 80      # 指定Service轉發請求的埠
    nodePort: 31001
  type: NodePort        # 指定Service的型別,在這裡使用NodePort來對外訪問

  對一些應用的某些部分(如前端),可能希望將其暴露給 Kubernetes 叢集外部 的 IP 地址

  KubernetesServiceTypes允許指定你所需要的 Service 型別,預設是ClusterIP

  Type的取值以及行為如下:

    • ClusterIP:通過叢集的內部 IP 暴露服務,選擇該值時服務只能夠在叢集內部訪問。 這也是預設的ServiceType

    • NodePort:通過每個節點上的 IP 和靜態埠(NodePort)暴露服務。NodePort服務會路由到自動建立的ClusterIP服務。 通過請求<節點 IP>:<節點埠>,你可以從叢集的外部訪問一個NodePort服務。

    • LoadBalancer:使用雲提供商的負載均衡器向外部暴露服務。 外部負載均衡器可以將流量路由到自動建立的NodePort服務和ClusterIP服務上。

    • ExternalName:通過返回CNAME和對應值,可以將服務對映到externalName欄位的內容(例如,foo.bar.example.com)。 無需建立任何型別代理。

  b、Headless Services(無頭服務)

   有時不需要或不想要負載均衡,以及單獨的 Service IP。 遇到這種情況,可以通過指定 Cluster IP(spec.clusterIP)的值為"None"來建立HeadlessService。

  • 帶選擇算符的服務

對定義了選擇算符的無頭服務,Endpoint 控制器在 API 中建立了 Endpoints 記錄, 並且修改 DNS 配置返回 A 記錄(IP 地址),通過這個地址直接到達Service的後端 Pod 上。

  • 無選擇算符的服務

對沒有定義選擇算符的無頭服務,Endpoint 控制器不會建立Endpoints記錄。 然而 DNS 系統會查詢和配置,無論是:

    • 對於ExternalName型別的服務,查詢其 CNAME 記錄
    • 對所有其他型別的服務,查詢與 Service 名稱相同的任何Endpoints的記錄

三、使用Service訪問應用:

 訪問在前面建立的服務:由於本機IP為:192.168.0.109,直接訪問192.168.0.109:31001 時,直接訪問失敗。安裝Service型別的描述,該Service型別為NodePort;應該就可以直接訪問成功。

 但由於本機的k8s環境是使用:minikube 執行在Docker環境中。真實的k8s Node不是本機,導致訪問失敗。

 啟動服務訪問:

//開啟服務訪問
PS > minikube service  k8sdemoweb-service
|-----------|--------------------|-------------|---------------------------|
| NAMESPACE |        NAME        | TARGET PORT |            URL            |
|-----------|--------------------|-------------|---------------------------|
| default   | k8sdemoweb-service |          80 | http://192.168.49.2:31001 |
|-----------|--------------------|-------------|---------------------------|
* Starting tunnel for service k8sdemoweb-service.
|-----------|--------------------|-------------|------------------------|
| NAMESPACE |        NAME        | TARGET PORT |          URL           |
|-----------|--------------------|-------------|------------------------|
| default   | k8sdemoweb-service |             | http://127.0.0.1:29752 |
|-----------|--------------------|-------------|------------------------|
* 正通過預設瀏覽器開啟服務 default/k8sdemoweb-service...
! Because you are using a Docker driver on windows, the terminal needs to be open to run it.

 訪問地址:http://127.0.0.1:29752

   

  通過上圖看到,訪問應用通過Service負載到不同的Pod節點上。

  

四、參考 
 https://kubernetes.io/zh/docs/concepts/services-networking/service/