Kubernetes對象之Service

系列目錄html

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

  • Pod IP僅僅是集羣內可見的虛擬IP,外部沒法訪問。nginx

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

所以,Kubernetes中的Service對象就是解決以上問題的核心關鍵。數據庫

Service的建立

Service能夠看做是一組提供相同服務的Pod對外的訪問接口。藉助Service,應用能夠方便地實現服務發現和負載均衡json

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描述文件:api

  • 經過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的值。session

  • 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 影響了客戶端輸入

相關文章
相關標籤/搜索