如何在 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:


关于解决方法

假设(出于示例目的):

  • 有 2 个部署:hellogoodbye
  • 两者都与他们的服务相关联,名称为:hello-servicegoodbye-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