天天看點

Kubernetes 服務概述

Kubernetes 服務概述

了解不同類型的 Kubernetes 服務和 Ingress 控制器

Kubernetes 服務概述

在 Kubernetes 環境中,您可以擁有數百個甚至數千個臨時 Pod。無論是因為節點縮減、pod 副本縮減,還是 pod 被重新排程到新節點,pod 的 IP 位址永遠無法保證相同。

Pod 的 IP 位址是在它被排程到特定節點之後并且在它被引導之前配置設定的。鑒于我們處于雲原生環境中,我們希望能夠水準擴充 pod。是以,跟蹤我們所有應用程式的所有 IP 位址将是一項非常困難的任務。

Kubernetes 有一種資源類型可以解決這個不斷變化的 pod IP 的問題,稱為服務。

Kubernetes 服務允許您建立一個單一的常量 IP 位址,其中包含一組包含相同服務的 Pod 的 IP 位址。這非常有用,因為服務 IP 保持靜态,而 Pod 的 IP 可以不斷變化。您永遠不必擔心沒有正确的 IP 位址。

服務如何運作

要想了解服務如何運作?首先配置一個service開始。

讓我們首先建立一個包含三個 nginx pod 執行個體的部署。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
           

應用部署清單後,我們可以看到我們有三個使用 IP 運作的 nginx 執行個體10.244.242.66, 10.244.242.67, 10.244.230,199。另外,請注意我們為這些 pod 配置設定的标簽,app=nginx這對于服務如何監控這些 pod 至關重要。

~ kubectl get pods -owide - show-labels
NAME READY STATUS RESTARTS AGE IP NODE LABELS
nginx-8f458dc5b-6vcxt 1/1 Running 0 2m27s 10.244.242.66 nodepool-a-95e9c8e86208 app=nginx,pod-template-hash=8f458dc5b
nginx-8f458dc5b-ktvtf 1/1 Running 0 2m27s 10.244.242.67 nodepool-a-95e9c8e86208 app=nginx,pod-template-hash=8f458dc5b
nginx-8f458dc5b-mlkwd 1/1 Running 0 2m27s 10.244.230.199 nodepool-a-11aa1dc199fa app=nginx,pod-template-hash=8f458dc5b

           

現在,讓我們定義我們的服務清單,它在下面定義,并對定義的内容進行細分。

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

當我們開始分解這個清單時,我們注意到類型是Service. 接下來,中繼資料部分應該很熟悉,因為它與其他 Kubernetes 資源上的中繼資料字段相同。規範部分是我們定義我們的服務将如何互動以及與之互動的地方。字段selector 您可以在該字段中定義希望該服務監控哪些 pod。這是通過标簽比對完成的。

你會注意到這selector有一個定義app: nginx。如果您還記得這些是我們在部署清單中為我們的 pod 定義的标簽。通過這個選擇器定義,我們聲明任何帶有标簽的 pod 都app=nginx将成為該服務的一部分。

接下來,我們有type字段。這定義了我們将成為該服務的一部分希望它成為什麼樣的服務。稍後我們将更深入地研究服務類型,但現在我們将其定義為ClusterIP.

最後,我們有ports字段。在這裡,我們定義流量将如何以及在何處流經服務。請注意,此字段接受一個數組,是以您可以定義多個條目。讓我們細分端口中的每個字段:

  • name:您可以為給定的端口條目。配置設定一個特定的名稱。
  • port:這是服務将偵聽的端口。
  • targetPort:這是服務将請求轉發到的端口。這應該與 pod 正在偵聽的端口相比對。
  • protocol:您希望服務監聽和互動的特定協定。

現在我們對服務清單的作用以及它如何與 pod 互動有了基本的了解,我們部署清單并檢查服務。

~  kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   90m
nginx        ClusterIP   10.108.176.62   <none>        80/TCP    18m

☁  ~  kubectl describe svc nginx
Name:              nginx
Namespace:         default
Labels:            app=nginx
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.108.176.62
IPs:               10.108.176.62
Port:              80-80  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.230.199:80,10.244.242.66:80,10.244.242.67:80
Session Affinity:  None
Events:            <none>
           

describe 指令中的所有内容都應與清單定義一緻,除了兩個字段“IP”和“Endpoints”。

