k8s负载均衡器配置请求重定向

在某些情况下,后端服务中的公开URI与Ingress规则中的指定路径不同。如果没有rewrite,任何请求都将返回404,可以将Ingress里annotations设置nginx.ingress.kubernetes.io/rewrite-target为服务所需的路径。

通过annotations做rewrite基本配置:

以下操作在k8s 1.13.2版本;ingress-nginx控制器0.24.1版本上进行。

示例一

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: https://www.jianshu.com/u/33c582f040ae
  name: nginx-ingress-1
  namespace: default
spec:
  rules:
  - host: bb.test.com
    http:
      paths:
      - backend:
          serviceName: nginx-svc
          servicePort: 8080
        path: /aaa

当访问http://bb.test.com:8088/aaa时,会被重定向到简书主页https://www.jianshu.com/u/33c582f040ae,如果有多个path,每个都会被rewrite,所以如果只需要替换单个path(也就是location)的时候单独使用一个ingress写。

这里没有配置kubernetes.io/ingress.class将会使用启动参数中没有加--ingress-class的ingress-nginx(同一k8s集群中可能会有多个负载ingress-nginx,这个启动参数用于标识标记了kubernetes.io/ingress.class的ingress将会被哪个ingress-nginx处理)


创建该ingress后,可以在ingress-nginx容器内nginx.conf中看到,location中多了rewrite配置

server {
    server_name bb.test.com ;
    
    listen 80;
    
    set $proxy_upstream_name "-";
    set $pass_access_scheme $scheme;
    set $pass_server_port $server_port;
    set $best_http_host $http_host;
    set $pass_port $pass_server_port;
    
    location ~* "^/aaa" {
      
      set $namespace      "default";
      set $ingress_name   "nginx-ingress-1";
      set $service_name   "nginx-svc";
      set $service_port   "80";
      set $location_path  "/aaa";
      
      rewrite_by_lua_block {
        lua_ingress.rewrite({
          force_ssl_redirect = false,
          use_port_in_redirects = false,
        })
        balancer.rewrite()
        plugins.run()
      }
            
            ##此处省略
      
      rewrite "(?i)/aaa" https://www.jianshu.com/u/33c582f040ae break;
      proxy_pass http://upstream_balancer;
      
      proxy_redirect                          off;
      
    }
    
    location ~* "^/" {
      
      set $namespace      "";
      set $ingress_name   "";
      set $service_name   "";
      set $service_port   "0";
      set $location_path  "/";
      
      rewrite_by_lua_block {
        lua_ingress.rewrite({
          force_ssl_redirect = false,
          use_port_in_redirects = false,
        })
        balancer.rewrite()
        plugins.run()
      }
      
      header_filter_by_lua_block {
        
        plugins.run()
      }
      body_filter_by_lua_block {
        
      }
      
      log_by_lua_block {
        
        balancer.log()
        
        monitor.call()
        
        plugins.run()
      }
      
            ##此处省略
      
      rewrite "(?i)/" https://www.jianshu.com/u/33c582f040ae break;
      proxy_pass http://upstream_balancer;
      
      proxy_redirect                          off;
      
    }
    
  }

访问

配置hosts文件:

192.168.1.103为负载均衡器IP;bb.test.com为上面ingress中配置的host

以上软件为switchhost(方便管理,灵活切换hosts的一款开源软件)

当访问http://bb.test.com:8088/aaa时,会被重定向到简书主页:

其中8088为ingress-nginx的http端口(hostPort方式暴露)

示例二

从版本0.22.0开始,使用注释的入口定义nginx.ingress.kubernetes.io/rewrite-target不向后兼容以前的版本。在版本0.22.0及更高版本中,必须在捕获组中

(https://www.regular-expressions.info/refcapture.html)

明确定义需要传递到重写路径的请求URI中的任何子字符串。

捕获组保存在编号占位符,按时间顺序,形式$1,$2... $n。这些占位符可用作rewrite-target注释中的参数。

创建以下ingress:

$ echo '
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: rewrite
  namespace: default
spec:
  rules:
  - host: rewrite.bar.com
    http:
      paths:
      - backend:
          serviceName: http-svc
          servicePort: 80
        path: /something(/|$)(.*)
' | kubectl create -f -

在此入口定义中,(.*)将捕获的任何字符都将分配给占位符$2,然后将其用作rewrite-target注释中的参数。

生成的nginx.conf内容如下:

server {
    server_name rewrite.bar.com ;
    
    listen 80;
    
    set $proxy_upstream_name "-";
    set $pass_access_scheme $scheme;
    set $pass_server_port $server_port;
    set $best_http_host $http_host;
    set $pass_port $pass_server_port;
    
    location ~* "^/something(/|$)(.*)" {
      
      set $namespace      "default";
      set $ingress_name   "rewrite";
      set $service_name   "http-svc";
      set $service_port   "80";
      set $location_path  "/something(/|${literal_dollar})(.*)";
      
      rewrite_by_lua_block {
        lua_ingress.rewrite({
          force_ssl_redirect = false,
          use_port_in_redirects = false,
        })
        balancer.rewrite()
        plugins.run()
      }
      
      header_filter_by_lua_block {
        
        plugins.run()
      }
      body_filter_by_lua_block {
        
      }
      
      log_by_lua_block {
        
        balancer.log()
        
        monitor.call()
        
        plugins.run()
      }
      ## 此处省略
      
      rewrite "(?i)/something(/|$)(.*)" /$2 break;
      proxy_pass http://upstream_balancer;
      
      proxy_redirect                          off;
      
    }
    
    location ~* "^/" {
      
      set $namespace      "";
      set $ingress_name   "";
      set $service_name   "";
      set $service_port   "0";
      set $location_path  "/";
      
      rewrite_by_lua_block {
        lua_ingress.rewrite({
          force_ssl_redirect = false,
          use_port_in_redirects = false,
        })
        balancer.rewrite()
        plugins.run()
      }
      
      header_filter_by_lua_block {
        
        plugins.run()
      }
      body_filter_by_lua_block {
        
      }
      
      log_by_lua_block {
        
        balancer.log()
        
        monitor.call()
        
        plugins.run()
      }
      
            ## 此处省略
      
      rewrite "(?i)/" /$2 break;
      proxy_pass http://upstream_balancer;
      
      proxy_redirect                          off;
      
    }
    
  }

上面的ingress定义结果将会是如下结果:

- rewrite.bar.com/something重写为rewrite.bar.com/

- rewrite.bar.com/something/重写为rewrite.bar.com/

- rewrite.bar.com/something/new重写为rewrite.bar.com/new

原文发布于微信公众号 - 我的小碗汤(mysmallsoup)

原文发表时间:2019-07-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券