圖解Kubernetes Ingress

kubernetes ingress不是一個kubernetes service。非常簡單,它只是一個將請求重定向到其他內部服務(ClusterIP)的nginx pod。這個pod本身可以透過kubernetes service(最常見的是LoadBalancer)訪問。

你應該閱讀本文麼

首先,我希望能給您一個清晰而簡單的概述,瞭解這個神秘的kubernetes ingress背後是什麼,這將使您容易理解您實際實現的內容,甚至您應該實現的內容。稍後,我將根據我們本文中所使用的示例展示一些它們的配置。

為什麼使用ingress

您可以使用它從叢集外部訪問內部服務。它為您節省了寶貴的靜態IP,因為您不需要宣告多個LoadBalancer服務。此外,正如我們將要看到的,它允許更多的配置和更簡單的設定。

本文要介紹什麼

首先,我們要介紹一下下http伺服器(尤其是nginx)是如何工作的,以及它們可以做什麼。

然後我們將展示如何手動設定ingress,不需要使用花哨的kubernetes ingress資源。

接下來,我們將看到kubernetes ingress只不過是一個預配置的nginx伺服器。

聽起來很迷惑麼?讀完本文你將瞭解這一切。

HTTP伺服器的簡單介紹

在這裡,我們回到容器、kubernetes和雲的現代世界出現之前的時代。

一個HTTP伺服器能做什麼

它可以透過HTTP協議接收針對特定檔案路徑的請求,檢查連線的檔案系統上的檔案路徑,如果存在,則返回該檔案。

圖解Kubernetes Ingress

例如,在nginx中,這可以透過類似以下內容完成:

location /folder { root /var/www/; index index。html;}

一個HTTP伺服器還能做什麼

它可以接收針對特定檔案路徑的請求,將該請求重定向到另一臺伺服器上(這意味著它充當代理),然後將該伺服器的響應重定向回客戶端。對於客戶端,沒有任何更改,接收到的結果仍然是請求的檔案(如果存在)。

圖解Kubernetes Ingress

我們不會深入討論這一點,在nginx中,代理重定向可以配置為:

