How to manage two paths on the same hostname? - kubernetes

I'm using Kubernetes v1.23.16 cluster (One master and three workers) bare metal based.
I have created couple of services in a separate namespace. The same as follows.
$ kubectl get services --all-namespaces
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 11d
app1 app1-service ClusterIP 10.103.151.235 <none> 80/TCP 19h
app2 app2-service ClusterIP 10.105.88.151 <none> 80/TCP 11d
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 11d
Now I'm having below nginx resource yml to access the service outside. For example i would like access as given below.
http://web.example.com/app1
http://web.example.com/app2
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: app-ingress
spec:
ingressClassName: nginx
rules:
- host: web.example.com
http:
paths:
- path: /app1
pathType: Prefix
backend:
service:
name: app1-service
port:
number: 80
- path: /app2
pathType: Prefix
backend:
service:
name: app2-service
port:
number: 80
When i apply the nginx resource yml file it says service not found error.
$ kubectl describe ingress app-ingress
Name: app-ingress
Labels: <none>
Namespace: default
Address:
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
web.example.com
/app1 app1-service:80 (<error: endpoints "app1-service" not found>)
/app2 app2-service:80 (<error: endpoints "app2-service" not found>)
Annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2
Since my applications services are running in different namespace separately and my nginx resource yml is running in default namespace. So now how do i configure nginx resource file to access both of my service?

An Ingress resource can only refer to Services in the same namespace as the Ingress. To manage two paths on the same hostname that lead to backends in different namespaces, you will need two separate Ingress resources.
In the app1 namespace:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
namespace: app1
spec:
ingressClassName: nginx
rules:
- host: web.example.com
http:
paths:
- path: /app1
pathType: Prefix
backend:
service:
name: app1-service
port:
number: 80
And in the app2 namespace:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
namespace: app2
spec:
ingressClassName: nginx
rules:
- host: web.example.com
http:
paths:
- path: /app2
pathType: Prefix
backend:
service:
name: app2-service
port:
number: 80
With these resources in place, requests for http://web.example.com/app1 will go to app1-service, and requests for http://web.example.com/app2 will go to app2-service.
NB: I've removed your nginx.ingress.kubernetes.io/rewrite-target annotation because you're not doing any regex-based path rewriting in this example.
I've put a deployable example online here.

Just remove your rewrite path in single ingress you can achieve it.
If you are creating the multiple make sure to change the name as Larsks suggested else it will overwrite the existing one.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
spec:
ingressClassName: nginx
rules:
- host: web.example.com
http:
paths:
- path: /app1
pathType: Prefix
backend:
service:
name: app1-service
port:
number: 80
- path: /app2
pathType: Prefix
backend:
service:
name: app2-service
port:
number: 80

Related

Warning: Rejected - All hosts are taken by other resources

I'm trying to setup Nginx-ingress controller to manage two paths on the same hostname in bare metal based cluster.
In the app1 namespace i have below nginx resource:-
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app1-ingress
namespace: app1
spec:
ingressClassName: nginx
rules:
- host: web.example.com
http:
paths:
- path: /app1
pathType: Prefix
backend:
service:
name: app1-service
port:
number: 80
And in the app2 namespace i have below nginx resource:-
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app2-ingress
namespace: app2
spec:
ingressClassName: nginx
rules:
- host: web.example.com
http:
paths:
- path: /app2
pathType: Prefix
backend:
service:
name: app2-service
port:
number: 80
My app1-service applied first and it is running fine, now when i applied the second app2-service it shows below warning and not able to access it on browser.
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Rejected 54s nginx-ingress-controller All hosts are taken by other resources
Warning Rejected 54s nginx-ingress-controller All hosts are taken by other resources
Warning Rejected 54s nginx-ingress-controller All hosts are taken by other resources
How do i configure my nginx ingress resource to connect multiple service paths on the same hostname?
Default Nginx Ingress controller doesn't support having different Ingress resources with the same hostname. You can have one Ingress resource that contains multiple paths, but in this case all apps should live in one namespace. Like this:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app1-ingress
namespace: app1
spec:
ingressClassName: nginx
rules:
- host: web.example.com
http:
paths:
- path: /app1
pathType: Prefix
backend:
service:
name: app1-service
port:
number: 80
- path: /app2
pathType: Prefix
backend:
service:
name: app2-service
port:
number: 80
Splitting ingresses between namespaces is currently not supported by standard Nginx Ingress controller.
You may however take a look at an alternative implementation of Nginx Ingress by Nginx Inc. They have support for Mergeable Ingresses.

Error: endpoints "default-http-backend" not found

