Kubernetes中Service機制

post200發表於2021-09-09

Service

Pod的IP是在docker0網段動態分配的,當發生重啟,擴容等操作時,IP地址會隨之變化。當某個Pod(frontend)需要去訪問其依賴的另外一組Pod(backend)時,如果backend的IP發生變化時,如何保證fronted到backend的正常通訊變的非常重要。由此,引出了Service的概念。

這裡docker0是一個網橋,docker daemon啟動container時會根據docker0的網段來劃粉container的IP地址

在實際生產環境中,對Service的訪問可能會有兩種來源:Kubernetes叢集內部的程式(Pod)和Kubernetes叢集外部,為了滿足上述的場景,Kubernetes service有以下三種型別:

  • ClusterIP:提供一個叢集內部的虛擬IP以供Pod訪問。

  • NodePort:在每個Node上開啟一個埠以供外部訪問。

  • LoadBalancer:透過外部的負載均衡器來訪問。

ClusterIP && NodePort && LoadBalancer

1. ClusterIP

此模式會提供一個叢集內部的虛擬IP(與Pod不在同一網段),以供叢集內部的pod之間通訊使用。
ClusterIP也是Kubernetes service的預設型別。

圖片描述

service-network.png

為了實現圖上的功能主要需要以下幾個元件的協同工作

  • apiserver 使用者透過kubectl命令向apiserver傳送建立service的命令,apiserver接收到請求以後將資料儲存到etcd中。

  • kube-proxy kubernetes的每個節點中都有一個叫做kube-proxy的程式,這個程式負責感知service,pod的變化,並將變化的資訊寫入本地的iptables中。

  • iptables 使用NAT等技術將virtualIP的流量轉至endpoint中。

下面我們實際釋出一個Service,能夠更清晰的瞭解到Service是如何工作的。

1.1 釋出一個rc,並指定replices count為3.

yancey@ yancey-macbook kubernetes-1$kubectl create -f rc_nginx.yaml
yancey@ yancey-macbook kubernetes-1$kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
k8s-master-core-v2-01    4/4       Running   0          8m
k8s-proxy-core-v2-01     1/1       Running   0          8m
nginx-controller-6bovu   1/1       Running   0          4m
nginx-controller-iowux   1/1       Running   0          4m
nginx-controller-o7m6u   1/1       Running   0          4m
yancey@ yancey-macbook kubernetes-1$kubectl describe pod nginx-controller-6bovu
Name:       nginx-controller-6bovu
Namespace:  default
Node:       core-v2-01/172.17.8.101
Start Time: Fri, 17 Jun 2016 15:22:20 +0800
Labels:     app=nginx
Status:     Running
IP:     10.1.13.3
Controllers:    ReplicationController/nginx-controller

1.2. 釋出一個service,並指定步驟1中的label。

yancey@ yancey-macbook kubernetes-1$kubectl create -f service_nginx.yaml
yancey@ yancey-macbook kubernetes-1$kubectl get svc
NAME            CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes      10.0.0.1     <none>        443/TCP    9m
nginx-service   10.0.0.252   <none>        8000/TCP   4m

kubernetes為nginx-server這個service建立了一個10.0.0.252這個ClusterIP,也可以稱為VirtualIP.

yancey@ yancey-macbook kubernetes-1$kubectl get ep
NAME            ENDPOINTS                                AGE
kubernetes      172.17.8.101:6443                        9m
nginx-service   10.1.13.2:80,10.1.13.3:80,10.1.13.4:80   4m

檢視endpoint資訊,發現nginx-service一共有三個endpoint地址,分別對應nginx的三個pod。

1.3. 檢視iptables,觀察其NAT表中的資訊(只擷取了部分和這個service有關的資訊)

檢視iptables中NAT表的命令:iptables -L -v -n -t nat

Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination   37  2766 KUBE-SERVICES  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */
   33  2112 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

在PREROUTING鏈中會先匹配到KUBE-SERVICES這個Chain。

Chain KUBE-SERVICES (2 references)
 pkts bytes target     prot opt in     out     source               destination    0     0 KUBE-SVC-GKN7Y2BSGW4NJTYL  tcp  --  *      *       0.0.0.0/0            10.0.0.252           /* default/nginx-service: cluster IP */ tcp dpt:8000
   18  1080 KUBE-NODEPORTS  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL

