Unable to add multiple Ingresses with same host on nginx-ingress - kubernetes

I am trying to add multiple Ingresses which should share the same host.
One Ingress should handle requests to www.example.de/some and the one all other requests.
Here is a snipped with the Ingress configurations
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: some-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: "www.example.de"
http:
paths:
- path: "/some"
backend:
serviceName: some-svc
servicePort: 8585
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: other-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: "www.example.de"
http:
paths:
- backend:
serviceName: other-svc
servicePort: 8080
As an ingress-controller I installed the nginx-stable/nginx-ingress via Helm
helm install my-ingress nginx-stable/nginx-ingress
When attempting to create the two Ingresses from above only one is working when trying to access www.example.de (this is mapped to 127.0.0.1 in my /etc/hosts).
In the nginx-ingress log is see the following warnings:
2020/01/08 09:33:51 [warn] 560#560: conflicting server name "www.example.de" on 0.0.0.0:80, ignored
2020/01/08 09:33:51 [warn] 560#560: conflicting server name "www.example.de" on 0.0.0.0:443, ignored

Turns out that I was using the wrong nginx-ingress controller. The nginxinc/kubernetes-ingress controller does not support merging Ingress rules with the same host (only via Mergeable Ingresses).
Instead the kubernetes/ingress-nginx should be used.
The differences between these controllers are listed here.
Deleting the old controller and installing kubernetes/ingress-nginx instead using the following command fixed the problem.
helm install my-nginx stable/nginx-ingress
See https://kubernetes.github.io/ingress-nginx/deploy/#using-helm

Just to compliment Brass' reply by referring to the docs:
If multiple Ingresses define different paths for the same host, the ingress controller will merge the definitions.

Related

Defining Ingress for k3s traefik

I am running k3s version 1.25.5 and I would like to define traefik as an ingress for one of the services defined through an external helm chart. I am struggling to find the right ingress definition. I tried with the below yaml file but that gives an error stating
error: resource mapping not found for name: "c8-ingress" namespace: "" from "zeebe-traefik.yaml": no matches for kind "Ingress" in version "extensions/v1beta1"
ensure CRDs are installed first
This seems to be because of the an old apiVersion used in the yaml file. How to do it the right way?
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: c8-ingress
annotations:
kubernetes.io/ingress.class: "traefik"
spec:
rules:
- http:
paths:
- path: "/"
backend:
serviceName: dev-zeebe-gateway
servicePort: 26500
Thanks.
Your example is using an outdated Ingress definition. In v1.25.x you need to use the stable networking.k8s.io/v1 API, as described here.
It is also recommended to provide the fitting namespace. This is useful for documentation, but also required for resource backends. It will also avoid adding -n YOURNAMESPACE to every kubectl apply.
In your case, this may look something like:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: c8-ingress
namespace: YOURNAMESPACE
spec:
rules:
- http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: dev-zeebe-gateway
port:
number: 26500
I hope this helps to solve your issue.
In many cases, you can run kubectl explain RESOURCE to get useful links and resources for a given api-resource.

Ingress on self-hosted Kubernetes on custom interface

I would like to deploy an ngingx-ingress controller on my self-hosted Kubernetes (microk8s) that is configurable to listen on one or more interfaces (external IPs).
Not even sure if that is easily possible and I should just switch to an external solution, such as HAProxy or an nginx.
Required behavior:
192.168.0.1-H"domain.com":443/frontend -> 192.168.0.1 (eth0) -> ingress -> service-frontend
192.168.0.1-H"domain.com":443/backend -> 192.168.0.1 (eth0) -> ingress -> service-backend
88.88.88.88-H"domain.com":443/frontend -> 88.88.88.88 (eth1) -> ? -> [403 or timeout]
88.88.88.88-H"domain.com":443/backend -> 88.88.88.88 (eth1) -> ? -> [403 or timeout]
And then later the eth1 interface should be able to be switched on, so that requests on that interface behave the same as on eth0.
I would like to be able to deploy multiple instances of services for load-balancing. I would like to keep the configuration in my namespace (if possible) so I can always delete and apply everything at once.
I'm using this guide as a reference: https://kubernetes.github.io/ingress-nginx/deploy/baremetal/
I was able to get something working with minikube, but obviously could not expose any external IPs and performance was quite bad. For that, I just configured a "kind: Ingress" and that was it.
So far, the ingress controller that's default on microk8s seems to listen on all interfaces and I can only configure it in its own namespace. Defining my own ingress seems to not have any effect.
I would like to deploy an ngingx-ingress controller on my self-hosted
Kubernetes (microk8s) that is configurable to listen on one or more
interfaces (external IPs).
For above scenario, you have to deploy the multiple ingress controller of Nginx ingress and keep the different class name in it.
Official document : https://kubernetes.github.io/ingress-nginx/user-guide/multiple-ingress/
So in this scenario, you have to create the Kubernetes service with Loadbalancer IP and each will point to the respective deployment and class will be used in the ingress object.
If you looking forward to use the multiple domains with a single ingress controller you can easily do it by mentioning the host into ingress.
Example for two domain :
bar.foo.dev
foo.bar.dev
YAML example
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: frontdoor-bar
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
tls:
- hosts:
- bar.foo.dev
secretName: tls-secret-bar
rules:
- host: bar.foo.dev
http:
paths:
- backend:
serviceName: barfoo
servicePort: 80
path: /(.*)
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: frontdoor-foo
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- foo.bar.dev
secretName: tls-secret-foo
rules:
- host: foo.bar.dev
http:
paths:
- backend:
serviceName: foobar
servicePort: 9000
path: /(.*)
One potential fix was much simpler than anticipated, no messing with MetalLB needed or anything else.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
kubernetes.io/ingress.class: "public"
nginx.ingress.kubernetes.io/whitelist-source-range: 192.168.0.0/24
...
This does not answer the question of splitting an Ingress across multiple interfaces, but it does solve the problem of restricting public access.
By default, bare-metal ingress will listen on all interfaces, which might be a security issue.
This solution works without enabling ingress on Microk8s:
install ingress controller : kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/baremetal/deploy.yaml
create your deployment and service and add this Ingress resource (all in the one namespace):
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-upstream: 'true'
nginx.ingress.kubernetes.io/rewrite-target: "/$2"
name: ingress-resource
namespace: namespace-name
spec:
rules:
- http:
paths:
- backend:
service:
name: service-name
port:
number: service-port
path: /namespace-name/service-name(/|$)(.*)
pathType: Prefix
kubectl get svc -n ingress-nginx
now get either CLUSTER-IP or EXTERNAL-IP and :
curl ip/namespace-here/service-here

