在 Nginx Ingress 控制器内配置外部 IP 重定向

在 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 资源都将其服务发布到互联网。

答案1

裸机环境缺乏传统云环境所提供的商品,传统云环境提供网络负载均衡器,单个 K8s 清单足以为 NGINX 入口控制器提供单点联系。当然,我们必须记住,内部重定向遵循入口资源,然后入口资源会相应地配置入口控制器。

外部 IP方法 HTTP 的源 IP 不会被保留,因此尽管它看起来很简单,但不建议使用它。因此,您将丢失有关请求的信息(除非您将监控入口控制器)

要回答如何在 Nginx Ingress Controller 中配置外部 IP 重定向的问题,我们必须首先了解 Ingress 实际上是什么:

Ingress 将集群外部的 HTTP 和 HTTPS 路由暴露给集群内的服务。流量路由由 Ingress 资源上定义的规则控制。必须有一个 Ingress 控制器来满足 Ingress 要求。仅创建 Ingress 资源不起作用。

为了实现预期结果,您应该创建两个单独的入口对象(而不是控制器)。第一个没有指定主机,因此规则适用于通过指定的 IP 地址的所有入站 HTTP 流量,如入口规则

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

为了测试目的,我快速部署了这两个 ingress 对象和 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 地址的多个主机名。文档中的示例告诉后备负载均衡器根据主机头

例如在文档页面上述路由将请求的流量路由first.bar.comservice1,将请求的流量second.foo.com路由到,并将任何发往请求中未定义(即没有提供请求标头)service2的 IP 地址的流量路由到。hostnameservice3

答案2

嘿,看看“默认后端”:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#default-backend

此注释的形式为 nginx.ingress.kubernetes.io/default-backend:,用于指定自定义默认后端。这是对您应用此注释的同一命名空间内的服务的引用。此注释将覆盖全局默认后端。

无关:为了提高安全性,我将我的 IP(ingress-nginx)隐藏在 cloudflares 网络后面。我只允许 cloudflare IP 通过脚本连接到我的网络服务器。独立主机的示例: https://raw.githubusercontent.com/cloudpanel-io/scripts/master/cloudflare/whitelist_ips

优点:

  • 没人知道我的真实 IP
  • 用户只需通过“真实” DNS 记录即可连接

缺点:

  • 您必须使用 Cloudflare(提供免费计划)
  • 更高的 TTFB

附言:我与 cloudflare 没有任何关系,也不为他们工作。

相关内容