所有destinationIP為10.0.0.252的包都轉到KUBE-SVC-GKN7Y2BSGW4NJTYL這個Chain

Chain KUBE-SVC-GKN7Y2BSGW4NJTYL (1 references)
 pkts bytes target     prot opt in     out     source               destination    0     0 KUBE-SEP-7ROBBXFV7SD4AIRW  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/nginx-service: */ statistic mode random probability 0.33332999982
    0     0 KUBE-SEP-XY3F6VJIZ7ELIF4Z  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/nginx-service: */ statistic mode random probability 0.50000000000
    0     0 KUBE-SEP-JIDZHFC4A3T535AK  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/nginx-service: */

這裡能看到請求會平均執行KUBE-SEP-7ROBBXFV7SD4AIRW,KUBE-SEP-XY3F6VJIZ7ELIF4Z,KUBE-SEP-XY3F6VJIZ7ELIF4Z這三個Chain.最後我們看下KUBE-SEP-7ROBBXFV7SD4AIRW這個Chain做了什麼

Chain KUBE-SEP-7ROBBXFV7SD4AIRW (1 references)
 pkts bytes target     prot opt in     out     source               destination    0     0 KUBE-MARK-MASQ  all  --  *      *       10.1.13.2            0.0.0.0/0            /* default/nginx-service: */
    0     0 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/nginx-service: */ tcp to:10.1.13.2:80

這個Chain使用了DNAT規則將流量轉發到10.1.13.2:80這個地址。至此從Pod發出來的流量透過本地的iptables將流量轉至了service背後的pod上。

2. NodePort

Kubernetes將會在每個Node上開啟一個埠並且每個Node的埠都是一樣的,透過<NodeIP>:NodePort的方式Kubernetes叢集外部的程式可以訪問Service。

修改kubernetes/service_nginx.yaml,將Service的type改為NodePort型別。

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:  type: NodePort
  ports:
  - port: 8000
    targetPort: 80
    protocol: TCP  # just like the selector in the replication controller,
  # but this time it identifies the set of pods to load balance
  # traffic to.
  selector:
    app: nginx

釋出這個service,可以看到已經隨機分配了一個NodePort埠。

yancey@ yancey-macbook kubernetes-1$kubectl get svc nginx-service -o yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: 2016-06-18T03:29:42Z
  name: nginx-service  namespace: default
  resourceVersion: "1405"
  selfLink: /api/v1/namespaces/default/services/nginx-service
  uid: e50ba23a-3504-11e6-a94f-080027a75e9e
spec:
  clusterIP: 10.0.0.229
  ports:
  - nodePort: 30802
    port: 8000
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}

觀察Iptables中的變化,KUBE-NODEPORTS這個Chain中增加了如下內容

Chain KUBE-NODEPORTS (1 references)
 pkts bytes target     prot opt in     out     source               destination    0     0 KUBE-MARK-MASQ  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/nginx-service: */ tcp dpt:30802
    0     0 KUBE-SVC-GKN7Y2BSGW4NJTYL  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/nginx-service: */ tcp dpt:30802

可以看到流量會轉至KUBE-SVC-GKN7Y2BSGW4NJTYL這個Chain中處理一次,也就是ClusterIP中提到的透過負載均衡將流量平均分配到3個endpoint上。

3. LoadBalancer

待補充。

服務發現

當釋出一個服務之後,我們要使用這個服務,第一個問題就是要拿到這些服務的IP和PORT,kubernetes提供兩種方式以便在程式中去動態的獲取這些資訊。

  1. ENV環境變數
    在Pod其中之後,kubernetes會將現有服務的IP,PORT以環境變數的方式寫入pod中,程式只要讀取這些環境變數即可。

  2. DNS,程式中可以使用server的名稱對服務進行訪問,在程式啟時候,不必預先讀取環境變數中的內容。



作者:Yancey_BFD
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2249/viewspace-2820563/,如需轉載,請註明出處,否則將追究法律責任。

相關文章