I'm using Minikube single-node Kubernetes cluster inside Oracle VM Virtualbox. One of the pods in the node is a Next.js based client and the rest of the pods are different microservices. Let's say my client (Pod1) needs to send a HTTP request to the auth microservice (Pod2), before rendering - see the diagram: Minikube Cluster
Below is my ingress-service.yaml file:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
rules:
- host: dummyweb.info
http:
paths:
- path: /api/users/?(.*)
backend:
serviceName: auth-srv
servicePort: 3000
- path: /?(.*)
backend:
serviceName: client-srv
servicePort: 3000
You can see that each service has a specific path. Thus, I would like to send the HTTP request from client (Pod1) to Ingress Service and then Ingress to reroute the request to the appropriate service, depending on the path. In other words, client living in Pod1 will send HTTP GET request to auth service living in Pod2 through Ingress Service using the following URL:
http://<ingress-service-url>/api/users/....
I need to figure out what is the URL of the Ingress service.
I enabled NGINX Ingress controller:
minikube addons enable ingress
I verified that the NGINX Ingress controller is running:
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-f9fd979d6-hfnfj 1/1 Running 5 45h
etcd-minikube 1/1 Running 5 45h
ingress-nginx-admission-create-dkthv 0/1 Completed 0 23h
ingress-nginx-admission-patch-4gtth 0/1 Completed 0 23h
ingress-nginx-controller-789d9c4dc-qdqxv 1/1 Running 3 23h
kube-apiserver-minikube 1/1 Running 5 45h
kube-controller-manager-minikube 1/1 Running 5 45h
kube-proxy-sr6pt 1/1 Running 5 45h
kube-scheduler-minikube 1/1 Running 5 45h
storage-provisioner 1/1 Running 11 45h
Then, I'm checking what services are available in kube-system namespace:
kubectl get services -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller-admission ClusterIP 10.97.5.35 <none> 443/TCP 24h
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 45h
I'm assuming that the inner URL to the Ingress service is:
http://ingress-nginx-controller-admission.kube-system.svc.cluster.local
As we saw above, ingress-nginx-controller-admission service exposes only port 443, so on HTTP request I'm getting the following error:
Server Error
Error: connect ETIMEDOUT 10.97.5.35:80
This error happened while generating the page. Any console logs will be displayed in the terminal window.
Call Stack
<unknown> (Error: connect ETIMEDOUT
10.97.5.35 (80)
TCPConnectWrap.afterConnect [as oncomplete]
net.js (1145:16)
I'm not interested in connecting directly to auth service.
There is a very simple solution to the problem described above:
1. I assume that you have already enabled ingress addon. If not: minikube addons enable ingress
.
2. You'll need Helm to install NGINX Ingress Controller:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install my-release ingress-nginx/ingress-nginx
where you can replace my-release
with whatever you like. In my case this is dimi
.
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
auth-mongo-srv ClusterIP 10.110.44.53 <none> 27017/TCP 46m
auth-srv ClusterIP 10.106.154.84 <none> 3000/TCP 46m
client-srv ClusterIP 10.108.31.36 <none> 3000/TCP 46m
dimi-ingress-nginx-controller LoadBalancer 10.102.12.127 <pending> 80:31599/TCP,443:32639/TCP 34m
dimi-ingress-nginx-controller-admission ClusterIP 10.102.171.116 <none> 443/TCP 34m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 58m
nats-srv ClusterIP 10.110.239.15 <none> 4222/TCP,8222/TCP 46m
orders-mongo-srv ClusterIP 10.101.67.81 <none> 27017/TCP 46m
orders-srv ClusterIP 10.103.29.63 <none> 3000/TCP 46m
tickets-mongo-srv ClusterIP 10.107.137.160 <none> 27017/TCP 46m
tickets-srv ClusterIP 10.106.203.231 <none> 3000/TCP 46m
dimi-ingress-nginx-controller
service of type LoadBalancer. So, if you need to deal with Server Side Rendering (SSR) and send a HTTP request from one pod (where your Next.js App is runnig) to one of your microservices (that is runnig in a different pod), before the page is even rendered, you can send the request to http://dimi-ingress-nginx-controller.default.svc.cluster.local/<path_set_in_the_Ingress_Resource>
.
For example, if my Next.js App needs to send a request to my Auth microservice the URL will be: http://dimi-ingress-nginx-controller.default.svc.cluster.local/api/users
. This way the HTTP(S) traffic will be handled by the Ingress Resource, where we already have a list of rules matched against all incoming requests. Keep in mind that Ingress
is a separate type of resource. It is not a Service
. Here you can read what things get DNS names in kubernetes and Ingress
is not among of them.
If you want to connect to your app, exposed via Ingress
simply execute the following command:
kubectl get ingress
It will show you its IP address and you should be able to curl it or send HTTP GET request in any other way from within your Pod
. Below output from my example:
$ kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
example-ingress hello-world.info 10.0.2.15 80 5m54s
Now we can kubectl exec
to a different Pod
and connect to our app running in another Pod
, exposed via Ingress
:
$ kubectl exec -ti static-web -- /bin/bash
root@static-web:/# curl --header 'Host: hello-world.info' http://10.0.2.15
Hello, world!
Version: 1.0.0
Hostname: web-9bbd7b488-qvg85
root@static-web:/#
If you rather want to use DNS name, you can always add your dummyweb.info
domain to /etc/hosts
file of your Pod
. You can read on how to do it here.
If you don't specify the correct hostname (as you can see above I specified it in http reqest's header) you'll get 404
anyway:
root@static-web:/# curl http://10.0.2.15
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>openresty/1.15.8.1</center>
</body>
</html>