如何在 nginx ingress 中基于 http header 重定向 URL?
How to redirect URL based on http header in nginx ingress?
我的请求是通过 Cloudflare 代理的,它根据 IP 地址在 http header 中设置了一个 header 指示国家/地区。我想根据 Nginx 入口控制器中的 header 使用某些路径重定向请求。我该怎么做?
当前 Ingress
nginx-ingress
的资源定义不支持基于 header 的路由。
我找到了一个 解决方法 来路由请求 header (我已经包含了以下步骤)并带有以下注释:
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($http_LocationHeader = "PL") { proxy_pass http://goodbye-service.default.svc.cluster.local:5678; }
其他可能solutions/workarounds:
- 使用
Traefik
:Docs.traefik.io: Routing: Routers
- 使用
Ambassador
:Getambassador.io: Docs: Using: Headers
- 使用
Istio
:Istio.io: Traffic management: Request routing
- 使用基于 header 的路由逻辑将流量从
nginx-ingress
路由到 nginx pod/deployment/daemonset:whosebug.com:如何有一个 header 与 nginx ingress-controller 的路由逻辑?
(答案下的最后评论)
关于解决方法:
假设(出于示例目的):
- 有 2 个部署:
hello
、goodbye
- 两者都与他们的服务相关联,名称为:
hello-service
、goodbye-service
Ingress
资源将以 hello
应始终应答的方式配置,但添加 configuration-snippet
后,流量将被重定向到 goodbye
。
此部署的响应:
| hello | goodbye |
|----------------|----------------|
| Hello, world! | Hello, world! |
| Version: 2.0.0 | Version: 1.0.0 | # notice the version
hello
附加服务的部署示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
spec:
selector:
matchLabels:
app: hello
replicas: 1
template:
metadata:
labels:
app: hello
spec:
containers:
- name: hello
image: "gcr.io/google-samples/hello-app:2.0"
env:
- name: "PORT"
value: "50001"
---
apiVersion: v1
kind: Service
metadata:
name: hello-service
spec:
selector:
app: hello
ports:
- name: hello-port
port: 5678 # IMPORTANT
targetPort: 50001
type: NodePort
要获得 goodbye
部署,请将 hello
替换为 goodbye
并将映像版本更改为 1.0
。
通过 header 重新路由请求的入口定义如下所示:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: hello-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($http_LocationHeader = "PL") { proxy_pass http://goodbye-service.default.svc.cluster.local:5678; }
spec:
rules:
- host:
http:
paths:
- path: /
backend:
serviceName: hello-service
servicePort: hello-port
默认情况下,没有 configuration-snippet
的入口定义将始终将流量路由到 hello-service
,然后再路由到 hello
pods。通过添加:
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($http_LocationHeader = "PL") { proxy_pass http://goodbye-service.default.svc.cluster.local:5678; }
它将检查名为 LocationHeader
的 header 是否存在以及是否匹配 PL
。如果是,它将通过它的 DNS 名称将请求发送到 goodbye-service
。
专注于:
http://goodbye-service.default.svc.cluster.local:5678
http://service_name.namespace.svc.cluster.local:port
(没有值的 DNS 名称)
应用此 Ingress
资源后,您应该能够使用 LocationHeader=PL
发送请求(例如使用 Postman)并获得响应:
Hello, world!
Version: 1.0.0
Hostname: goodbye-5758448754-wr64c
When I tried to use map
directive I was getting following messages:
nginx: [emerg] "map" directive is not allowed here in /tmp/nginx-OMMITED
我的请求是通过 Cloudflare 代理的,它根据 IP 地址在 http header 中设置了一个 header 指示国家/地区。我想根据 Nginx 入口控制器中的 header 使用某些路径重定向请求。我该怎么做?
当前 Ingress
nginx-ingress
的资源定义不支持基于 header 的路由。
我找到了一个 解决方法 来路由请求 header (我已经包含了以下步骤)并带有以下注释:
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($http_LocationHeader = "PL") { proxy_pass http://goodbye-service.default.svc.cluster.local:5678; }
其他可能solutions/workarounds:
- 使用
Traefik
:Docs.traefik.io: Routing: Routers - 使用
Ambassador
:Getambassador.io: Docs: Using: Headers - 使用
Istio
:Istio.io: Traffic management: Request routing - 使用基于 header 的路由逻辑将流量从
nginx-ingress
路由到 nginx pod/deployment/daemonset:whosebug.com:如何有一个 header 与 nginx ingress-controller 的路由逻辑? (答案下的最后评论)
关于解决方法:
假设(出于示例目的):
- 有 2 个部署:
hello
、goodbye
- 两者都与他们的服务相关联,名称为:
hello-service
、goodbye-service
Ingress
资源将以 hello
应始终应答的方式配置,但添加 configuration-snippet
后,流量将被重定向到 goodbye
。
此部署的响应:
| hello | goodbye |
|----------------|----------------|
| Hello, world! | Hello, world! |
| Version: 2.0.0 | Version: 1.0.0 | # notice the version
hello
附加服务的部署示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
spec:
selector:
matchLabels:
app: hello
replicas: 1
template:
metadata:
labels:
app: hello
spec:
containers:
- name: hello
image: "gcr.io/google-samples/hello-app:2.0"
env:
- name: "PORT"
value: "50001"
---
apiVersion: v1
kind: Service
metadata:
name: hello-service
spec:
selector:
app: hello
ports:
- name: hello-port
port: 5678 # IMPORTANT
targetPort: 50001
type: NodePort
要获得 goodbye
部署,请将 hello
替换为 goodbye
并将映像版本更改为 1.0
。
通过 header 重新路由请求的入口定义如下所示:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: hello-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($http_LocationHeader = "PL") { proxy_pass http://goodbye-service.default.svc.cluster.local:5678; }
spec:
rules:
- host:
http:
paths:
- path: /
backend:
serviceName: hello-service
servicePort: hello-port
默认情况下,没有 configuration-snippet
的入口定义将始终将流量路由到 hello-service
,然后再路由到 hello
pods。通过添加:
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($http_LocationHeader = "PL") { proxy_pass http://goodbye-service.default.svc.cluster.local:5678; }
它将检查名为 LocationHeader
的 header 是否存在以及是否匹配 PL
。如果是,它将通过它的 DNS 名称将请求发送到 goodbye-service
。
专注于:
http://goodbye-service.default.svc.cluster.local:5678
http://service_name.namespace.svc.cluster.local:port
(没有值的 DNS 名称)
应用此 Ingress
资源后,您应该能够使用 LocationHeader=PL
发送请求(例如使用 Postman)并获得响应:
Hello, world!
Version: 1.0.0
Hostname: goodbye-5758448754-wr64c
When I tried to use
map
directive I was getting following messages:
nginx: [emerg] "map" directive is not allowed here in /tmp/nginx-OMMITED