Ingress-controller redirect to serviceName according to ip addresses - kubernetes

I have an ingress controller and two nginx in one Kubernetes namespace. One service has the name nginx-1 and the second name nginx-2.
I need to create a situation where nginx-1 will be default backend, and nginx-2 will be a target for a few IP addresses.
I have tried to do this using a ConfigMap but without results.
Maybe someone had a problem like this?

Never saw on Kubernetes docs something like this, but I would like to purpose another approach. You can configure your ingress to use named based virtual hosting, so that few IP addresses would connect using a different domain.
Here and example:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: service1
servicePort: 80
- host: bar.foo.com
http:
paths:
- backend:
serviceName: service2
servicePort: 80
Reference: https://kubernetes.io/docs/concepts/services-networking/ingress/#name-based-virtual-hosting

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

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: access Ingress within a Pod

I have an Ingress object set up to route traffic to the appropriate Service based on the Url path. I would like to access/expose this Ingress object within another Pod. I'm wondering if this is possible?
I tried to set up a Service on the Ingress but that didn't seem to work.
So, for whatever reason (ssr, lots of microservices, etc) you want to access k8s resources using their ingress path mapping, instead of calling each service by its internal name.
For example, you have an ingress config like that:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
rules:
- host: example.com
http:
paths:
- path: /api/users/?(.*)
backend:
serviceName: auth-service
servicePort: 80
- path: /api/cart/?(.*)
backend:
serviceName: cart-service
servicePort: 80
and you want to access auth-service using http://example.com/api/auth instead of http://auth-service.
All you have to do is replace domain part (example.com in our case) with ingress service url. It depends on your configuration and environment, but usually it looks like http://[SERVICE_NAME].[NAMESPACE], for example:
GCP - http://ingress-nginx-controller.ingress-nginx
Helm ingress nginx - http://my-release-ingress-nginx-controller (here we are
using only service name part, because helm installs ingress in
default namespace)
Minikube - if you are using minikube ingress
addon, then you might run into problem where you cannot access
ingress, then just use helm version. (dont disable ingress addon - just install helm version alongside of it)
Get namespaces: kubectl get namespaces
Get service names inside namespace kubectl get services -n [NAMESPACE].
If you have assigned a host name, you also have to provide the domain name and IP address of the cluster to the /etc/hosts file. When you access a service via Ingress from outside the cluster, this is the file that is consulted for host name resolution.
However, a pod running inside a cluster does not have access to this /etc/hosts file. It has its own /etc/hosts file. To use ingress, the pod needs to have the same domain name and IP address entry in it's own /etc/hosts file.
To achieve this, you have to use hostAliases. Here's a sample of how that works:
apiVersion: v1
kind: Pod
metadata:
...
spec:
hostAliases:
- ip:<IP address>
hostnames:
- <host name>
For more detail on hostAliases, go to this link
I have spend so much time on this issue. I found very simple solution. I am using Mac Docker Desktop 3.3.1.
My Kubernetes Version: 1.19.7
I am trying to access UI URL from another pod running in the cluster.
My UI Service
apiVersion: v1
kind: Service
metadata:
name: my-ui-service
spec:
type: LoadBalancer
selector:
app: my-ui
ports:
- protocol: TCP
port: 8080
targetPort: 8080
Ingress for the service
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: my-site.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: my-ui-service
port:
number: 8080
I have used NGINX Ingress Controller.
Command to run the Ingress Controller:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.48.1/deploy/static/provider/cloud/deploy.yaml
Once the controller is ready run the command to see the status of ingress.
kubectl get ingress
Now see the description of the ingress:
kubectl describe ingress my-ingress
Here you will find
Rules:
Host Path Backends
---- ---- --------
my-site.com
/ my-ui-service:8080 (10.1.2.198:8080)
In any pod in the cluster you can access the domain my-site.com by using my-ui-service:8080.
Inside your cluster your pods use services to reach other pods.
From outside the cluster a client may use ingress to reach services.
Ingress resource allows connection to services.
So your pod need to be reachable by a service (my-svc-N in the following example), which you're going to use in your ingress definition.
Take a look at this example:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example-ing
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
backend:
serviceName: default-http-backend
servicePort: 80
rules:
- host: my-kube.info
http:
paths:
- path: /
backend:
serviceName: my-svc-1
servicePort: 80
- host: cheeses.all
http:
paths:
- path: /aaa
backend:
serviceName: my-svc-2
servicePort: 80
- path: /bbb
backend:
serviceName: my-svc-3
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

Troubleshooting kubernetes nginx controller routing

I can't get the nginx controller to route based on the hostname. The YAML below doesn't work - traffic goes to the default back-end / I get a 404. However, if I remove the value for host, the ingress controller successfully routes traffic to my-service. The service works successfully if I place it behind a load balancer but I want to have multiple services working for different host names so I want to use an ingress controller and use a single IP. Thoughts?
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: test1.mydomain.com
http:
paths:
- path: /
backend:
serviceName: my-service
servicePort: 80
The yaml looks slightly different than the rewrite example located here. The yaml is valid and kubectl apply or create should work but not produce the results you are expecting. Do you need the rewrite annotation or could you remove it and the back end service will respond without issue? If you don't need to rewrite anything try removing the yaml to just look like:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-nginx
spec:
rules:
- host: test1.mydomain.com
http:
paths:
- backend:
serviceName: my-service
servicePort: 80