Kubernetes ingress is giving me 404 if I don't use wildcard - kubernetes

I am working on a microservice app and I use nginx ingress. I setup rules with 3 services, when I mention host in the rules like this bellow it always gives me 404 for all the services
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-srv
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
cert-manager.io/issuer: "local-selfsigned"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- "tradephlo.local"
secretName: tls-ca
rules:
- host: "tradephlo.local"
- http:
paths:
- path: /api/main/?(.*)
pathType: Prefix
backend:
service:
name: tradephlo-main-srv
port:
number: 4000
- path: /api/integration/?(.*)
pathType: Prefix
backend:
service:
name: tradephlo-integration-srv
port:
number: 5000
- path: /?(.*)
pathType: Prefix
backend:
service:
name: tradephlo-client-srv
port:
number: 3000
However if I put wildcard in the host under the rules it works perfectly
rules:
- host: "*.tradephlo.local"
I don't want to generate wildcard SSL in the production. Please help me point out what I am doing wrong here.

The problem is in dash - in the following line:
rules:
- host: "tradephlo.local"
- http:
Otherwise, it is 2 different hosts - tradephlo.local abd *.
We can check this with the following command:
kubectl describe ing ingress-srv
And we get this:
$ kubectl describe ing ingress-srv
Name: ingress-srv
Namespace: default
Address: xxxxxxxxxx
Default backend: default-http-backend:80 (10.60.0.9:8080)
TLS:
tls-ca terminates tradephlo.local
Rules:
Host Path Backends
---- ---- --------
*
/api/main/?(.*) nginx:80 (yyyyy:80)
And we get this after removed -:
$ kubectl describe ing ingress-srv
Name: ingress-srv
Namespace: default
Address: xxxx
Default backend: default-http-backend:80 (10.60.0.9:8080)
TLS:
tls-ca terminates tradephlo.local
Rules:
Host Path Backends
---- ---- --------
tradephlo.local
/api/main/?(.*) nginx:80 (yyyyyy:80)
So there is no need to use wildcard, when you do this, ingress treats *.tradephlo.local as different host and proceeds to * rule.

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.

Kubernetes Ingress www.example.com gives 404 while https://example.com works

Does anyone know what could be the problem that i'm getting a 404 when trying to access the website via www.example.com while https://example.com works without any issues.
Here is the example of my ingress:
# Ingress
apiVersion: networking.k8s.io/v1
# make a new cert
kind: Ingress
metadata:
name: ${APP_NAME}
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
nginx.ingress.kubernetes.io/from-to-www-redirect: 'true'
spec:
defaultBackend:
service:
name: ${APP_NAME}
port:
number: 80
tls:
- secretName: ${APP_NAME}
hosts:
- ${URL}
- www.${URL}
Also I tried to run
kubectl describe ingress
it returns:
host: example.com
Is there an issue with the configuration or why does the www. not redirect properly?
You don't specify the hosts. They need to be specified in spec.rules, for example:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress-no-third-host
spec:
rules:
- host: first.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: second.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
Note: Keep in mind that TLS will not work on the default rule because the certificates would have to be issued for all the possible sub-domains. Therefore, hosts in the tls section need to explicitly match the host in the rules section.
Source

Kubernetes: Issue with 2 Ingress object with regex path

