Navigation on website with Kubernetes Ingress - express

I'm trying to expose a website inside my Kubernetes Cluster. Therefor I created an Ingress that links to my Service and so to my Pod. Till this point, everything works perfectly fine.
But now when I start navigating on my Page the URL changes, but the shown site stays the “Homepage”.
How is it possible to navigate on the page and access all the subpages properly?
My Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: wichteln-deployment
spec:
replicas: 1
selector:
matchLabels:
app: wichteln
template:
metadata:
labels:
app: wichteln
spec:
containers:
- image: jonasgoetz01/website:V1.0
name: wichteln-container
command: ["/bin/sh"]
args:
- -c
- >-
apt update
My Service:
apiVersion: v1
kind: Service
metadata:
name: wichteln-service
spec:
selector:
app: wichteln
ports:
- protocol: TCP
port: 5000
targetPort: 5000
My Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wichteln-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: public
rules:
- http:
paths:
- path: /wichteln/*
pathType: Prefix
backend:
service:
name: wichteln-service
port:
number: 5000
The Webpage is a NodeJS express Webpage.
Here is my routes.js file for reference (If you need more files, please let me know):
const express = require('express');
const router = express.Router();
const controller = require('../controllers/controller');
// Routes
router.get('/', controller.home);
router.get('/usermanagement/', controller.viewuser);
router.post('/usermanagement/', controller.finduser);
router.get('/usermanagement/adduser', controller.formuser);
router.post('/usermanagement/adduser', controller.createuser);
router.get('/usermanagement/edituser/:id', controller.edituser);
router.post('/usermanagement/edituser/:id', controller.updateuser);
router.get('/usermanagement/viewuser/:id', controller.viewalluser);
router.get('/usermanagement/:id',controller.deleteuser);
module.exports = router;
Every time I try to access the page, I start at the homepage. When I click on some buttons that normally would redirect me to a subpage, I stay at the homepage even if the URL changes correctly.
For example, the home URL is: www.mydomain.com/wichteln → I can see the homepage.
www.mydomain.com/wichteln/usermanagement → I can still see the homepage but want to see the subpage “usermanagement”.
Thank you for your help.

The issue is most likely coming from the rewrite that you have in your ingress manifest.
nginx.ingress.kubernetes.io/rewrite-target: /
this means that when the ingress receives the request from the client it takes the path portion of the url and rewrites it to be /, before passing it down to your backend, which in turn results in backend returning the root page of your website.

You should remove the rewrite annotation and use this one:
nginx.ingress.kubernetes.io/use-regex: "true"
And in your path configuration you can try something like that:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wichteln-ingress
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: public
rules:
- http:
paths:
- path: /wichteln/.*
pathType: Prefix
backend:
service:
name: wichteln-service
port:
number: 5000
This configuration creates the following NGINX location block:
location ~* "^/wichteln/.*" {
...
}

Path Rewrite + Capture Groups
You can use capture groups to capture the part after the path prefix and use it in the rewrite rule see the docs.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wichteln-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: public
rules:
- http:
paths:
- path: /wichteln/(/|$)(.*)
pathType: Prefix
backend:
service:
name: wichteln-service
port:
number: 5000
Context Path
Alternatively, and not uncommon, is it to inject a context path into your application. Then you don't need any path rewrite on your ingress manifest.
...
const ctx = process.env.CONTEXT_PATH || ''
router.get(`${ctx}/`, controller.home);
router.get(`${ctx}/usermanagement/`, controller.viewuser);
...
To inject it, add it to the pod spec.
...
spec:
containers:
- image: jonasgoetz01/website:V1.0
env:
- name: CONTEXT_PATH
value: /wichteln
...

Related

Add custom response header traefik ingress on K3S

How does one add a custom response header to traefik ingress on a K3S ?
I have followed the official doc and a few answers from stackoverflow. But none seems to work.
Here is my ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: traeffic-custom-response-header
namespace: mynamespace
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/custom-response-headers: Bypass-Tunnel-Reminder:true
ingress.kubernetes.io/custom-response-headers: Bypass-Tunnel-Reminder:true
spec:
rules:
- host: localhost
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: scc-worker
port:
number: 8000
I am running a local K3S cluster on my PC for testing.
And I am not able to add custom response header.
Ok, I solved this issue by adding middleware and then configuring it in my Ingress Controller Configuration
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: add-bypass-tunnel-header
namespace: mynamespace
spec:
headers:
customResponseHeaders:
Bypass-Tunnel-Reminder: "true"
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: traeffic-custom-request-header
namespace: mynamespace
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.entrypoints: web
traefik.ingress.kubernetes.io/router.middlewares: mynamespace-add-bypass-tunnel-header#kubernetescrd
traefik.ingress.kubernetes.io/custom-response-headers: Bypass-Tunnel-Reminder:true
ingress.kubernetes.io/custom-response-headers: Bypass-Tunnel-Reminder:true
spec:
rules:
- host: localhost
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: scc-worker
port:
number: 8000
Here add-bypass-tunnel-header is a middle ware being created
And then adding it to traefik ingress by traefik.ingress.kubernetes.io/router.middlewares: mynamespace-add-bypass-tunnel-header#kubernetescrd annotation

Ingress unable to find backend service in Kubernetes v1.21.5

I am using Kubernetes v1.21.5 on docker. The following is my ingress YAML file
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- host: triver.dev
http:
paths:
- path: /service/account/?(.*)
pathType: Prefix
backend:
service:
name: auth-srv
port:
number: 3000
I am running an auth srv image and the following is its YAML file
kind: Deployment
metadata:
name: auth-depl
spec:
replicas: 1
selector:
matchLabels:
app: auth
template:
metadata:
labels:
app: auth
spec:
containers:
- name: auth
image: triver/auth
env:
- name: MONGO_URI
value: 'mongodb://mongo-srv:27017/auth'
- name: JWT_KEY
valueFrom:
secretKeyRef:
name: jwt-secret
key: JWT_KEY
---
apiVersion: v1
kind: Service
metadata:
name: auth-srv
spec:
selector:
app: auth
ports:
- name: auth
protocol: TCP
port: 3000
targetPort: 3000
but when I try to send a request to any route that I created in auth service for example I created a triver.dev/service/account/signup post express router for a user to signup. When I try to send a post request to the route through Postman it gives an error (404) of ECONNRefused. Couldn't send a request. Why is it happening? (My postman is working fine. It's not an issue on the postman end.)
What am I doing wrong
The app works but I just can't access the route. It's definitely an ingress issue. Can someone help me, please? This is a very important project.
This is what show up when I use the command 'kubectl get ingress'
Everything works fine when I run the application using skaffold dev.
it's due to you have not mentioned the hostname into the ingress, also make sure your ingress controller is running
example ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: hello-world.info
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 8080
host: hello-world.info
Reference : https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/
you can also checkout : https://kubernetes.io/docs/concepts/services-networking/ingress/
if you have set default backend set in ingress and host is not issue
make sure you are sending the request on HTTP instead of HTTPS
nginx.ingress.kubernetes.io/ssl-redirect: "false"
as you are not using the certificate SSL/TLS so please try the URL with HTTP

Traefik 2.2 http to https redirect

I'm following the guide and I'm able to access my website via HTTP and HTTPs however redirect is not working for me, any ideas on what might be wrong?
# IngresRoute
---
kind: IngressRoute
apiVersion: traefik.containo.us/v1alpha1
metadata:
name: whoami
namespace: default
spec:
entryPoints:
web:
address: :80
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
address: :443
routes:
- match: Host(`hello.mydomain.io`)
kind: Rule
services:
- name: whoami
port: 80
tls: {}
I use Docker compose, so might not be spot on for you. But suggestion is to add a scheme redirect middleware to your dynamic config file.
http:
middlewares:
https_redirect:
redirectScheme:
scheme: https
permanent: true
Or just add the middleware to your service if you don't have access to the Traefik configs.
I prefer the dynamic config, because then you can register it on any service as required using https_redirect#file.
You do need a router per entrypoint though, using this method. And register the middleware on only the http router.
I'm sure there are other, better ways. But if you need some apps automatically redirecting and some not this is the best solution I've found thusfar.
I have a working configuration which uses Ingress objects instead of IngressRoute , but I hope this will help some people :
Thus, here is a working configuration :
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: redirect
namespace: some_namespace
spec:
redirectScheme:
scheme: https
permanent: true
and
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wordpress
namespace: your_app_namespace
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.middlewares: some_namespace-redirect#kubernetescrd
spec:
tls:
- secretName: your_certificate
hosts:
- www.your_website.com
rules:
- host: www.your_website.com
http:
paths:
- path: /
backend:
service:
name: your_service
port:
number: 80
pathType: ImplementationSpecific
So the trick is to :
define a Middleware object (in any namespace you want, but that may be in the same one as your app)
reference it in traefik.ingress.kubernetes.io/router.middlewares with the syntax <NAMESPACE>-<NAME>#kubernetescrd (where NAMESPACE and NAME are those of the Middleware object)

how to config traefik 2.2 forward url and remove keywords

I want to forward my request using treafik 2.2 and config my ingress like this:
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: soa-illidan-forward
namespace: dabai-pro
selfLink: /apis/extensions/v1beta1/namespaces/dabai-pro/ingresses/soa-illidan-forward
uid: b0778435-4fff-4e78-b85f-a534833b73e0
resourceVersion: '322554'
generation: 1
creationTimestamp: '2020-06-07T11:04:43Z'
spec:
rules:
- host: manage.example.net
http:
paths:
- path: /service
backend:
serviceName: zuul-service
servicePort: 8088
status:
loadBalancer: {}
but the forward still using the key word service and forward to backend, how to remove the keywards service when forward request? I also tried this:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: pro-manage-route
namespace: dabai-pro
spec:
entryPoints:
- web
routes:
- match: Host(`manage.example.net`)
kind: Rule
services:
- name: be-illidan-frontend
port: 80
- match: Host(`manage.example.net`) && PathPrefix(`/service`)
kind: Rule
services:
- name: zuul-service
port: 8088
but still not work. and this is my request path:
https://manage.example.net/service/illidan/report/user/captcha
and I want forward to backend zuul-service's url is /illidan/report/user/captcha. not /service/illidan/report/user/captcha.
just using traefik StripPrefix middleware, for example:
http:
middlewares:
test-stripprefix:
stripPrefix:
prefixes:
- "/foobar"
- "/fiibar"
for more detail, read the traefik docs.

Traefik v2 Middlewares not being detected

Middlewares are not being detected and therefore paths are not being stripped resulting in 404s in the backend api.
Middleware exists in k8s apps namespace
$ kubectl get -n apps middlewares
NAME AGE
traefik-middlewares-backend-users-service 1d
configuration for middleware and ingress route
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
annotations:
kubernetes.io/ingress.class: traefik
name: apps-services
namespace: apps
spec:
entryPoints:
- web
routes:
- kind: Rule
match: Host(`example.com`) && PathPrefix(`/users/`)
middlewares:
- name: traefik-middlewares-backend-users-service
priority: 0
services:
- name: backend-users-service
port: 8080
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: traefik-middlewares-backend-users-service
namespace: apps
spec:
stripPrefix:
prefixes:
- /users
Static configuration
global:
checkNewVersion: true
sendAnonymousUsage: true
entryPoints:
http:
address: :80
traefik:
address: :8080
providers:
providersThrottleDuration: 2s
kubernetesIngress: {}
api:
# TODO: make this secure later
insecure: true
ping:
entryPoint: http
log: {}
Traefik dasboard has no middlewares
Spring Boot 404 page. Route is on example.com/actuator/health
The /users is not being stripped. This worked for me in traefik v1 perfectly fine.
Note: actual domain has been replaced with example.com and domain.com in the examples.
To get this working, I had to:
Add the Kubernetes CRD provider with the namespaces where the custom k8s CRDs for traefik v2 exist
Add TLSOption resource definition
Update cluster role for traefik to have permissions for listing and watching new v2 resources
Make sure all namespaces with new resources are configured
Traefik Static Configuration File
providers:
providersThrottleDuration: 2s
kubernetesCRD:
namespaces:
- apps
- traefik
TLSOption CRD
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsoptions.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSOption
plural: tlsoptions
singular: tlsoption
scope: Namespaced
Updated Static Configuration for Traefik
global:
checkNewVersion: true
sendAnonymousUsage: true
entryPoints:
http:
address: :80
traefik:
address: :8080
providers:
providersThrottleDuration: 2s
kubernetesCRD:
namespaces:
- apps
- traefik
api:
# TODO: make this secure later
insecure: true
ping:
entryPoint: http
log: {}