How to install "ingress-nginx"? - docker

I got the following code that uses ingress-nginx within infra\k8s-dev\ingress-srv.yaml 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"
spec:
rules:
- host: mysite.local
http:
paths:
- path: /api/users/?(.*)
pathType: Prefix
backend:
service:
name: auth-srv
port:
number: 3000
- path: /?(.*)
pathType: Prefix
backend:
service:
name: client-srv
port:
number: 3000
I searched through the internet and found the following command to install it:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.4.0/deploy/static/provider/cloud/deploy.yaml
But I am not sure where should I run this command? Is there any ingress-nginx package that I also must install from NPM?
I am using Docker-Desktop on Windows 10 machine.

Command you have mentioned is right
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.4.0/deploy/static/provider/cloud/deploy.yaml
it self will download and apply the YAML config from URL, it will deploy the Nginx controller. Nginx ingress controller will manage the Ingress you are creating above.
Ingress is rule to divert the traffic and controller manages these rules (ingress).
So just running the apply to K8s cluster context will download and start the PODs of the Nginx controller.
as you mentioned in your ingress annotation
kubernetes.io/ingress.class: nginx
that specific ingress rule will get connected or managed by nginx controller.
inside the ingress you have mentioned mysite.local so make sure in local setup host file you are mapping the domain to IP.
Once controller is up and running opening the URL (mysite.local) into the browser will show the site.

Related

getting not found: NGINX Ingress

I am trying to learn .NET Microservice. I have been following a great tutorial on Youtube (Time: 4:44:55, Adding An API Gateway). Everything worked well until NGINX Ingress came into the picture. I pasted the same YAML file from the GitHub account of the trainer I doubled checked all the things but couldn't find anything:
I can see all the pods and services are working fine:
I updated my host file.
What did I miss?
URL, I am using: http://acme.com/api/platforms/
Error: HTTP Error 404. The requested resource is not found.
The output of the Ingress YAML:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.k8s.io/v1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx","nginx.ingress.kubernetes.io/use-regex":"true"},"name":"ingress-srv","namespace":"default"},"spec":{"rules":[{"host":"acme.com","http":{"paths":[{"backend":{"service":{"name":"platforms-clusterip-srv","port":{"number":80}}},"path":"/api/platforms","pathType":"Prefix"},{"backend":{"service":{"name":"commands-clusterip-srv","port":{"number":80}}},"path":"/api/c/platforms","pathType":"Prefix"}]}}]}}
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
creationTimestamp: "2021-09-18T00:12:41Z"
generation: 1
name: ingress-srv
namespace: default
resourceVersion: "2274742"
uid: a7376202-8b1b-4f1a-a42f-08de5f602192
spec:
rules:
- host: acme.com
http:
paths:
- backend:
service:
name: platforms-clusterip-srv
port:
number: 80
path: /api/platforms
pathType: Prefix
- backend:
service:
name: commands-clusterip-srv
port:
number: 80
path: /api/c/platforms
pathType: Prefix
status:
loadBalancer:
ingress:
- hostname: localhost
Services:
UPDATE: Tried below commands and got some new information:
UPDATE: Result of
Kubectl get pods --namespace=ingress-nginx
Try removing the regex annotation from th ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
name: ingress-srv
namespace: default
spec:
rules:
- host: acme.com
http:
paths:
- backend:
service:
name: platforms-clusterip-srv
port:
number: 80
path: /api/platforms
pathType: Prefix
- backend:
service:
name: commands-clusterip-srv
port:
number: 80
path: /api/c/platforms
pathType: Prefix
or just try this nginx.ingress.kubernetes.io/rewrite-target: /
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: acme.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: commands-clusterip-srv
port:
number: 80
in above ingress, all requests will go to service commands-clusterip-srv so from browser side you pass anything either /api or /api/c ingress will route the traffic to that service if your host is acme.com
Error 404 clearly means there is some issue with your Nginx configuration path is not matching or host issue, Nginx not able to find upstream or target so it throws 404.
Update
Try adding IP and entry into the host file for
192.168.1.28 acme.com
i am not sure you have used the IP POD to curl ideally you should me using the acme.com as you can to access the data.
also hope you service, deployment and ingress are in same namespace.
First of all, Thank you Harsh for your precious time. I tried all the things but no error was found.
It was really a miracle that I am able to resolve it issue on HTTPS. I am able to access "https://acme.com/api/platforms". But still, HTTP is giving me the same error. However, I am fine with HTTPS

