Kubernetes對象之Service


系列目錄

通過ReplicaSet來創建一組Pod來提供具有高可用性的服務。雖然每個Pod都會分配一個單獨的Pod IP,然而卻存在如下兩問題:

  • Pod IP僅僅是集群內可見的虛擬IP,外部無法訪問。

  • Pod IP會隨着Pod的銷毀而消失,當ReplicaSet對Pod進行動態伸縮時,Pod IP可能隨時隨地都會變化,這樣對於我們訪問這個服務帶來了難度。

因此,Kubernetes中的Service對象就是解決以上問題的核心關鍵。

Service的創建

Service可以看作是一組提供相同服務的Pod對外的訪問接口。借助Service,應用可以方便地實現服務發現和負載均衡

Service同其他Kubernetes對象一樣,也是通過yaml或json文件進行定義。此外,它和其他Controller對象一樣,通過Label Selector來確定一個Service將要使用哪些Pod。一個簡單的Service定義如下:

apiVersion: v1
kind: Service
metadata:
  labels:
    run: nginx
  name: nginx-service
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 81
  selector:
    app: nginx
  type: ClusterIP

下面簡單分析一下上面的Service描述文件:

  • 通過spec.selector字段確定這個Service將要使用哪些Label。在本例中,這個名為nginx的Service,將會管理所有具有app: nginxLabel的Pod。

  • spec.ports.port: 80表明此Service將會監聽80端口,並將所有監聽到的請求轉發給其管理的Pod。spec.ports.targetPort: 81表明此Service監聽到的80端口的請求都會被轉發給其管理的Pod的81端口,此字段可以省略,省略后其值會被設置為spec.ports.port的值。

  • type: ClusterIP表面此Service的type,會在下文中講到。

Service的類型

在Serive定義時,我們需要指定spec.type字段,這個字段擁有四個選項:

  • ClusterIP。默認值。給這個Service分配一個Cluster IP,它是Kubernetes系統自動分配的虛擬IP,因此只能在集群內部訪問。

  • NodePort將Service通過指定的Node上的端口暴露給外部。通過此方法,訪問任意一個NodeIP:nodePort都將路由到ClusterIP,從而成功獲得該服務。

  • LoadBalancer。在 NodePort 的基礎上,借助 cloud provider 創建一個外部的負載均衡器,並將請求轉發到 :NodePort。此模式只能在雲服務器(AWS等)上使用。

  • ExternalName。將服務通過 DNS CNAME 記錄方式轉發到指定的域名(通過 spec.externlName 設定)。需要 kube-dns 版本在 1.7 以上。

注:kubernetes 1.13以后默認集群coreDns,不再使用默認kube-dns,對ExternalName支持情況需要進一步確認

NodePort類型

在定義Service時指定spec.type=NodePort,並指定spec.ports.nodePort的值,Kubernetes就會在集群中的每一個Node上打開你定義的這個端口,這樣,就能夠從外部通過任意一個NodeIP:nodePort訪問到這個Service了。

下面是一個簡單的例子:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    run: nginx
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    nodePort: 30001
  type: NodePort

假如有3個app: nginx Pod運行在3個不同的Node中,那么此時客戶端訪問任意一個Node的30001端口都能訪問到這個nginx服務。

LoadBalancer類型

如果雲服務商支持外接負載均衡器,則可以通過spec.type=LoadBalancer來定義Service,一個簡單的例子如下:

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
  clusterIP: 10.0.171.239
  loadBalancerIP: 78.11.24.19
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 146.148.47.155

Service without selector

Service可以抽象訪問Pod集群,同時 Service也可以抽象其他后端

  • 在生產環境中使用外部數據庫,在測試環境中使用自己的數據庫

  • 將自己的Service指向其他集群或者其他命名空間的Service

  • 遷移應用到k8s,但是還是有些應用運行在k8s之

通過定義不包含selector的Service實現

kind: service
apiVersion: v1
metadata:
  name: my-service
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

Service 沒有Selector,K8s不會創建Endpoints,你可以通過手動創建Endpoint指向自己的endpoint

kind: Endpoints
apiVersion: v1
metadata:
  name: my-service
  subsets:
   - addresses:
      ip: 1.2.3.4
   - ports:
      port: 9376

Endpoint的IP不能是loopback(127.0.0.1/8),link-local(169.254.0.0/16), link-local
multicast (224.0.0.0/24).

訪問不含有selector的Service和訪問含有Selector的Service 方式一樣,都會講流向重定向的endpoint

其他命名空間的服務是一個特例,他不會定義ports和endpoint,他只是返回一個訪問外部服務的別名

其它名稱空間

其他命名空間的服務是一個特例,他不會定義ports和endpoint,他只是返回一個訪問外部服務的別名

kind: kind
apiVersion: v1
metadata:
  name: my-service
  namespace: prod
  spec:
    type: ExternalName
    externalName: my.database.example.com

當你訪問服務my-service.prod.svc.CLUSTER時,cluster的dns服務會返回記錄my.database.example.com 的CNAME,這個重定向是發生在dns解析階段。

虛擬IP 和服務代理

代理

K8s集群內每個節點都會運行kube-proxy,負責實現服務的虛擬機IP(不是externalName)。1.0版本的代理模式在是userspace,1.1增加了iptables proxy,從1.2開始 iptables 代理是默認的模式

K8s 1.0的service是三層(TCP/UDP),從k8s1.1開始,增加了Ingress,實現七層(HTTP)服務

用戶空間的代理模式

Kube-proxy監控k8s master節點來發現Service、Endpointd的增加和刪除,對於Service,在本地打開一個隨機端口作為代理端口,任何訪問改代理端口的連接都會被指向Service對象的Pod集合,最終指向哪個Pod取決於Service的SessionAffinity,最后,他會配置iptables,捕獲流向Service 的Cluster IP 和Port的連接,並重定向到這個代理端口。

最終結果,任何到Service Cluster Ip 和port的流量都會指向合適的Pod

默認情況下,都是輪訓算法選擇后端,也可以通過設置service.spec.sessionAffinity 為ClientIP,將選擇算法改為Client-IP based session affinity

Iptables的代理模式

該模式與userspace模式類似,只是沒有這個代理端口

比userspace方式更快更可靠,然后與userspace方式不同,當選擇的pod異常時,該方式無法自動嘗試選擇其他Pod。

  • userspace模式只不適合大規模集群使用(數千個服務)

  • userspace模式隱藏了訪問服務的源IP,iptables模式雖然沒有隱藏源IP,但是也是通過負載均衡或者nodeport 影響了客戶端輸入


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM