【问题标题】:Kubernetes Ingress path based routing not working as expected基于 Kubernetes 入口路径的路由未按预期工作
【发布时间】:2020-06-26 17:42:12
【问题描述】:

我在 kubernetes 集群中安装了NGINX Ingress。当我尝试通过 Ingress Controller 访问微服务端时,它没有按预期工作

我已经部署了两个spring boot应用

入口规则

  • 路径 1 -> /customer
  • 路径 2 -> /prac

当我尝试访问其中一项服务时。 http://test.practice.com/prac/practice/getprac,不行

但是当我尝试在没有入口路径 http://test.practice.com/practice/getprac 的情况下访问时,它可以工作

我无法理解为什么 Ingress 路径无法正常工作,而其他服务也会发生同样的情况

微服务 1(端口 9090)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: customer
  namespace: practice
  labels: 
    app: customer
spec:
  replicas: 5
  selector:
    matchLabels: 
      app: customer
  template: 
    metadata:
      labels: 
        app: customer
    spec: 
      imagePullSecrets:
      - name: testkuldeepsecret
      containers:
      - name: customer
        image: kuldeep99/customer:v1
        ports:
        - containerPort: 9090
          hostPort: 9090

---
apiVersion: v1
kind: Service
metadata:                     
  name: customer-service
  namespace: practice
  labels: 
spec:                         
  ports: 
  - port: 9090 
    targetPort: 9090
    protocol: TCP
    name: http
  selector:
    app: customer

微服务2(8000端口)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: prac
  namespace: practice
  labels: 
    app: prac
spec:
  replicas: 4
  selector:
    matchLabels: 
      app: prac
  template: 
    metadata:
      labels: 
        app: prac
    spec: 
      imagePullSecrets:
      - name: testkuldeepsecret
      containers:
      - name: prac
        image: kuldeep99/practice:v1
        ports:
        - containerPort: 8000
          hostPort: 8000

---
apiVersion: v1
kind: Service
metadata:                     
  name: prac-service
  namespace: practice
  labels: 
spec:                         
  ports: 
  - port: 8000 
    targetPort: 8000
    protocol: TCP
    name: http
  selector:
    app: prac

服务(客户服务和实践服务)

NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
customer-service   ClusterIP   10.97.203.19    <none>        9090/TCP   39m
ngtest             ClusterIP   10.98.74.149    <none>        80/TCP     21h
prac-service       ClusterIP   10.96.164.210   <none>        8000/TCP   15m
some-mysql         ClusterIP   None            <none>        3306/TCP   2d16h

入口

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: practice-ingress
  namespace: practice
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec: 
  rules:
  - host: practice.example.com
    http: 
      paths:
      - backend:
          serviceName: customer-service
          servicePort: 9090
        path: /customer
      - backend:
          serviceName: prac-service
          servicePort: 8000
        path: /prac

