Sending http request from kubernetes pod through ingress service to another pod in Minikube

10/8/2020

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)
  1. Is this the right inner URL to access Ingress Service in Minikube?
  2. If it is, how to open port 80?

I'm not interested in connecting directly to auth service.

-- Dimitar Georgiev
kubernetes
kubernetes-ingress
minikube

2 Answers

10/22/2020

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.

  1. Check the available services in the default namespace:
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
  1. Now we have 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.
-- Dimitar Georgiev
Source: StackOverflow

10/9/2020

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>
-- mario
Source: StackOverflow