Nginx Ingress配置URL重写规则

简介

Ingress 内置变量

内置预定义变量即无需声明就可以使用的变量,通常包括一个http请求或响应中一部分内容的值,以下为一些常用的内置预定义变量:

变量名 定义
$arg_PARAMETER  GET请求中变量名PARAMETER参数的值。
$args   这个变量等于GET请求中的参数。例如,foo=123&bar=blahblah;这个变量只可以被修改
$binary_remote_addr 二进制码形式的客户端地址。
$body_bytes_sent    传送页面的字节数
$content_length 请求头中的Content-length字段。
$content_type   请求头中的Content-Type字段。
$cookie_COOKIE  cookie COOKIE的值。
$document_root  当前请求在root指令中指定的值。
$document_uri   与$uri相同。
$host   请求中的主机头(Host)字段,如果请求中的主机头不可用或者空,则为处理请求的server名称(处理请求的server的server_name指令的值)。值为小写,不包含端口。
$hostname   机器名使用 gethostname系统调用的值
$http_HEADER    HTTP请求头中的内容,HEADER为HTTP请求中的内容转为小写,-变为_(破折号变为下划线),例如:$http_user_agent(Uaer-Agent的值);
$http_user_agent : 客户端agent信息;
$http_cookie : 客户端cookie信息;
$sent_http_HEADER   HTTP响应头中的内容,HEADER为HTTP响应中的内容转为小写,-变为_(破折号变为下划线),例如: $sent_http_cache_control, $sent_http_content_type…;
$is_args    如果$args设置,值为"?",否则为""。
$limit_rate 这个变量可以限制连接速率。
$nginx_version  当前运行的nginx版本号。
$query_string   与$args相同。
$remote_addr    客户端的IP地址。
$remote_port    客户端的端口。
$remote_user    已经经过Auth Basic Module验证的用户名。
$request_filename   当前连接请求的文件路径,由root或alias指令与URI请求生成。
$request_body   这个变量(0.7.58+)包含请求的主要信息。在使用proxy_pass或fastcgi_pass指令的location中比较有意义。
$request_body_file  客户端请求主体信息的临时文件名。
$request_completion 如果请求成功,设为"OK";如果请求未完成或者不是一系列请求中最后一部分则设为空。
$request_method 这个变量是客户端请求的动作,通常为GET或POST。包括0.8.20及之前的版本中,这个变量总为main request中的动作,如果当前请求是一个子请求,并不使用这个当前请求的动作。
$request_uri    这个变量等于包含一些客户端请求参数的原始URI,它无法修改,请查看$uri更改或重写URI,
包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
$scheme 所用的协议,比如http或者是https,比如rewrite ^(.+)$ $scheme://example.com$1 redirect;
$server_addr    服务器地址,在完成一次系统调用后可以确定这个值,如果要绕开系统调用,则必须在listen中指定地址并且使用bind参数。
$server_name    服务器名称。
$server_port    请求到达服务器的端口号。
$server_protocol    请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$uri    请求中的当前URI(不带请求参数,参数位于args),不同于浏览器传递的args),不同于浏览器传递的args),不同于浏览器传递的request_uri的值,它可以通过内部重定向,或者使用index指令进行修改。uri不包含主机名,如”/foo/bar.html”。

Ingress 正则表达式