【问题讨论】:

    标签: spring-boot kubernetes kubernetes-ingress nginx-ingress


    【解决方案1】:

    你已经安装了这个nginx ingress

    nginx.ingress.kubernetes.io/rewrite-target: / 注释要正常工作,您需要安装此nginx ingress

    解决这个问题的另一种方法是在spring应用程序中将contextPath配置为/prac

    【讨论】:

    • 删除注释后行为也相同
    • 所以 Spring Boot 应用程序有一个用于 /practice/getprac 的休息控制器?
    • 在 Spring Boot 应用程序中将 contextPath 设置为 /prac
    • 感谢它的工作,我没有任何示例指定上下文路径应与入口路径匹配。想了解 rewrite-target 注解
    • 你安装的是 nginx plus ingress 而不是 kubernetes nginx ingress...这就是注解不起作用的原因
    【解决方案2】:

    我确实花了一天的时间来解决这个问题。问题只是安装了错误的 nginx。我使用 helm found here 来安装 nginx-ingress

    安装它,请使用 helm 版本 3:

    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    helm repo update
    
    helm install ingress-nginx ingress-nginx/ingress-nginx
    

    运行后,您将在日志中看到一个 sn-p,说明您的入口应该是什么样子。如果您想执行上述操作,您可以使用上面建议的注释,以后,您可以按照教程here 来实现更多,例如重写。

    我的集群使用 GKE 部署在 GCP 上

    完成后,这是输出日志:

    NAME: ingress-nginx
    LAST DEPLOYED: Sat Apr 24 07:56:11 2021
    NAMESPACE: default
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    NOTES:
    The ingress-nginx controller has been installed.
    It may take a few minutes for the LoadBalancer IP to be available.
    You can watch the status by running 'kubectl --namespace default get services -o wide -w ingress-nginx-controller'
    
    An example Ingress that makes use of the controller:
    
      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress
      metadata:
        annotations:
          kubernetes.io/ingress.class: nginx
        name: example
        namespace: foo
      spec:
        rules:
          - host: www.example.com
            http:
              paths:
                - backend:
                    serviceName: exampleService
                    servicePort: 80
                  path: /
        # This section is only required if TLS is to be enabled for the Ingress
        tls:
            - hosts:
                - www.example.com
              secretName: example-tls
    
    If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:
    
      apiVersion: v1
      kind: Secret
      metadata:
        name: example-tls
        namespace: foo
      data:
        tls.crt: <base64 encoded cert>
        tls.key: <base64 encoded key>
      type: kubernetes.io/tls
    

    这是安装后的样子:

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: nginx
        nginx.ingress.kubernetes.io/rewrite-target: /$2
    
      name: example
      # namespace: foo
    spec:
      rules:
        - host: [your ip address].sslip.io
          http:
            paths:
              - backend:
                  serviceName: registry-app-server
                  servicePort: 8761
                path: /eureka/(.*)
              - backend:
                  serviceName: api-gateway-server
                  servicePort: 7000
                path: /api(/|$)(.*)
    

    如您所见,我正在使用 kubernetes(gke) 部署 Spring 微服务。 使用 nginx-ingress 比内置 gke ingress 有很多好处,而且比its counterparts更受欢迎

    【讨论】:

    • "nginx.ingress.kubernetes.io/rewrite-target: /$2" 解决了我的问题,在配置之前,我收到一个错误:Whitelabel Error Page。我已经为这个问题花了三天时间。非常感谢 Arsene
    【解决方案3】:

    在讨论中,我观察到一件事。我们不应该混淆

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    

    首先确保我们使用的是哪个 Ingress 控制器,并根据该控制器决定 apiVersion。我正在使用“ingress-nginx”(不是“nginx-ingress”)。这个支持“apiVersion:networking.k8s.io/v1beta1”,并根据“Arsene”评论发挥魅力。

    这个 Ingress yaml 文件与“ingress-nginx”入口控制器一起工作

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: nginx
        nginx.ingress.kubernetes.io/rewrite-target: /$2
    
      name: k8-exercise-03-two-app-ingress
    spec:
      rules:
        - host: ex03.k8.sb.two.app.ingress.com
          http:
            paths:
              - backend:
                  serviceName: k8-excercise-01-app-service
                  servicePort: 8080
                path: /one(/|$)(.*)
              - backend:
                  serviceName: k8-exercise-03-ms-service
                  servicePort: 8081
                path: /two(/|$)(.*)
    

    但是,这个 Ingress yaml 文件不适用于“ingress-nginx”入口控制器

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
        name: k8-exercise-03-two-app-ingress
        annotations:
           kubernetes.io/ingress.class: "nginx"
    #       nginx.ingress.kubernetes.io/use-regex: "true"
           ingress.kubernetes.io/rewrite-target: /$2
    spec:
    #  ingressClassName: nginx
      rules:
     #192.168.1.5 ex03.k8.sb.com is mapped in host file. 192.168.1.5 is Host machine IP
      - host: ex03.k8.sb.two.app.ingress.com
        http:
            paths:
            - backend:
                service:
                    name: k8-excercise-01-app-service
                    port:
                        number: 8080  
              path: /one(/|$)(.*)
              pathType: Prefix
              
            - pathType: Prefix
              path: /two(/|$)(.*)
              backend:
                service:
                    name: k8-exercise-03-ms-service
                    port:
                        number: 8081
    

    我可以像这样访问 Spring Boot API 调用:

    对于 App-1:

    http://ex03.k8.sb.two.app.ingress.com/one/
    Result: App One - Root
    
    http://ex03.k8.sb.two.app.ingress.com/one/one
    Result: App One - One API
    
    http://ex03.k8.sb.two.app.ingress.com/one/api/v1/hello
    Result: App One - Hello API
    

    App-2:

    http://ex03.k8.sb.two.app.ingress.com/two/message/James%20Bond
    Result: App Two- Hi James Bond API
    

    最后,如果有人知道如何更改“apiVersion:networking.k8s.io/v1”yaml 以支持“ingress-nginx”控制器,将不胜感激。谢谢你。内容太长见谅

    【讨论】:

      猜你喜欢
      • 2019-06-22
      • 2020-02-27
      • 2014-05-02
      • 1970-01-01
      • 2016-08-19
      • 2015-09-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多