How to map unmatched routes with ingress on GKE - kubernetes

I'm trying to automatically provision a loadbalancer on GCP by using the ingress object with our GKE cluster.
I have three GKE deployments and each is available with a service on port 8080 with a unique nodePort.
When using ingress-fanout.yaml, it creates 4 backend services instead of the 3 specified in the yaml. The 4th service defaults to all unmatched routes. I assume the 4th service is because we don't match unmapped routes in the yaml.
How can one map unmatched routes to one of the services? Is that possible?
Here's ingress-fanout.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: fanout-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "our-static-ip"
ingress.gcp.kubernetes.io/pre-shared-cert: "our-ssl-cert"
kubernetes.io/ingress.allow-http: "false"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
rules:
- host: our-website.com
http:
paths:
- path: /*
backend:
serviceName: li-frontend
servicePort: 8080
- path: /backend/*
backend:
serviceName: li-django
servicePort: 8080
- path: /notifications/*
backend:
serviceName: li-notifications
servicePort: 8080
Update: I removed many of the original questions and narrowed the scope of the question. When health checks started succeeding, that cleared the old issues.

First of all, "backends" have nothing to do with the "paths" you specified. "backends" on GCP Console are pointing to your GKE node pools.
Ingress supports adding a default backend. You could have tried just searching for "ingress default backend". You can find documentation about this here: https://kubernetes.io/docs/concepts/services-networking/ingress/#single-service-ingress
Basically doing this will set a default backend when nothing else is matched:
spec:
backend:
serviceName: testsvc
servicePort: 80
rules:
[...your stuff here...]

Related

How to configure nginx ingress to use single ingress load balancer for multiple hosts and multiple namespaces

I'm planning to deploy more than 30 apps in 5 namespaces. I will be using existing AWS EKS 1.21 Cluster. All the apps will be requiring external access because it's being used by clients. I don't want to use multiple load balancers to ease the management and also avoiding extra cost on AWS side (because ELB is charged based on hourly usage too.)
What I'm trying to do it basically ;
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: random-ingress
spec:
rules:
- host: randomhost-in-namespace1.com
http:
paths:
- path: /
backend:
serviceName: randomhost-in-namespace1 (in first namespace)
servicePort: 80
- host: randomhost-in-namespace2.com
http:
paths:
- path: /
backend:
serviceName: randomhost-in-namespace2 (in second namespace)
servicePort: 80
- host: randomhost-in-namespace1.com
http:
paths:
- path: /
backend:
serviceName: randomhost-in-namespace3 (in third namespace)
servicePort: 80
Something like this.
Is it possible to cover all these apps in all these namespaces with a single ingress load balancer? I didn't find any clear information about this.
Any help will be highly appreciated.
Thank you.
using the AWS LB Controller and not Nginx LB, you can have 1x ALB, re-used by each namespace.
define Ingress.yaml file per namespace and annotate them with the same alb-group-name.
If group.name specified, all Ingresses with this IngressClass will
belong to the same IngressGroup specified and result in a single ALB.
the AWS LB Controller will then create 1x ALB, it desired rules, listeners to TG's and register the right EC2 nodes etc.
this can be something like this:
Ingress-namespace1.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: random-ingress
namespace: namespace1
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/group.name: my-group
alb.ingress.kubernetes.io/scheme: internet-facing
spec:
rules:
- host: randomhost-in-namespace1.com
http:
paths:
- path: /
backend:
serviceName: randomhost-in-namespace1 (in first namespace)
servicePort: 80
Ingress-namespace2.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: random-ingress
namespace: namespace2
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/group.name: my-group
alb.ingress.kubernetes.io/scheme: internet-facing
spec:
rules:
- host: randomhost-in-namespace2.com
http:
paths:
- path: /
backend:
serviceName: randomhost-in-namespace2 (in second namespace)
servicePort: 80
where both files contain same group.name and differ by their namespace and host rule.
you can also follow AWS LBC logs to see if everything has been created successfully (should contain no errors on logs):
kubectl logs deploy/aws-load-balancer-controller -n kube-system --follow

how to setup yaml ingress in google cloud with redirect

I’m setting up an environment in Google Cloud with an ingress and load balancers.
I know how to setup hosts and paths to it but I can't figure out how to setup when a user goes to a specific site http://example.com/ I want him to redirect to http://example.com/en.
Note:
http => https
/ => /en
UPDATED
I added app-root: /en (but it doesn't do anything).
This is my current yaml:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: gce
kubernetes.io/ingress.global-static-ip-name: our-frontend-static-ip
networking.gke.io/managed-certificates: example-certificate
appgw.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/app-root: /en
name: example-ingress
namespace: default
spec:
rules:
- host: anotherexample.com
http:
paths:
- backend:
serviceName: anotherexample-service
servicePort: 80
- host: example.com
http:
paths:
- path: /nl
backend:
serviceName: example-nl-service
servicePort: 80
- path: /en
backend:
serviceName: example-en-service
servicePort: 80
So, there are 2 hosts in my yaml and I want: when the url is correct for 1 of the hosts: example.com it must go to example.com/en (this is for Multilanguage purposes)
We can change the settings in the loadbalancer ban after the sync from the ingress in changes it back.
Kubernetes supports multiple Ingress Controllers which are different from each other. For example, you are trying to use the Ingress GCE and there is also a popular Nginx Ingress.
The main problem in your use case is that the Ingress GCE is not supporting rewrites. An on-going feature request regarding that can be found here.
To be able to use the rewrites you will need to deploy the Nginx Ingress Controller and switch annotation in your yaml from:
kubernetes.io/ingress.class: "gce"
to:
kubernetes.io/ingress.class: "nginx"
The sources that will help you out with this are as follows:
Installation Guide
Rewrite
An example

REST URI with NGINX Ingress Controller

I'm trying to configure NGINX Ingress controller as the correct entry point to my Kubernetes cluster. Inside the cluster, I've created two REST Web services as well as frontend application. I'm trying to achieve the following scenario.
When the ingress IP is hit without any parameters it should be routed
to the frontend app. Example: 192.168.1.20 should lead to frontend
service on port 80.
When parameters are given, the request should be
routed to correct REST service. Example:
192.168.1.20/first-rest/api/flower?id=1 should route the request to
the first-rest service so that it could return the flower with id =
1.
I can correctly access the frontend application but when trying to access any REST service I'm getting 404 error or no response at all. First-rest, Second-rest and frontend are running correctly and are accessible when configured as LoadBalancer services. With Nginx, they are configured as ClusterIp services.
My ingress configuration
------------------------
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: main-routes
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- http:
paths:
- path: /first-rest(/|$)(.*)
backend:
serviceName: first-rest
servicePort: 8090
- path: /second-rest(/|$)(.*)
backend:
serviceName: second-rest
servicePort: 9000
- path: /(.*)
backend:
serviceName: frontend
servicePort: 80
It seems like NGINX is cutting short my URL parameters that are required for my REST API. Is there any way to pass the right URL path so that `192.168.1.20/first-rest/api/flower?id=1` would be routed to `[first-rest add and port]/api/flower?id=1` ?
You need to specify the ingress path type otherwise , depending on the ingress class specific implementation it will default to either exact or prefix (I assume in your case it is defaulting to exact)
So, you need to do something like
spec:
rules:
- http:
paths:
- path: /first-rest
pathType: Prefix
backend:
serviceName: first-rest
servicePort: 8090
see docs on ingress path here

Is there a way url redirect internally to particular service based on context path?

There are multiple same pods running in one cluster but different namespaces. This is the web application running in Kubernetes. I have the URL <HOSTNAME>:<PORT>/context/abc/def/...... I want to redirect to particular service based on the context. Is there a way i can achieve it using ingress controller ? Or Is there any way i can achieve it using different ports through ingress ?
My web application works fine if the URL is <HOSTNAME>:<PORT>/abc/def/...... Since i have to access the different pods using the same URL, I am adding context to it. Do we have any other way to achieve this use case ?
You can do that with rewrite-target. In example below i used <HOSTNAME> value of rewrite.bar.com and <PORT> with value 80.
apiVersion: extensions/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: context-service
servicePort: 80
path: /context1(/|$)(.*)
- backend:
serviceName: context-service2
servicePort: 80
path: /context2(/|$)(.*)
For example, the ingress definition above will result in the following rewrites:
rewrite.bar.com/context1 rewrites to rewrite.bar.com/ for context 1 service.
rewrite.bar.com/context2 rewrites to rewrite.bar.com/ for context 2 service.
rewrite.bar.com/context1/new rewrites to rewrite.bar.com/new for context 1 service.
rewrite.bar.com/context2/new rewrites to rewrite.bar.com/new for context 2 service.
You can manage how the traffic is pointed to the correct service by using the rules configuration of the ingress, here is a simple example from the documentation:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: app-ingress
spec:
rules:
- http:
paths:
- path: /abc
backend:
serviceName: abc-service
servicePort: 80
- path: /context
backend:
serviceName: context-service
servicePort: 80

kubernetes gke multiple ingresses single global ip

I have multiple MSA on k8s on GKE. Each is on separate subdomain like:
msa1.example.com
msa2.example.com
I have it in single ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: main-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: lalala-ip-1
kubernetes.io/ingress.allow-http: "false"
spec:
tls:
- hosts:
- msa1.example.com
secretName: msa1-tls
backend:
serviceName: sink
servicePort: 80
rules:
- host: msa1.example.com
http:
paths:
- path: /.well-known/*
backend:
serviceName: letsencrypt
servicePort: 80
- path: /*
backend:
serviceName: lalala
servicePort: 80
- host: msa2.example.com
http:
paths:
- path: /*
backend:
serviceName: lalala2
servicePort: 80
... and all is nice.
The thing is, that I want to have each MSA in separate file.
Problem is this kubernetes.io/ingress.global-static-ip-name: lalala-ip-1 line. If I have it in two ingresses only first started is bounded to IP, but other ones no.
Is there a way, to share IP on GKE ingress controller between two ingresses?
A way around it could be to run your own nginx-ingress controller in your cluster and expose it via LoadBalancer service type. Then you would have 1 IP for your ingress and be able to serve all ingresses via nginx controller by adding annotation kubernetes.io/ingress.class: "nginx"
Reference: https://kubernetes.github.io/ingress-nginx/user-guide/multiple-ingress/
Confirmed my comment:
Only one resource at a time can use a static external IP address.
https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address
GKE has recently added support for the new Kubernetes Gateway API. Both the GKE Gateway implementation as well as the Kubernetes Gateway API specification are still in alpha at this point.
The Kubernetes Gateway-API, is intended to support use cases, where you have a central Gateway (with a single IP), but want different Routes (with different hostnames or paths), managed in separate objects or even namespaces.
References:
https://gateway-api.sigs.k8s.io/
https://cloud.google.com/kubernetes-engine/docs/concepts/gateway-api