I have Kubernetes cluster v1.19.16 set up in bare metal Ubuntu-18.04 server and currently i want to connect cluster jenkins service through http://jenkins.company.com. Haproxy server side frontend & backend already been configured.
My service.yaml file content as follows,
apiVersion: v1
kind: Service
metadata:
name: jenkins-svc
namespace: jenkins
annotations:
prometheus.io/scrape: 'true'
prometheus.io/path: /
prometheus.io/port: '8080'
spec:
selector:
app: jenkins-server
type: ClusterIP
ports:
- protocol: TCP
port: 8080
targetPort: 80
ingress-resource.yaml file content as follows,
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: jenkins-ingress
namespace: jenkins
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: "jenkins.company.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
serviceName: jenkins-svc
servicePort: 8080
# kubectl get service -n jenkins
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jenkins-svc ClusterIP 10.96.136.255 <none> 8080/TCP 20m
# kubectl get ing jenkins-ingress
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
jenkins-ingress <none> jenkins.company.com 80 5h42m
# kubectl describe ingress -n jenkins
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
Name: jenkins-ingress
Namespace: jenkins
Address:
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
jenkins.dpi.com
/ jenkins-svc:8080 (10.244.0.16:80)
Annotations: ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: nginx
Events: <none>
When i tried to access http://jenkins.company.com it shows below error message on browser.
Please let me know what i'm missing here?
The issue with the service port and container port. Jenkins default port is 8080, so I assume your service port is 80
ports:
- protocol: TCP
port: 80
targetPort: 8080
and ingress should be
spec:
rules:
- host: "jenkins.company.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
serviceName: jenkins-svc
servicePort: 80
port: The port of this service
targetPort The target port on the pod(s) to forward traffic to
Difference between targetPort and port in Kubernetes Service definition

tekton-pipeline ingress route conflicts with kubesphere-console

I have two ingress routes created as below,
kubesphere-console
tekton-pipelines
My manifest files are as like below.
**cat ingress-tekton-dashboard.yaml **
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tekton-dashboard
annotations:
ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
ingressClassName: nginx
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: tekton-dashboard
port:
number: 9097
#host: *
...
cat ../kubesphere/ingress-route-kubesphere.yaml
cat ../kubesphere/ingress-route-kubesphere.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubesphere-console
annotations:
kubesphere.io/creator: admin
spec:
ingressClassName: nginx
rules:
- host: crashandburn.australiaeast.cloudapp.azure.com
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: ks-console
port:
number: 80
---
My ingress are as below:
k get ing -nkubesphere-system
NAME CLASS HOSTS ADDRESS PORTS AGE
kubesphere-console nginx * 20.92.133.79 80 28h
ameya#Azure:~/tekton$ k get ing -ntekton-pipelines
NAME CLASS HOSTS ADDRESS PORTS AGE
tekton-dashboard <none> * 80 2m32s
My service for tekton dashboard is like below:
k get svc -n tekton-pipelines
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
tekton-dashboard ClusterIP 10.0.202.127 <none> 9097/TCP 2d3h
tekton-pipelines-controller ClusterIP 10.0.53.46 <none> 9090/TCP,8008/TCP,8080/TCP 2d6h
tekton-pipelines-webhook ClusterIP 10.0.222.121 <none> 9090/TCP,8008/TCP,443/TCP,8080/TCP 2d6h
However, I get the error like below:
k apply -f ingress-tekton-dashboard.yaml -ntekton-pipelines
Error from server (BadRequest): error when applying patch:
{"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"networking.k8s.io/v1\",\"kind\":\"Ingress\",\"metadata\":{\"annotations\":{\"ingress.kubernetes.io/ssl-redirect\":\"false\",\"ingressClassName\":\"nginx\",\"nginx.ingress.kubernetes.io/ssl-redirect\":\"false\"},\"name\":\"tekton-dashboard\",\"namespace\":\"tekton-pipelines\"},\"spec\":{\"ingressClassName\":\"nginx\",\"rules\":[{\"http\":{\"paths\":[{\"backend\":{\"service\":{\"name\":\"tekton-dashboard\",\"port\":{\"number\":9097}}},\"path\":\"/\",\"pathType\":\"Prefix\"}]}}]}}\n"}},"spec":{"ingressClassName":"nginx"}}
to:
Resource: "networking.k8s.io/v1, Resource=ingresses", GroupVersionKind: "networking.k8s.io/v1, Kind=Ingress"
Name: "tekton-dashboard", Namespace: "tekton-pipelines"
for: "ingress-tekton-dashboard.yaml": admission webhook "validate.nginx.ingress.kubernetes.io" denied the request: host "_" and path "/" is already defined in ingress kubesphere-system/kubesphere-console
However, I am using two differnt ports for tekton-dashboard and kubesphere-console so wondering why it is complaining.

