Docker Kubernetes入口服务不适用于不同于根的url

Docker Kubernetes入口服务不适用于不同于根的url,docker,nginx,kubernetes,nginx-ingress,Docker,Nginx,Kubernetes,Nginx Ingress,我正在本地k8s集群上测试一个简单的应用程序,该集群由React FE和Spring Boot BE组成。群集正在docker desktop for windows中运行,版本为1.14.8(docker desktop 2.1.0.5) 我的问题是,配置的入口服务似乎无法将流量路由到be部署,而FE服务效果很好(我实际上可以在浏览器中看到react应用程序,但其余调用be失败)。我尝试过不同的解决方案,但我无法理解我的配置出了什么问题 FE映像公开端口3000,BE映像公开端口8080(根路

我正在本地k8s集群上测试一个简单的应用程序,该集群由React FE和Spring Boot BE组成。群集正在docker desktop for windows中运行,版本为1.14.8(docker desktop 2.1.0.5)

我的问题是,配置的入口服务似乎无法将流量路由到be部署,而FE服务效果很好(我实际上可以在浏览器中看到react应用程序,但其余调用be失败)。我尝试过不同的解决方案,但我无法理解我的配置出了什么问题

FE映像公开端口3000,BE映像公开端口8080(根路径为/apptest),使用docker运行映像,按预期运行这两个工作,回答这些端口上的请求

对于k8s配置,我为这两个映像定义了一个部署,FE为containerPort 3000,BE为containerPort 8080。然后,我创建了两个ClusterIP服务,一个用于FE的端口3000和targetPort 3000,另一个用于BE的端口8080和targetPort 8080

入口服务被配置为通过路径/响应到servicePort 3000(FE)的任何请求,并通过路径/api响应到servicePort 8080的任何请求(在这种情况下,是删除“api”位)。FE配置为使用/api路径启动后端调用

当应用k8s集群上的文件时,所有文件都会正确启动,POD中没有错误,我可以在上访问react应用程序。但是,如果我尝试使用url调用后端,它们将失败,并给出502错误网关

FE Dockerfile

FROM node:12-alpine as builder
WORKDIR /app
COPY ./package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx
EXPOSE 3000
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/build /usr/share/nginx/html
FE Nginx配置

server {
    listen 3000;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-fe-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest-fe # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest-fe
    spec:
      containers:
        - name: apptest-fe
          imagePullPolicy: Always
          image: registryipaddress:5000/apptestgroup/apptest-fe:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 3000

apiVersion: v1
kind: Service
metadata:
  name: apptest-fe-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest-fe
  ports:
    - port: 3000
      targetPort: 3000

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest
    spec:
      containers:
        - name: apptest
          imagePullPolicy: Always
          # Di default kubernetes va su docker hub a recuperare l'immagine.
          # Se il tag dell'immagine inizia con un indirizzo ip, lo interpreta come
          # il registro da cui pullare l'immagine.
          image: registryipaddress:5000/apptestgroup/apptest:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 8080

apiVersion: v1
kind: Service
metadata:
  name: apptest-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest
  ports:
    - port: 8080
      targetPort: 8080
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: apptest-ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - http:
        paths:
          - path: /?(.*)
            backend:
              serviceName: apptest-fe-cluster-ip
              servicePort: 3000
          - path: /api/?(.*)
            backend:
              serviceName: apptest-cluster-ip
              servicePort: 8080

xhr.js:172 POST http://localhost/api/apptest/documents/base64/aaa333 502 (Bad Gateway)...
createError.js:16 Uncaught (in promise) Error: Request failed with status code 502
    at e.exports (createError.js:16)
    at e.exports (settle.js:17)
    at XMLHttpRequest.f.onreadystatechange (xhr.js:59)
成为Dockerfile

FROM java:8
VOLUME /tmp
ARG JAR_FILE
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
FE部署

server {
    listen 3000;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-fe-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest-fe # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest-fe
    spec:
      containers:
        - name: apptest-fe
          imagePullPolicy: Always
          image: registryipaddress:5000/apptestgroup/apptest-fe:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 3000

apiVersion: v1
kind: Service
metadata:
  name: apptest-fe-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest-fe
  ports:
    - port: 3000
      targetPort: 3000

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest
    spec:
      containers:
        - name: apptest
          imagePullPolicy: Always
          # Di default kubernetes va su docker hub a recuperare l'immagine.
          # Se il tag dell'immagine inizia con un indirizzo ip, lo interpreta come
          # il registro da cui pullare l'immagine.
          image: registryipaddress:5000/apptestgroup/apptest:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 8080

apiVersion: v1
kind: Service
metadata:
  name: apptest-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest
  ports:
    - port: 8080
      targetPort: 8080
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: apptest-ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - http:
        paths:
          - path: /?(.*)
            backend:
              serviceName: apptest-fe-cluster-ip
              servicePort: 3000
          - path: /api/?(.*)
            backend:
              serviceName: apptest-cluster-ip
              servicePort: 8080

xhr.js:172 POST http://localhost/api/apptest/documents/base64/aaa333 502 (Bad Gateway)...
createError.js:16 Uncaught (in promise) Error: Request failed with status code 502
    at e.exports (createError.js:16)
    at e.exports (settle.js:17)
    at XMLHttpRequest.f.onreadystatechange (xhr.js:59)
FE集群

server {
    listen 3000;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-fe-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest-fe # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest-fe
    spec:
      containers:
        - name: apptest-fe
          imagePullPolicy: Always
          image: registryipaddress:5000/apptestgroup/apptest-fe:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 3000

apiVersion: v1
kind: Service
metadata:
  name: apptest-fe-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest-fe
  ports:
    - port: 3000
      targetPort: 3000

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest
    spec:
      containers:
        - name: apptest
          imagePullPolicy: Always
          # Di default kubernetes va su docker hub a recuperare l'immagine.
          # Se il tag dell'immagine inizia con un indirizzo ip, lo interpreta come
          # il registro da cui pullare l'immagine.
          image: registryipaddress:5000/apptestgroup/apptest:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 8080

apiVersion: v1
kind: Service
metadata:
  name: apptest-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest
  ports:
    - port: 8080
      targetPort: 8080
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: apptest-ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - http:
        paths:
          - path: /?(.*)
            backend:
              serviceName: apptest-fe-cluster-ip
              servicePort: 3000
          - path: /api/?(.*)
            backend:
              serviceName: apptest-cluster-ip
              servicePort: 8080

xhr.js:172 POST http://localhost/api/apptest/documents/base64/aaa333 502 (Bad Gateway)...
createError.js:16 Uncaught (in promise) Error: Request failed with status code 502
    at e.exports (createError.js:16)
    at e.exports (settle.js:17)
    at XMLHttpRequest.f.onreadystatechange (xhr.js:59)
BE部署

server {
    listen 3000;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-fe-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest-fe # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest-fe
    spec:
      containers:
        - name: apptest-fe
          imagePullPolicy: Always
          image: registryipaddress:5000/apptestgroup/apptest-fe:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 3000

apiVersion: v1
kind: Service
metadata:
  name: apptest-fe-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest-fe
  ports:
    - port: 3000
      targetPort: 3000

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest
    spec:
      containers:
        - name: apptest
          imagePullPolicy: Always
          # Di default kubernetes va su docker hub a recuperare l'immagine.
          # Se il tag dell'immagine inizia con un indirizzo ip, lo interpreta come
          # il registro da cui pullare l'immagine.
          image: registryipaddress:5000/apptestgroup/apptest:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 8080

apiVersion: v1
kind: Service
metadata:
  name: apptest-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest
  ports:
    - port: 8080
      targetPort: 8080
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: apptest-ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - http:
        paths:
          - path: /?(.*)
            backend:
              serviceName: apptest-fe-cluster-ip
              servicePort: 3000
          - path: /api/?(.*)
            backend:
              serviceName: apptest-cluster-ip
              servicePort: 8080

xhr.js:172 POST http://localhost/api/apptest/documents/base64/aaa333 502 (Bad Gateway)...
createError.js:16 Uncaught (in promise) Error: Request failed with status code 502
    at e.exports (createError.js:16)
    at e.exports (settle.js:17)
    at XMLHttpRequest.f.onreadystatechange (xhr.js:59)
成为集群

server {
    listen 3000;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-fe-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest-fe # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest-fe
    spec:
      containers:
        - name: apptest-fe
          imagePullPolicy: Always
          image: registryipaddress:5000/apptestgroup/apptest-fe:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 3000

apiVersion: v1
kind: Service
metadata:
  name: apptest-fe-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest-fe
  ports:
    - port: 3000
      targetPort: 3000

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest
    spec:
      containers:
        - name: apptest
          imagePullPolicy: Always
          # Di default kubernetes va su docker hub a recuperare l'immagine.
          # Se il tag dell'immagine inizia con un indirizzo ip, lo interpreta come
          # il registro da cui pullare l'immagine.
          image: registryipaddress:5000/apptestgroup/apptest:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 8080

apiVersion: v1
kind: Service
metadata:
  name: apptest-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest
  ports:
    - port: 8080
      targetPort: 8080
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: apptest-ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - http:
        paths:
          - path: /?(.*)
            backend:
              serviceName: apptest-fe-cluster-ip
              servicePort: 3000
          - path: /api/?(.*)
            backend:
              serviceName: apptest-cluster-ip
              servicePort: 8080

xhr.js:172 POST http://localhost/api/apptest/documents/base64/aaa333 502 (Bad Gateway)...
createError.js:16 Uncaught (in promise) Error: Request failed with status code 502
    at e.exports (createError.js:16)
    at e.exports (settle.js:17)
    at XMLHttpRequest.f.onreadystatechange (xhr.js:59)
入口服务

server {
    listen 3000;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-fe-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest-fe # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest-fe
    spec:
      containers:
        - name: apptest-fe
          imagePullPolicy: Always
          image: registryipaddress:5000/apptestgroup/apptest-fe:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 3000

apiVersion: v1
kind: Service
metadata:
  name: apptest-fe-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest-fe
  ports:
    - port: 3000
      targetPort: 3000

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest
    spec:
      containers:
        - name: apptest
          imagePullPolicy: Always
          # Di default kubernetes va su docker hub a recuperare l'immagine.
          # Se il tag dell'immagine inizia con un indirizzo ip, lo interpreta come
          # il registro da cui pullare l'immagine.
          image: registryipaddress:5000/apptestgroup/apptest:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 8080

apiVersion: v1
kind: Service
metadata:
  name: apptest-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest
  ports:
    - port: 8080
      targetPort: 8080
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: apptest-ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - http:
        paths:
          - path: /?(.*)
            backend:
              serviceName: apptest-fe-cluster-ip
              servicePort: 3000
          - path: /api/?(.*)
            backend:
              serviceName: apptest-cluster-ip
              servicePort: 8080

xhr.js:172 POST http://localhost/api/apptest/documents/base64/aaa333 502 (Bad Gateway)...
createError.js:16 Uncaught (in promise) Error: Request failed with status code 502
    at e.exports (createError.js:16)
    at e.exports (settle.js:17)
    at XMLHttpRequest.f.onreadystatechange (xhr.js:59)
来自Chrome的502错误

server {
    listen 3000;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-fe-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest-fe # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest-fe
    spec:
      containers:
        - name: apptest-fe
          imagePullPolicy: Always
          image: registryipaddress:5000/apptestgroup/apptest-fe:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 3000

apiVersion: v1
kind: Service
metadata:
  name: apptest-fe-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest-fe
  ports:
    - port: 3000
      targetPort: 3000

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apptest-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: apptest # uguale al template specificato sotto
  template:
    metadata:
      labels:
        component: apptest
    spec:
      containers:
        - name: apptest
          imagePullPolicy: Always
          # Di default kubernetes va su docker hub a recuperare l'immagine.
          # Se il tag dell'immagine inizia con un indirizzo ip, lo interpreta come
          # il registro da cui pullare l'immagine.
          image: registryipaddress:5000/apptestgroup/apptest:latest
          resources:
            limits:
              memory: "128Mi"
              cpu: "10m"
          ports:
            - containerPort: 8080

apiVersion: v1
kind: Service
metadata:
  name: apptest-cluster-ip
spec:
  type: ClusterIP
  selector:
    component: apptest
  ports:
    - port: 8080
      targetPort: 8080
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: apptest-ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - http:
        paths:
          - path: /?(.*)
            backend:
              serviceName: apptest-fe-cluster-ip
              servicePort: 3000
          - path: /api/?(.*)
            backend:
              serviceName: apptest-cluster-ip
              servicePort: 8080

xhr.js:172 POST http://localhost/api/apptest/documents/base64/aaa333 502 (Bad Gateway)...
createError.js:16 Uncaught (in promise) Error: Request failed with status code 502
    at e.exports (createError.js:16)
    at e.exports (settle.js:17)
    at XMLHttpRequest.f.onreadystatechange (xhr.js:59)
我有点确信问题在于为ReactApp提供服务的FE容器中的nginx,它以某种方式绕过入口服务并尝试将流量路由到它不知道的路径,但我不确定如何找到解决方法

更新


我尝试将FE映射到ingress服务中的/app,以便检查问题是否出在容器内的nginx上。导航到react应用程序工作,即使没有完全工作,但尝试与邮递员联系仍然会出现502错误

第一条进入规则每次都会匹配,请求不会到达BE。检查位置块是如何生成的:

您将在nginx中完成以下操作:

location ~* ^/?(.*) {
  ...
}

location ~* "^/api/?(.*)" {
  ...
}

当您遇到入口问题时,请务必检查日志以查看哪个服务获得请求,这是一个建议。调试时直接在浏览器中访问,比通过前端更不容易出错。

这不是入口问题,我复制了您的场景,您的语法是正确的

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress-service
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - host: hello-world.info
    http:
      paths:
      - path: /?(.*)
        backend:
          serviceName: web
          servicePort: 8080
      - path: /api/?(.*)
        backend:
          serviceName: webv2
          servicePort: 8080
测试输出:

user@minikube:~$ curl http://hello-world.info/aaa.any
Hello, world! Version: 1.0.0
Hostname: web-9bbd7b488-hlxd4

user@minikube:~$ curl http://hello-world.info/api/bbb.any
Hello, world! Version: 2.0.0
Hostname: web2-74cf4946cc-8c586

user@minikube:~$ curl http://hello-world.info/
Hello, world! Version: 1.0.0
Hostname: web-9bbd7b488-hlxd4

user@minikube:~$ curl http://hello-world.info/api/
Hello, world! Version: 2.0.0
Hostname: web2-74cf4946cc-8c586
-入口路径匹配:

为了实现更精确的路径匹配,ingress nginx在将路径作为位置块写入nginx模板之前,首先按降序长度对路径进行排序

您上次的更新清楚地表明问题出在您的后端应用程序中,因为它返回相同的
502坏网关

请仔细检查。

原来问题在于后端应用程序的资源分配。我把它们设置得很低,因为在我的电脑上,pod不会启动。我只是在部署配置中添加了多一点资源,现在一切正常了


让我觉得问题在于,即使资源不足,pod仍能正常启动(并保持正常运行),并且不会报告容器内的任何问题,即使spring boot应用程序中的tomcat没有正常运行。

谢谢,原来它确实是后端应用程序