1

I'm trying the official example Example: Deploying PHP Guestbook application with MongoDB.

Everything is good, but when I deploy a ingress for it, I can see next in chrome network debug (Here, 31083 is the nodeport):

Request URL: http://10.192.244.109:31083/gb 200 OK
Request URL: http://10.192.244.109:31083/controllers.js 404 Not Found

ingress.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: gb-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /gb
        pathType: Prefix
        backend:
          service:
            name: frontend
            port:
              number: 80

ingress-nginx: (Use the one here)

apiVersion: v1
kind: Service
metadata:
  annotations:
  labels:
    helm.sh/chart: ingress-nginx-3.27.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.45.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
    - name: https
      port: 443
      protocol: TCP
      targetPort: https
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/component: controller

The source code of K8s guestbook index page which I get from chrome:


<html ng-app="guestbook">
  <head>
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <title>Guestbook</title>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script>
    <script src="controllers.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.0/ui-bootstrap-tpls.js"></script>
  </head>
  <body ng-controller="guestbookCtrl">
    <div style="width: 50%; margin-left: 20px">
      <h2>Guestbook</h2>
    <form>
    <fieldset>
    <input ng-model="msg" placeholder="Messages" class="form-control" type="text" name="input"><br>
    <button type="button" class="btn btn-primary" ng-click="controller.onguestbook()">Submit</button>
    </fieldset>
    </form>
    <div>
      <div ng-repeat="msg in messages track by $index">
        {{msg}}
      </div>
    </div>
    </div>
  </body>
</html>

I know my ingress just specify /gb prefix, so http://10.192.244.109:31083/controllers.js can't route to correct service, but how can I make it work?

I think about maybe could add another ingress rule for js rewrite, but what if I have more than one application? Any suggestion?

atline
  • 28,355
  • 16
  • 77
  • 113
  • I also see [this](https://www.edureka.co/community/19789/ingress-nginx-loading-resource-404-in-kubernetes), the answer mentioned we need to remove `/` in ``, but here it already not `/controllers.js`. I guess this is simple common problem, but I'm surprised I didn't find any good answer through google, still google-ing – atline Apr 15 '21 at 05:55

1 Answers1

3

You should be able to do this with the correct rewrite-rule and path pattern:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: gb-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - http:
      paths:
      - path: /gb(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: frontend
            port:
              number: 80

This will rewrite your requests in the following way:

  • /gb -> /
  • /gb/controller.js -> /controller.js
  • /gb/foo -> /foo
chresse
  • 5,486
  • 3
  • 30
  • 47
  • I tried it, looks not work. The browser still send `http://10.192.244.109:31083/controllers.js` to backend, your `/gb/controller.js` looks has no chance to make effect? – atline Apr 15 '21 at 01:45
  • Your changes just make `http://10.192.244.109:31083/gb/controllers.js` ok to visit if I manual paste this url to browser. But the guestbook index page indeed send `http://10.192.244.109:31083/controllers.js` to backend, no `gb` in url, so looks your fix no chance to work. – atline Apr 15 '21 at 05:16
  • only to understand you correctly: is the controller.js provided from the service "frontend" or from another service? If the file is provided from the same service as your index page (frontend service), what is the reason you want to provide the index under `/gb/` and everything else under `/`? – chresse Apr 15 '21 at 05:58
  • See [deployment](https://kubernetes.io/docs/tutorials/stateless-application/guestbook/#set-up-and-expose-the-guestbook-frontend) and [service](https://kubernetes.io/docs/tutorials/stateless-application/guestbook/#creating-the-frontend-service). YES, the file is from the same POD, same service, in fact in docker container, I could see them in same folder: `root@frontend-868556665f-g94bm:/var/www/html# ls controllers.js guestbook.php index.html`. It's not me want it be in '/' prefix, all code is k8s official example, I just can't make it work with ingress-nginx... – atline Apr 15 '21 at 06:04
  • If I could let browser visit `http://10.192.244.109:31083/gb/controllers.js` not `http://10.192.244.109:31083/controllers.js`, then everything is ok. But I don't know how... It's defined in `index.html` as next `` – atline Apr 15 '21 at 06:06
  • and you get a 404 for the `controller.js` if you visit your index page in `/gb` via browser? – chresse Apr 15 '21 at 06:17
  • YES, I visit `http://10.192.244.109:31083/gb`, then see the `index.html`, the `index.html` itself will be rendered to browser, but the browser will try to fetch `http://10.192.244.109:31083/controllers.js` as it's in index.html, then get 404, I can see it if I open the chrome debug. NOTE: the deployment and service is documented in official doc, the ingress part is defined by myself, I don't know if my configure is correct or not. – atline Apr 15 '21 at 06:50
  • Ok. I don't know, why the controller.js is provided in another directory as the index.html. Anyhow, if the ingress is defined by yourself, just change the path to `/` instead of `/gb` – chresse Apr 15 '21 at 07:08
  • This could be an option, I think it's certainly work. But if I have 2 apps, it's impossible for me to distinguish the 2 apps if just use `/`. Maybe I can use `host` in ingress to distinguish different apps, different apps different domain name, but in my local situation, I can just use one domain name. – atline Apr 15 '21 at 07:17
  • From [this](https://github.com/kubernetes/ingress-nginx/issues/333#issuecomment-634667359): `The rewrite-target annotation changes the paths from the request to the mongo-express application, not the paths returned by the application.`. And also mongo-express supply a variable `ME_CONFIG_SITE_BASEURL` to change the base url for itself. So I guess every application need to do similar like what mongo-express do, to support this scenario, intrusive changes had to be made to change base url of javascript/css. So plus your answers, we could make it work, I guess it's the only way. – atline Apr 15 '21 at 09:33