Ingress .yml file isn't being applied to GKE but works fine in minikube

I've been using minikube and this yml file:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- http:
paths:
- path: /?(.*)
pathType: Prefix
backend:
service:
name: client-cluster-ip
port:
number: 3000
- path: /api/?(.*)
pathType: Prefix
backend:
service:
name: server-cluster-ip
port:
number: 5000
I've installed helm on my GKE cluster and installed ingress-nginx via helm following their directions here.
I kubectl apply my k8s and they all spin up besides the ingress-service from the file above.
Any help is much appreciated.
I've tried this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
namespace: my-ingress-nginx
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- http:
paths:
- path: /*
backend:
serviceName: client-cluster-ip
servicePort: 3000
- path: /api/*
backend:
serviceName: server-cluster-ip
servicePort: 5000
I'm really stuck here. Not seeing ingress-service show up like I would in minikube and I have no idea why.
server-cluster-ip:
apiVersion: v1
kind: Service
metadata:
name: server-cluster-ip
spec:
type: ClusterIP
selector:
component: server
ports:
- port: 5000
targetPort: 5000
client-cluster-ip:
apiVersion: v1
kind: Service
metadata:
name: client-cluster-ip
spec:
type: ClusterIP
selector:
component: web
ports:
- port: 3000
targetPort: 3000
The deployments and the clusterIp services above are being applied to the cluster but the ingress-service to direct traffic to them is not.
Services:
NAME TYPE
client-cluster-ip ClusterIP
kubernetes ClusterIP
my-ingress-nginx-controller LoadBalancer
my-ingress-nginx-controller-admission ClusterIP
postgres-cluster-ip ClusterIP
redis-cluster-ip ClusterIP
server-cluster-ip ClusterIP
the my-ingress-nginx-controller and my-ingress-nginx-controller-admission was created when I did helm install my-ingress-nginx ingress-nginx/ingress-nginx
Why can't I create an ingress service?
I realized I needed to open port 8443 from the documentation.
So I went to the firewall list in google cloud. Found the rules that had tcp:80,443 in the Protocols / ports. Clicked it, clicked edit and added 8443 to it.
I had an error after but this fixed it:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-resource
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- http:
paths:
- path: /?(.*)
backend:
serviceName: client-cluster-ip
servicePort: 3000
- path: /api/?(.*)
backend:
serviceName: server-cluster-ip
servicePort: 5000
Notice I changed * for ?(.*)

ingress can not get the default http backend

The ingress I config to run with the controller ingress-nginx.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
tls:
- hosts:
- XXX.XX.com
secretName: app-tls
rules:
- host: XXX.XX.com
http:
paths:
- path: /my-api(/|$)(.*)
backend:
serviceName: app
servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-api
spec:
selector:
app: my-api
ports:
- name: app
port: 3000
targetPort: 3000
I can run the api locally curl localIP:3000/testapi, but it can not run remotely.
# kubectl describe ingress app-ingress
Name: app-ingress
Namespace: default
Address: XX.XX.XX.XX
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
app-tls terminates www.daichenchen.cn
Rules:
Host Path Backends
---- ---- --------
XXX.XX.com
/my-api(/|$)(.*) app:80 (<error: endpoints "app" not found>)
I already succeed install the ingress-nginx and all the pod work without error.
Your defined serviceName in Ingress rules and Service should be same.
Like this :
...
rules:
- host: XXX.XX.com
http:
paths:
- path: /my-api(/|$)(.*)
backend:
serviceName: app
servicePort: 80
apiVersion: v1
kind: Service
metadata:
name: app
spec:
selector:
app: my-api
ports:
- name: app
port: 3000
targetPort: 3000
If Ingress and the Service is in different namespace, you can also add the service name to the ingress rule. In this case you need to use dns name for service <service-name>.<namespace>.
For example:
rules:
- host: example.com
http:
paths:
- path: /my-api
backend:
serviceName: test-service.test-namespace
servicePort: 80
apiVersion: v1
kind: Service
metadata:
name: test-service
namespace: test-namespace
The way ingress controller finds out Endpoints of a service is it searches for a kubernetes service with the serviceName provided in the ingress resource in the namespace where you have created the ingress resource. If there is no kubernetes service with serviceName found you get endpoints not found.
The Endpoints of the service contains the IPs of pods behind the kubernetes service.
So in your case either the kubernetes service does not exist or it's in a different namespace than where ingress resource is created.
Some variant of nginx ingress controller does not support default backend and for this it's expected to have the error: endpoints "default-http-backend" not found
Another variant of nginx ingress controller supports default backend.
Double check which variant of nginx ingress controller you installed