簡體   English   中英

Kubernetes 入口:nginx,使用正則表達式匹配精確的 URL 路徑

[英]Kubernetes Ingress: nginx, use-regex to match exact URL path

我有幾個 pod,我正在嘗試匹配它們各自服務的 URL。

Please note that I need to use nginx.ingress.kubernetes.io/rewrite-target to solve this and not 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 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;
    }
}
  • authdata是 Flask API 豆莢工作正常
  • tile-server也是一個 Flask pod,但不需要進行任何模式匹配。 我需要准確匹配/api/tile-server/ URL

我嘗試了以下模式但失敗了:

  • /api/tile-server/
  • /api/tile-server/?(.*)
  • /api/tile-server(/|$)?(.*)

我可以確認 Pod/服務正在其正確的端口上運行,並且我可以通過節點端口訪問它們,但不能通過負載均衡器/域訪問它們。 /api/tile-server/ URL 完全匹配的正確模式是什么?

第一個解決方案- 為具有重寫目標注釋的 tile-server 創建單獨的入口 object。 這將起作用,因為具有相同主機的入口規則由入口 controller 合並在一起,並且單獨的入口 object 允許每個 object 使用不同的注釋:

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: "/$2"
    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: "/$1"

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: "/$1"
    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

如果您希望將它們轉發到其他/匹配的服務,請添加? 在路徑中的(?:/|$)之后。

從 v1beta1 移動到 v1 並使用 pathType: Exact - https://kubernetes.io/docs/concepts/services-networking/ingress/

這是我的解決方案

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: "/$1" name: ingress-staging namespace: staging spec: ingressClassName: nginx rules:

  • http:路徑:

    • path: /(.*) pathType: Prefix backend: service: name: acp-service port: number: 80
  • http:路徑:

    • 路徑:/service-ecommerce(?:/|$)(.*) pathType:前綴后端:服務:名稱:電子商務服務端口:編號:80

謝謝@馬特

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM