Nginx Ingress controller with K8s returning 404 - nginx

I have a service which is accepting the request at /api/v1/orders. I was able to validate the response using the Cluster IP. I logged into a pod and hit the curl http://order-service/api/v1/orders and getting the response.
I then set up a Nginx Ingress Controller and the ingress with the below yaml definition. I used the cafe example and the cafe ingress is working fine.
When I try to access my order-service I am getting 404. I am not sure how to debug this.
Note: My API is accessible on http://context/api/v1/orders endpoint. How do I redirect the path the /orders/api/v1/orders from the ingress?
curl -v -H "Content-type: application/j son" -H "Accept: application/json" https://classpath.com/orders/api/v1/orders --insec ure
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: orders-microservice-ingress
spec:
ingressClassName: nginx # use only with k8s version >= 1.18.0
tls:
- hosts:
- classpath.com
secretName: cafe-secret
rules:
- host: classpath.com
http:
paths:
- path: /orders
backend:
serviceName: order-service
servicePort: 80
I have set the aws loadbalancer IP to classpath.com in the /etc/hosts file.

Related

www.example.com gives 404 while example.com works perfectly

I have a problem with Kubernetes deployment. My service works perfectly when accessing "example.com" or "https://example.com" but it does not work when accessing over "www.example.com" or "http://example.com" the default nginx backend shows up with a 404.
Here is my ingress implementation:
# 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/from-to-www-redirect: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: example.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: ${APP_NAME}
port:
number: 80
tls:
- secretName: ${APP_NAME}
hosts:
- example.com
- www.example.com
Here is my certificate configuration:
# Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ${APP_NAME}
spec:
secretName: ${APP_NAME}
dnsNames:
- example.com
- www.example.com
issuerRef:
name: letsencrypt-production
# We can reference ClusterIssuers by changing the kind here.
# The default value is Issuer (i.e. a locally namespaced Issuer)
kind: ClusterIssuer
group: cert-manager.io
I configured the following DNS records:
example.com A 300 xx.xxx.xx.xx
*.example.com A 300 xx.xxx.xx.xx
www.example.com CNAME 300 example.com
Does anyone knows what could be the issue here? Every help is appreciated a lot!
You need to map your ingress controller external IP to your domain as a DNS record:
it's present under your services
kubectl -n $NAMESPACE get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.0.XX.XXX XX.XXX.XX.XXX 80:XXXXX/TCP,443:XXXX/TCP Xd
Add a DNS record in your DNS zone example.com ==> $EXTERNAL-IP
the 404 was coming from Nginx. I'm not sure what went wrong but after reinstalling Nginx on my cluster it works now. I recommend everyone having this problem runing a curl -v and see if it is a redirect header or not.

Kubernetes Nginx Ingress - Rewrite Dynamic URL

Here i have kubernetes running on minikube and it has 2 services backend and frontend. And i have installed ingress addon for minikube.
I wanted to rewrite whenever the frontend request the path url is /users/{user-id} it goes to backend service with the same url dynamically.
Let say the request is /users it rewrite to backend service to /users, /users/1 it goes to /users/1.
I tried to read nginx manual found some special expression i don't understand.
This is my ingress configuration.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-be
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /users/$1
spec:
ingressClassName: nginx
rules:
- host: backend
http:
paths:
- path: /users/(.*)
pathType: Prefix
backend:
service:
name: backend
port:
number: 5000
My configuration seems fine when the request is /users/{users-id} but when the request is /users, my ingress won't redirect me to '/users' in backend service.
When i tested with curl, this is the output.
curl http://backend/users/3
{"id":3,"name":"Sofia","email":"sofia#gmail.com","gender":"Female","createdAt":"2022-04-05T15:46:46.000Z","updatedAt":"2022-04-05T15:46:46.000Z"}%
curl http://backend/users
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
What am i missing here?
Thank you in advance for your help!
Update!
Andreas in the comment suggest me to use /users/ and it works!
Then i decided to modified my ingress configuration.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-be
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /users/$2
spec:
ingressClassName: nginx
rules:
- host: backend
http:
paths:
- path: /users(/|$)(.*)
pathType: Prefix
backend:
service:
name: backend
port:
number: 5000

nginx.ingress.kubernetes.io/server-snippet annotation contains invalid word location

