Kubernetes Ingress 只是 Kubernetes 中的一個普通資源對象,須要一個對應的 Ingress 控制器來解析 Ingress 的規則,暴露服務到外部,好比 ingress-nginx
,本質上來講它只是一個 Nginx Pod,而後將請求重定向到其餘內部(ClusterIP)服務去,這個 Pod 自己也是經過 Kubernetes 服務暴露出去,最多見的方式是經過 LoadBalancer 來實現的。一樣本文咱們但願用一個簡單清晰的概述,讓你來了解 Kubernetes Ingress 背後的東西,讓你更容易理解使用的 Ingress。html
咱們可使用 Ingress 來使內部服務暴露到集羣外部去,它爲你節省了寶貴的靜態 IP,由於你不須要聲明多個 LoadBalancer 服務了,這次,它還能夠進行更多的額外配置。下面咱們經過一個簡單的示例來對 Ingress 進行一些說明吧。python
簡單 HTTP server
首先,咱們先回到容器、Kubernetes 以前的時代。nginx
以前咱們更多會使用一個(Nginx)HTTP server 來託管咱們的服務,它能夠經過 HTTP 協議接收到一個特定文件路徑的請求,而後在文件系統中檢查這個文件路徑,若是存在則就返回便可。git
![](http://static.javashuo.com/static/loading.gif)
例如,在 Nginx 中,咱們能夠經過下面的配置來實現這個功能。github
location /folder {
root /var/www/;
index index.html;
}
除了上面提到的功能以外,咱們能夠當 HTTP server 接收到請求後,將該請求重定向到另外一個服務器(意味着它做爲代理)去,而後將該服務器的響應重定向到客戶端去。對於客戶端來講,什麼都沒有改變,接收到的結果仍然仍是請求的文件(若是存在的話)。web
![](http://static.javashuo.com/static/loading.gif)
一樣若是在 Nginx 中,重定向能夠配置成下面的樣子:api
location /folder {
proxy_pass http://second-nginx-server:8000;
}
這意味着 Nginx 能夠從文件系統中提供文件,或者經過代理將響應重定向到其餘服務器並返回它們的響應。瀏覽器
簡單的 Kubernetes 示例
使用 ClusterIP 服務
在 Kubernetes 中部署應用後,咱們應該先去了解 Kubernetes Service 服務(前文中講解的)。好比咱們有兩個 worker 節點,有兩個服務 service-nginx 和 service-python,它們指向不一樣的 pods。這兩個服務沒有被調度到任何特定的節點上,也就是在任何節點上都有可能,以下圖所示:緩存
![](http://static.javashuo.com/static/loading.gif)
在集羣內部咱們能夠經過他們的 Service 服務來請求到 Nginx pods 和 Python pods 上去,如今咱們想讓這些服務也能從集羣外部進行訪問,按照前文提到的咱們就須要將這些服務轉換爲 LoadBalancer 服務。安全
使用 LoadBalancer 服務
固然使用 LoadBalancer 服務的前提是咱們的 Kubernetes 集羣的託管服務商要能支持才行,若是支持咱們能夠將上面的 ClusterIP 服務轉換爲 LoadBalancer 服務,能夠建立兩個外部負載均衡器,將請求重定向到咱們的節點 IP,而後重定向到內部的 ClusterIP 服務。
![](http://static.javashuo.com/static/loading.gif)
咱們能夠看到兩個 LoadBalancers 都有本身的 IP,若是咱們向 LoadBalancer 22.33.44.55
發送請求,它請被重定向到咱們的內部的 service-nginx 服務去。若是發送請求到 77.66.55.44,它將被重定向到咱們的內部的 service-python 服務。
這個確實很方便,可是要知道 IP 地址是比較稀有的,並且價格可不便宜。想象下咱們 Kubernetes 集羣中不僅是兩個服務,有不少的話,咱們爲這些服務建立 LoadBalancers 成本是否是就成倍增長了。
那麼是否有另外一種解決方案可讓咱們只使用一個 LoadBalancer 就能夠把請求轉發給咱們的內部服務呢?咱們先經過手動(非 Kubernetes)的方式來探討下這個問題。
手動配置 Nginx 代理服務
咱們知道 Nginx 能夠做爲一個代理使用,因此咱們能夠很容易想到運行一個 Nginx 來代理咱們的服務。以下圖所示,咱們新增了一個名爲 service-nginx-proxy 的新服務,它其實是咱們惟一的一個 LoadBalancer 服務。service-nginx-proxy 仍然會指向一個或多個 Nginx-pod-endpoints(爲了簡單沒有在圖上標識),以前的另外兩個服務轉換爲簡單的 ClusterIP 服務了。
![](http://static.javashuo.com/static/loading.gif)
能夠看到咱們只分配了一個 IP 地址爲 11.22.33.44
的負載均衡器,對於不一樣的 http 請求路徑咱們用黃色來進行標記,他們的目標是一致的,只是包含的不一樣的請求 URL。
service-nginx-proxy 服務會根據請求的 URL 來決定他們應該將請求重定向到哪一個服務去。
在上圖中咱們有兩個背後的服務,分別用紅色和藍色進行了標記,紅色會重定向到 service-nginx 服務,藍色重定向到 service-python 服務。對應的 Nginx 代理配置以下所示:
location /folder {
proxy_pass http://service-nginx:3001;
}
location /other {
proxy_pass http://service-python:3002;
}
只是目前咱們須要去手動配置 service-nginx-proxy 服務,好比新增了一個請求路徑須要路由到其餘服務去,咱們就須要去從新配置 Nginx 的配置讓其生效,可是這個確實是一個可行的解決方案,只是有點麻煩而已。
而 Kubernetes Ingress 就是爲了讓咱們的配置更加容易、更加智能、更容易管理出現的,因此在 Kubernetes 集羣中咱們會用 Ingress 來代替上面的手動配置的方式將服務暴露到集羣外去。
使用 Kubernetes Ingress
如今咱們將上面手動配置代理的方式轉換爲 Kubernetes Ingress 的方式,以下圖所示,咱們只是使用了一個預先配置好的 Nginx(Ingress),它已經爲咱們作了全部的代理重定向工做,這爲咱們節省了大量的手動配置工做了。
![](http://static.javashuo.com/static/loading.gif)
這其實就已經說明了 Kubernetes Ingress 是什麼,下面讓咱們來看看一些配置實例吧。
安裝 Ingress 控制器
Ingress 只是 Kubernetes 的一種資源對象而已,在這個資源中咱們能夠去配置咱們的服務路由規則,可是要真正去實現識別這個 Ingress 並提供代理路由功能,還須要安裝一個對應的控制器才能實現。
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.1/deploy/mandatory.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.1/deploy/provider/cloud-generic.yaml
使用下面的命令,能夠看到安裝在命名空間 ingress-nginx 中的 k8s 資源。
![](http://static.javashuo.com/static/loading.gif)
咱們能夠看到一個正常的 LoadBalancer 服務,有一個外部 IP 和一個所屬的 pod,咱們可使用命令 kubectl exec
進入該 pod,裏面包含一個預配置的 Nginx 服務器。
![](http://static.javashuo.com/static/loading.gif)
其中的 nginx.conf
文件就包含各類代理重定向設置和其餘相關配置。
Ingress 配置示例
咱們所使用的 Ingress yaml 例子能夠是這樣的。
# just example, not tested
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
namespace: default
name: test-ingress
spec:
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 對象會被上面安裝的 Ingress 控制器轉換爲對應的 Nginx 配置。
若是你的一個內部服務,即 Ingress 應該重定向到的服務,是在不一樣的命名空間裏,怎麼辦?由於咱們定義的 Ingress 資源是命名空間級別的。在 Ingress 配置中,只能重定向到同一命名空間的服務。
若是你定義了多個 Ingress yaml 配置,那麼這些配置會被一個單一的Ingress 控制器合併成一個 Nginx 配置。也就是說全部的人都在使用同一個 LoadBalancer IP。
配置 Ingress Nginx
有時候咱們須要對 Ingress Nginx 進行一些微調配置,咱們能夠經過 Ingress 資源對象中的 annotations 註解來實現,好比咱們能夠配置各類平時直接在 Nginx 中的配置選項。
kind: Ingress
metadata:
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.qikqiak.com' ) {
rewrite ^ https://qikqiak.com$request_uri permanent;
}
這些註釋都將被轉換成 Nginx 配置,你能夠經過手動鏈接(kubectl exec
)到 nginx pod 中檢查這些配置。
關於 ingress-nginx 更多的配置使用能夠參考官方文檔相關說明:
-
https://github.com/kubernetes/ingress-nginx/tree/master/docs/user-guide/nginx-configuration -
https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md#lua-resty-waf
查看 ingress-nginx 日誌
要排查問題,經過查看 Ingress 控制器的日誌很是有幫助。
![](http://static.javashuo.com/static/loading.gif)
使用 Curl 測試
若是咱們想測試 Ingress 重定向規則,最好使用 curl -v [yourhost.com](http://yourhost.com)
來代替瀏覽器,能夠避免緩存等帶來的問題。
重定向規則
在本文的示例中咱們使用 /folder
和 /other/directory
等路徑來重定向到不一樣的服務,此外咱們也能夠經過主機名來區分請求,好比將 api.myurl.com 和 site.myurl.com 重定向到不一樣的內部 ClusterIP 服務去。
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: simple-fanout-example
spec:
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
SSL/HTTPS
可能咱們想讓網站使用安全的 HTTPS 服務,Kubernetes Ingress 也提供了簡單的 TLS 校驗,這意味着它會處理全部的 SSL 通訊、解密/校驗 SSL 請求,而後將這些解密後的請求發送到內部服務去。
若是你的多個內部服務使用相同(多是通配符)的 SSL 證書,這樣咱們就只須要在 Ingress 上配置一次,而不須要在內部服務上去配置,Ingress 可使用配置的 TLS Kubernetes Secret 來配置 SSL 證書。
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: tls-example-ingress
spec:
tls:
- hosts:
- sslexample.foo.com
secretName: testsecret-tls
rules:
- host: sslexample.foo.com
http:
paths:
- path: /
backend:
serviceName: service1
servicePort: 80
不過須要注意的是若是你在不一樣的命名空間有多個 Ingress 資源,那麼你的 TLS secret 也須要在你使用的 Ingress 資源的全部命名空間中可用。
總結
這裏咱們簡單介紹了 Kubernetes Ingress 的原理,簡單來講:它不過是一種輕鬆配置 Nginx 服務器的方法,它能夠將請求重定向到其餘內部服務去。這爲咱們節省了寶貴的靜態 IP 和 LoadBalancers 資源。
另外須要注意的是還有其餘的 Kubernetes Ingress 類型,它們內部沒有設置 Nginx 服務,但可能使用其餘代理技術,同樣也能夠實現上面的全部功能。
原文: https://codeburst.io/kubernetes-ingress-simply-visually-explained-d9cad44e4419
翻譯: 感謝陽明老師的翻譯與分享。
你可能還喜歡
點擊下方圖片便可閱讀
本文分享自微信公衆號 - 雲原生生態圈(CloudNativeEcoSystem)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。