該IP字段定義服務 IP 位址。這是可用于通路服務後面的 pod 的靜态 IP。

該Endpoints字段定義目前配置設定給此服務的 pod IP。您注意到這些 IP 是來自我們的 nginx 部署的 IP。

在我們繼續其他服務類型之前,讓我們展示縮減 nginx 部署并檢視該服務将如何處理此更改。

kubectl scale deployment/nginx --replicas 1
deployment.apps/nginx scaled

☁  kubectl get pods -owide
NAME                    READY   STATUS    RESTARTS   AGE   IP               NODE                      NOMINATED NODE   READINESS GATES
nginx-8f458dc5b-mlkwd   1/1     Running   0          43m   10.244.230.199   nodepool-a-11aa1dc199fa   <none>           <none>

☁  kubectl describe service nginx | grep Endpoints  
Endpoints:         10.244.230.199:80

☁  kubectl scale deployment/nginx --replicas 5
deployment.apps/nginx scaled

☁  kubectl get pods -owide
NAME                    READY   STATUS    RESTARTS   AGE    IP               NODE                      NOMINATED NODE   READINESS GATES
nginx-8f458dc5b-9pmhb   1/1     Running   0          108s   10.244.242.69    nodepool-a-95e9c8e86208   <none>           <none>
nginx-8f458dc5b-mlkwd   1/1     Running   0          47m    10.244.230.199   nodepool-a-11aa1dc199fa   <none>           <none>
nginx-8f458dc5b-r2pcp   1/1     Running   0          108s   10.244.242.70    nodepool-a-95e9c8e86208   <none>           <none>
nginx-8f458dc5b-vgwv6   1/1     Running   0          108s   10.244.242.68    nodepool-a-95e9c8e86208   <none>           <none>
nginx-8f458dc5b-x6thl   1/1     Running   0          108s   10.244.230.200   nodepool-a-11aa1dc199fa   <none>           <none>

☁  kubectl describe service nginx | grep Endpoints
Endpoints:         10.244.230.199:80,10.244.230.200:80,10.244.242.68:80 + 2 more...
           

您可以看到向上和向下擴充 pod 會立即反映在允許單個靜态 IP 通路 pod 的服務中。

服務種類

在服務資源中,存在三種不同的類型。它們如下:

  1. 叢集IP
  2. 節點端口
  3. 負載均衡器

這些都有自己的行為和特定的用例,是以知道何時使用它們很重要。在接下來的部分中,我們将對其中的每一個進行更深入的探讨。

叢集IP

ClusterIP 是最“基本”的服務類型。它将建立一個靜态 IP 位址,該位址位于與 pod IP 範圍不同的子網上,并将通過标簽選擇器監視一組 pod。

Kubernetes 服務概述

ClusterIP 允許 pod 輕松地互相通信,因為 pod 可以将請求發送到靜态 IP 或使用 Kubernetes DNS 将請求發送到{service-name}.{namespace}. 在前面的示例中,我們部署的 DNS 應該是nginx.default. 使用 ClusterIP 有一些限制。最大的一個是沒有辦法向外界公開這項服務。這是服務類型nodePort和loadBalancer應該使用的地方。

節點端口

該NodePort服務建立在類型之上ClusterIP。它ClusterIP通過在工作節​點上打開一個端口來轉發流量來向外界公開。這意味着,如果您有 50 個工作節點,即使 pod 不在該工作節點上,每個工作節點也會偵聽配置設定的端口。

Kubernetes 服務概述

要建立NodePort服務,唯一的差別是定義Type為NodePort.

kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  ports:
  - name: 80-80
    port: 80
    protocol: TCP
    targetPort: 80
    # nodePort: 30001
  selector:
    app: nginx
  type: NodePort
           

您可能會注意到 被nodePort注釋掉了,這是因為如果您沒有nodePort在該ports部分中定義,Kubernetes 會自動從 range 中配置設定一個随機端口30000–32767。如果你想定義一個特定的端口,它必須從這個範圍内完成。部署 NodePort 服務清單并讓我們檢查它。

kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        135m
nginx        NodePort    10.98.246.253   <none>        80:30828/TCP   5s

