I have one service and a single ingress resource with kubenetes nginx ingress controller. I want the /student path of my url to go to the root of the application and match any other url segments which follow the student.
For example: http://example.com/student/ver should match the /ver route of my application.
However, my ingress always hit the application with the /student url path prefixing the other url segments. If I call http://example.com/student/ver, my application is hit with the same url (student/ver).
My ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
name: ingress-resource
spec:
rules:
- host: example.com
http:
paths:
- backend:
serviceName: lesson-streaming
servicePort: 80
path: /student
I spent days with this and was not successful once.
Edit:
The ingress is changed to the following - not my requests say http 404
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rewrite-target: /$2
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
name: ingress-resource
namespace: default
spec:
rules:
- host: example.com
http:
paths:
- backend:
serviceName: lesson-streaming
servicePort: 80
path: /student(/|$)(.*)
You can follow the link to use the rewrite-target annotation correctly and keep the right key nginx.ingress.kubernetes.io/rewrite-target.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: rewrite
namespace: default
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /something(/|$)(.*)
Im using k8 - v1.25.2 along with nginx-Ingress v2.4.1 https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/
nginx.ingress.kubernetes.io/rewrite-target: /$2 - doesnt work
instead use :
nginx.org/rewrites: "serviceName=app1-svc rewrite=/;serviceName=app2-svc rewrite=/"
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-ingress
namespace: default
annotations:
nginx.org/rewrites: "serviceName=app1-svc rewrite=/;serviceName=app2-svc rewrite=/"
spec:
ingressClassName: nginx
rules:
- host: apps.relo.com
http:
paths:
- backend:
service:
name: app1-svc
port:
number: 2041
path: /app1
pathType: Prefix
- backend:
service:
name: app2-svc
port:
number: 2042
path: /app2
pathType: Prefix
I have tried many times to execute properly path based routing in nginx ingress controller but I have found the main reason behind the path based routing not working.
replace the (nginx.ingress.kubernetes.io/rewrite-target: /) to (nginx.org/rewrites: "serviceName=servicename rewrite=/")
must add ingressClassName in spec
in my case
I have kubernetes 1.23.0 & nginx/1.21.6
I hope this will resolve the above problem.
Best of luck
Related
Im looking for the way to configure OAuth2 and Azure provider for Nginx Ingress with multiple hosts definitions.
I need add authentication over for my application dev.example.com on AKS which has internal auth based on Identity service.
I've read examples like this:
https://kristhecodingunicorn.com/post/k8s_nginx_oauth/#setting-up-authentication-with-oauth-20
I've created Application in Azure AD and configure it like described above:
Redirect URIs - https://dev.example.com/oauth2/callback
Front-channel logout - URL https://dev.example.com/oauth2/sign_out
As far I can see almost all works ok - when I open dev.example.com in browser it redirect me to MS Sign In form, then runs 2FA, and opens dev.example.com.
But there is one error during opening web site:
Access to XMLHttpRequest at
'https://api.dev.example.com/identity/.well-known/openid-configuration'
from origin 'https://dev.example.com' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
Redirect is not allowed for a preflight request.
the main application tries to connect to internal Identity service and gets an error because of CORS.
Is there a way to fix this?
here is my Nginx ingress for application:
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: dev-ingress
annotations:
cert-manager.io/issuer: letsencrypt-cert
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri
nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth
nginx.ingress.kubernetes.io/ssl-redirect: 'false'
nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
tls:
- hosts:
- dev.example.com
- api.dev.example.com
secretName: letsencrypt-cert
rules:
- host: dev.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: dev-service
port:
number: 80
- host: api.dev.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
and OAuth2 Configuration:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: oauth2-proxy
name: oauth2-proxy
namespace: dev
spec:
replicas: 1
selector:
matchLabels:
k8s-app: oauth2-proxy
template:
metadata:
labels:
k8s-app: oauth2-proxy
spec:
containers:
- args:
- --provider=oidc
#- --provider=azure
- --azure-tenant=xxxxxxxxxxxxxx
- --skip-jwt-bearer-tokens=true
- --skip-auth-preflight=true
- --email-domain=*
- --http-address=0.0.0.0:4180
- --cookie-domain=.example.com
- --whitelist-domain=.example.com
- --oidc-issuer-url=https://login.microsoftonline.com/xxxxxxxx/v2.0
env:
- name: OAUTH2_PROXY_CLIENT_ID
valueFrom:
secretKeyRef:
name: client-id
key: oauth2_proxy_client_id
- name: OAUTH2_PROXY_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: client-secret
key: oauth2_proxy_client_secret
- name: OAUTH2_PROXY_COOKIE_SECRET
valueFrom:
secretKeyRef:
name: cookie-secret
key: oauth2_proxy_cookie_secret
image: quay.io/oauth2-proxy/oauth2-proxy:latest
imagePullPolicy: Always
name: oauth2-proxy
ports:
- containerPort: 4180
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: oauth2-proxy
name: oauth2-proxy
namespace: dev
spec:
ports:
- name: http
port: 4180
protocol: TCP
targetPort: 4180
selector:
k8s-app: oauth2-proxy
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: oauth2-proxy
namespace: dev
spec:
ingressClassName: nginx
rules:
- host: dev.example.com
http:
paths:
- path: /oauth2
pathType: Prefix
backend:
service:
name: oauth2-proxy
port:
number: 4180
- host: api.dev.example.com
http:
paths:
- path: /oauth2
pathType: Prefix
backend:
service:
name: oauth2-proxy
port:
number: 4180
You seem to have an SPA and API architecture here. Therefore you need to deal with CORS on the API side of things. As a first step you could implement CORS in your api-service, by plugging in a library.
A more elegant solution is to do so in the ingress, via a CORS plugin. This example is from Kong but maybe there is an equivalent plugin in NGINX. The approach is to build a custom ingress controller image and then add a configuration snippet to inject settings into the nginx.conf file, though it may prove difficult.
Be aware that in oauth2-proxy you are using a website security solution, which is unlikely to be SPA friendly during Ajax calls to APIs, eg when you need to refresh an expired access token. A backend for frontend (BFF) with a more complete design is preferred.
I'm looking for any working samples of applying different certificates on AKS with Application Gateway as Ingress Controller.
I have Key Vault with a certificate that is used imported in ApGw/Ingress as sitecomcert and here is Ingress manifest:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: site-agic-ig
annotations:
kubernetes.io/ingress.class: azure/application-gateway
appgw.ingress.kubernetes.io/appgw-ssl-certificate: sitecomcert
appgw.ingress.kubernetes.io/ssl-redirect: "true"
appgw.ingress.kubernetes.io/request-timeout: "180"
appgw.ingress.kubernetes.io/cookie-based-affinity: "true"
spec:
rules:
- host: "site.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: site-svc
port:
number: 80
...
Everything works perfect here.
Now I have a second certificate in Key Vault for site2.com and this cert is already imported in Ap Gw as site2comcert and I have container that should serve requests coming to site2.com which point to Ap Gw Public IP.
So I'm about to add
- host: "site2.com" <--- How can I attach **site2comcert** cert?
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: site2-svc
port:
number: 80
but with this setup I receive Untrusted Connection warning in browser because sitecomcert is used. How to configure ApGw / Ingress in a way that allows to use site2comcert for site2.com host specified above?
You can have multiple ingress resource definitions (snipped for brevity):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: site-agic-ig
annotations:
kubernetes.io/ingress.class: azure/application-gateway
appgw.ingress.kubernetes.io/appgw-ssl-certificate: sitecomcert
spec:
rules:
- host: "site.com"
and
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: site-agic-ig-site2
annotations:
kubernetes.io/ingress.class: azure/application-gateway
appgw.ingress.kubernetes.io/appgw-ssl-certificate: site2comcert
spec:
rules:
- host: "site2.com"
I surfed on many websites, stackoverflow post and others but cannot find the workaround. Using AKS 1.23.8 and Ingress installed with helm install ingress nginx-stable/nginx-ingress --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz --set controller.service.externalTrafficPolicy=Local
and this is the multiple paths ingress rule :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: az-ingress
spec:
ingressClassName: nginx
rules:
- host: k8s.test.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: azure-vote-front
port:
number: 80
- path: /hello
pathType: Prefix
backend:
service:
name: hello-world-service
port:
number: 80
Which was showed in this post :
Why only / path works in AKS with NGINX Ingress Controller and https://github.com/Azure/AKS/issues/2907
Path / works but path /hello return Cannot GET /hello
If i use different host for each service, it works like a charm :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: az-ingress
spec:
ingressClassName: nginx
rules:
- host: k8s.test.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: azure-vote-front
port:
number: 80
- host: k8s.test2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-world-service
port:
number: 80
what could be the issue ?
This is the log :
Hows your luck if you try "pathType: Exact" for /hello
I'm new to Kubernetes and I'm trying to deploy a React app to my cluster. Here's the basic info:
Docker Desktop, single-node Kubernetes cluster
React development frontend, exposing port 3000
Node.js/Express backend, exposing port 8080
NGINX Ingress Controller, serving my React frontend on "localhost:3000" and routing my Fetch API requests (fetch("localhost:3000/api/...", OPTIONS)) to the backend (which works)
I am having an issue when opening the React app. The Ingress Controller correctly routes to the app but the 3 bundles (bundle.js, main.chink.js, the third one which I don't remember) aren't loaded. I get the following error:
GET http://localhost/static/js/main.chunk.js net::ERR_ABORTED 404 (Not Found) ingress (one example)
I understand why this error happens. The Ingress Controller correctly routes the traffic but only loads the index.html file. In this file, there are calls to 3 scripts (referring to the bundles) which aren't loaded. I understand the error, the files don't get sent to the browser so the index.html file can't load them in, but do not know how to fix it.
Does anyone have any suggestions? de and then pulled from Docker Hub. Does anybody know what a possible solution could be? For example, does deploying the build/ folder (built React app using "npm run build") fix this? Do I have to use nginx inside my Dockerfile to build the container?
Ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: titanic-ingress
#labels:
#name: titanic-ingress
spec:
ingressClassName: nginx
rules:
- host: localhost
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: titanicfrontendservice
port:
number: 3000
- path: /api
pathType: Exact
backend:
service:
name: titanicbackendservice
port:
number: 8080
Ingress controller deployment yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ingress
namespace: nginx-ingress
spec:
replicas: 1
selector:
matchLabels:
app: nginx-ingress
template:
metadata:
labels:
app: nginx-ingress
#annotations:
#prometheus.io/scrape: "true"
#prometheus.io/port: "9113"
spec:
serviceAccountName: nginx-ingress
containers:
- image: nginx/nginx-ingress:1.10.0
imagePullPolicy: IfNotPresent
name: nginx-ingress
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
- name: readiness-port
containerPort: 8081
#- name: prometheus
#containerPort: 9113
readinessProbe:
httpGet:
path: /nginx-ready
port: readiness-port
periodSeconds: 1
securityContext:
allowPrivilegeEscalation: true
runAsUser: 101 #nginx
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
args:
- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
- -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
#- -v=3 # Enables extensive logging. Useful for troubleshooting.
- -report-ingress-status
- -external-service=nginx-ingress
#- -enable-prometheus-metrics
#- -global-configuration=$(POD_NAMESPACE)/nginx-configuration
Ingress controller service yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress
namespace: nginx-ingress
spec:
externalTrafficPolicy: Local
type: LoadBalancer
ports:
- port: 3000
targetPort: 80
protocol: TCP
name: http
- port: 443
targetPort: 443
protocol: TCP
name: https
selector:
app: nginx-ingress
TL;DR
Switch your pathType in both /api and / path to Prefix.
I've included some explanation with fixed Ingress resource below.
For the reproduction purposes I used the titanic manifests that you provided in the another question:
Github.com: Strobosco: Titanicfullstack
The issue with your configuration is with: pathType.
Using your Ingress resource with pathType: Exact showed me blank page.
Modifying your Ingress resource with pathType: Prefix solved the issue.
Side note!
The message: "Would you have survived the sinking of the Titanic?" showed.
The exact Ingress configuration should be following:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: titanic-ingress
spec:
ingressClassName: nginx
rules:
- host: localhost
http:
paths:
- path: /
pathType: Prefix # <-- IMPORTANT
backend:
service:
name: titanicfrontendservice
port:
number: 3000
- path: /api
pathType: Prefix # <-- IMPORTANT
backend:
service:
name: titanicbackendservice
port:
number: 8080
Why I think it happened?
Citing the official documentation:
Path types
Each path in an Ingress is required to have a corresponding path type. Paths that do not include an explicit pathType will fail validation. There are three supported path types:
ImplementationSpecific: With this path type, matching is up to the IngressClass. Implementations can treat this as a separate pathType or treat it identically to Prefix or Exact path types.
Exact: Matches the URL path exactly and with case sensitivity.
Prefix: Matches based on a URL path prefix split by /. Matching is case sensitive and done on a path element by element basis. A path element refers to the list of labels in the path split by the / separator. A request is a match for path p if every p is an element-wise prefix of p of the request path.
-- Kubernetes.io: Docs: Concepts: Services networking: Ingress: Path types (there are some examples on how the path matching is handled)
Ingress controller is forced to match only the / path leaving rest of the dependencies (apart from the index.html) on other paths like /super.jpg and /folder/awesome.jpg to error with 404 code.
Side note!
You can test yourself this behavior by spawning an nginx Pod and placing example files in it. After applying the Ingress resource with / and pathType: Exact you won't be able to request it through the Ingress controller but you could access them within the cluster.
I encourage you to check the additional resources:
Kubernetes.io: Docs: Concepts: Services networking: Ingress
Kubernetes.github.io: Ingress nginx: User guide: Ingress path matching
The issue with your ingress.yaml is that the route for your ui should be /* and placed below the backend routing. Also, check your routing for APIs
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: titanic-ingress
#labels:
#name: titanic-ingress
spec:
ingressClassName: nginx
rules:
- host: localhost
http:
paths:
- path: /api/*
pathType: Exact
backend:
service:
name: titanicbackendservice
port:
number: 8080
- path: /*
pathType: Exact
backend:
service:
name: titanicfrontendservice
port:
number: 3000
Accessing my nodejs/react site using the URL displays "Invalid Host header". Accessing it through the public IP displays "default backend - 404".
I am using Kubernetes nginx controller with Azure cloud and load balancer.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myrule
namespace: mynamespace
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-staging
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
tls:
- hosts:
- mysite.uknorth.cloudapp.azure.com
secretName: tls-secret
rules:
- host: mysite.uknorth.cloudapp.azure.com
http:
paths:
- backend:
serviceName: service-ui
servicePort: 8080
path: /
- backend:
serviceName: service-api
servicePort: 8999
path: /api
Any guidance appreciated.
So let's assume the SSL part is ok (link) since you can reach the nginx ingress controller.
Your rewrite annotation is not necessary for what you need. Take a look at these rules:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myrule
namespace: mynamespace
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-staging
spec:
tls:
- hosts:
- mysite.uknorth.cloudapp.azure.com
secretName: tls-secret
rules:
- host: mysite.uknorth.cloudapp.azure.com
http:
paths:
- backend:
serviceName: service-ui
servicePort: 8080
path: /
- backend:
serviceName: service-api
servicePort: 8999
path: /api
Whatever you send to /api/.* will be redirected to service-api. And whatever you send to / will be send to service-ui.
Thanks for your feedback. It turns out the problem was not with the ingress rule above. The service-ui was running the incorrect command parameters thus not acknowledging the request. I missed the fact that the service-api was responding correctly.
In short, check the endpoints and running services are configured correctly - more a lesson for me than anyone else. I received a response by curling the service locally but that didn't mean it could handle https requests over ingress as the service was configured incorrectly.
Also, another lesson for me, ask the developers if the correct image is being used for the build. And ask them again if they say yes.