在 Nginx Ingress 控制器內部配置外部 IP 重定向
問題
我想知道如何配置 Nginx Ingress 控制器以在呼叫外部 IP 地址時重定向到 URL。
入口控制器 yaml
apiVersion: v1 kind: Service metadata: labels: helm.sh/chart: ingress-nginx-3.4.1 app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/version: 0.40.2 app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: controller name: ingress-nginx-controller namespace: ingress-nginx spec: type: NodePort ports: - name: http port: 80 protocol: TCP targetPort: http - name: https port: 443 protocol: TCP targetPort: https externalIPs: - ip1 - ip2 - ip3 selector: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/component: controller
如果我在瀏覽器中輸入我的外部 IP,我當然會進入 Nginx 404 頁面。在這種特殊情況下,我想設置一個重定向到它的特定域,例如 google.com。我想提高公共 K8s 集群的安全性。我還沒有配置這種特殊情況,想知道是否可以設置這樣的轉發過程。所有配置的 Ingress 資源都將其服務發佈到 Internet。
裸機環境缺乏傳統雲環境提供的網路負載均衡器可用的商品,並且單個 K8s 清單足以提供與 NGINX 入口控制器的單點聯繫。當然,我們必須記住,內部重定向遵循入口資源,然後相應地配置入口控制器。
使用外部 IP方法不會保留 HTTP 的源 IP,因此儘管它看起來很簡單,但不建議使用它。因此,您將失去與您的請求有關的資訊(除非您將監控入口控制器)
要回答如何在 Nginx 入口控制器中配置外部 IP 重定向的問題,我們必須從了解入口實際是什麼開始:
Ingress 將來自集群外部的 HTTP 和 HTTPS 路由暴露給集群內的服務。流量路由由 Ingress 資源上定義的規則控制。必須有一個 Ingress 控制器來滿足一個 Ingress。僅創建 Ingress 資源沒有任何效果。
為了達到預期的結果,您應該創建兩個單獨的入口對象(而不是控制器)。第一個沒有指定主機,因此該規則適用於通過指定 IP 地址的所有入站 HTTP 流量,如Ingress 規則中所述:
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/permanent-redirect: "https://www.google.com" name: ingress-redirect spec: rules: - http: paths: - path: / pathType: Prefix backend: serviceName: example servicePort: 12
第二個入口對象與提供的主機(例如,hello-world.info,以便規則適用於該主機。如下例所示:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-host spec: rules: - host: hello-world.info http: paths: - path: / pathType: Prefix backend: serviceName: web servicePort: 80
如下所示,上述配置在 nginx-ingress-controller 的 nginx.conf 中創建了以下部分。一個負責為帶有特定 Host: 標頭的請求提供服務,另一個負責為沒有 Host: 標頭的請求提供服務,例如,如果請求直接發送到 IP 地址:
enter http { # works when no Host header is provided ## start server _ server { server_name _ ; listen 80 default_server reuseport backlog=511 ; listen 443 default_server reuseport backlog=511 ssl http2 ; location / { set $namespace "default"; set $ingress_name "ingress-redirect"; set $service_name ""; set $service_port ""; set $location_path "/"; return 301 https://www.google.com; # works when specific Host header is provided ## start server hello-world.info server { server_name hello-world.info ; listen 80 ; listen 443 ssl http2 ; location / { set $namespace "default"; set $ingress_name "ingress-host"; set $service_name "web"; set $service_port "80"; set $location_path "/"; } } ## end server hello-world.info
出於測試目的,我已經快速部署了這兩個入口對象和 nginx pod:
➜ kubectl run --image nginx web
並將其公開以在第二個入口對像後面提供服務:
➜ kubectl expose pod web --port 80
正如您所看到的,當捲曲重定向按預期工作時:
➜ ~ curl $(minikube ip) -I HTTP/1.1 301 Moved Permanently Server: nginx/1.19.0 Date: Tue, 27 Oct 2020 13:22:06 GMT Content-Type: text/html Content-Length: 169 Connection: keep-alive Location: https://www.google.com
如果你 curl 與主機名相同的地址,它會重定向到 nginx pod:
➜ ~ curl $(minikube ip) -H "Host: hello-world.info" --- <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> ---
另外值得一提的是 Kubernetes 文件,它也提供了基於名稱的虛擬主機的良好範例。它支持將 HTTP 流量路由到同一 IP 地址的多個主機名。文件中的範例告訴備份負載均衡器根據Host 標頭路由請求。
例如,上面文件頁面中提到的 Ingress 將請求的流量路由
first.bar.com
到service1
、second.foo.com
到service2
以及任何沒有hostname
在請求中定義的 IP 地址(即沒有顯示請求標頭)的流量到service3
。