claygilk / k8s-bookshelf

0 stars 0 forks source link

Add ingress controller #2

Open tonygilkerson opened 2 years ago

tonygilkerson commented 2 years ago

This issue is to describe how to expose an api behind your web server

Install ingress controller

First install an ingress controller. An ingress controller will allow you to create routing rules for ingress network traffic

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/cloud/deploy.yaml

Give it a few minutes to download and install the nginx container then run the following to verify. Notice the "EXTERNAL-IP" is 'localhost'. When you run in the cloud this would be your domain name like foo.com. Any request to local host ports 80 and 443 will be handled by this ingress controller.

kubectl -n ingress-nginx get svc ingress-nginx-controller

Create Ingress Resource

Create a file in your k8s folder called ingress.yaml and past in the following content.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: bookshelf
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /(.*)
        pathType: Prefix
        backend:
          service:
            name: vue-bookshelf-svc
            port:
              number: 8080
      - path: /api/(.*)
        pathType: Prefix
        backend:
          service:
            name: node-api-svc
            port:
              number: 80

Then deploy it into the cluster:

kubectl apply -f k8s/ingress/yaml

You can verify by running:

kubectl get ing

Accessing your app

Now when you point your browser at the following you should see your bookshelf UI

http://localhost

Note: you can now remove the node port from vue-bookshelf-svc

Use the following to access your API

http://localhost/api/

I don't know what endpoints your API exposes but if for example your api exposes a books endpoint then you would use the following URL

http://localhost/api/books

The api is removed and your api receives a request for /books

Accessing the API from your web app

Notice the web app and the api are under the same domain, the web app can reach the api by doing something like the following:


var apiURL = window.location.origin + /api

// get mybook
const response = await fetch(apiURL  + "/books/mybook");
claygilk commented 2 years ago

So I made all the changes you mentioned and the ingress is able to direct traffic to the front end without issue. When I go to localhost it displays the webpage, but when I try to get a response from the back end by sending a GET to the backend (localhost/api/books) I get the following chunk of html. From googling this looks like a Vue.js error, which is weird bc the backend doesn't use Vue obviously. I get this error when using the UI, when typing in the URL manually, and when using curl/postman.

Any thoughts on what might be causing this? I can't tell if this is just a node issue, or if I set up something wrong with k8s, but I'm leaning towards the former.


<!DOCTYPE html>
<html lang="">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="/favicon.ico">
    <title>bookshelf</title>
    <link href="/js/about.js" rel="prefetch">
    <link href="/js/app.js" rel="preload" as="script">
    <link href="/js/chunk-vendors.js" rel="preload" as="script">
</head>

<body>
    <noscript>
        <strong>We're sorry but bookshelf doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <script type="text/javascript" src="/js/chunk-vendors.js"></script>
    <script type="text/javascript" src="/js/app.js"></script>
</body>

</html>
claygilk commented 2 years ago

Frontend Repo: https://github.com/claygilk/Vue-Books

Backend Repo: https://github.com/claygilk/NodeBooksApi