Kubernetes Ingress:nginx,使用正则表达式匹配精确的 URL 路径
Kubernetes Ingress: nginx, use-regex to match exact URL path
我有一些 pods 正在尝试匹配 URL 以获取它们各自的服务。
请注意我需要使用nginx.ingress.kubernetes.io/rewrite-target
来解决这个问题不是nginx.ingress.kubernetes.io/rewrite-target
我的入口配置文件如下所示。请注意 /api/tile-server/
没有任何正则表达式模式
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/use-regex: "true"
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
namespace: default
spec:
tls:
- hosts:
- example.com
secretName: tls-secret
rules:
- host: example.com
http:
paths:
- path: /?(.*)
backend:
serviceName: client
servicePort: 80
- path: /api/auth/?(.*)
backend:
serviceName: auth
servicePort: 8000
- path: /api/data/?(.*)
backend:
serviceName: data
servicePort: 8001
- path: /api/tile-server/
backend:
serviceName: tile-server
servicePort: 7800
client
pod 是内置在 nginx 中的 React 应用程序 docker 图像工作正常
nginx.conf
看起来像这样(如果有帮助的话)
server {
# listen on port 80
listen 80;
# where the root here
root /usr/share/nginx/html;
# what file to server as index
index index.html index.htm;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to redirecting to index.html
try_files $uri $uri/ /index.html;
}
# Media: images, icons, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
}
# Javascript and CSS files
location ~* \.(?:css|js)$ {
try_files $uri =404;
expires 1y;
access_log off;
add_header Cache-Control "public";
}
# Any route containing a file extension (e.g. /devicesfile.js)
location ~ ^.+\..+$ {
try_files $uri =404;
}
}
auth
和 data
是 Flask API pods 工作正常
tile-server
也是一个 Flask pod,但不需要进行任何模式匹配。我需要匹配准确的 /api/tile-server/
URL
我尝试了以下模式但失败了:
/api/tile-server/
/api/tile-server/?(.*)
/api/tile-server(/|$)?(.*)
我可以确认 pods/services 在它们正确的端口上 运行,我可以通过节点端口访问它们,但不能通过负载 balancer/domain 访问它们。
完全匹配 /api/tile-server/
URL 的正确模式是什么?
从 v1beta1 移至 v1 并使用路径类型:精确 - https://kubernetes.io/docs/concepts/services-networking/ingress/
第一个解决方案 - 使用重写目标注释为 tile-server 创建单独的入口对象。这将起作用,因为具有相同主机的入口规则由入口控制器合并在一起,并且单独的入口对象允许每个对象使用不同的注释:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: tile-ingress-service
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: "/"
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
namespace: default
spec:
tls:
- hosts:
- example.com
secretName: tls-secret
rules:
- host: example.com
http:
paths:
- path: /api/tile-server(/|$)(.*)
backend:
serviceName: tile-server
servicePort: 7800
第二种解决方案 - 重写当前入口以使用重写路径。需要对正则表达式进行一些更改。
注意非捕获组表示法:(?:<regex>)
。这允许跳过这些组的编号,因为我需要所有相关的东西都在第一组中才能工作,因为 rewrite-target: "/"
.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: "/"
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
namespace: default
spec:
tls:
- hosts:
- example.com
secretName: tls-secret
rules:
- host: example.com
http:
paths:
- path: /(.*)
backend:
serviceName: client
servicePort: 80
- path: /(api/auth(?:/|$).*)
backend:
serviceName: auth
servicePort: 8000
- path: /(api/data(?:/|$).*)
backend:
serviceName: data
servicePort: 8001
- path: /api/tile-server(?:/|$)(.*)
backend:
serviceName: tile-server
servicePort: 7800
以下是重写的工作方式:
- 授权服务(数据服务同理)
/api/auth ---> /api/auth
/api/auth/ ---> /api/auth/
/api/auth/xxx ---> /api/auth/xxx
- 磁贴服务器服务:
/api/tile-server ---> /
/api/tile-server/ ---> /
/api/tile-server/xxx ---> /xxx
- 客服
/xxx ---> /xxx
注意以下路径将被转发到客户端服务(其中 xxx 是任何字母数字字符串):
/api/authxxx
/api/dataxxx
/api/tile-serverxxx
如果您希望将它们转发到 other/matching 服务,请在路径中的 (?:/|$)
之后添加 ?
。
这是我的解决方案
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/"
name: ingress-staging
namespace: staging
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /(.*)
pathType: Prefix
backend:
service:
name: acp-service
port:
number: 80
- http:
paths:
- path: /service-ecommerce(?:/|$)(.*)
pathType: Prefix
backend:
service:
name: ecommerce-service
port:
number: 80
谢谢@Matt
我有一些 pods 正在尝试匹配 URL 以获取它们各自的服务。
请注意我需要使用nginx.ingress.kubernetes.io/rewrite-target
来解决这个问题不是nginx.ingress.kubernetes.io/rewrite-target
我的入口配置文件如下所示。请注意 /api/tile-server/
没有任何正则表达式模式
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/use-regex: "true"
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
namespace: default
spec:
tls:
- hosts:
- example.com
secretName: tls-secret
rules:
- host: example.com
http:
paths:
- path: /?(.*)
backend:
serviceName: client
servicePort: 80
- path: /api/auth/?(.*)
backend:
serviceName: auth
servicePort: 8000
- path: /api/data/?(.*)
backend:
serviceName: data
servicePort: 8001
- path: /api/tile-server/
backend:
serviceName: tile-server
servicePort: 7800
client
pod 是内置在 nginx 中的 React 应用程序 docker 图像工作正常nginx.conf
看起来像这样(如果有帮助的话)
server {
# listen on port 80
listen 80;
# where the root here
root /usr/share/nginx/html;
# what file to server as index
index index.html index.htm;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to redirecting to index.html
try_files $uri $uri/ /index.html;
}
# Media: images, icons, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
}
# Javascript and CSS files
location ~* \.(?:css|js)$ {
try_files $uri =404;
expires 1y;
access_log off;
add_header Cache-Control "public";
}
# Any route containing a file extension (e.g. /devicesfile.js)
location ~ ^.+\..+$ {
try_files $uri =404;
}
}
auth
和data
是 Flask API pods 工作正常tile-server
也是一个 Flask pod,但不需要进行任何模式匹配。我需要匹配准确的/api/tile-server/
URL
我尝试了以下模式但失败了:
/api/tile-server/
/api/tile-server/?(.*)
/api/tile-server(/|$)?(.*)
我可以确认 pods/services 在它们正确的端口上 运行,我可以通过节点端口访问它们,但不能通过负载 balancer/domain 访问它们。
完全匹配 /api/tile-server/
URL 的正确模式是什么?
从 v1beta1 移至 v1 并使用路径类型:精确 - https://kubernetes.io/docs/concepts/services-networking/ingress/
第一个解决方案 - 使用重写目标注释为 tile-server 创建单独的入口对象。这将起作用,因为具有相同主机的入口规则由入口控制器合并在一起,并且单独的入口对象允许每个对象使用不同的注释:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: tile-ingress-service
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: "/"
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
namespace: default
spec:
tls:
- hosts:
- example.com
secretName: tls-secret
rules:
- host: example.com
http:
paths:
- path: /api/tile-server(/|$)(.*)
backend:
serviceName: tile-server
servicePort: 7800
第二种解决方案 - 重写当前入口以使用重写路径。需要对正则表达式进行一些更改。
注意非捕获组表示法:(?:<regex>)
。这允许跳过这些组的编号,因为我需要所有相关的东西都在第一组中才能工作,因为 rewrite-target: "/"
.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: "/"
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
namespace: default
spec:
tls:
- hosts:
- example.com
secretName: tls-secret
rules:
- host: example.com
http:
paths:
- path: /(.*)
backend:
serviceName: client
servicePort: 80
- path: /(api/auth(?:/|$).*)
backend:
serviceName: auth
servicePort: 8000
- path: /(api/data(?:/|$).*)
backend:
serviceName: data
servicePort: 8001
- path: /api/tile-server(?:/|$)(.*)
backend:
serviceName: tile-server
servicePort: 7800
以下是重写的工作方式:
- 授权服务(数据服务同理)
/api/auth ---> /api/auth
/api/auth/ ---> /api/auth/
/api/auth/xxx ---> /api/auth/xxx
- 磁贴服务器服务:
/api/tile-server ---> /
/api/tile-server/ ---> /
/api/tile-server/xxx ---> /xxx
- 客服
/xxx ---> /xxx
注意以下路径将被转发到客户端服务(其中 xxx 是任何字母数字字符串):
/api/authxxx
/api/dataxxx
/api/tile-serverxxx
如果您希望将它们转发到 other/matching 服务,请在路径中的 (?:/|$)
之后添加 ?
。
这是我的解决方案
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/"
name: ingress-staging
namespace: staging
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /(.*)
pathType: Prefix
backend:
service:
name: acp-service
port:
number: 80
- http:
paths:
- path: /service-ecommerce(?:/|$)(.*)
pathType: Prefix
backend:
service:
name: ecommerce-service
port:
number: 80
谢谢@Matt