Handling multiple sub paths via Nginx Ingress - kubernetes

I am struggling to have Ingress controller to properly handle sub paths. My architecture - two services sat on diff paths of one domain. Each service has its own ingress configuration:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress1
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: "letsencrypt-production-issuer"
kubernetes.io/ingress.allow-http: "false"
spec:
tls:
- hosts:
- api.mydomain.com
secretName: my-secret
rules:
- host: api.mydomain.com
http:
paths:
- path: /path1
backend:
serviceName: service1
servicePort: 80
And
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress2
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-production-issuer"
kubernetes.io/ingress.allow-http: "false"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- api.mydomain.com
secretName: my-secret
rules:
- host: api.mydomain.com
http:
paths:
- path: /path2
backend:
serviceName: service2
servicePort: 80
With the above configuration, 1st ingress works and i am able to reach my endpoints at api.mydomain.com/path1, in the same time api.mydomain.com/path2 returns http 400. What am i doing wrong?

So the actual problem was a bit different to ingress not being able to find an endpoint. My backend services are secure gRPC services and therefore expect to be called via https or grpcs. So setting an ingress to be running against secure backends solved the problem:
nginx.ingress.kubernetes.io/secure-backends: "true"
For a newer versions of k8s you should use different attributes.

Related

Combining routes of frontend and backend

I have a React front-end and Flask API as back-end.
I wish to have both front-end and back-end routes accessible at same address. E.g frontend at myapp.web.com and backend at myapp.web.com/api.
It will have different deployments for them. I want to know how to do this.
Yes, you can have the same domain that can point to multiple services based on the path.
Normally this can help you to resolve the CORS issue.
API
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
name: backend-ingress
namespace: backend-api
spec:
rules:
- host: myapp.web.com
http:
paths:
- backend:
service:
name: backend-service-name
port:
number: 80
path: /api
pathType: Prefix
tls:
- hosts:
- myapp.web.com
secretName: my-secret-tls
Frontend ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
name: frontend-service
namespace: frontend-service
spec:
rules:
- host: myapp.web.com
http:
paths:
- backend:
service:
name: frontend-service-name
port:
number: 80
path: /
pathType: Prefix
tls:
- hosts:
- myapp.web.com
secretName: my-secret-tls
so in this case, all the requests that start with /api will route to the backend app and rest of the requests will route to frontend.

How to configure ingress to deploy services to subdomains without creating a new loadbalancer

I am new to Kubernetes and have an application deployed via GKE on mydomain.com and now want to add another service which should be available on api.mydomain.com without adding a new expensive load balancer. What should the new ingress file for api.mydomain look like? I read the documentation, but cannot figure out how to do this.
This is my first service running on mydomain.com:
kind: Service
apiVersion: v1
metadata:
name: app-service
spec:
selector:
app: app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: app-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "ip"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
acme.cert-manager.io/http01-edit-in-place: "true"
kubernetes.io/tls-acme: "true"
spec:
rules:
- host: mydomain.com
http:
paths:
- backend:
serviceName: app-service
servicePort: 80
tls:
- hosts:
- mydomain.com
secretName: my-certs
I tried to use the same configuration for the subdomain api.mydomain.com, but this does not work.
kind: Service
apiVersion: v1
metadata:
name: api-service
spec:
selector:
app: api
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: api-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "ip"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
acme.cert-manager.io/http01-edit-in-place: "true"
kubernetes.io/tls-acme: "true"
spec:
rules:
- host: api.mydomain.com
http:
paths:
- backend:
serviceName: api-service
servicePort: 80
tls:
- hosts:
- api.mydomain.com
secretName: my-certs-api
Maybe I'm approaching the problem in the wrong way, I'm new in GKE, any suggestions?
Try "nginx" ingress.class . The config shall be like the following (I have removed tls part out it).
Nginx Ingress controller
is quite easy and functional.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: double-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
# nginx.ingress.kubernetes.io/rewrite-target: /$2 ### you can use it to route different paths to different services under the same host
spec:
rules:
- host: mydomain.com
http:
paths:
- path: /
# - path: /doc/common(/|$)(.*) ### if you are using rewrite
backend:
serviceName: app-service
servicePort: 80
- host: api.mydomain.com
http:
paths:
- path: /
backend:
serviceName: api-service
servicePort: 80
tls:
- hosts:
- api.mydomain.com
secretName: my-certs-api
Hope that helps!
You would generally use a different Ingress Controller than the default ingress-gce. ingress-nginx is very common and easy to get started with, but there are many options so I recommend you research them and pick which one matches your use case best.
As per my understanding you are trying to create one HTTP load balancer with one public IP address for two different domains.
It's doable using standard GKE ingress controller GCE L7 at least for HTTP protocol (see example below).
Please also find documentation page about using multiple SSL certificates with GCE L7 ingress.
Example:
( mydomain.com is replaced with example.com, because... an answer body cannot contain it.)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: app-ingress
spec:
rules:
- host: example.com
http:
paths:
- backend:
serviceName: app-service
servicePort: 80
- host: api.example.com
http:
paths:
- backend:
serviceName: api-service
servicePort: 80
Applying this yaml to GKE cluster results creating one HTTP load-balancer with the following Host and path rules:
http://example.com:80/* -> app-service:80 (if app-service health-check passed)
http://example.com:80/* -> default-backend:80 (return 404) (if app-service heath-check fails and default-backend health-check passed)
http://api.example.com:80/* -> api-service:80 (if app-service health-check passed)
http://api.example.com:80/* -> default-backend:80 (return 404) (if api-service heath-check fails and default-backend health-check passed)
http://lb.ip.address:80 -> default-backend:80 (return 404) (if default-backend health-check passed)
HTTP LB returns 502 if all backends' health-checks are failed.

