如何根据 nginx 入口中的 http 标头重定向 URL?

Sud*_*thy 0 google-kubernetes-engine kubernetes-ingress nginx-ingress

我的请求是通过 Cloudflare 代理的,Cloudflare 会根据 IP 地址在 http 标头中设置一个标头,指示国家/地区。我想根据 Nginx 入口控制器中的此标头使用某些路径重定向请求。我该怎么做呢?

Daw*_*ruk 6

当前Ingress资源定义nginx-ingress不支持基于标头的路由。

我找到了一种解决方法,可以通过其标头(我已经包含以下步骤)使用以下注释路由请求:

    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($http_LocationHeader = "PL") { proxy_pass http://goodbye-service.default.svc.cluster.local:5678; }
Run Code Online (Sandbox Code Playgroud)

其他可能的解决方案/解决方法:


至于解决方法

假设(例如目的):

  • 有 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
Run Code Online (Sandbox Code Playgroud)

hello附加服务的部署示例:

|     hello      |    goodbye     |
|----------------|----------------|
| Hello, world!  | Hello, world!  |
| Version: 2.0.0 | Version: 1.0.0 | # notice the version
Run Code Online (Sandbox Code Playgroud)

要获得goodbye部署,请替换hellogoodbye并将图像版本更改为1.0.

通过标头重新路由请求的入口定义如下所示:

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
Run Code Online (Sandbox Code Playgroud)

默认情况下,没有 的 Ingress 定义configuration-snippet将始终将流量路由hello-servicehelloPod ,然后再路由到Pod。通过添加:

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
Run Code Online (Sandbox Code Playgroud)

它将检查命名的标头LocationHeader是否存在以及是否匹配PL。如果是,它将goodbye-service通过它的 DNS 名称发送请求。

专注于:

  • http://goodbye-service.default.svc.cluster.local:5678
  • http://service_name.namespace.svc.cluster.local:port (没有值的 dns 名称)

应用此Ingress资源后,您应该能够发送请求LocationHeader=PL(例如使用Postman)并获得响应:

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
Run Code Online (Sandbox Code Playgroud)

当我尝试使用map指令时,我收到以下消息:

  • nginx: [emerg] "map" directive is not allowed here in /tmp/nginx-OMMITED