正则表达式匹配,其中:
~       为区分大小写匹配
~*      为不区分大小写匹配
!~和!~*  分别为区分大小写不匹配及不区分大小写不匹配
.      匹配除换行符以外的任意字符
\w     匹配字母或数字或下划线或汉字
\s     匹配任意的空白符
\d     匹配数字
\b     匹配单词的开始或结束
^      匹配字符串的开始
$      匹配字符串的结束
*         重复零次或更多次
+         重复一次或更多次
?         重复零次或一次
{n}       重复n次
{n,}      重复n次或更多次
{n,m}     重复n到m次
*?        复任意次,但尽可能少重复
+?        重复1次或更多次,但尽可能少重复
??        重复0次或1次,但尽可能少重复
{n,m}?    重复n到m次,但尽可能少重复
{n,}?     重复n次以上,但尽可能少重复
\W        匹配任意不是字母,数字,下划线,汉字的字符
\S        匹配任意不是空白符的字符
\D        匹配任意非数字的字符
\B        匹配不是单词开头或结束的位置
[^x]      匹配除了x以外的任意字符
[^aeiou]  匹配除了aeiou这几个字母以外的任意字符   
(exp)         匹配exp,并捕获文本到自动命名的组里
(?<name>exp)  匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
(?:exp)       匹配exp,不捕获匹配的文本,也不给此分组分配组号   
(?=exp)       匹配exp前面的位置
(?<=exp)      匹配exp后面的位置
(?!exp)       匹配后面跟的不是exp的位置
(?<!exp)      匹配前面不是exp的位置
(?#comment)   注释分组不对正则表达式的处理产生任何影响

配置URL重写规则

Nginx反向代理配置示例

如果想实现访问的url 匹配到的location,不携带给后端服务

location /something {
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-Port $server_port;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_pass http://abc_other/;   # 结尾带了"/"代表反向代理给后端的upstream节点不携带"something"这个关键字.
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection $connection_upgrade;
  proxy_connect_timeout   60s;
  proxy_send_timeout      60s;
  proxy_read_timeout      60s;
  proxy_buffering off;
}
  • 假设我的请求是https://www.qshtest.com/something/abc/create ,当请求到达nginx时,nginx会将/abc/create 这段url反向代理访问后端的节点

Ingress 配置案例

只要有一个Ingress使用了rewrite-target,则所有Ingress定义下同一个host下所有path都会正则大小写敏感,包括没有使用rewrite-target的Ingress。

$  cat ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - host: demo.qshtest.com
    http:
      paths:
      - path: '/something(/|$)(.*)'
        pathType: ImplementationSpecific
        backend:
          service:
            name: <your_service_name>  #替换为您的目标服务名称
            port:
              number: <your_service_port>  #替换为您的目标服务端口
  ingressClassName: nginx

$ kubectl apply -f ingress.yml
ingress.networking.k8s.io/demo configured

以上案例Ingress重写是通过nginx.ingress.kubernetes.io/rewrite-target注解实现不同路径的重写规则。占位符$2表示将第二个括号即(.*)中匹配到的所有字符填写到nginx.ingress.kubernetes.io/rewrite-target注解中。

上面的Ingress正则匹配式将导致多种情况的URL重写,可能的情形如下:

  • 访问“/something”路径重写为“/”路径
  • 访问“/something/”路径重写为“/”路径
  • 访问“/something/new”路径重写为“/new”路径

想必大家都知道Ingress是基于Nginx开发的,此时是通过Ingress CRD进行创建的重写配置,其本质也是修改Nginx配置文件的,此时从Ingress里的Nginx拷贝出来的配置如下:

  server {
    server_name _ ;
    ...
    location ~* "^/something(/|$)(.*)" {
      set $namespace      "default";
      set $ingress_name   "ingress-test";
      set $service_name   "<your_service_name>";
      set $service_port   "80";
      ...
      rewrite "(?i)/something(/|$)(.*)" /$2 break;
      ...
    }
  }

Rewrite指令基本语法结构

rewrite regex replacement [flag];
  • regex:匹配URI的正则表达式。在上述例子中,“(?i)/something(/|$)(.*)”即为匹配URI的正则表达式,其中“(?i)”表示不区分大小写。
  • replacement:重写内容。在上述例子中,“/$2”即为重写内容,表示把路径重写为第二个括号“(.*)”中匹配到的所有字符。
  • flag:表示重写形式的标记,包括:
    • last:表示本条规则匹配完成后继续向下匹配。
    • break:表示本条规则匹配完成后停止匹配。
    • redirect:表示临时重定向,返回状态码302。
    • permanent:表示永久重定向,返回状态码301。

重定向就是将网页自动转向重定向:

  • 301永久性重定向:新网址完全继承旧网址,旧网址的SEO网络搜索引擎的排名等完全清零
  • 301重定向是网页更改地址后对搜索引擎友好的最好方法,只要不是暂时搬移的情况,都建议使用301来做转址。
  • 302临时性重定向:对旧网址没有影响,但新网址不会有排名
  • 搜索引擎爬虫会抓取新的内容而保留旧的网址

高级Rewrite配置规则

对于一些复杂的重写规则需求,可以通过如下注解来实现,其本质也是修改Nginx配置文件,可以实现上面提到的“nginx.ingress.kubernetes.io/rewrite-target”注解的功能,但是自定义程度更高,适合更加复杂的Rewrite需求。

  • nginx.ingress.kubernetes.io/server-snippet:在nginx.conf的“server”字段中添加自定义配置。
  • nginx.ingress.kubernetes.io/configuration-snippet:在nginx.conf的“location”字段中添加自定义配置。

snippet配置在NGINX Ingress控制器版本为2.4.6版本及以上时(对应社区版本为v1.9.3)不再默认启用,详情请参见allow-snippet-annotations启用。

Location 配置案例

永久重定向(permanent)
annotations:
  kubernetes.io/ingress.class: "nginx"
  nginx.ingress.kubernetes.io/configuration-snippet: |
    rewrite ^/$ https://www.baidu.com permanent;
  • 301永久重定向,浏览器器地址栏会显示跳转后的URL地址,真实效果可以通过浏览器访问测试验证
临时重定向(redirect)
  • 通过URL重定向,访问/test/info,直接重定向302跳转到/user/info。
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/configuration-snippet: |
       rewrite ^/test/(.*)$ /user/$1 redirect;
  • 302 说明已经重定向了,实际效果可以通过浏览器访问查看
添加前缀路径
annotations:
  kubernetes.io/ingress.class: "nginx"
  nginx.ingress.kubernetes.io/configuration-snippet: |
    rewrite ^/test/(.*)$ /something/test/$1 redirect;  # 添加 /something 前缀
    rewrite ^/images/(.*)$ /something/images/$1 redirect;  # 添加 /something 前缀
  • 当用户访问“/stylesheets/new.css”路径时,重写为“/something/stylesheets/new.css”路径。
  • 当用户访问“/images/new.jpg”路径时,重写为“/something/images/new.jpg”路径。

更多Rewrite配置案例

指定路径返回401错误码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo
  annotations:
    nginx.ingress.kubernetes.io/server-snippet: |
       location /ops {
        return 401;
        }
spec:
  rules:
  - host: demo.qshtest.com
    http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: <your_service_name>  #替换为您的目标服务名称
            port:
              number: <your_service_port>  #替换为您的目标服务端口
  ingressClassName: nginx
同域名前后端项目转发配置

实现:请求"/“时,访问的前端,访问”/api"时,会将/api 后面的url 传递给后端服务,同时不将api传递给后端,起到了只匹配location的作用

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-test-web
  namespace: ops
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: 100M
    nginx.ingress.kubernetes.io/proxy-next-upstream: error timeout http_500 http_502 http_503 http_504
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite /api/(.*)  /$1 break;
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: "ingress-nginx"
  tls:
   - hosts:
     - admin-int.xxx.cn
     secretName: xxx-tls
  rules:
    - host: admin-int.xxx.cn
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: xxx-front
                port:
                  number: 8099
          - path: /api
            pathType: ImplementationSpecific
            backend:
              service:
                name: xxx-java
                port:
                  number: 8080
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值