Nginx Ingress works only if nodeport is added to the host name. How to make it work without nodeport?

I'm trying a simple microservices app on a cloud Kubernetes cluster. This is the Ingress yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx-nginx-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: nginx
spec:
defaultBackend:
service:
name: auth-svc
port:
number: 5000
rules:
- host: "somehostname.xyz"
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: auth-svc
port:
number: 5000
The problem:
When I use this URL, I'm able to access the auth service: http://somehostname.xyz:31840. However, if I use http://somehostname.xyz, I get a "This site can’t be reached somehostname.xyz refused to connect." error.
The auth service sends GET requests to other services too, and I'm able to see the response from those services if I use:
http://somehostname.xyz:31840/go or http://somehostname.xyz:31840/express. But again, these work only if the nodeport 31840 is used.
My questions:
What typically causes such a problem, where I can access the service
using the hostname and nodeport, but it won't work without supplying the
nodeport?
Is there a method to test this in a different way to figure out where
the problem is?
Is it a problem with the Ingress or Auth namespace? Is it a problem
with the hostname in Flask? Is it a problem with the Ingress
controller? How do I debug this?
These are the results of kubectl get all and other commands.
NAME READY STATUS RESTARTS
pod/auth-flask-58ccd5c94c-g257t 1/1 Running 0
pod/ingress-nginx-nginx-ingress-6677d54459-gtr42 1/1 Running 0
NAME TYPE EXTERNAL-IP PORT(S)
service/auth-svc ClusterIP <none> 5000/TCP
service/ingress-nginx-nginx-ingress LoadBalancer 172.xxx.xx.130 80:31840/TCP,443:30550/TCP
NAME READY UP-TO-DATE AVAILABLE
deployment.apps/auth-flask 1/1 1 1
deployment.apps/ingress-nginx-nginx-ingress 1/1 1 1
NAME DESIRED CURRENT READY
replicaset.apps/auth-flask-58ccd5c94c 1 1 1
replicaset.apps/ingress-nginx-nginx-ingress-6677d54459 1 1 1
NAME CLASS HOSTS ADDRESS PORTS
ingress-nginx-nginx-ingress <none> somehostname.xyz 172.xxx.xx.130 80
Describing ingress also seems normal.
kubectl describe ingress ingress-nginx-nginx-ingress
Name: ingress-nginx-nginx-ingress
Namespace: default
Address: 172.xxx.xx.130
Default backend: auth-svc:5000 (10.x.xx.xxx:5000)
Rules:
Host Path Backends
---- ---- --------
somehostname.xyz
/ auth-svc:5000 (10.x.xx.xxx:5000)
Annotations: kubernetes.io/ingress.class: nginx
This is the code of Auth.
import requests
from flask import Flask
app = Flask(__name__)
#app.route('/')
def indexPage():
return ' <!DOCTYPE html><html><head><meta charset="UTF-8" />\
<title>Microservice</title></head> \
<body><div style="text-align: center;">Welcome to the Auth page</div></body></html>'
#app.route('/go')
def getGoJson():
return requests.get('http://analytics-svc:8082/info').content
#app.route('/express')
def getNodeResponse():
return requests.get('http://node-svc:8085/express').content
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0")
and Auth's Dockerfile:
FROM python:3.8-slim-buster
WORKDIR /usr/src/app
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
ENV FLASK_ENV=development
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]
The part of docker-compose yaml for auth:
version: "3.3"
services:
auth:
build: ./auth/
image: nav9/auth-flask:v1
ports:
- "5000:5000"
Auth's Kubernetes manifest:
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-flask
spec:
selector:
matchLabels:
any-name: auth-flask
template:
metadata:
labels:
any-name: auth-flask
spec:
containers:
- name: auth-name
image: nav9/auth-flask:v1
imagePullPolicy: Always
ports:
- containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
name: auth-svc
spec:
# type: ClusterIP
ports:
- targetPort: 5000
port: 5000
selector:
any-name: auth-flask
What typically causes such a problem, where I can access the service using the hostname and nodeport, but it won't work without supplying the nodeport?
If the URL works when using the nodeport and not without the nodeport, then this means that the ingress is not configured properly for what you want to do.
Is there a method to test this in a different way to figure out where the problem is?
Steps for troubleshooting are:
The first step is determine if the error is from the ingress or from your back-end service.
In your case, the error This site can’t be reached somehostname.xyz refused to connect, sounds like the Ingress found the service to map to and used port 5000 to connect to it, and the connection was refused or nothing was listening on port 5000 for that service.
I'd next look at the auth-svc logs to see that that request came into the system and why it was refused.
My guess is that the auth service is listening on port 31840 but your ingress says to connect to port 5000 based on the configuration.
You might try adding a port mapping from 80 to 31840 as a hack/test to see if you get a different error.
Something like:
spec:
rules:
- host: "somehostname.xyz"
http:
paths:
- path: "/"
backend:
service:
port:
number: 31840
I've only included the part needed to show the indentation properly.
So the other way to test this out is to create additional URLs that map to different ports, so for example:
/try1 => auth-svc:5000
/try2 => auth-svc:31840
/try3 => auth-svc:443
The other part that I haven't played with that might be an issue is that you are using http and I don't know of any auth service that would use http, so simply trying to connect using http to an app that wants https will get a connection either refused or a strange error, so that might be related to the problem/error you are seeing.
Hope this gives you some ideas to try.
The solution has three parts:
Use kubectl get all to find out the running ingress service:
NAME TYPE EXTERNAL-IP PORT(S)
service/ingress-nginx-nginx-ingress LoadBalancer 172.xxx.xx.130 80:31840/TCP,443:30550/TCP
Copy the EXTERNAL-IP of the service (in this case 172.xxx.xx.130).
Add a DNS A record named *.somehostname.xyz for the cloud cluster, and use the IP address 172.xxx.xx.130.
When accessing the hostname via the browser, make sure that http is used instead of https.

