Issue
I am trying to define routes for external traffic ie where should requests go once they reach my app gateway. I have a frontend and backend service, defined at ports 3000 and 5001 respectively. I want all traffic to go to my frontend service, however I would like api calls to go to my backend service (anything that has "/api"). This is how my ingress is setup currently:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
kubernetes.io/ingress.class: azure/application-gateway
appgw.ingress.kubernetes.io/ssl-redirect: "true" # Enable SSL redirect
appgw.ingress.kubernetes.io/backend-protocol: "http" # protocol AGIC communicates to pods with
appgw.ingress.kubernetes.io/backend-path-prefix: "/"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- mydomain.com
secretName: letsencrypt-prod-secret
rules:
- host: mydomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 3000
- path: /(api)(.*)
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 5001
This does give me the result I want for navigating to my page visually, but when I try to do anything that requires backend calls such as signup, login, etc I get a 404 error. I also don't see any requests in the pods logs for these.
Backend logs before change:
2024-01-26 00:44:54,541 INFO :- - [26/Jan/2024 00:44:54] "GET / HTTP/1.1" 200 -
2024-01-26 00:44:55,099 INFO :- - [26/Jan/2024 00:44:55] "GET / HTTP/1.1" 200 -
2024-01-26 00:45:24,542 INFO :- - [26/Jan/2024 00:45:24] "GET / HTTP/1.1" 200 -
2024-01-26 00:45:25,098 INFO :- - [26/Jan/2024 00:45:25] "GET / HTTP/1.1" 200 -
2024-01-26 00:45:54,545 INFO :- - [26/Jan/2024 00:45:54] "GET / HTTP/1.1" 200 -
2024-01-26 00:45:55,101 INFO :- - [26/Jan/2024 00:45:55] "GET / HTTP/1.1" 200 -
How should I define my ingress routes? In summary, I want all traffic to go to the frontend pod set up and I want any request with "/api" to be sent to the backend pod. Should I be going about this in a different way?
However, if I change my ingress to (only changes):
appgw.ingress.kubernetes.io/backend-path-prefix: "/api"
rules:
- path: /api
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 5001
I am able to see the requests being made to the backend but am no longer able to navigate to mydomain.com and see the frontend page I want up. After change:
2024-01-26 00:46:49,859 INFO :- - [26/Jan/2024 00:46:49] "GET /api HTTP/1.1" 404 -
2024-01-26 00:46:50,047 INFO :- - [26/Jan/2024 00:46:50] "GET /api HTTP/1.1" 404 -
2024-01-26 00:46:51,819 INFO :- - [26/Jan/2024 00:46:51] "POST /api/login HTTP/1.1" 404 -
I get a 404 after the changes because all my routes in flask don't have "/api" defined in them (I think).
Solution
The behavior you're experiencing is likely due to the way the Ingress controller is routing the traffic based on the paths defined in your Ingress resource. The first configuration you posted is close to what you need, but the ordering of the rules and the path
definitions are critical in Kubernetes Ingress.
Ingress paths are evaluated in order, and the first match is where the traffic will be routed. Therefore, if the catch-all path /
is listed before /api
, all traffic will go to the frontend service, including your API calls. To fix this, you should define the more specific /api
path before the general /
path.
Try adjusting your Ingress something like this:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
kubernetes.io/ingress.class: azure/application-gateway
appgw.ingress.kubernetes.io/ssl-redirect: "true"
appgw.ingress.kubernetes.io/backend-protocol: "http"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- mydomain.com
secretName: letsencrypt-prod-secret
rules:
- host: mydomain.com
http:
paths:
- path: /api/ # Note the trailing slash
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 5001
- path: / # The catch-all rule should be last
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 3000
In this setup:
- Requests to
mydomain.com/api/
(and anything that follows) will be routed to the backend service on port 5001. - All other requests will be routed to the frontend service on port 3000.
Remember to include the trailing slash in the /api/
path, as it denotes a prefix. Without it, only the exact path /api
would be matched, not paths like /api/login
Reference:
Kubernetes Ingress Documentation Ingress Path Matching Introduction to Application Gateway Ingress Controller Annotations for Application Gateway Ingress Controller Use Let's Encrypt with Azure Kubernetes Service (AKS)
Answered By - Arko
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.