☁  kubectl describe svc nginx
Name:                     nginx
Namespace:                default
Labels:                   app=nginx
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.98.246.253
IPs:                      10.98.246.253
Port:                     80-80  80/TCP
TargetPort:               80/TCP
NodePort:                 80-80  30828/TCP
Endpoints:                10.244.230.199:80,10.244.230.200:80,10.244.242.68:80 + 2 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
           

在這裡,我們看到一個名為的新字段NodePort,其值為30828/TCP。這是配置設定給該服務的端口和協定。現在,如果我們要向具有該端口的任何工作節點 IP 位址發送請求,請求将被發送到服務,然後服務被發送到我們的 pod。

☁  kubectl get nodes -owide
NAME                      STATUS   ROLES    AGE    VERSION   INTERNAL-IP   EXTERNAL-IP     OS-IMAGE                       KERNEL-VERSION    CONTAINER-RUNTIME
nodepool-a-11aa1dc199fa   Ready    <none>   140m   v1.24.4   10.1.96.5     45.77.152.173   Debian GNU/Linux 10 (buster)   4.19.0-22-amd64   containerd://1.6.8
nodepool-a-95e9c8e86208   Ready    <none>   140m   v1.24.4   10.1.96.4     140.82.44.105   Debian GNU/Linux 10 (buster)   4.19.0-22-amd64   containerd://1.6.8
☁  curl 140.82.44.105:30828
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

☁  curl 45.77.152.173:30828
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
           

雖然這是向外界公開我們的服務的一種有用方式,但它的擴充性并不好。在高度自動擴充的 Kubernetes 叢集中,工作節點可能是短暫的,因為它們可能會不斷地上下旋轉。這給我們留下了一個與 pod 類似的問題,我們可以在 pod 中找到 IP 是什麼,但這并不意味着它們将永遠存在。如果您的服務需要靜态外部 IP 位址,則LoadBalancer服務類型将滿足該需求。

負載均衡器

NodePort與建構于 之上的方式類似ClusterIP,該LoadBalancer服務建構于 之上NodePort。通過該LoadBalancer服務,每個工作節點繼續擁有配置設定給特定服務的唯一端口。但是,現在部署了 L4 并将其配置為路由到特定的工作節點和端口。進階請求流程如下:一個請求被發送到負載均衡器,它被轉發到特定的工作節點nodeport,然後被傳遞到特定的服務,最後被發送到一個 pod。注意:部署的負載均衡器取決于您運作 Kubernetes 的雲提供商。

Kubernetes 服務概述

如果需要,配置LoadBalancer服務會涉及更多。一個非常簡單的配置可以如下所示,隻需将type字段更改為LoadBalancer.

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

例如,如果您希望更改您的負載均衡器以強制 SSL 重定向、配置防火牆規則、使用 HTTPS 而不是 HTTP,或者使用不同的平衡算法,那麼這将需要在您的服務上進行定義Annotations。這是一個LoadBalancer使用 Vultrs Load Balancer 內建的示例清單。

apiVersion: v1
kind: Service
metadata:
  annotations:
    service.beta.kubernetes.io/vultr-loadbalancer-protocol: "http"
    service.beta.kubernetes.io/vultr-loadbalancer-https-ports: "443"
    # You will need to have created a TLS Secret and pass in the name as the value
    service.beta.kubernetes.io/vultr-loadbalancer-ssl: "ssl-secret"
    service.beta.kubernetes.io/vultr-loadbalancer-algorithm: "least_connections"
    service.beta.kubernetes.io/vultr-loadbalancer-ssl-redirect: "true"
    service.beta.kubernetes.io/vultr-loadbalancer-firewall-rules: "0.0.0.0/80;0.0.0.0/443"
  labels:
    app: nginx
  name: nginx
spec:
  ports:
    - port: 80
      name: "http"
    - port: 443
      name: "https"
  selector:
    app: nginx
  type: LoadBalancer
           

可在此處找到可與 Vultr 負載均衡器一起使用的所有可用注釋的清單。請檢查您的特定雲提供商以擷取配置選項。首次部署LoadBalancer服務時,您會看到該EXTERNAL-IP部分是pending

kubectl get svc
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP      10.96.0.1        <none>        443/TCP        150m
nginx        LoadBalancer   10.103.252.120   <pending>     80:30092/TCP   4s