Enable Ingress controller on Docker Desktop with WLS2

Currently, I'm using Docker Desktop with WSL2 integration. I found that Docker Desktop automatically had created a cluster for me. It means I don't have to install and use Minikube or Kind to create cluster.
The problem is that, how could I enable Ingress Controller if I use "built-in" cluster from Docker Desktop?
I tried to create an Ingress to check if this work or not, but as my guess, it didn't work.
The YAML file I created as follows:
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
minReadySeconds: 30
selector:
matchLabels:
app: webapp
replicas: 1
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nodejs-helloworld:v1
---
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
selector:
app: webapp
ports:
- name: http
port: 3000
nodePort: 30090 # only for NotPort > 30,000
type: NodePort #ClusterIP inside cluster
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: webapp-ingress
spec:
defaultBackend:
service:
name: webapp-service
port:
number: 3000
rules:
- host: ingress.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp-service
port:
number: 3000
I tried to access ingress.local/ but it was not successful. (I added ingress.local to point to 127.0.0.1 in host file. And the webapp worked fine at kubernetes.docker.internal:30090 )
Could you please help me to know the root cause?
Thank you.
Finally I found the way to fix. I have to deploy ingress Nginx by command:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.41.2/deploy/static/provider/cloud/deploy.yaml
(Follows the instruction at https://kubernetes.github.io/ingress-nginx/deploy/#docker-for-mac. It works just fine for Docker for Windows)
Now I can access http://ingress.local successfully.
You have to install an ingress-nginx controller on your cluster, so that your nodes will have an opened port 80/443.
Using helm (v3 - see documentation):
helm install --namespace kube-system nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx
Using kubectl (see documentation):
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.43.0/deploy/static/provider/cloud/deploy.yaml
Then manually adding your ingresses' hostnames to /etc/hosts:
127.0.0.1 ingress.local
127.0.0.1 my.other.service.local
# ...
Then if you make a request on http://ingress.local:
the DNS resolution will route to your cluster node
then the ingress controller will serve the request on port 80
then ingress will route the request to the configured backend service
and the service will route to an available pod
The newest version of Docker Desktop for Windows already adds a hosts file entry: 127.0.0.1 kubernetes.docker.internal.
You had to do use kubernetes.docker.internal URL as a hostname in Ingress definition if you want to point to 127.0.0.1. This should be in the docs on this page kubernetes.github.io/ingress-nginx/deploy but there is no Docker Desktop for Windows section there.
Your files should look like this:
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
type: NodePort
selector:
app: webapp
ports:
- name: http
protocol: TCP
port: 3000
nodePort: 30090
Your Ingress file should look like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: webapp-ingress
spec:
rules:
- host: kubernetes.docker.internal
http:
paths:
- path: /
backend:
serviceName: webapp-service
servicePort: http
Then you are able to connect to app using http://kubernetes.docker.internal/.
Example you can see here: wsl2-docker-for-desktop.
I used the Docker-Desktop version to install the nginx-ingress controller
https://kubernetes.github.io/ingress-nginx/deploy/#docker-desktop
curl http://kubernetes.docker.internal/
Offcourse I've not installed any workload yet but the default ingress controller works just fine.
With Kustomize you can simply use
helmCharts:
- name: ingress-nginx
releaseName: ingress-nginx
repo: https://kubernetes.github.io/ingress-nginx
This is just to point out that Amel Mahmuzićs comment is still valid with a recent (I used the ingress-nginx Helm Chart 4.4.2) ingress deployment.
I could not get this to work for far too long (I tried to follow the Strapi fodadvisor example with Docker Desktop build in Kubernetes instead of minikube) and always received a 404 from the ingress.
However, after using this yaml with the added annotation
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: foodadvisor.backend
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: foodadvisor-backend
port:
number: 1337
- host: foodadvisor.client
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: foodadvisor-frontend
port:
number: 3000
it worked immediately. The K82 docs mention, that this annotation is deprecated.

Nginx Ingress Controller Returns 404 Kubernetes

I am trying to create an ingress controller that points to a service that I have exposed via NodePort.
Here is the yaml file for the ingress controller (taken from https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/):
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- host: hello-world.info
http:
paths:
- path: /
backend:
serviceName: appName
servicePort: 80
I can connect directly to the node port and the frontend is displayed.
Please note that I am doing this because the frontend app is unable to connect to other deployments that I have created and I read that an ingress controller would be able to solve the issue. Will I still have to add an Nginx reverse proxy? If so how would I do that? I have tried adding this to the nginx config file but with no success.
location /middleware/ {
proxy_pass http://middleware/;
}
You must use a proper hostname to reach the route defined in the Ingress object. Either update your /etc/hosts file or use curl -H "hello-world.info" localhost type command. Alternatively, you can delete the host mapping and redirect all traffic to one default service.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: appName
servicePort: 80

Empty Address on Docker Desktop kubernates for Ingress

k8 ingress yaml which is used to deploy ingress in docker desktop k8 but not working address is always empty any one please help me on this
$ kubectl get ingress springboot-ingress
NAME HOSTS ADDRESS PORTS AGE
springboot-ingress espark.com,localhost 80 12m
working code git url
https://github.com/adarshkumarsingh83/kubernetes/tree/master/springboot-kubernetes-ingress-lb
i have used below url
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/cloud-generic.yaml
$ kubectl apply -f $(pwd)/kubernates/ingress.yaml
and change the ingress yaml one line and it worked for me
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: springboot-ingress
spec:
rules:
- host: espark.com
http:
paths:
- path: /v1/api/address
backend:
serviceName: espark-address-service
servicePort: 8080
- path: /v1/api/employee
backend:
serviceName: espark-employee-service
servicePort: 8080
- host: localhost
http:
paths:
- path: /v1/api/address
backend:
serviceName: espark-address-service
servicePort: 8080
- path: /v1/api/employee
backend:
serviceName: espark-employee-service
servicePort: 8080
Check if endpoint is generated for your service by kubectl get endpoints and verify it has IP. If not, check the selectors and port in your service resource, they should match at least one running pod, otherwise what you see above will happen.

Resources