Kubernetes:服務與負載均衡

不羈的羅恩發表於2022-03-16

Blog:部落格園 個人
參考:Service | Kubernetes、《Kubernetes進階實戰》

有了 Workload,我們可以方便地管理多例項的應用,但是要想能夠方便地訪問應用,我們還需要一個類似於 負載均衡 的資源來分發請求,在 kubernetes 中,有兩個資源負責這個功能,分別是 Service 以及 Ingress。其中 Service 主要負責叢集內部的訪問,而 Ingress 主要負責來自叢集外部的訪問。

Kubernetes Service從邏輯上代表了一組Pod(通常稱為微服務),具體是哪些Pod則是由label來挑選的(selector)。Service有自己的IP,而且這個IP是不變的。客戶端只需要訪問Service的IP,Kubernetes則負責建立和維護Service與Pod的對映關係。無論後端Pod如何變化,對客戶端不會有任何影響,因為Service沒有變。

舉個例子,考慮一個圖片處理後端,它執行了 3 個副本。這些副本是可互換的 —— 前端不需要關心它們呼叫了哪個後端副本。 然而組成這一組後端程式的 Pod 實際上可能會發生變化, 前端客戶端不應該也沒必要知道,而且也不需要跟蹤這一組後端的狀態。

Service 定義的抽象能夠解耦這種關聯。

Service型別

Service有4種型別:

  • ClusterIP:通過叢集的內部 IP 暴露服務,選擇該值時服務只能夠在叢集內部訪問。 這也是預設的 ServiceType
  • NodePort:通過每個節點上的 IP 和靜態埠(NodePort)暴露服務。 NodePort 服務會路由到自動建立的 ClusterIP 服務。 通過請求 <節點 IP>:<節點埠>,你可以從叢集的外部訪問一個 NodePort 服務。
  • LoadBalancer:使用雲提供商的負載均衡器向外部暴露服務。 外部負載均衡器可以將流量路由到自動建立的 NodePort 服務和 ClusterIP 服務上。
  • ExternalName:通過返回 CNAME 和對應值,可以將服務對映到 externalName 欄位的內容(例如,foo.bar.example.com)。 無需建立任何型別代理。

總體來說,若需要將Service資源釋出至叢集外部,應該將其配置為NodePort或Load-Balancer型別,而若要把外部的服務釋出於叢集內部供Pod物件使用,則需要定義一個ExternalName型別的Service資源,只是這種型別的實現要依賴於v1.7及更高版本的Kubernetes。

?Tips:Service的預設協議是 TCP。

代理模式(proxy mode)

代理模式分為3種:userspace、iptables和ipvs。

userspace代理模式

此處的userspace是指Linux作業系統的使用者空間。在這種模型中,kube-proxy負責跟蹤API Server上Service和Endpoints物件的變動(建立或移除),並據此調整Service資源的定義。

對於每個Service物件,它會隨機開啟一個本地埠(執行於使用者空間的kube-proxy程式負責監聽),任何到達此代理埠的連線請求都將被代理至當前Service資源後端的各Pod物件,至於哪個Pod物件會被選中則取決於當前Service資源的排程方式,預設排程演算法是輪詢(round-robin)

另外,此類Service物件還會建立iptables規則以捕獲任何到達ClusterIP和埠的流量。在Kubernetes 1.1版本之前,userspace是預設的代理模型。

image-20220316142655672

iptables代理模式

建立Service物件的操作會觸發叢集中的每個kube-proxy並將其轉換為定義在所屬節點上的iptables規則,用於轉發工作介面接收到的、與此Service資源ClusterIP和埠相關的流量。客戶端發來請求將直接由相關的iptables規則進行目標地址轉換(DNAT)後根據演算法排程並轉發至叢集內的Pod物件之上,而無須再經由kube-proxy程式進行處理,因而稱為iptables代理模式。

使用 iptables 處理流量具有較低的系統開銷,因為流量由 Linux netfilter 處理, 而無需在使用者空間和核心空間之間切換。 這種方法也可能更可靠。但是效能一般,而且受規模影響較大,僅適用於少量Service規模的叢集。

對於每個Endpoints物件,Service資源會為其建立iptables規則並指向其iptables地址和埠,而流量轉發到多個Endpoint物件之上的預設排程機制是隨機演算法。iptables代理模型由Kubernetes v1.1版本引入,並於v1.2版本成為預設的型別。

image-20220316144248272

ipvs代理模式

Kubernetes自v1.9版本起引入ipvs代理模式,且自v1.11版本起成為預設設定。在此種模型中,kube-proxy跟蹤API Server上Service和Endpoints物件的變動,並據此來呼叫netlink介面建立或變更ipvs(NAT)規則。

它與iptables規則的不同之處僅在於客戶端請求流量的排程功能由ipvs實現,餘下的其他功能仍由iptables完成。

image-20220316144658093

ipvs代理模型中Service的服務發現和負載均衡功能均基於核心中的ipvs規則實現。類似於iptables,ipvs也構建於核心中的netfilter之上,但它使用hash表作為底層資料結構且工作於核心空間,因此具有流量轉發速度快、規則同步效能好的特性,適用於存在大量Service資源且對效能要求較高的場景。

支援的排程演算法:

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

示例

建立一個 Nginx Pod:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80

然後執行:

kubectl apply -f ./run-nginx.yaml

檢視執行:

[root@master test]# kubectl get pods -l run=my-nginx -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP              NODE     NOMINATED NODE   READINESS GATES
my-nginx-5b56ccd65f-rnv9b   1/1     Running   0          34s   10.233.112.27   node-1   <none>           <none>
my-nginx-5b56ccd65f-rx2mq   1/1     Running   0          34s   10.233.112.26   node-1   <none>           <none>

檢查 Pod 的 IP 地址:

[root@master test]# kubectl get pods -l run=my-nginx -o yaml | grep ' podIP:'
    podIP: 10.233.112.27
    podIP: 10.233.112.26

建立service:

[root@master test]# kubectl expose deployment/my-nginx
service/my-nginx exposed

這等價於使用 kubectl create -f 命令建立,對應如下的 yaml 檔案:

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx

檢視 Service 資源:

[root@master test]# kubectl get svc my-nginx
NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
my-nginx   ClusterIP   10.233.22.145   <none>        80/TCP    79s

一個 Service 由一組 backend Pod 組成。這些 Pod 通過 endpoints 暴露出來。 Service Selector 將持續評估,結果被 POST 到一個名稱為 my-nginx 的 Endpoint 物件上。 當 Pod 終止後,它會自動從 Endpoint 中移除,新的能夠匹配上 Service Selector 的 Pod 將自動地被新增到 Endpoint 中。 檢查該 Endpoint:

[root@master test]# kubectl describe svc my-nginx
Name:              my-nginx
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          run=my-nginx
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.233.22.145
IPs:               10.233.22.145
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.233.112.26:80,10.233.112.27:80
Session Affinity:  None
Events:            <none>

檢視endporints:

[root@master test]# kubectl get ep my-nginx
NAME       ENDPOINTS                           AGE
my-nginx   10.233.112.26:80,10.233.112.27:80   3m22s

任意節點測試:

# master節點
[root@master test]# curl 10.233.22.145
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

# worker節點
[root@node-2 ~]# curl 10.233.22.145
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

相關文章