Home > Software design >  Mistakes in my ingress yaml file or process?
Mistakes in my ingress yaml file or process?

Time:12-21

I'm trying kubernetes and making some progress, but I'm running into an issue with ingress when trying to make my hello world app publicly available.

SUCCESS WITH DEPLOYMENT AND SERVICE

I created a simple hello world type of nodejs app and pushed the image to my docker hub johnlai2004/swarm2. I successfully created a deployment and service with this yaml file:

nodejs.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-hello
  labels:
    app: nodejs-hello
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nodejs-hello
  template:
    metadata:
      labels:
        app: nodejs-hello
    spec:
      containers:
      - name: nodejs-hello
        image: johnlai2004/swarm2
        ports:
        - containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
  name: nodejs-hello-service
spec:
  selector:
    app: nodejs-hello
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 3000
      targetPort: 3000
      nodePort: 30000

I uploaded these files to a VPS with a new installation of ubuntu 20.04, minikube, kubectl and docker.

I ran the following commands and got the results I wanted:

minikube start --driver=docker
kubectl apply -f nodejs.yaml
minikube service nodejs-hello-service
|-----------|----------------------|-------------|---------------------------|
| NAMESPACE |         NAME         | TARGET PORT |            URL            |
|-----------|----------------------|-------------|---------------------------|
| default   | nodejs-hello-service |        3000 | http://192.168.49.2:30000 |
|-----------|----------------------|-------------|---------------------------|

When I do a wget http://192.168.49.2:30000, I get an index.html file that says hello from nodejs-hello-556dc868-6lrdz at 12/19/2021, 10:29:56 PM. This is perfect.

FAILURE WITH INGRESS

Next, I want to use ingress so that I can see the page at http://website.example.com (replace website.example.com with the actual domain that points to my server). I put this file on my server:

nodejs-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nodejs-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    - host: website.example.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: nodejs-hello-service
              port:
                number: 3000

And I ran the commands

minikube addons enable ingress
kubectl apply -f nodejs-ingress.yaml
kubectl get ingress
NAME             CLASS    HOSTS                   ADDRESS     PORTS   AGE
nodejs-ingress   <none>   website.example.com     localhost   80      15m

But when I visit http://website.example.com with my browser, the browser says it can't connect. Using wget http://website.example.com gave the same connection issue.

Can someone point out what I may have done wrong?


UPDATE

I ran these commands because I think it shows I didn't install ingress-controller in the right name space?

kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create--1-tqsrp     0/1     Completed   0          4h25m
ingress-nginx-admission-patch--1-sth26      0/1     Completed   0          4h25m
ingress-nginx-controller-5f66978484-tmx72   1/1     Running     0          4h25m

kubectl get pod -n default
NAME                          READY   STATUS    RESTARTS   AGE
nodejs-hello-556dc868-6lrdz   1/1     Running   0          40m

So does this mean my nodejs app is in a name space that doesn't have access to the ingress controller?


UPDATE 2

I also tried following this guide step by step: enter image description here

Does this difference matter? I'm hosting things in a cloud vps called linode.com. Does that change the way I do things?

CodePudding user response:

The behaviour you have is expected. Let me explain why. Going point through point, and at the end I will present my tips.

First I think it's worth to present minikube architecture. I'm assuming you have installed minikube using default driver docker as you have address 192.168.49.2 which is standard for docker driver.

The layers are:

  • your VM with Ubuntu 20.04
  • Kubernetes cluster setup by minikube which is docker container with address 192.168.49.2 on the VM

So... you can not just run curl on the VM using a localhost address to connect to the service. The localhost is referring to the device that you are making curl request (so your VM), not the docker container. That's why you need to use the 192.168.49.2 address.

You can type docker ps -a, and you will see the container which is an actual Kubernetes cluster. You can exec into it using docker exec command and then run curl command with the localhost address:

user@example-ubuntu-minikube-template-1:~$ curl -H "Host: hello-world.info" localhost
curl: (7) Failed to connect to localhost port 80: Connection refused
user@example-ubuntu-minikube-template-1:~$ docker ps -a
CONTAINER ID   IMAGE                                 COMMAND                  CREATED      STATUS      PORTS                                                                                                                                  NAMES
1a4ba3895990   gcr.io/k8s-minikube/kicbase:v0.0.28   "/usr/local/bin/entr…"   4 days ago   Up 4 days   127.0.0.1:49157->22/tcp, 127.0.0.1:49156->2376/tcp, 127.0.0.1:49155->5000/tcp, 127.0.0.1:49154->8443/tcp, 127.0.0.1:49153->32443/tcp   minikube
user@example-ubuntu-minikube-template-1:~$ docker exec -it 1a sh
# curl -H "Host: hello-world.info" localhost
Hello, world!
Version: 1.0.0
Hostname: web-79d88c97d6-nl4c7

Keep in mind that you can access this container only from the VM that is hosting this container. Without any further configuration it's you can't just access it from the other VMs. It is possible, but not recommended.

Good explanation in the minikube FAQ:

How can I access a minikube cluster from a remote network?

minikube’s primary goal is to quickly set up local Kubernetes clusters, and therefore we strongly discourage using minikube in production or for listening to remote traffic. By design, minikube is meant to only listen on the local network.

However, it is possible to configure minikube to listen on a remote network. This will open your network to the outside world and is not recommended. If you are not fully aware of the security implications, please avoid using this.

For the docker and podman driver, use --listen-address flag:

minikube start --listen-address=0.0.0.0

So I'd avoid it. I will present a better possible solution at the end of the answer.

You asked:

But when I visit http://website.example.com with my browser, the browser says it can't connect. Using wget http://website.example.com gave the same connection issue.

Can someone point out what I may have done wrong?

Your computer does not know what it is website.example.com. It's not aware that this name is used by your Ingress. If your computer does not find this name in hosts file it will start looking for this over the Internet.

So you have some possible solutions:

  • use curl -H 'HOST: website.example.com' http://192.168.49.2:80 - it will work only on the VM where is minikube
  • add host to the hosts file - something like 192.168.49.2 website.example.com - it will work only on the VM where is minikube
  • Setup a bare-metal cluster (more details in the sum up section) and point the domain address to the VM address. In GCP and AWS you can do it using Google Cloud DNS or Amazon Route 53. On linode cloud maybe this one - DNS Manager ?

EDIT: You wrote that you have a domain pointed to the server, so please just check the sum up section of my answer.

Also you asked:

I ran these commands because I think it shows I didn't install ingress-controller in the right name space?

So does this mean my nodejs app is in a name space that doesn't have access to the ingress controller?

It's absolutely normal:

It will install the controller in the ingress-nginx namespace, creating that namespace if it doesn't already exist.

Also:

I also tried following this guide step by step: https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/

One difference I noticed was when I ran the command kubectl get ingress, ADDRESS says localhost. But in the guide, it says it is supposed to be 172.17.0.15

Does this difference matter? I'm hosting things in a cloud vps called linode.com. Does that change the way I do things?

It's also normal and expected when using minikube with a docker driver.

To sum up / other tips:

CodePudding user response:

Can you try kubectl get ingress nodejs-ingress to see if the ingress resource is created successfully.

Then curl with curl -H 'HOST: <replace with HOSTS from the output of get ingress command>' http://<ADDRESS from the output of get ingress command>:<PORTS from the output of get ingress command>

  • Related