location /folder { proxy_pass http://second-nginx-server:8000;}

這意味著nginx可以提供來自檔案系統的檔案,也可以透過充當代理將請求重定向到其他伺服器並返回它們的響應。

一個簡單的kubernetes service例子

在這裡你應該知道kubernetes service是什麼了,如果不瞭解,請參考上一篇文章。

使用ClusterIP服務

我們有兩個工作節點,在這裡我們忽略了主節點。我們有兩個service service-nginx和service-python,它們分別指向各自不同的pod。service不在任何特定節點上排程,姑且說它們“在叢集中任何地方都可用”。

圖解Kubernetes Ingress

在叢集內部我們可以透過它們的service訪問pod-nginx和pod-python。接下來我們還希望在叢集外部提供這些服務。因此,我們將ClusterIP轉換為LoadBalancer。

使用LoadBalancer服務

你可以看到,我們將ClusterIP轉換為了LoadBalancer,因為我們的kubernetes叢集由雲服務商託管,雲服務商可以處理這一問題。它建立兩個外部負載均衡器,將請求重定向到我們的外部節點IP,然後重定向到叢集內部的ClusterIP。

圖解Kubernetes Ingress

我們看到有兩個負載均衡器,每個都有自己的IP。如果我們向負載均衡器22。33。44。55傳送請求,它將被重定向到叢集內部的service-nginx。如果我們向負載均衡器77。66。55。44傳送請求,它將被重定向到叢集內部的service-python。

這可以正常工作。但是IP地址很少,而且負載均衡器的定價取決於雲服務商。現在假設我們不止有兩個,而是有更多的內部服務,我們想要為其建立負載均衡器,成本將會增加。

是否有其它解決方案允許我們只使用一個負載均衡器,但仍然可以直接訪問我們的兩個內部服務呢?讓我們首先透過手動(非kubernetes)方法來探索這一點。

手動配置一個nginx服務作為代理

如前所述,nginx可以充當代理。在下圖中,我們看到一個名為nginx-service-proxy的新service,它實際上是我們唯一的LoadBalancer服務。nginx-service-proxy仍然指向一個或多個nginx pod,但為簡單起見,沒有將其包括在下圖中。前面另外兩個service被轉換為簡單的ClusterIP。

圖解Kubernetes Ingress

我們可以看到,我們只用了一個負載均衡器,對於不同的http URL,請求顯示為黃色,因為他們的目標是相同的,只是包含不同的路徑(URL)。service-nginx-proxy根據傳遞的URL決定應該將請求重定向到哪個服務。在這種情況下,我們有兩種選擇,紅色和藍色,紅色重定向到service-nginx,藍色重定向到service-python。

location /folder { proxy_pass http://service-nginx:3001;}location /other { proxy_pass http://service-python:3002;}

目前,我們需要手動配置service-nginx-proxy,比如建立指向ClusterIP服務的正確的nginx配置檔案。這在很大程度上是一種可能的、有效的和常見的解決方案。由於這是一種常見的解決方案,因此建立了kubernetes ingress以使配置更簡單和更易於管理。

在我們的例子中使用kubernetes ingress

將下圖與上圖進行比較,真的沒有什麼變化。我們剛剛使用了一個預配置的nginx(kubernetes ingress),它已經為我們完成了所有的代理重定向,這為我們節省了大量的手動配置工作:

圖解Kubernetes Ingress

這就是理解什麼是kubernetes ingress的全部內容。現在讓我們看一些示例的配置。

安裝kubernetes ingress controller

kubernetes ingress是附加的kubernetes資源,可透過以下方式安裝:

kubectl apply -f https://raw。githubusercontent。com/kubernetes/ingress-nginx/nginx-0。24。1/deploy/mandatory。yamlkubectl apply -f https://raw。githubusercontent。com/kubernetes/ingress-nginx/nginx-0。24。1/deploy/provider/cloud-generic。yaml

使用下面的命令你將看到安裝在名稱空間ingress-nginx中的k8s資源:

kubectl get svc,pod ——namespace=ingress-nginx

圖解Kubernetes Ingress

您看到的是具有外部IP和所屬pod的普通LoadBalancer服務。您甚至可以透過kubectl exec進入該pod來檢視它是否包含一個預配置的nginx伺服器。

圖解Kubernetes Ingress

在檔案nginx。conf中,您將看到各種代理重定向設定和其他相關配置。

kubernetes ingress配置的例子

我們示例所使用的ingress yaml如下所示:

apiVersion: networking。k8s。io/v1beta1kind: Ingressmetadata: annotations: kubernetes。io/ingress。class: nginx namespace: default name: test-ingressspec: rules: - http: paths: - path: /folder backend: serviceName: service-nginx servicePort: 3001 - http: paths: - path: /other backend: serviceName: service-python servicePort: 3002

像建立其他資源一樣,使用kubectl create -f ingress。yaml建立該ingress。此yaml將由先前安裝的ingress controller轉換為nginx配置。

不同名稱空間下kubernetes ingress的示例

現在,如果ingress應該重定向到的某個服務位於不同的名稱空間中,該怎麼辦呢?因為定義的ingress是屬於某個名稱空間下的,在ingress配置中,你只能重定向到同一名稱空間中的服務。如果你定義了多個ingress yaml,這些配置會被單一的ingress controller合併到一個nginx配置中。

讓我們考慮一下service-nginx在default名稱空間中

apiVersion: networking。k8s。io/v1beta1kind: Ingressmetadata: annotations: kubernetes。io/ingress。class: nginx namespace: default name: ingress1spec: rules: - http: paths: - path: /folder backend: serviceName: service-nginx servicePort: 3001

然後service-python位於名稱空間namespace2中:

apiVersion: networking。k8s。io/v1beta1kind: Ingressmetadata: annotations: kubernetes。io/ingress。class: nginx namespace: namespace2 name: ingress2spec: rules: - http: paths: - path: /other backend: serviceName: service-python servicePort: 3002

因此我們建立了兩個ingress資源。

如何微調ingress nignx的配置

你可以透過Ingress Kubernetes Resource上的註釋來做到這一點。例如,你可以配置通常可以在nginx中直接配置的各種選項:

kind: Ingressmetadata: name: ingress annotations: kubernetes。io/ingress。class: nginx nginx。ingress。kubernetes。io/proxy-connect-timeout: ‘30’ nginx。ingress。kubernetes。io/proxy-send-timeout: ‘500’ nginx。ingress。kubernetes。io/proxy-read-timeout: ‘500’ nginx。ingress。kubernetes。io/send-timeout: “500” nginx。ingress。kubernetes。io/enable-cors: “true” nginx。ingress。kubernetes。io/cors-allow-methods: “*” nginx。ingress。kubernetes。io/cors-allow-origin: “*”。。。

你甚至可以執行非常具體的規則:

nginx。ingress。kubernetes。io/configuration-snippet: | if ($host = ‘www。wuestkamp。com’ ) { rewrite ^ https://wuestkamp。com$request_uri permanent; }

然後這些註釋將被轉換為nginx配置。你始終可以透過連線(kubectl exec)到ingress nginx pod來檢視這些配置。

檢視ingress/nginx的日誌

要找問題或錯誤時,檢視日誌很有幫助:

kubectl logs -n ingress-nginx ingress-nginx-controller-6cfd5b6544-k2r4n

圖解Kubernetes Ingress

使用curl測試配置

如果你想測試ingress/nginx重定向規則,最好使用curl -v yourhost。com而不是使用瀏覽器,以避免快取等問題。

重定向規則

在本文的例項中,我們使用/Folder或/Other/directory之類的路徑重定向到不同的服務,這叫做“路徑列表”。還可以透過主機名來區分請求,例如將api。myurl。com和website。myurl。com重定向到不同的內部ClusterIP服務,這可能如下所示:

apiVersion: networking。k8s。io/v1beta1kind: Ingressmetadata: name: simple-fanout-examplespec: rules: - host: api。myurl。com http: paths: - path: /foo backend: serviceName: service1 servicePort: 4200 - path: /bar backend: serviceName: service2 servicePort: 8080 - host: website。myurl。com http: paths: - path: / backend: serviceName: service3 servicePort: 3333

在本例中,我們看到對於特定的主機名,我們將不同的http路徑重定向到不同的內部服務。

SSL / HTTPS

kubernetes ingress提供了相當簡單的“TLS終止”,這意味著它處理所有SSL通訊,解密/終止SSL請求,然後將解密後的請求傳送到您的內部服務。如果您的多個內部服務正在使用相同的SSL證書,這是非常棒的,因為這樣您只需在ingress上配置一次,而不需要在所有內部服務上配置。ingress可以使用已配置的TLS Kubernetes Secret中的SSL證書。

apiVersion: networking。k8s。io/v1beta1kind: Ingressmetadata: name: tls-example-ingressspec: tls: - hosts: - sslexample。foo。com secretName: testsecret-tls rules: - host: sslexample。foo。com http: paths: - path: / backend: serviceName: service1 servicePort: 80

你只需確保,如果您在不同的名稱空間中有多個ingress資源,那麼您的TLS密碼也需要在使用它定義ingress資源的所有名稱空間中都可用。

總結

我只是想給你一個關於神秘的kubernetes ingress背後是什麼的廣泛概述。簡單來講,這只不過是一種輕鬆配置nginx伺服器的方法,該伺服器可以將請求重定向到其他內部服務。

這為您節省了寶貴的靜態IP和負載均衡器。但是kubernetes ingress不應該被認為是kubernetes service的一部分。ingress本身不是kubernetes的service,但它通常使用一個,主要是LoadBalancer。

需要注意的是,還有其他kubernetes ingress型別,它們不在內部設定nginx服務,而是可能使用其他代理技術。