☁  kubectl describe service nginx
Name:                     nginx
Namespace:                default
Labels:                   app=nginx
Annotations:              <none>
Selector:                 app=nginx
Type:                     LoadBalancer
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.103.252.120
IPs:                      10.103.252.120
Port:                     80-80  80/TCP
TargetPort:               80/TCP
NodePort:                 80-80  30092/TCP
Endpoints:                10.244.230.199:80,10.244.230.200:80,10.244.242.68:80 + 2 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type     Reason                  Age               From                Message
  ----     ------                  ----              ----                -------
  Normal   EnsuringLoadBalancer    8s (x4 over 44s)  service-controller  Ensuring load balancer
  Warning  SyncLoadBalancerFailed  8s (x4 over 44s)  service-controller  Error syncing load balancer: failed to ensure load balancer: load-balancer is not yet active - current status: pending

           

您會注意到 Kubernetes 在這裡部署了一個負載均衡器,并且不斷進行通信以檢查負載均衡器是否已配置并配置設定了 IP。一旦 Load Balancer 已配置并準備好進行流量,您将在該EXTERNAL-IP字段中看到一個配置設定的 IP 位址,并且 LB 已被“確定”。這意味着 Kubernetes 現在可以控制相應地監控和更新負載均衡器。另外,請注意nodeport配置設定了唯一性。

kubectl get svc
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)        AGE
kubernetes   ClusterIP      10.96.0.1        <none>         443/TCP        154m
nginx        LoadBalancer   10.103.252.120   45.63.15.140   80:30092/TCP   4m9s

☁  kubectl describe service nginx
Name:                     nginx
Namespace:                default
Labels:                   app=nginx
Annotations:              <none>
Selector:                 app=nginx
Type:                     LoadBalancer
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.103.252.120
IPs:                      10.103.252.120
LoadBalancer Ingress:     45.63.15.140
Port:                     80-80  80/TCP
TargetPort:               80/TCP
NodePort:                 80-80  30092/TCP
Endpoints:                10.244.230.199:80,10.244.230.200:80,10.244.242.68:80 + 2 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type     Reason                  Age                    From                Message
  ----     ------                  ----                   ----                -------
  Warning  SyncLoadBalancerFailed  2m21s (x5 over 3m37s)  service-controller  Error syncing load balancer: failed to ensure load balancer: load-balancer is not yet active - current status: pending
  Normal   EnsuringLoadBalancer    61s (x6 over 3m37s)    service-controller  Ensuring load balancer
  Normal   EnsuredLoadBalancer     60s                    service-controller  Ensured load balancer

           

EXTERNAL-IP為了驗證我們的負載均衡器是否正常工作,我們可以向負載均衡器的公共 IP 位址發送請求。

curl 45.63.15.140
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
           

您可以将LoadBalancer服務類型視為一個絕妙的解決方案。但是,它們有一個缺點;您不能定義任何類型的 URL 路徑,它不允許靈活性或将其路由到多個服務。該LoadBalancer服務與單個服務相關聯,是以如果您想從叢集中公開另一個應用程式,您将部署另一個負載均衡器,如果您有多個應用程式,它會快速增加成本。

這個問題的解決方案不是另一種服務類型,而是一種不同的 Kubernetes 資源,稱為ingress.

請求入口

ingress 資源是一種更靈活的方式來定義您的服務以供外界通路。這裡最大的賣點之一是您可以定義單個入口資源,并在您定義的子域、端口或 URL 路徑下使用此路由到您的所有服務。它們還提供了大量其他功能,例如速率限制、身份驗證、自動 TLS、權重路由等等。所有這些都可以通過單個負載均衡器完成,因為Ingress資源與服務類型一起工作,LoadBalancer唯一的差別是部署負載均衡器充當代理,将所有流量發送到“Ingress”資源,該資源充當 L7 負載均衡器簇。

Kubernetes 服務概述

入口控制器這裡唯一需要注意的是 Kubernetes 沒有自帶入口控制器。

社群有各種入口控制器,都具有不同類型的功能。

最終,在決定安裝哪個入口控制器之前,這取決于您的需求和場景。

繼續閱讀