iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 16
0
DevOps

Kubernetes and Istio 三十天系列 第 16

[Day16] 如何將Cluster內的服務對外Expose

  • 分享至 

  • twitterImage
  •  

前言

今天就先以如何將Cluster內的服務對外Expose為主軸。

如何從外部訪問Kubernetes

Kubernetes Pod IP and Cluster IP都只能在Cluster內部互相訪問,而我們通常需要從外部訪問Cluster中的服務(Service),Kubernetes提供了下述幾種方式來為Cluster提供外部流量入口。

NodePort

NodePort
NodePort在Cluster中的主機Node上為Service提供一個代理端口,以允許從Node網絡上對Service進行訪問。

Service type設定為NodePort,Kubernetes會通過Cluster中Node上的Kube-proxy為Service在Node上建立一個監聽端口。Kube-proxy並不會直接接收該Node Port進入的流量,而是會建立相應的Iptables規則,並通過Iptables將從該Node Port收到的流量直接轉發到Service註冊的Pod中。

NodePort的流量轉發機制和Cluster IP的iptables模式類似,唯一不同之處是在主機網絡上開了一個“NodePort”來接受外部流量。從上面的規則也可以看出,在創建Nodeport時,Kube-proxy也會同時為Service創建Cluster IP相關的iptables規則。

LoadBalancer

LoadBalancer

NodePort提供了一種訪問Kubernetes Cluster Service的方式,但有一些限制,導致這種方式只適用於開發階段,不適合用於產品階段。

Kubernetes Cluster Node的IP必須是一個well-known IP,即客戶端必須知道該IP。但Cluster中的Node是被作為Resource Pool,可以水平增加刪除,每個Node的IP是動態分配的,因此並不能認為Node IP對客戶端而言是well-known IP。

客戶端訪問某一個固定的Node IP的方式會有可能存在單點故障,當發生狀況時Kubernetes cluster會把Pod reload到其他的Node上,但客戶端就無法通過該Node的NodePort訪問Service了。

通過一個NodePort作為Service EndPoint,在網絡流量較大時存在性能瓶頸。
為了解決這些問題,Kubernetes提供了LoadBalancer。通過將Service Type設定為LoadBalancer類型,Kubernetes在Node的NodePort前提供了一個L4的Load Balancer。該L4的Load Balancer負責將外部網絡流量分發到後面的NodePort上。

上圖Kubernetes如何通過Service Type LoadBalancer方式對外提供流量入口,圖中LoadBalancer後面接入了兩個Node上的NodePort,部署三個Pod提供服務。根據集群的規模,可以在LoadBalancer後面可以接入更多的Node,以進行負荷分擔。

LoadBalancer類型需要雲端服務商的支持,如何創建則是由Google Cloud或Amazon Cloud等雲服務商提供的,創建的Load Balancer的過程不在Kubernetes Cluster的管理範圍中。

目前WS, Azure, CloudStack, GCE 和 OpenStack 等主流的公有雲和私有雲提供商都可以為Kubernetes提供Load Balancer。一般來說,公有雲提供商還會為Load Balancer提供一個External IP,以提供Internet接入。如果你的產品沒有使用雲提供商,而是自建Kubernetes Cluster,則需要自己提供LoadBalancer,目前有還在Beta的METALLB可以使用在自建Kubernetes。

Ingress

Ingress

LoadBalancer Service提供的是L4 Load Balancer,當只需要向外暴露一個服務的時候,采用這種方式是沒有問題的。但當一個應用需要對外提供多個服務時,采用該方式則要求為每一個L4(IP+Port)都創建一個外部LoadBalancer。

一般來說,同一個應用的多個服務/資源會放在同一個域名下,在這種情況下,創建多個LoadBalancer是完全沒有必要的,反而帶來了額外的開銷和管理成本。另外直接將服務暴露給外部用戶也會導致了前端和後端的耦合,影響了後端架構的靈活性,如果以後由於業務需求對服務進行調整會直接影響到客戶端。

在這種情況下,我們可以通過使用Kubernetes Ingress來統一網絡入口。Kubernetes Ingress聲明了一個應用層(OSI七層)的Load Balancer。Ingress定義了對L7 Gateway的要求,包括URL分發規則,基於不同域名的規則,SSL證書等。Kubernetes使用Ingress Controller來管理Ingress,並通過一個L7 Gateway來實現這些要求,一般可以使用Nginx,HAProxy,Envoy等。

雖然Ingress Controller通過L7 Gateway為多個Service提供了統一的入口,但由於其部署在集群中,因此並不能直接對外提供服務。實際上Ingress需要配合NodePort和LoadBalancer才能提供對外的流量入口。

Production Ingress Gateway

外部網絡到達Pod的完整路徑如下:

外部請求先通過四層Load Balancer進入內部網絡

Load Balancer將流量分發到後端多個主機節點上的NodePort

NodePort進入到Ingress Controller (iptabes規則,Ingress Controller本身是一個NodePort類型的Service)

Ingress Controller根據Ingress rule進行L7分發,根據HTTP的URL和Host將請求分發給不同的Service

Service將請求最終導入到後端提供服務的Pod中

從前面的介紹可以看到,K8S Ingress提供了一個基礎的L7 Gateway功能的抽象定義,其作用是對外提供一個L7服務的統一入口,並根據URL/HOST將請求路由到集群內部不同的服務上。

結語

今天比較細節的討論到Kubernetes Cluster內如何將服務對外Expose,在Istio中,通過為每個Pod部署一個Envoy Proxy,Istio接管了Service之間的請求流量。可以對Service Mesh中的所有Envoy Proxy進行統一配置,實現了對Service Mesh流量的路由控制,但是,Istio並沒有為Gateway提供一個較為完善的解決方案,明天就會針對這部份再進一步討論。

圖片來源

Service


上一篇
[Day15] 如何將Cluster內的服務互相溝通
下一篇
[Day17] 如何為Cluster選擇一個好的Gateway
系列文
Kubernetes and Istio 三十天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言