How to expose nginx via cloud-managed kubernetes without using load balancers, helm, etc?

4/23/2021

I'm trying to learn Kubernetes fundamentals, and although I've played around with kubectl and minikube locally, I'd like to expose the basic nginx docker image, over the internet, on a domain I have access to (for this example, nginx.mydomain.com), using DigitalOcean managed Kubernetes. My stumbling point seems to be all-networking related (services and ingress controllers).

However, I'd also like to avoid having to spin up tons of cloud resources, and without use too many dependencies to abstract the problem away from me—so no LoadBalancers or Helm please. Right now, the majority of the answers I've seen for problems like this either solve the problem by invoking these two pieces of tooling.

Here's my nginx.deployment.yaml file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  strategy:
    rollingUpdate:
      maxSurge: 1
  replicas: 1
  selector:
    matchLabels:
      app: nginx-deployment
  template:
    metadata:
      labels:
        app: nginx-deployment
    spec:
      containers:
        - name: nginx-app
          image: nginx
          ports:
            - containerPort: 80

I apply this to my cluster: kubectl apply -f k8s/nginx.deployment.yaml. My understanding is that is creates an nginx container, in a pod, able to accept connections on port 80 (ideal for nginx). I also expose my pod using a NodePort service:

kubectl expose deployment nginx-deployment --port=8080 --type=NodePort --name=nginx-service

From here, I also create an nginx Ingress controller, and apply that via kubectl also:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: testing-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: nginx.mydomain.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx-service
                port:
                  number: 8080

I can confirm this ran, but for some reason, the address field is blank? I take it this shouldn't be the case?

~ % kubectl get ingress
NAME              CLASS    HOSTS                         ADDRESS   PORTS   AGE
testing-ingress   <none>   nginx.mydomain.com                      80      83m

Given I have then added an A DNS record to bind nginx.mydomain.com to the DigitalOcean droplet running my node in my cluster, shouldn't I be able to access nginx.mydomain.com on port 80 and see the nginx welcome page? Right now, I simply get connection refused:

curl http://nginx.mydomain.com
curl: (7) Failed to connect to http://nginx.mydomain.com port 80: Connection refused

What am I missing here?

-- marked-down
kubernetes
nginx

2 Answers

5/2/2021

IF the control plane node is accessible via somenode.somecloudprovider.com, then you will need to do the following:

  1. Install nginx-ingress-controller in the cluster. This is fairly simple, just follow the official documentation.
  2. On the control node (outside the cluster) install the nginx proxy service.
  3. Get the port the nginx-ingress-controller is listening on as a load-balancer. For example:
    > kubectl get svc --namespace=ingress-nginx
    > Output
      NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP       PORT(S)                      AGE
      ingress-nginx-controller             LoadBalancer   10.245.201.120   203.0.113.0   80:31818/TCP,443:31146/TCP   14m
      ingress-nginx-controller-admission   ClusterIP      10.245.239.119   <none>            443/TCP                      14m
    Here 31818 is the port.
  4. Configure the outer nginx proxy to listen to port 80 and forward it to localhost:31818
    http {
      server {
        listen 80
        location / {
            proxy_pass http://localhost:31818;
        }
      }
    }
    

Now when you access the address somenode.somecloudprovider.com the outer nginx proxy will route it to nginx-ingress-controller within the cluster. From there, the ingress-controller will look at the ingress resources defined in the cluster and send it to the matching service.

Also if you want to enable HTTPS, just update the outer proxy to listen on 443 with a certificate.

-- S.D.
Source: StackOverflow

4/23/2021

i am not sure which IP address you have added in your DNS to resolve your domain address.

the idea flow for ingress gose something like :

internet traffic > ingress > ingress controller > service > deployment > Pod

respective ingress controller is required to run & manage the ingress object.

When you set up the ingress controller it will create the service with LoadBalancer type and provide you one external IP.

you can add this external IP into DNS as A record and after that, you can create the ingress for a specific domain.

For example, you have added a record in DNS :

*.beta.example.com A 30 TTL 192.168.1.52(whatever your loadbalancer IP)

DNS will divert all the traffic to the ingress controller and the ingress controller will check the ingress object configuration redirect traffic to specific Kubernetes service.

you will might also require in future to use the cert-manager for managing the SSL/TLS certificates please refer this nice blog post from digital ocean for setting up Nginx controller: https://www.digitalocean.com/community/tutorials/how-to-set-up-an-nginx-ingress-with-cert-manager-on-digitalocean-kubernetes

OR

Still, if you are looking forward with not running LoadBalancer and all

it's possible to run Nginx ingress controller without LoadBalancer however personally I would not suggest it.

you can follow this : https://stackoverflow.com/a/43190775/5525824

Note : in any case, you require to install the ingress controller and use it. with NodePort issue is that you have to use the External IP of Node (VM), now during the scale down or scaling up if node get crashed your IP won't work and traffic to the cluster gets stop.

-- Harsh Manvar
Source: StackOverflow