29

I have the following that config that works when I try <NodeIP>:30080

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        name: app-node
    spec:
      containers:
        - name: app
          image: myregistry.net/repo/app:latest
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
          env:
            - name: NODE_ENV
              value: production
---
apiVersion: v1
kind: Service
metadata:
  name: app-service
spec:
  selector:
    name: app-node
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 30080
  type: NodePort

I am trying to use an Ingress:

 apiVersion: extensions/v1beta1
 kind: Ingress
 metadata:
   name: nginx-ingress
 spec:
   rules:
   - host: myhost.com
     http:
       paths:
       - path: /app
         backend:
           serviceName: app-service
           servicePort: 80

myhost.com works with the nginx intro screen, but myhost.com/app gives 404 Not Found. Where is the issue in my setup?


UPDATE:

   - path: /
     backend:
       serviceName: app-service
       servicePort: 80

If I do root path it works, but how come /app doesn't?

atkayla
  • 8,143
  • 17
  • 72
  • 132
  • 1
    root(/) might be pointing to default backend which would be nginx welcome page, but /app might not be configured properly that,s why when routing request to that gives 404. try other url e.g myhost.com/app1 and see if nginx page shows up. – captainchhala Aug 26 '18 at 05:32

3 Answers3

33

Your ingress definition creates rules that proxy traffic from the {path} to the {backend.serviceName}{path}. In your case, I believe the reason it's not working is that /app is proxied to app-service:80/app but you're intending on serving traffic at the / root. Try adding this annotation to your ingress resource: nginx.ingress.kubernetes.io/rewrite-target: /

Source: https://github.com/kubernetes/ingress-nginx/tree/master/docs/examples/rewrite

brandon-barnett
  • 1,035
  • 9
  • 13
  • 3
    If I understand correctly, yes I would like `myhost.com/app/foo => app-service:80/foo`, not `myhost.com/app/foo => app-service:80/app/foo`. That explains why my config is wrong, and why only the root config (`path: /`) works, however `nginx.ingress.kubernetes.io/rewrite-target: /` does not seem to point it correctly. I have also tried `ingress.kubernetes.io/rewrite-target: /` with no luck. – atkayla Aug 26 '18 at 18:54
  • How did you install `nginx-ingress`? Do you have manifests or instructions? – brandon-barnett Aug 26 '18 at 20:48
  • https://console.bluemix.net/docs/containers/cs_ingress.html#ingress (Step 3: Create the Ingress resource) – atkayla Aug 26 '18 at 20:54
  • Ah indeed. That annotation is specific to nginx, but your ingress controller is managed by IBM (according to the docs). If you were [installing a custom nginx-ingress controller](https://console.bluemix.net/docs/containers/cs_ingress.html#user_managed) that annotation would probably work. In your case, check out the [annotation options](https://console.bluemix.net/docs/containers/cs_annotations.html#ingress_annotation). Seems like `rewrite-path` should do it instead of `nginx.ingress.kubernetes.io/rewrite-target` – brandon-barnett Aug 26 '18 at 21:26
  • I tried `ingress.bluemix.net/rewrite-path: /` as well, but it didn't work, and doesn't seem to function the same as `rewrite-target`. Confusing. Perhaps I should just consult their support, as this issue seems specific to them as a provider. I appreciate your help in pointing me towards the right direction though, thanks! – atkayla Aug 26 '18 at 21:31
  • One last shot -- did you try this? https://console.bluemix.net/docs/containers/cs_annotations.html#rewrite-path – brandon-barnett Aug 26 '18 at 21:32
  • It finally works! Thank you! I had to do two things: 1. `ingress.bluemix.net/rewrite-path: "serviceName=app-service rewrite=/"` AND 2. `path: /app/` (missing trailing slash!!!). – atkayla Aug 26 '18 at 21:42
  • @brandon-barnett you're a life savior. Works like charm. – Amit Yadav Aug 22 '19 at 07:10
  • In my case (on mac with docker desktop), it worked by changing annotations to the following. (in ingress yaml) `annotations: kubernetes.io/ingress.class: nginx` – Anup_Tripathi Sep 02 '22 at 12:20
8

As specified by brandon-barnett the issue is coming from the path but after reading the link he shared, big ups to you Brandon, I realised that a more specific rewrite rule would have to specified for it to work. In my case

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: rewrite
  namespace: default
spec:
  ingressClassName: nginx
  rules:
  - host: rewrite.bar.com
    http:
      paths:
      - path: /something(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: http-svc
            port: 
              number: 80

The trick is with /$2 at annotation and (/|$)(.*) at the path. So what this rewrite does is that it picks everything that comes after something/ and replaces $2 with it, so:

  • rewrite.bar.com/something rewrites to http-svc:80/
  • rewrite.bar.com/something/ rewrites to http-svc:80/
  • rewrite.bar.com/something/new rewrites to http-svc:80/new
  • rewrite.bar.com/something/new/old rewrites to http-svc:80/new/old
KwakuCsc
  • 169
  • 2
  • 4
3

In case it's useful to others:

I had the same thing, and it was nothing to do with Kubernetes Ingress Nginx. It was the Nginx server in my pod running the UI (Vue.JS in my case).

Solution:

  1. Add an nginx.conf file to my UI app.
     user  nginx;
     worker_processes  auto;
     error_log  /var/log/nginx/error.log warn;
     pid        /var/run/nginx.pid;
     events {
         worker_connections  1024;
     }
     http {
         include       mime.types;
         default_type  application/octet-stream;
         sendfile        on;
         keepalive_timeout  65;
         log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                           '$status $body_bytes_sent "$http_referer" '
                           '"$http_user_agent" "$http_x_forwarded_for"';
         access_log  /var/log/nginx/access.log  main;
         server {
             listen       80;
             root /usr/share/nginx/html;
             index index.html;
             location / {
                 try_files $uri $uri/ /index.html;
             }
         }
     }
    
  2. Add this line to my Dockerfile for the Vue.js app to copy the nginx.conf to your container.
     # production stage
     FROM nginx:stable-alpine as production-stage
     COPY nginx.conf /etc/nginx/
     COPY --from=build-stage /app/dist /usr/share/nginx/html
     EXPOSE 80
     CMD ["nginx", "-g", "daemon off;"]
    

Ref: https://stackoverflow.com/a/54193517/4059810

ChrisE
  • 376
  • 4
  • 14
  • 1
    Same here! But in my case ReactJs running in kubernetes. Forgot to add custom nginx.conf to my deployment – OBAA Sep 15 '22 at 12:20