Route for annotation methods in traefik-ingress with kubernetes

I need to route methods like PUT, PATCH, GET and POST in two different URLs, but I didn't find the best entry for my entry pod. I tried the annotation he used, but it doesn't work. Could you help me with this?
edit yaml added
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: traefik
traefik.frontend.rule: PathPrefixStrip;Method:PUT,PATCH,POST
traefik.ingress.kubernetes.io/frontend-entry-points: http,https
traefik.ingress.kubernetes.io/rewrite-target: /
name: services-ingress-xx-api-mock
namespace: develop-v1-0
spec:
rules:
- host: xx
http:
paths:
- backend:
serviceName: xx-api-mock
servicePort: http
path: xx/xxx
tls:
- secretName: mysecret

How do I apply session stickiness with nginx-ingress on just one backend service?

I've got an Ingress object with multiple backends, like this:
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: my-app
annotations:
certmanager.k8s.io/issuer: letsencrypt-prod
fabric8.io/generated-by: exposecontroller
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: 'true'
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
nginx.ingress.kubernetes.io/proxy-body-size: 500m
nginx.ingress.kubernetes.io/session-cookie-expires: '172800'
nginx.ingress.kubernetes.io/session-cookie-max-age: '172800'
spec:
tls:
- hosts:
- my-app.<tld>
secretName: tls-my-app
rules:
- host: my-app.<tld>
http:
paths:
- path: /_ui/
backend:
serviceName: ui
servicePort: 443
- backend:
serviceName: api
servicePort: 443
I only need session stickiness on my api service. But the nginx.ingress.kubernetes.io/affinity: cookie annotation applies to all backend services. Does someone know how I can accomplish what I need?
Annotations are applied to every path (location) defined on your Ingress object. If you need different annotations for each path, you could create one different Ingress for each path:
Annotations are applied to all the paths in the Ingress.
Multiple Ingresses can define different annotations. These definitions are not shared between Ingresses.
If multiple Ingresses define different paths for the same host, the ingress controller will merge the definitions.
Nginx Ingress Controller will watch and collect those Ingress rules, applying them accordingly.
For example:
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: my-app-ui
annotations:
certmanager.k8s.io/issuer: letsencrypt-prod
fabric8.io/generated-by: exposecontroller
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: 'true'
# No session affinity here
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
nginx.ingress.kubernetes.io/proxy-body-size: 500m
nginx.ingress.kubernetes.io/session-cookie-expires: '172800'
nginx.ingress.kubernetes.io/session-cookie-max-age: '172800'
spec:
tls:
- hosts:
- my-app.<tld>
secretName: tls-my-app
rules:
- host: my-app.<tld>
http:
paths:
- path: /_ui/
backend:
serviceName: ui
servicePort: 443
---
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: my-app-api
annotations:
certmanager.k8s.io/issuer: letsencrypt-prod
fabric8.io/generated-by: exposecontroller
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: 'true'
nginx.ingress.kubernetes.io/affinity: cookie # <-- Session affiniy is here
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
nginx.ingress.kubernetes.io/proxy-body-size: 500m
nginx.ingress.kubernetes.io/session-cookie-expires: '172800'
nginx.ingress.kubernetes.io/session-cookie-max-age: '172800'
spec:
tls:
- hosts:
- my-app.<tld>
secretName: tls-my-app
rules:
- host: my-app.<tld>
http:
paths:
- path: /_api/
backend:
serviceName: api
servicePort: 443
---
Note: The API extensions/v1beta1 was deprecated on Kubernetes 1.16. Consider migrating to networking.k8s.io/v1beta1.

Serve one path internally and a different one externally

I have an helm chart serving an Mediawiki using apache. Internally it does so from /wiki.
I'd like to run multiply instances and externally reach it from /something-wiki, /other-wiki and so on.
So in other words I'd like to have my ingress controller react to one path and internally go to another path.
I tried the below but it just sends a 301 (moved permanently) which doesn't work since the folder doesn't exists.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /wiki
name: wiki-environment-erst-env
namespace: wiki
spec:
rules:
- host: aks-dev.something.com
http:
paths:
- backend:
serviceName: erst-wiki-package
servicePort: 80
path: /erst-wiki
tls:
- hosts:
- aks-dev.something.com
secretName: erst-tls-secret
Any ideas?
If I understand correctly, regexp redirection might work. And the wiki configuration should be handled accordingly.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/use-regex: true
name: wiki-environment-erst-env
namespace: wiki
spec:
rules:
- host: aks-dev.something.com
http:
paths:
- backend:
serviceName: erst-wiki-package
servicePort: 80
path: /erst-wiki/.*
tls:
- hosts:
- aks-dev.something.com
secretName: erst-tls-secret