I am new to kubernetes and using AWS EKS cluster 1.21. I am trying to write the nginx ingress config for my k8s cluster and blocking some request using server-snippet. My ingress config is below
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: abc-ingress-external
namespace: backend
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: nginx-external
nginx.ingress.kubernetes.io/server-snippet: |
location = /ping {
deny all;
return 403;
}
spec:
rules:
- host: dev-abc.example.com
http:
paths:
- backend:
service:
name: miller
port:
number: 80
path: /
pathType: Prefix
When I apply this config, I get this error:
for: "ingress.yml": admission webhook "validate.nginx.ingress.kubernetes.io" denied the request: nginx.ingress.kubernetes.io/server-snippet annotation contains invalid word location
I looked into this and got this is something related to annotation-value-word-blocklist. However i don't know how to resolve this. Any help would be appreciated.
Seems there's issue using location with some versions. The following was tested successfully on EKS cluster.
Install basic ingress-nginx on EKS:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.0/deploy/static/provider/aws/deploy.yaml
Note: If your cluster version is < 1.21, you need to comment out ipFamilyPolicy and ipFamilies in the service spec.
Run a http service:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/docs/examples/http-svc.yaml
Create an ingress for the service:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: http-svc
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/server-snippet: |
location = /ping {
deny all;
return 403;
}
spec:
rules:
- host: test.domain.com
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: http-svc
port:
number: 8080
Return 200 as expected:
curl -H 'HOST: test.domain.com' http://<get your nlb address from the console>
Return 200 as expected:
curl -H 'HOST: test.domain.com' -k https://<get your nlb address from the console>
Return 403 as expected, the snippet is working:
curl -H 'HOST: test.domain.com' -k https://<get your nlb address from the console>/ping
Use the latest release to avoid the "annotation contains invalid word location" issue.
Alternatively, replacing nginx.ingress.kubernetes.io/server-snippet by nginx.org/server-snippets fixed the issue for me. See for instance here

ingress nginx - proxy to external URL

I search (since many days ...) How to use Ingress Nginx in order to use External url as backend.
Yes I use Service object with externalName. I also test many many directive in nginx without succes...
The goal is simple:
user can resolv and join only my public URL (url-public.com & url-public-2.com)
I want to send request to external backend than is out of my control and cluster (url-ext.com)
My ingress can resolv url-ext.com, user cannot. Of course, url-ext.com have here proper certificat and is expose as HTTPS ;).
Nota : My ingress expose 2 url, but I don't think this is important.
My Code :
Service :
kind: Service
apiVersion: v1
metadata:
name: external-eip
namespace: external-url
spec:
type: ExternalName
externalName: url-ext.com
Ingress :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: external-eip
namespace: external-url
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/upstream-vhost: "url-ext.com"
nginx.ingress.kubernetes.io/configuration-snippet: |
# more_clear_input_headers "Host" "X-Forwarded-Host";
more_set_input_headers 'Host: url-ext.com';
proxy_set_header Host url-ext.com;
spec:
rules:
- host: url-public.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: external-eip
port:
number: 443
- host: url-public-2.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: external-eip
port:
number: 443
Result (curl or Browser access ) :
<html>
<head><title>504 Gateway Time-out</title></head>
<body>
<center><h1>504 Gateway Time-out</h1></center>
<hr><center>nginx</center>
</body>
</html>
And Ingress Log :
2021/08/06 21:44:45 [error] 10873#10873: *2914631 upstream timed out (110: Operation timed out) while connecting to upstream, client: 10.203.65.14, server: url-public.com, request: "GET / HTTP/2.0", upstream: "https://10.203.64.5:443/", host: "url-ext.com"
10.203.64.5 is the real IP of url-ext.com.
And, curl https://10.203.64.5:443/ -k -v -H "Host: url-ext.com" work.
Don't ask me "why using this annotation", I don't know :p many Google search and many test ...
So, what is the correct ingress configuration for using externalName, when this externalName is (probably) under RP also ?
Nota : Rewrite and other redirect not work, because it rewrite user location and I don't want it. User canno't acces and resolv url-ext.com, only url-public.com.
Br, Thanks
Reply to my self. The problem was my Ingress (and all my K8S cluster) is under HTTP Squid proxy.
I have mounted all env variable for proxy but it seems the Ingress container doesn't use it ...
So, to get it working, I allow my cluster to outbound 80/443 ports to the destination.
You just need this annotation:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/upstream-vhost: "url-ext.com"
But, if any of you know how to setup my Ingress to use my HTTP proxy, I will need it.
br

Ingress intra-cluster Kubernetes communication

I have an nginx ingress running in minikube (addon enabled) with a couple pods and services, the ingress has the following configuration:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx
spec:
rules:
- host: api.info
http:
paths:
- backend:
serviceName: api-service
servicePort: 80
- host: web.info
http:
paths:
- backend:
serviceName: web-service
servicePort: 80
When I'm outside the cluster the following works fine:
curl --header 'Host: api.info' $(minikube ip)/health
But, when I'm inside the cluster, I would expect the containers to be able to talk to each other using their host names listed in my Ingress template. For example, I would expect the following to work, but it doesn't:
$ kubectl exec -it web-6c656c58d5-lpxsk /bin/bash
root#web-6c656c58d5-lpxsk:/web# curl api.info/health
Instead, it returns results from the actual api.info website, which I have no affiliation. First, can someone please confirm that this is suppose to work?
Thank you.
Firstly, .info is a generic TLD, this makes DNS resolution messy.
Consider using a protected TLD or your own registered one e.g. api.example.com
You should edit your /etc/hosts with a line similar to:
<ip_address> api.info
or changing resolv.conf to prioritise your internal DNS.

Resources