天天看點

Kubernetes 中的服務:ClusterIP、Nodeport 和 LoadBalancer

作者:Robert的書簽

在K8s中Pod 是短暫的。但是他們很重要。如果使用 Deployment,它們可以被無縫銷毀和替換。或者,它們可以在使用 Horizo​ntal Pod Autoscaling (HPA) 時在某個時間點進行縮放。

這意味着我們不能依賴 Pod IP 位址來連接配接在内部或外部容器中運作的應用程式,因為 Pod 将來可能不存在。

您可能已經注意到 Kubernetes Pod 被配置設定了一個 IP 位址:

stable-kube-state-metrics-758c964b95-6fnbl               1/1     Running   0          3d20h   100.96.2.5      ip-172-20-54-111.ec2.internal   <none>           <none>
stable-prometheus-node-exporter-4brgv                    1/1     Running   0          3d20h   172.20.60.26    ip-172-20-60-26.ec2.internal
           

這是此特定 Pod 的唯一内部 IP,但由于 Pod 的性質,無法保證此 IP 将來會存在。

服務

Kubernetes 服務是一種在内部和外部公開應用程式的機制。

每項服務都将建立一個可用作連接配接器的永久 IP 位址。

此外,它将打開一個port與targetPort. 一些服務可以在每個Node中建立端口,甚至可以建立外部 IP 以在叢集外部建立連接配接器。

通過 IP 和端口的組合,我們可以建立一種唯一辨別應用程式的方法。

建立服務

每個服務都有一個選擇器,用于過濾将它與叢集中的一組 Pod 連結起來。

spec:
  selector:
    app.kubernetes.io/name: myapp
           

是以,所有帶有标簽myapp的 Pod 都将連結到此服務。

服務配置涉及三個端口屬性:

ports:
  - port: 80
    targetPort: 8080
    nodePort: 30036
    protocol: TCP
           
  • 端口:将建立以連接配接到應用程式的新服務端口。
  • targetPort:我們希望以服務請求為目标的應用程式端口。
  • nodePort:這是30000-32767範圍内的一個端口,會在每個節點開放。如果留白,Kubernetes 會在該範圍内選擇一個空閑的。
  • 協定:TCP 是預設協定,但您可以使用其他協定,如 SCTP 或 UDP。

您可以檢視使用以下方式建立的服務:

kubectl get services
kubectl get svc
           

服務種類

Kubernetes 允許建立這些類型的服務:

  • ClusterIP(預設)
  • 節點端口
  • 負載均衡器
  • 外部名稱

讓我們詳細看看它們中的每一個。

  • ClusterIP

這是 Kubernetes 中服務的預設類型。

顧名思義,這隻是一個可以在叢集内部使用的位址。

以 Prometheus Stack 的初始 helm 安裝為例。它為 Prometheus 和 Grafana 生态系統安裝 Pod、部署和服務。

NAME                                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
alertmanager-operated                     ClusterIP   None            <none>        9093/TCP,9094/TCP,9094/UDP   3m27s
kubernetes                                ClusterIP   100.64.0.1      <none>        443/TCP                      18h
prometheus-operated                       ClusterIP   None            <none>        9090/TCP                     3m27s
stable-grafana                            ClusterIP   100.66.46.251   <none>        80/TCP                       3m29s
stable-kube-prometheus-sta-alertmanager   ClusterIP   100.64.23.19    <none>        9093/TCP                     3m29s
stable-kube-prometheus-sta-operator       ClusterIP   100.69.14.239   <none>        443/TCP                      3m29s
stable-kube-prometheus-sta-prometheus     ClusterIP   100.70.168.92   <none>        9090/TCP                     3m29s
stable-kube-state-metrics                 ClusterIP   100.70.80.72    <none>        8080/TCP                     3m29s
stable-prometheus-node-exporter           ClusterIP   100.68.71.253   <none>        9100/TCP 


           
Kubernetes 中的服務:ClusterIP、Nodeport 和 LoadBalancer

這會使用内部叢集 IP 位址和端口建立連接配接。

但是,如果我們需要從叢集外部使用這個連接配接器怎麼辦?這個 IP 是内部的,不會在外面工作。

這是其餘服務的用武之地……

NodePort

NodePort 與 ClusterIP 的不同之處在于它在每個節點中公開一個端口。

建立 NodePort 時,kube-proxy 會公開 30000-32767 範圍内的端口:

apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  selector:
  	app: myapp
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30036
    protocol: TCP           
Kubernetes 中的服務:ClusterIP、Nodeport 和 LoadBalancer

NodePort 是非 HTTP 通信的首選元素。

使用 NodePort 的問題是您仍然需要單獨通路每個節點。

那麼,讓我們看看清單中的下一項……

負載均衡器

LoadBalancer 是一種 Kubernetes 服務,它:

  • 建立像 ClusterIP 這樣的服務
  • 在每個節點中打開一個端口,如 NodePort
  • 使用來自您的雲提供商的 LoadBalancer 實作(您的雲提供商需要支援 LoadBalancer 才能工作)。
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - name: web
    port: 80
  selector:
    app: web
  type: LoadBalancer
my-service                                LoadBalancer   100.71.69.103   <pending>     80:32147/TCP                 12s
my-service                                LoadBalancer   100.71.69.103   a16038a91350f45bebb49af853ab6bd3-2079646983.us-east-1.elb.amazonaws.com   80:32147/TCP                 16m
           

在本例中,使用了 Amazon Web Service (AWS),是以建立了來自 AWS 的外部 IP。

然後,如果你使用kubectl describe my-service,你會發現增加了幾個新的屬性:

Name:                     my-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app.kubernetes.io/name=pegasus
Type:                     LoadBalancer
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       100.71.69.103
IPs:                      100.71.69.103
LoadBalancer Ingress:     a16038a91350f45bebb49af853ab6bd3-2079646983.us-east-1.elb.amazonaws.com
Port:                     <unset>  80/TCP
TargetPort:               9376/TCP
NodePort:                 <unset>  32147/TCP
Endpoints:                <none>
Session Affinity:         None
External Traffic Policy:  Cluster           

與 NodePort 的主要差別在于 LoadBalancer 可以通路,并且會嘗試将請求平均配置設定給 Nodes。

Kubernetes 中的服務:ClusterIP、Nodeport 和 LoadBalancer

外部名稱

由于需要連接配接到 Kubernetes 叢集外部的元素,是以引入了 ExternalName 服務。不要将其視為連接配接到叢集中的項目的一種方式,而是将其視為連接配接到叢集外部元素的連接配接器。

這有兩個目的:

  • 它為與該元素的所有通信建立一個單一端點。
  • 如果需要更換外部服務,隻需修改 ExternalName 即可更輕松地進行切換,而不是修改所有連接配接。
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
    - name: web
      port: 80
  selector:
    app: web
  type: ExternalName
  externalName: db.myexternalserver.com
           

結論

服務是 Kubernetes 的一個關鍵方面,因為它們提供了一種在叢集内外公開内部端點的方法。

ClusterIP 服務隻是為節點内通信建立一個連接配接器。僅當您有特定應用程式需要與節點中的其他應用程式連接配接時才使用它。

NodePort 和 LoadBalancer 用于對您的應用程式進行外部通路。最好使用 LoadBalancer 在多 pod 實作中平均配置設定請求,但請注意,您的供應商應該實作負載平衡才能實作這一點。

除此之外,Kubernetes 還提供 Ingresses,這是一種建立具有負載平衡的 HTTP 連接配接以供外部使用的方法。

繼續閱讀