1. 程式人生 > >Kubernetes Service配置資訊詳解

Kubernetes Service配置資訊詳解

Servicekubernetes最核心的概念,通過建立Service,可以為一組具有相同功能的容器應用提供一個統一的入口地址,並且將請求進行負載分發到後端的各個容器應用上。

Service服務是一個虛擬概念,邏輯上代理後端pod。眾所周知,pod生命週期短,狀態不穩定,pod異常後新生成的pod ip會發生變化,之前pod的訪問方式均不可達。通過servicepod做代理,service有固定的ipportip:port組合自動關聯後端pod,即使pod發生改變,kubernetes內部更新這組關聯關係,使得service能夠匹配到新的pod。這樣,通過service提供的固定ip

,使用者再也不用關心需要訪問哪個pod,以及pod是否發生改變,大大提高了服務質量。如果pod使用rc建立了多個副本,那麼service就能代理多個相同的pod,通過kube-proxy,實現負載均衡。

叢集中每個Node節點都有一個元件kube-proxy,實際上是為service服務的,通過kube-proxy,實現流量從servicepod的轉發,kube-proxy也可以實現簡單的負載均衡功能。

kube-proxy代理模式:userspace方式kube-proxy在節點上為每一個服務建立一個臨時埠,serviceIP:port過來的流量轉發到這個臨時埠上,kube-proxy

會用內部的負載均衡機制(輪詢),選擇一個後端pod,然後建立iptables,把流量匯入這個pod裡面。

Service定義詳解

yaml格式的Service定義檔案的完整內容:

apiVersion: v1
kind: Service
matadata:
  name: string
  namespace: string
  labels:
    - name: string
  annotations:
    - name: string
spec:
  selector: []
  type: string
  clusterIP: string
  sessionAffinity: string
ports: - name: string protocol: string port: int targetPort: int nodePort: int status: loadBalancer: ingress: ip: string hostname: string

這裡寫圖片描述

負載分發策略

目前kubernetes提供了兩種負載分發策略:RoundRobin和SessionAffinity

RoundRobin:輪詢模式,即輪詢將請求轉發到後端的各個Pod上

SessionAffinity:基於客戶端IP地址進行會話保持的模式,第一次客戶端訪問後端某個Pod,之後的請求都轉發到這個Pod上

預設是RoundRobin模式

在某些場景中,開發人員希望自己控制負載均衡的策略,不使用Service提供的預設負載,kubernetes通過Headless Service的概念來實現。不給Service設定ClusterIP(無入口IP地址):

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
  clusterIP: None
  selector:
    app: nginx

有時候,一個容器應用提供多個埠服務:

apiVersion: v1
kind: Service
metadata:
  name: webapp
spec:
  ports:
  - port: 8080
    targetPort: 8080
    name: web
  - port: 8005
    targetPort: 8005
    name: management
  selector:
    app: webapp

為不同的應用分配各自的埠。

另一個例子是兩個埠使用了不同的4層協議,即TCP或UDP

apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 169.169.0.100
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP

叢集外部訪問Pod或Service

為了讓外部客戶端可以訪問這些服務,可以將Pod或者Service的埠號對映到宿主主機,使得客戶端應用能夠通過物理機訪問容器應用。

將容器應用的埠號對映到物理機

通過設定容器級別的hostPort,將容器應用的埠號對映到物理機上:

pod-hostport.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: webapp
  labels:
    app: webapp
spec:
  containers:
  - name: webapp
    image: tomcat
    ports:
    - containerPort: 8080
      hostPort:8081

通過kubectl create建立這個Pod:

kubectl create -f pod-hostport.yaml

通過物理機的IP地址和8081埠號訪問Pod內的容器服務:

curl 10.0.11.151:8081

通過設定Pod級別的hostNetwork=true

通過設定Pod級別的hostNetwork=true,該Pod中所有容器的埠號都將被直接對映到物理機上,設定hostWork=true是需要注意,在容器的ports定義部分如果不指定hostPort,則預設hostPort等於containerPort,如果指定了hostPort,則hostPort必須等於containerPort的值。

pod-hostnetwork.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: webapp
  labels:
    app: webapp
spec:
  hostNetwork: true
  containers:
  - name: webapp
    image: tomcat
    imagePullPolicy: Never
    ports:
    - containerPort: 8080

建立這個Pod:

kubectl create -f pod-hostnetwork.yaml

通過物理機的IP地址和8080埠訪問Pod的容器服務:

curl 10.0.11.151:8080

將Service的埠號對映到物理機

通過設定nodePort對映到物理機,同時設定Service的型別為NodePort:

webapp-svc-nodeport.yaml:

apiVersion: v1
kind: Service
metadata:
  name: webapp
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 8081
  selector:
    app: webapp

建立這個Service:

kubectl create -f webapp-svc-nodeport.yaml

通過物理機的IP和埠訪問:

curl 10.0.11.151:8081

如果訪問不通,檢視下物理機的防火牆設定。同樣,對該Service的訪問也將被負載分發到後端多個Pod上