Prometheus dashboard exposed over ingress controller

I am trying to setup Prometheus in k8 cluster, able to run using helm. Accessing dashboard when i expose prometheus-server as LoadBalancer service using external ip.
Same does not work when I try to configure this service as ClusterIP and making it as backend using ingress controller. Receiving 404 error, any thoughts on how to troubleshoot this?
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ops-ingress
annotations:
#nginx.org/server-snippet: "proxy_ssl_verify off;"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- path: /prometheus(/|$)(.*)
backend:
serviceName: prometheus-server
servicePort: 80
with above ingress definition in place, url “http://<>/prometheus/ getting redirected to http://<>/graph/ and then 404 error page getting rendered. When url adjusted to http://<>/prometheus/graph some of webcontrols gets rendered with lots of errors on browser console.
Prometheus might be expecting to have control over the root path (/).
Please change the Ingress to prometheus.example.com and it should work fine. (Changing it to a subdomain)
Please change your Ingress configuration file, add host field:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ops-ingress
annotations:
#nginx.org/server-snippet: "proxy_ssl_verify off;"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: prometheus.example.com
http:
paths:
- path: /prometheus(/|$)(.*)
backend:
serviceName: prometheus-server
servicePort: 80
then apply changes executing command:
$ kubectl aply -f your_ingress_congifguration_file.yaml
The host header field in a request provides the host and port
information from the target URI, enabling the origin server to
distinguish among resources while servicing requests for multiple
host names on a single IP address.
Please take a look here: hosts-header.
Ingress definition: ingress.
Useful information: helm-prometheus.
Useful documentation: ingress-path-matching.

Creating a path based Ingress on a GKE cluster

So I am in the process of migrating my bare metal cluster onto GKE and ran into an issue with the ingress. On my bare metal cluster, I used the ingress controller from nginxinc which worked fine. Below is a sample of an Ingress file of a particular deployment:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: mynamespace
name: app-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: myhost
http:
paths:
- path: /dev/appname(/|$)(.*)
backend:
serviceName: app
servicePort: 80
Basically, when a user types in myhost/dev/appname, myhost is resolved to a HAProxy server. The proxy then routes the request to the NodePort that the ingress service is running on.
I tried to do the same thing on my GKE cluster with the only exception being that the Ingress controller on the GKE cluster is exposed using a LoadBalancer as per the documentation
However I get a 502 error if I try to access the URL.
TL;DR: Looking for the best way to access various applications (deployments) deployed on a GKE cluster using URL's like: myhost/dev/firstapp and myhost/dev/secondapp etc.
You can use Kong Ingress as your ingress controller on GKE for your path based ingresses. You can install Kong Ingress from GCP Marketplace. It is easy to integrate and also supports various plugins for authenticating, monitoring etc.
You'll get detailed information and installation instructions from https://github.com/Kong/google-marketplace-kong-app#basic-usage
I would follow this guide on setting up Nginx on GKE. The ingress looks like below:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-resource
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- http:
paths:
- path: /hello
backend:
serviceName: hello-app
servicePort: 8080
You should be able to access your app externally http://external-ip-of-ingress-controller/hello
Now to debug 502 issue verify that the health-checks from the Loadbalancer to your app is passing or not.

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