When using a nginx kubernetes routing LoadBalancer with path redirects, why can I not access my service correctly? - kubernetes

I am using AKS with Helm v2.2 to try deploying a chart that utilizes an nginx LoadBalancer Pod to control all ingress into my services via a single ip address. This is very much in the experimental phase but I have proven that when I use the following Helm ingress configuration for my .net core webapi service:
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
hosts:
- host:
paths:
- /
That I can indeed then visit my exposed api and see the swagger ui at
http://[My External IP]/index.html
what I then want to do is place several services behind the same LoadBalancer (as you are intended to) so my expectations were that I could then change the above service configuration to something like this:
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
hosts:
- host:
paths:
- /serviceA
Which should then mean I can access the same service via the now updated url:
http://[My External IP]/serviceA/index.html
Is this what I should be expecting to work? Do I need to use any sort of re-write system as so far I get errors back from this url saying that it cannot find certain missing resources. Any attempts at using the re-write annotation have not resulted in helping me here either. Could someone help me out and point out what I may be doing wrong? With the new url path I end up with the following types of errors on what appears to be the files that the index.html page is trying to load suggesting it is half working but needs some re-writing or something?
Failed to load resource: the server responded with a status of 404 ()
As a result of the Helm chart template engine the following ingress yaml file is created:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: myrelease-release-manager
labels:
app.kubernetes.io/name: release-manager
helm.sh/chart: release-manager-0.1.0
app.kubernetes.io/instance: release-name
app.kubernetes.io/version: "1.0"
app.kubernetes.io/managed-by: Tiller
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /serviceA
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- host:
http:
paths:
- path: /serviceA
backend:
serviceName: myrelease-release-manager
servicePort: 80
As a result of this ingress file I want to visit this service when I go to my external ip address with the path /serviceA/index.html.

Close, you need to update the rewrite target to /$2
nginx.ingress.kubernetes.io/rewrite-target: /$2
Rewrites
/serviceB/foo -> /foo
/serviceA/foo -> /foo
But each one will be directed to the services for that path
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: myrelease-release-manager
labels:
app.kubernetes.io/name: release-manager
helm.sh/chart: release-manager-0.1.0
app.kubernetes.io/instance: release-name
app.kubernetes.io/version: "1.0"
app.kubernetes.io/managed-by: Tiller
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- backend:
serviceName: serviceB
servicePort: 80
path: /serviceB(/|$)(.*)
- backend:
serviceName: serviceA
servicePort: 80
path: /serviceA(/|$)(.*)

Related

Ingress to redirect to service from LB ip

