How to expose 80 port in kubernetes nginx controller

11/1/2020

I installed kubernete in several raspberry pi 4 without using cloud. I follow tutorial to deploy mongodb and mongo express and I can get inside the mongo express website using node port mode. However, when I change to use nignx controller, it works when I type ip address:port (192.168.1.194:30574 It is my master node ip and the port is where the ingress-nginx-controller expose) or domain:port (mymongo.com:30574). But if I just use domain name (mymongo.com) without port, it cannot get inside the website. Do I miss something? Thank you! Here is my yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: 
  name: mongo-express-ingress
spec:
  rules:
   - host: "mymongo.com"
   - http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: mongo-express-service
            port:
              number: 8081
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongo-express
  labels:
    app: mongo-express
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mongo-express
  template:
    metadata:
      labels:
        app: mongo-express
    spec:
      containers:
        - name: mongo-express
          image: mongo-express
          ports:
            - containerPort: 8081
          env:
            - name: ME_CONFIG_MONGODB_ADMINUSERNAME
              valueFrom:
                secretKeyRef:
                  name: mongodb-secret
                  key: mongo-root-username
            - name: ME_CONFIG_MONGODB_ADMINPASSWORD 
              valueFrom:
                secretKeyRef:
                  name: mongodb-secret
                  key: mongo-root-password
            - name: ME_CONFIG_MONGODB_SERVER
              valueFrom:
                configMapKeyRef:
                  name: mongodb-configmap
                  key: database_url
---
apiVersion: v1
kind: Service
metadata:
  name: mongo-express-service
spec:
  selector:
    app: mongo-express
  ports:
    - protocol: TCP
      port: 8081
      targetPort: 8081
ubuntu@master:~/k8s-config$ kubectl get services --all-namespaces
NAMESPACE              NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
default                kubernetes                           ClusterIP   10.96.0.1       <none>        443/TCP                      8d
default                mongo-express-service                ClusterIP   10.107.95.131   <none>        8081/TCP                     6d19h
default                mongodb-service                      ClusterIP   10.101.118.57   <none>        27017/TCP                    6d19h
ingress-nginx          ingress-nginx-controller             NodePort    10.96.94.30     <none>        80:30574/TCP,443:31882/TCP   6d4h
ingress-nginx          ingress-nginx-controller-admission   ClusterIP   10.104.121.41   <none>        443/TCP                      6d4h
kube-system            kube-dns                             ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP,9153/TCP       8d
kubernetes-dashboard   dashboard-metrics-scraper            ClusterIP   10.99.4.159     <none>        8000/TCP                     6d22h
kubernetes-dashboard   kubernetes-dashboard                 NodePort    10.98.92.238    <none>        443:31044/TCP             
-- benben520
kubernetes
kubernetes-ingress
nginx
nginx-ingress

1 Answer

11/2/2020

In your current configuration, it works as expected.

Your Nginx Ingress Controller is configured as NodePort Type

NodePort: Exposes the Service on each Node's IP at a static port (the NodePort). A ClusterIP Service, to which the NodePort Service routes, is automatically created. You'll be able to contact the NodePort Service, from outside the cluster, by requesting <NodeIP>:<NodePort>.

So if you are using NodePort type, you will be able to connect only when you will specify <NodeIP:NodePort>, in your case mymongo.com:30574 (NodeIP: mymongo.com, NodePort: 30574).

If you would like to use only a domain, you would need to consider ServiceType as LoadBalancer.

LoadBalancer: Exposes the Service externally using a cloud provider's load balancer. NodePort and ClusterIP Services, to which the external load balancer routes, are automatically created.

To achieve that without using Cloud LoadBalancer you can use MetalLB solution.

Your current configuration is also described in Nginx Ingress Documentation as Over a NodePort Service.

You can also consider using host network solution as alternative for baremaetal solution.

In a setup where there is no external load balancer available but using NodePorts is not an option, one can configure ingress-nginx Pods to use the network of the host they run on instead of a dedicated network namespace. The benefit of this approach is that the NGINX Ingress controller can bind ports 80 and 443 directly to Kubernetes nodes' network interfaces, without the extra network translation imposed by NodePort Services.

template:
  spec:
    hostNetwork: true
-- PjoterS
Source: StackOverflow