I have 2 ingress objects
first-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: first-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
tls:
- hosts:
- www.example.com
secretName: example-tls
rules:
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: first-service
port:
number: 80
second-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: second-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /$2
cert-manager.io/cluster-issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
tls:
- hosts:
- www.example.com
secretName: example-tls
spec:
rules:
- host: www.example.com
http:
paths:
- path: /test(/|$)(.*)
pathType: Prefix
backend:
service:
name: second-service
port:
number: 80
The expectation is:
www.example.com/test/whatever -> second-service
www.example.com -> first-service
What I saw is that both www.example.com/test/whatever and www.example.com reach to the first-service
If I change the second-ingress to replace the regex with a static path, it will work. www.example.com/test/whatever will hit the second-service
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: second-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt"
acme.cert-manager.io/http01-edit-in-place: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
tls:
- hosts:
- www.example.com
secretName: example-tls
spec:
rules:
- host: www.example.com
http:
paths:
- path: /test
pathType: Prefix
backend:
service:
name: second-service
port:
number: 80
Any idea why regex does not work? I need the rewrite-target rule, which is the reason I use the regex
The regex that you posted is exactly the same as from the example from the NGINX Ingress Controller docs, but the yaml file is wrong (one mistake with the double spec, below more information) - I tested your yamls files on Kubernetes v.1.21, NGINX Controller version v.1.0.2 and Cert Manager v1.6.1.
A few notes/thoughts about what may be wrong:
Instead of using twice spec: (second-ingress.yaml) , use spec only once. I did not observe the change in the behaviour in the prefixes itself, but in the kubectl get ing command for the second ingress there was no 443 port specified. When I ran kubectl get ing second-ingress -o yaml, there was missing TLS part.
Before (wrong setup):
second-ingress.yaml file:
spec:
tls:
- hosts:
- www.example.com
secretName: example-tls
spec:
rules:
kubectl get ing output (missing port 443 for the second ingress):
user#cloudshell:~/ingress-two-services $ kubectl get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
first-ingress <none> www.example.com xx.xx.xx.xx 80, 443 5h7m
second-ingress <none> www.example.com xx.xx.xx.xx 80 50m
kubectl get ing second-ingress -o yaml output (missing tls part):
user#cloudshell:~/ingress-two-services $ kubectl get ing second-ingress -o yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
...
spec:
rules:
- host: www.example.com
http:
paths:
- backend:
service:
name: second-service
port:
number: 80
path: /test(/|$)(.*)
pathType: Prefix
status:
...
After (good setup):
second-ingress.yaml file:
spec:
tls:
- hosts:
- www.example.com
secretName: example-tls
rules:
kubectl get ing output:
user#cloudshell:~/ingress-two-services $ kubectl get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
first-ingress <none> www.example.com xx.xx.xx.xx 80, 443 5h18m
second-ingress <none> www.example.com xx.xx.xx.xx 80, 443 61m
kubectl get ing second-ingress -o yaml output:
user#cloudshell:~/ingress-two-services $ kubectl get ing second-ingress -o yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
...
spec:
rules:
- host: www.example.com
http:
paths:
- backend:
service:
name: second-service
port:
number: 80
path: /test(/|$)(.*)
pathType: Prefix
tls:
- hosts:
- www.example.com
secretName: example-tls
status:
...
Another thing worth noting that the modified configuration for the second ingress is behaving differently than the one that does not work for you.
Using nginx.ingress.kubernetes.io/rewrite-target: /$2 + path: /test(/|$)(.*):
www.example.com/test/ will rewrite the request to the pod to /
www.example.com/test/whatever will rewrite the request to the pod to /whatever
However, using only path: /test:
www.example.com/test/ will rewrite the request to the pod to /test
www.example.com/test/whatever will rewrite the request to the pod to /test/whatever
Please make sure that you are using a proper setup for which your app is designed to.
Other tips:
make sure that ingress is applied by running kubectl get ing command
get the logs of the NGINX Ingress Controller. Get the name of the Ingress Controller pod (kubectl get pods -n ingress-nginx) and then run kubectl logs -n ingress-nginx ingress-nginx-controller-{...}. Check how your requests are handled and where (which service) they are forwarded to
check the logs of the pods from the deployments and check how they are handling request (kubectl logs {pod-name})
if you are using some out-dated version of the Kubernetes better upgrade it

Ingress uses wildcard, although I didn't specify that

I have the following ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
namespace: apps
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/custom-http-errors: '404'
spec:
tls:
- hosts:
- mywebsite.com
secretName: my-secret-tls
rules:
- host: mywebsite.com
- http:
paths:
- path: /api/events
pathType: ImplementationSpecific
backend:
service:
name: my-events-api-svc
port:
number: 80
When I kubectl describe this ingress, I see the following
Name: my-ingress
Namespace: apps
Address: 52.206.112.10
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
my-secret-tls terminates mywebsite.com
Rules:
Host Path Backends
---- ---- --------
*
/api/events my-events-api-svc:80 (10.244.4.145:4000,10.244.5.118:4000)
Annotations: kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/custom-http-errors: 404
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal UPDATE 9s (x7 over 153m) nginx-ingress-controller Ingress apps/my-ingress
The issue is that the specified path doesn't work, I'm getting 404. I noticed that in the output above, there is a * under the Host. My other ingresses are configured pretty much the same (only have different paths set), and there is no * in the kubectl describe output. Instead, in my other ingresses the proper Host - "mywebsite.com" - is shown.
The output above also has some error (<error: endpoints "default-http-backend" not found>), but I see it as well in my other ingresses (that do work).
What could be the problem?
Its your indentation, please check official example
spec:
rules:
- host: hello-world.info
http:
paths:
Try
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
namespace: apps
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/custom-http-errors: '404'
spec:
tls:
- hosts:
- mywebsite.com
secretName: my-secret-tls
rules:
- host: mywebsite.com
http:
paths:
- path: /api/events
pathType: ImplementationSpecific
backend:
service:
name: my-events-api-svc
port:
number: 80

Is it possible to use same hostname with multiple Ingress resources running in different namespaces?

I want to use the same hostname let's say example.com with multiple Ingress resources running in different namespaces i.e monitoring and myapp. I'm using Kubernetes nginx-ingress controller.
haproxy-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: haproxy-ingress
namespace: myapp
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- hosts:
# fill in host here
- example.com
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: haproxy
port:
number: 80
grafana-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grafana-ingress
namespace: monitoring
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
tls:
- hosts:
- example.com
rules:
- host: example.com
http:
paths:
# only match /grafana and paths under /grafana/
- path: /grafana(/|$)(.*)
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000
When I'm doing curl example.com then it is redirecting me to the deployment running in namespace one(as expected) but when I'm doing curl example.com/grafana then still it is redirecting me to namespace one deployment.
Please help.
Yes it is possible.
There can be two issues in your case.
One is you don't need the regex path for grafana ingress. Simple /grafana path will be fine with path type Prefix as with path type Prefix any /grafana/... will be redirected associated service. So the manifest file will be:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grafana-ingress
namespace: monitoring
spec:
tls:
- hosts:
- example.com
rules:
- host: example.com
http:
paths:
- path: /grafana
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000
And the second issue can be the related service or deployment might not be the under same namespace monitoring. Please make sure the deployment/service/secret or other resources needed for grafana remains under the same namespace monitoring.