I'm trying to create an Ingress rule to redirect requests from LoadBalancer to Service.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: hostlessendpoint
spec:
rules:
- http:
paths:
- path: /hostless
backend:
serviceName: node-red
servicePort: 1880
The above yaml script is supposed to redirect all requests from https://LOAD_BALANCER_IP/hostless to node-red on port 1880
If I try to request the above URL, I got an error Cannot GET /hostless. Requesting the root gives 404 page not found.
I can access my services with the direct URL (eg. http://LOAD_BALANCER_IP:1880 will redirect to Node-red service).
Service yaml looks like that:
apiVersion: v1
kind: Service
metadata:
labels:
app: node-red
name: node-red
spec:
ports:
- name: "1880"
port: 1880
protocol: TCP
targetPort: 1880
selector:
app: node-red
sessionAffinity: None
type: LoadBalancer
How to use ingress to reach a service whereas a custom port ?
I've found a way to make it works !
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
traefik.ingress.kubernetes.io/redirect-entry-point: https
kubernetes.io/ingress.class: "traefik"
traefik.ingress.kubernetes.io/router.middlewares: "kube-system-traefik-stripprefix#kubernetescrd"
name: traefik-all
namespace: partner
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: nginx-demo
servicePort: 2222
- path: /node
backend:
serviceName: node-red
servicePort: 1880
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: traefik-stripprefix
namespace: kube-system
spec:
stripPrefixRegex:
regex:
- "/[^/]+"
I use a middleware to remove the prefix as K3S Traefik does not support the traefik.ingress.kubernetes.io/rewrite-target annotation.
With the above code, all trafic from LOAD_BALANCER_IP/* will be redirected to nginx-demo:2222 service. All trafic from LOAD_BALANCER_IP/node/* will be redicted to node-red:1880 service.
I hope this could help someone !
Try setting a rewrite-target annotation, which will effectively rewrite /hostless requests to /, i.e. http://LOAD_BALANCER_IP:1880/hostless externally to http://node-red:1880 internally.
For example:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: hostlessendpoint
spec:
rules:
- http:
paths:
- path: /hostless(/|$)(.*)
backend:
serviceName: node-red
servicePort: 1880
See this link, assuming you are using Nginx ingress controller.

traefik ingress wildcard support

I am following traefik documentation (https://docs.traefik.io/routing/routers/), want to use PathPrefix matcher to match different paths with wildcard support, for example, to match path starting with api/v1, it should match
api/v1/customers,
api/v1alpha/customers,
api/v1beta/customers.
How to achieve it using wildcards in path syntax? Please find below my ingress yaml. I tried /api/{v1*}/customers but not working as expected.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: traefik
traefik.frontend.rule.type: PathPrefix
labels:
app: <app_name>
chart: <chart_name>
heritage: Tiller
release: <release_name>
name: <name>
namespace: default
spec:
rules:
- http:
paths:
- backend:
serviceName: <service_name>
servicePort: 443
path: /api/v1*/customers
I figured out how it works, posting here if someone wants to know. We can add regular expression in path
path: /api/{version:v1([a-z]*)}/customers

ERR_TOO_MANY_REDIRECTS for Minio via NGINX Ingress Controller

I have a Minio ClusterIP service running in a Kubernetes cluster. And on top of it, I have a NGINX Ingress Controller. NGINX Ingress needs to forward Minio traffic to the Minio service, and other traffic to their corresponding services.
My Ingress configuration looks like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- http:
paths:
- path: /app/?(.*)
backend:
serviceName: app-service
servicePort: 3000
- path: /minio/?(.*)
backend:
serviceName: minio-service
servicePort: 9000
Once deployed, the app works fine. However, the Minio page has problem, complaining:
This page isn’t working
example.mysite.com redirected you too many times.
Try clearing your cookies.
ERR_TOO_MANY_REDIRECTS
And indeed, the requests are kept redirecting. Here is the screenshot from Chrome DevTools' Network console.
Any ideas?
As Minio always redirects to /minio/, you need to keep /minio in the path and pass it on to the Minio service.
When I change its path rule to - path: /(minio/.*), it works. Now the Ingress configuration looks like below:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- http:
paths:
- path: /app/?(.*)
backend:
serviceName: app-service
servicePort: 3000
- path: /(minio/.*)
backend:
serviceName: minio-service
servicePort: 9000
And I've got the Minio service working in the browser:
Hope it is helpful.

Web app not displaying pages using Kubernetes traefik ingress controller

My app does not work when I use a path other than / in the ingress rule. The app works when I access the application using http://gv.cloud.test.com:nodeport outside kubernetes cluster however does not work with http://gv.cloud.test.com/mytestapp. Can someone help me? The web app is using / as the base_href path in angular.
I am using traefik as the ingress controller. I have tried all the available traefik rule types:
PathPrefixStrip
PathPrefix
etc
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/rule-type: PathPrefixStrip
labels:
app: my-testapp
env: dev
name: my-testapp-dev-ingress
namespace: jenkins
spec:
rules:
- host: gv.cloud.test.com
http:
paths:
- backend:
serviceName: my-testapp-service
servicePort: 8090
path: /mytestapp

traefik ingress custom error in kubernetes

I need to set a custom error in traefik ingress on kubernetes so that when there is no endpoint or when the status is "404", or "[500-600]" it redirects to another error service or another custom error message I used the annotation as it's in the documentation in the ingress file as this (Note: this a helm template output of passing the annotation as a yaml in the values.yaml file)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: frontend
namespace: "default"
annotations:
external-dns.alpha.kubernetes.io/target: "domain.com"
kubernetes.io/ingress.class: "traefik"
traefik.ingress.kubernetes.io/error-pages: "map[/:map[backend:hello-world status:[502 503]]]"
spec:
rules:
- host: frontend.domain.com
http:
paths:
- backend:
serviceName: frontend
servicePort: 3000
path: /
The answer by ldez is correct, but there are a few caveats:
First off, these annotations only work for traefik >= 1.6.x (earlier versions may support error pages, but not for the kubernetes backend)
Second, the traefik backend must be configured through kubernetes. You cannot create a backend in a config file and use it with kubernetes, at least not in traefik 1.6.x
Here's how the complete thing looks like. foo is just a name, as explained in the other answer, and can be anything:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: frontend
namespace: "default"
annotations:
external-dns.alpha.kubernetes.io/target: "domain.com"
kubernetes.io/ingress.class: "traefik"
traefik.ingress.kubernetes.io/error-pages: |-
foo:
status:
- "404"
- "500"
# See below on where "error-pages" comes from
backend: error-pages
query: "/{{status}}.html"
spec:
rules:
# This creates an ingress on an non-existing host name,
# which binds to a service. As part of this a traefik
# backend "error-pages" will be created, which is the one
# we use above
- host: error-pages
http:
paths:
- backend:
serviceName: error-pages-service
servicePort: https
- host: frontend.domain.com
http:
# The configuration for your "real" Ingress goes here
# This is the service to back the ingress defined above
# Note that you can use anything for this, including an internal app
# Also: If you use https, the cert on the other side has to be valid
---
kind: Service
apiVersion: v1
metadata:
name: error-pages-service
namespace: default
spec:
ports:
- name: https
port: 443
type: ExternalName
externalName: my-awesome-errors.mydomain.test
If you use this configuration, and your app sends a 404, then https://my-awesome-errors.mydomain.test/404.html would be shown as the error page.
The correct syntax is:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: frontend
namespace: "default"
annotations:
external-dns.alpha.kubernetes.io/target: "domain.com"
kubernetes.io/ingress.class: "traefik"
traefik.ingress.kubernetes.io/error-pages: |-
foo:
status:
- "404"
backend: bar
query: /bar
fii:
status:
- "500-600"
backend: bar
query: /bir
spec:
rules:
- host: frontend.domain.com
http:
paths:
- backend:
serviceName: frontend
servicePort: 3000
path: /
https://docs.traefik.io/v1.6/configuration/backends/kubernetes/#general-annotations
Note that, currently, the Helm Charts doesn't support this feature.
Ingress does not support that annotations that you guys are using there!
That annotations are supported with Service only, Ingress is using host section.